diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000000..c66944451a --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,54 @@ +name: "CodeQL" + +on: + push: + branches: [candidate, master] + pull_request: + # The branches below must be a subset of the branches above + branches: [candidate] + schedule: + - cron: '0 3 * * 3' + +jobs: + analyse: + name: Analyse + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + # We must fetch at least the immediate parents so that if this is + # a pull request then we can checkout the head. + fetch-depth: 2 + + # If this run was triggered by a pull request event, then checkout + # the head of the pull request instead of the merge commit. + - run: git checkout HEAD^2 + if: ${{ github.event_name == 'pull_request' }} + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + # Override language selection by uncommenting this and choosing your languages + # with: + # languages: go, javascript, csharp, python, cpp, java + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/shiftleft-analysis.yml b/.github/workflows/shiftleft-analysis.yml new file mode 100644 index 0000000000..831315f1ab --- /dev/null +++ b/.github/workflows/shiftleft-analysis.yml @@ -0,0 +1,36 @@ +# This workflow integrates ShiftLeft Scan with GitHub's code scanning feature +# ShiftLeft Scan is a free open-source security tool for modern DevOps teams +# Visit https://slscan.io/en/latest/integrations/code-scan for help +name: ShiftLeft Scan + +# This section configures the trigger for the workflow. Feel free to customize depending on your convention +on: push + +jobs: + Scan-Build: + # Scan runs on ubuntu, mac and windows + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + # Instructions + # 1. Setup JDK, Node.js, Python etc depending on your project type + # 2. Compile or build the project before invoking scan + # Example: mvn compile, or npm install or pip install goes here + # 3. Invoke ShiftLeft Scan with the github token. Leave the workspace empty to use relative url + + - name: Perform ShiftLeft Scan + uses: ShiftLeftSecurity/scan-action@master + env: + WORKSPACE: "" + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SCAN_AUTO_BUILD: true + with: + output: reports + # Scan auto-detects the languages in your project. To override uncomment the below variable and set the type + # type: credscan,java + # type: python + + - name: Upload report + uses: github/codeql-action/upload-sarif@v1 + with: + sarif_file: reports diff --git a/anet.yml b/anet.yml index 5d1774242c..4e5ad0f072 100644 --- a/anet.yml +++ b/anet.yml @@ -225,35 +225,20 @@ dictionary: componentClass: textarea style: height: 400px - assessment: - customFields: - issues: - type: special_field - label: Top 3 issues - placeholder: Enter the top 3 issues - widget: richTextEditor - style: - height: 300px - validations: - - type: required - params: [You must provide the top 3 issues] - status: - type: enum - label: Project status - helpText: Select an assessement status for objective - choices: - GREEN: - label: Green - color: '#c2ffb3' - AMBER: - label: Amber - color: '#ffe396' - RED: - label: Red - color: '#ff8279' - validations: - - type: required - params: [You must provide the assessment status] + assessments: + - recurrence: semiannualy + questions: + issues: + type: special_field + label: Top 3 issues + placeholder: Enter the top 3 issues + widget: richTextEditor + style: + height: 300px + validations: + - type: required + params: [You must provide the top 3 issues] + subLevel: shortLabel: Effort shortName: @@ -266,19 +251,48 @@ dictionary: componentClass: textarea style: height: 400px - assessment: - customFields: - issues: - type: special_field - label: Top 3 issues - placeholder: Enter the top 3 issues - widget: richTextEditor - style: - height: 300px - validations: - - type: required - params: [You must provide the top 3 issues] - + assessments: + - recurrence: monthly + questions: + issues: + type: special_field + label: Top 3 issues + placeholder: Enter the top 3 issues + widget: richTextEditor + style: + height: 300px + validations: + - type: required + params: [You must provide the top 3 issues] + status: + type: enum + label: Project status + helpText: Select an assessment status for objective + choices: + GREEN: + label: Green + color: '#c2ffb3' + AMBER: + label: Amber + color: '#ffe396' + RED: + label: Red + color: '#ff8279' + validations: + - type: required + params: [You must provide the assessment status] + - recurrence: weekly + questions: + issues: + type: special_field + label: Top 3 issues + placeholder: Enter the top 3 issues + widget: richTextEditor + style: + height: 300px + validations: + - type: required + params: [You must provide the top 3 issues] customFieldRef1: label: Parent task placeholder: Start typing to search for a higher level task @@ -304,13 +318,49 @@ dictionary: label: Responsible positions placeholder: Search for a position... customFields: - assessmentDefinition: - type: text - label: Assessment definition - placeholder: JSON that defines the effort (you need to know what you are doing) - componentClass: textarea - style: - height: 200px + assessments: + type: array_of_objects + label: Assessments definition + addButtonLabel: Add an assessment + objectLabel: Assessment + objectFields: + recurrence: + type: enum + label: Recurrence + helpText: Select a recurrence for this periodic assessment + choices: + once: + label: once + daily: + label: daily + weekly: + label: weekly + biweekly: + label: biweekly + semimonthly: + label: semimonthly + monthly: + label: monthly + quarterly: + label: quarterly + semiannualy: + label: semiannualy + relatedObjectType: + type: enum + label: Related object type + helpText: object type context in which the assessment will be made + choices: + report: + label: Report + null: + label: None + questions: + type: text + label: Questions + placeholder: JSON that defines the assessment (you need to know what you are doing) + componentClass: textarea + style: + height: 200px report: intent: Engagement purpose @@ -372,6 +422,10 @@ dictionary: - color: lightGray endValue: 10 label: advanced advanced advanced advanced + trainingDate: + type: date + label: Training date + visibleWhen: $[?(@.multipleButtons && @.multipleButtons.indexOf('train') != -1)] systemProcess: type: enum label: System / process @@ -649,6 +703,64 @@ dictionary: - value: "3" label: three color: '#ff8279' + assessments: + - recurrence: quarterly + questions: + test1: + type: enum + label: Test question 1 + choices: + "1": + label: one + color: '#c2ffb3' + "2": + label: two + color: '#ffe396' + "3": + label: three + color: '#ff8279' + test2: + type: enum + label: Test question 2 + choices: + "3": + label: three + color: '#ff8279' + "4": + label: four + color: '#ffe396' + "5": + label: five + color: '#c2ffb3' + test3: + type: enum + label: Test question 3 + choices: + "1": + label: one + color: '#c2ffb3' + "2": + label: two + color: '#ff8279' + "3": + label: three + color: '#ff8279' + - recurrence: once + relatedObjectType: report + questions: + question1: + type: enum + label: Attendee involvement + choices: + "1": + label: low + color: '#c2ffb3' + "2": + label: medium + color: '#ffe396' + "3": + label: high + color: '#ff8279' position: name: Afghan Tashkil @@ -728,3 +840,6 @@ dictionary: - label: decisives data: /data/dashboards/decisives.json type: decisives + - label: process board + type: board + data: /data/dashboards/process.json diff --git a/build.gradle b/build.gradle index a4eed07f7f..2a98a14296 100644 --- a/build.gradle +++ b/build.gradle @@ -1,8 +1,8 @@ plugins { id "org.kordamp.markdown.convert" version "1.2.0" - id "com.bmuschko.docker-remote-api" version "6.4.0" + id "com.bmuschko.docker-remote-api" version "6.6.1" id "com.github.node-gradle.node" version "2.2.4" - id "com.diffplug.gradle.spotless" version "4.4.0" + id "com.diffplug.spotless" version "5.1.1" } apply plugin: 'java' @@ -60,11 +60,11 @@ repositories { // In this section you declare the dependencies for your production and test code dependencies { // The production code uses the SLF4J logging API at compile time - implementation 'io.dropwizard:dropwizard-core:2.0.10' - implementation 'io.dropwizard:dropwizard-jdbi3:2.0.10' - implementation 'io.dropwizard:dropwizard-migrations:2.0.10' - implementation 'io.dropwizard:dropwizard-auth:2.0.10' - implementation 'io.dropwizard:dropwizard-views-freemarker:2.0.10' + implementation 'io.dropwizard:dropwizard-core:2.0.12' + implementation 'io.dropwizard:dropwizard-jdbi3:2.0.12' + implementation 'io.dropwizard:dropwizard-migrations:2.0.12' + implementation 'io.dropwizard:dropwizard-auth:2.0.12' + implementation 'io.dropwizard:dropwizard-views-freemarker:2.0.12' implementation 'io.dropwizard-bundles:dropwizard-configurable-assets-bundle:1.3.5' implementation 'ru.vyarus.guicey:guicey-jdbi3:5.1.0-2' @@ -72,9 +72,9 @@ dependencies { implementation 'commons-collections:commons-collections:3.2.2' // Supported databases: - implementation 'com.microsoft.sqlserver:mssql-jdbc:8.2.2.jre8' + implementation 'com.microsoft.sqlserver:mssql-jdbc:8.4.0.jre8' implementation 'org.postgresql:postgresql:42.2.14' // If using postgresql - implementation 'org.liquibase:liquibase-core:3.10.0' + implementation 'org.liquibase:liquibase-core:4.0.0' // For caching domain users (used in every request in the AuthenticationFilter) implementation 'org.ehcache:ehcache:3.8.1' @@ -88,12 +88,13 @@ dependencies { implementation 'com.github.waffle:waffle-jna:1.9.1' implementation 'com.graphql-java:java-dataloader:2.2.3' implementation 'io.leangen.graphql:spqr:0.10.1' - implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20200615.1' + implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20200713.1' + implementation 'com.mikesamuel:json-sanitizer:1.2.1' // Used for converting GraphQL request output to XML: implementation 'com.github.javadev:underscore-lodash:1.26' // For JSON schema validation - implementation 'com.networknt:json-schema-validator:1.0.41' + implementation 'com.networknt:json-schema-validator:1.0.42' // used for writing Excel documents implementation 'org.apache.poi:poi:4.1.2' @@ -105,8 +106,8 @@ dependencies { // For fast and simple image scaling implementation 'net.coobird:thumbnailator:0.4.11' - testImplementation 'io.dropwizard:dropwizard-testing:2.0.10' - testImplementation 'io.dropwizard:dropwizard-client:2.0.10' + testImplementation 'io.dropwizard:dropwizard-testing:2.0.12' + testImplementation 'io.dropwizard:dropwizard-client:2.0.12' testImplementation 'org.apache.commons:commons-io:1.3.2' testImplementation 'org.assertj:assertj-core:3.16.1' @@ -429,7 +430,8 @@ task dbMaintenance(dependsOn: 'compileJava', type: JavaExec) { args cmdline } -classes.dependsOn buildClient +jar.dependsOn buildClient +run.dependsOn buildClient //Configure the Java Checkstyle settings. Run with ./gradlew check checkstyle { diff --git a/client/config/wdio.config.js b/client/config/wdio.config.js index 9d39b8f341..029fd8e718 100644 --- a/client/config/wdio.config.js +++ b/client/config/wdio.config.js @@ -100,9 +100,7 @@ const config = { // // A key-value store of headers to be added to every selenium request. Values must be strings. Type: Object // Default: None - headers: { - Authorization: "Basic ZXJpbjplcmlu" - }, + // headers: {}, // // Default timeout for all waitFor* commands. waitforTimeout: 10000, diff --git a/client/config/webpack.client.dev.js b/client/config/webpack.client.dev.js index a1f89da7fc..76bc92b8e3 100644 --- a/client/config/webpack.client.dev.js +++ b/client/config/webpack.client.dev.js @@ -4,7 +4,7 @@ const HtmlWebpackPlugin = require("html-webpack-plugin") const common = require("./webpack.common.js") const paths = require("./paths") -module.exports = merge(common.clientConfig, { +module.exports = merge.merge(common.clientConfig, { resolve: { modules: [paths.appSrc, "node_modules", "platform/web-dev"] }, diff --git a/client/config/webpack.client.prod.js b/client/config/webpack.client.prod.js index cb1482c5e5..c4e2b540b3 100644 --- a/client/config/webpack.client.prod.js +++ b/client/config/webpack.client.prod.js @@ -7,7 +7,7 @@ const { CleanWebpackPlugin } = require("clean-webpack-plugin") const paths = require("./paths") const common = require("./webpack.common.js") -const clientConfig = merge(common.clientConfig, { +const clientConfig = merge.merge(common.clientConfig, { bail: true, devtool: "source-map", resolve: { diff --git a/client/config/webpack.common.js b/client/config/webpack.common.js index fc9514f785..ec96cc42cb 100644 --- a/client/config/webpack.common.js +++ b/client/config/webpack.common.js @@ -80,7 +80,7 @@ const commonConfig = { } module.exports = { - clientConfig: merge(commonConfig, { + clientConfig: merge.merge(commonConfig, { target: "web", entry: { anet: [require.resolve("./polyfills"), "./src/index.js"] @@ -115,7 +115,7 @@ module.exports = { ] }), - simConfig: merge(commonConfig, { + simConfig: merge.merge(commonConfig, { resolve: { modules: [paths.appSrc, "node_modules", "platform/node"] }, diff --git a/client/config/webpack.sim.dev.js b/client/config/webpack.sim.dev.js index 96a4023bea..ff0d1732b1 100644 --- a/client/config/webpack.sim.dev.js +++ b/client/config/webpack.sim.dev.js @@ -3,7 +3,7 @@ const webpack = require("webpack") const common = require("./webpack.common.js") const paths = require("./paths") -module.exports = merge(common.simConfig, { +module.exports = merge.merge(common.simConfig, { devtool: "eval-source-map", output: { pathinfo: true, diff --git a/client/package.json b/client/package.json index 44c33a7454..8664cc7ff2 100644 --- a/client/package.json +++ b/client/package.json @@ -4,66 +4,66 @@ "private": true, "homepage": "/assets/client", "devDependencies": { - "@babel/core": "7.10.3", - "@babel/plugin-proposal-class-properties": "7.10.1", - "@babel/plugin-proposal-decorators": "7.10.3", - "@babel/plugin-proposal-do-expressions": "7.10.1", - "@babel/plugin-proposal-export-default-from": "7.10.1", - "@babel/plugin-proposal-export-namespace-from": "7.10.1", - "@babel/plugin-proposal-function-sent": "7.10.1", - "@babel/plugin-proposal-json-strings": "7.10.1", - "@babel/plugin-proposal-logical-assignment-operators": "7.10.3", - "@babel/plugin-proposal-nullish-coalescing-operator": "7.10.1", - "@babel/plugin-proposal-numeric-separator": "7.10.1", - "@babel/plugin-proposal-optional-chaining": "7.10.3", - "@babel/plugin-proposal-pipeline-operator": "7.10.1", - "@babel/plugin-proposal-throw-expressions": "7.10.1", + "@babel/core": "7.11.1", + "@babel/eslint-parser": "7.11.0", + "@babel/plugin-proposal-class-properties": "7.10.4", + "@babel/plugin-proposal-decorators": "7.10.5", + "@babel/plugin-proposal-do-expressions": "7.10.4", + "@babel/plugin-proposal-export-default-from": "7.10.4", + "@babel/plugin-proposal-export-namespace-from": "7.10.4", + "@babel/plugin-proposal-function-sent": "7.10.4", + "@babel/plugin-proposal-json-strings": "7.10.4", + "@babel/plugin-proposal-logical-assignment-operators": "7.11.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "7.10.4", + "@babel/plugin-proposal-numeric-separator": "7.10.4", + "@babel/plugin-proposal-optional-chaining": "7.11.0", + "@babel/plugin-proposal-pipeline-operator": "7.10.5", + "@babel/plugin-proposal-throw-expressions": "7.10.4", "@babel/plugin-syntax-dynamic-import": "7.8.3", - "@babel/plugin-syntax-import-meta": "7.10.1", - "@babel/plugin-transform-proto-to-assign": "7.10.1", - "@babel/preset-react": "7.10.1", - "@babel/register": "7.10.3", - "@babel/runtime": "7.10.3", + "@babel/plugin-syntax-import-meta": "7.10.4", + "@babel/plugin-transform-proto-to-assign": "7.10.5", + "@babel/preset-react": "7.10.4", + "@babel/register": "7.10.5", + "@babel/runtime": "7.11.2", "@storybook/addon-actions": "5.3.19", "@storybook/react": "5.3.19", "@wdio/browserstack-service": "6.1.15", - "@wdio/cli": "6.1.22", - "@wdio/local-runner": "6.1.22", - "@wdio/mocha-framework": "6.1.19", - "@wdio/spec-reporter": "6.1.14", - "@wdio/sync": "6.1.14", + "@wdio/cli": "6.3.6", + "@wdio/local-runner": "6.3.6", + "@wdio/mocha-framework": "6.3.6", + "@wdio/spec-reporter": "6.3.6", + "@wdio/sync": "6.3.6", "aigle": "1.14.1", - "autoprefixer": "9.8.4", - "ava": "3.9.0", - "babel-eslint": "10.1.0", - "babel-jest": "26.1.0", + "autoprefixer": "9.8.6", + "ava": "3.11.1", + "babel-jest": "26.2.2", "babel-loader": "8.1.0", "babel-preset-react-app": "9.1.2", "cache-loader": "4.1.0", "chai": "4.2.0", "chalk": "4.1.0", - "chromedriver": "83.0.0", + "chromedriver": "84.0.1", "clean-webpack-plugin": "3.0.0", "colors": "1.4.0", "config": "3.3.1", - "copy-webpack-plugin": "6.0.2", - "countries-list": "2.5.4", + "copy-webpack-plugin": "6.0.3", + "countries-list": "2.5.6", "cross-fetch": "3.0.5", "cross-spawn": "7.0.3", - "css-loader": "3.6.0", + "css-loader": "4.2.0", "dotenv": "8.2.0", - "eslint": "7.3.1", + "eslint": "7.6.0", "eslint-config-react-app": "5.2.1", "eslint-config-standard": "14.1.1", "eslint-config-standard-react": "9.2.0", "eslint-loader": "4.0.2", - "eslint-plugin-flowtype": "5.1.3", + "eslint-plugin-flowtype": "5.2.0", "eslint-plugin-import": "2.22.0", "eslint-plugin-jsx-a11y": "6.3.1", "eslint-plugin-node": "11.1.0", "eslint-plugin-promise": "4.2.1", - "eslint-plugin-react": "7.20.0", - "eslint-plugin-react-hooks": "4.0.4", + "eslint-plugin-react": "7.20.5", + "eslint-plugin-react-hooks": "4.0.8", "eslint-plugin-standard": "4.0.1", "faker": "https://github.com/Marak/faker.js.git", "file-loader": "6.0.0", @@ -74,7 +74,7 @@ "html-webpack-plugin": "4.3.0", "i18n-iso-countries": "6.0.0", "ignore-loader": "0.1.2", - "jest": "26.1.0", + "jest": "26.2.2", "js-yaml": "3.14.0", "json-loader": "0.5.7", "moment-timezone": "0.5.31", @@ -86,29 +86,35 @@ "style-loader": "1.2.1", "thread-loader": "2.1.3", "wdio-chromedriver-service": "6.0.3", - "webdriverio": "6.1.22", - "webpack": "4.43.0", + "webdriverio": "6.3.6", + "webpack": "4.44.1", "webpack-cli": "3.3.12", "webpack-dev-server": "3.11.0", - "webpack-merge": "4.2.2", + "webpack-merge": "5.1.1", "xhr2": "0.2.0" }, "dependencies": { - "@apollo/react-hooks": "3.1.5", - "@blueprintjs/core": "3.29.0", - "@blueprintjs/datetime": "3.18.3", + "@apollo/client": "3.1.2", + "@blueprintjs/core": "3.30.1", + "@blueprintjs/datetime": "3.18.5", + "@emotion/core": "10.0.28", + "@emotion/styled": "10.0.27", "@fullcalendar/core": "4.4.2", "@fullcalendar/daygrid": "4.4.2", "@fullcalendar/interaction": "4.4.2", "@fullcalendar/list": "4.4.2", "@fullcalendar/react": "4.4.2", "@fullcalendar/timegrid": "4.4.2", - "apollo-boost": "0.4.9", + "@projectstorm/react-diagrams-core": "6.2.0", + "@projectstorm/react-diagrams-defaults": "6.2.0", + "@projectstorm/react-diagrams-routing": "6.2.0", "bootstrap": "3.4.1", "change-case": "4.1.1", "classnames": "2.2.6", + "closest": "0.0.1", "core-js": "3.6.5", "d3": "5.16.0", + "dagre": "0.8.5", "draft-convert": "2.1.10", "draft-js": "0.10.5", "draft-js-buttons": "2.0.2", @@ -116,9 +122,9 @@ "draftail": "1.3.0", "email-addresses": "3.1.0", "file-saver": "2.0.2", - "formik": "2.1.4", + "formik": "2.1.5", "graphiql": "1.0.3", - "graphql": "15.1.0", + "graphql": "15.3.0", "hopscotch": "0.3.1", "html-react-parser": "0.13.0", "jsonpath-plus": "4.0.0", @@ -128,9 +134,13 @@ "leaflet-gesture-handling": "1.1.8", "leaflet.markercluster": "1.4.1", "locale-compare-polyfill": "0.0.2", - "lodash": "4.17.15", + "lodash": "4.17.19", + "mathjs": "7.1.0", "milsymbol": "2.0.0", + "ml-matrix": "6.5.1", "moment": "2.27.0", + "pathfinding": "0.4.18", + "paths-js": "0.4.11", "pluralize": "8.0.0", "prop-types": "15.7.2", "react": "16.13.1", @@ -139,34 +149,36 @@ "react-confirm-bootstrap": "5.3.1", "react-container-dimensions": "1.4.1", "react-dom": "16.13.1", + "react-moment-proptypes": "1.7.0", "react-mosaic-component": "3.2.0", "react-notification-badge": "1.5.1", - "react-redux": "7.2.0", - "react-redux-loading-bar": "4.6.0", + "react-redux": "7.2.1", + "react-redux-loading-bar": "5.0.0", "react-router-bootstrap": "0.25.0", "react-router-dom": "5.2.0", - "react-scroll": "1.7.16", + "react-scroll": "1.8.0", "react-svg-text": "0.1.2", "react-tag-input": "6.4.3", - "react-toastify": "6.0.6", - "react-tooltip": "4.2.7", + "react-toastify": "6.0.8", + "react-tooltip": "4.2.8", "react-ultimate-pagination": "1.2.0", "react-use-dimensions": "1.2.1", "redux": "4.0.5", "redux-persist": "6.0.0", - "use-debounce": "3.4.2", - "yup": "0.29.1" + "resize-observer-polyfill": "1.5.1", + "use-debounce": "3.4.3", + "yup": "0.29.3" }, "scripts": { "build": "NODE_ENV=production webpack --mode production --config config/webpack.client.prod.js", "start": "export SERVER_URL=${SERVER_URL:-'http://localhost:8080'} DEV_PORT=${DEV_PORT:-3000} ; NODE_ENV=development webpack-dev-server --mode development --open --config config/webpack.client.dev.js", - "lint": "eslint '*.js' 'config/**/*.js' 'platform/**/*.js' 'scripts/**/*.js' 'src/**/*.js' 'stories/**/*.js' 'tests/**/*.js'", - "lint-fix": "prettier --write '*.js' 'config/**/*.js' 'platform/**/*.js' 'scripts/**/*.js' 'src/**/*.js' 'stories/**/*.js' 'tests/**/*.js' && eslint --fix '*.js' 'config/**/*.js' 'platform/**/*.js' 'scripts/**/*.js' 'src/**/*.js' 'stories/**/*.js' 'tests/**/*.js'", + "lint": "NODE_ENV=development eslint '*.js' 'config/**/*.js' 'platform/**/*.js' 'scripts/**/*.js' 'src/**/*.js' 'stories/**/*.js' 'tests/**/*.js'", + "lint-fix": "prettier --write '*.js' 'config/**/*.js' 'platform/**/*.js' 'scripts/**/*.js' 'src/**/*.js' 'stories/**/*.js' 'tests/**/*.js' && NODE_ENV=development eslint --fix '*.js' 'config/**/*.js' 'platform/**/*.js' 'scripts/**/*.js' 'src/**/*.js' 'stories/**/*.js' 'tests/**/*.js'", "test": "echo 'Run \"test-all\" to execute all client-side tests, or pick a specific test target: \"test-jest\", \"test-wdio\", \"test-wdio-ie\", \"test-e2e\".' ; exit 1", "test-all": "yarn run test-jest && yarn run test-wdio && yarn run test-wdio-ie && yarn run test-e2e", "test-e2e": "export SERVER_URL=${SERVER_URL:-'http://localhost:8180'} ; NODE_ENV=test node $(npm bin)/ava --config ava.config.js", - "test-wdio": "export SERVER_URL=${SERVER_URL:-'http://localhost:8180'} ; wdio --baseUrl ${SERVER_URL} ./config/wdio.config.js", - "test-jest": "export ANET_CONFIG=../anet.yml ; jest --testPathPattern='tests/(actions|reducers)'", + "test-wdio": "export SERVER_URL=${SERVER_URL:-'http://localhost:8180'} ; NODE_ENV=test wdio --baseUrl ${SERVER_URL} ./config/wdio.config.js", + "test-jest": "export ANET_CONFIG=../anet.yml ; NODE_ENV=test jest --testPathPattern='tests/(actions|reducers)'", "test-wdio-ie": "export SERVER_URL=${SERVER_URL:-'http://localhost:8180'} ; NODE_ENV=test node ./tests/util/wdio.ie.js", "storybook": "start-storybook -p 9001 -c .storybook", "sim": "export ANET_CONFIG=../anet.yml SERVER_URL=${SERVER_URL:-'http://localhost:8080'} ; NODE_ENV=development webpack --mode development --config config/webpack.sim.dev.js && node build/anet.sim.dev.js" @@ -246,7 +258,7 @@ "globals": { "browser": "readonly" }, - "parser": "babel-eslint", + "parser": "@babel/eslint-parser", "plugins": [ "flowtype", "import", diff --git a/client/public/index.hbs b/client/public/index.hbs index 01db6e1af2..76c2483901 100644 --- a/client/public/index.hbs +++ b/client/public/index.hbs @@ -23,20 +23,9 @@
- diff --git a/client/src/api.js b/client/src/api.js index 402109aba9..e384c3f4c2 100644 --- a/client/src/api.js +++ b/client/src/api.js @@ -1,12 +1,33 @@ import querystring from "querystring" -import { useQuery } from "@apollo/react-hooks" -import ApolloClient from "apollo-boost" -import { InMemoryCache } from "apollo-cache-inmemory" +import { + ApolloClient, + ApolloLink, + from, + HttpLink, + InMemoryCache, + useQuery +} from "@apollo/client" import _isEmpty from "lodash/isEmpty" const GRAPHQL_ENDPOINT = "/graphql" const LOGGING_ENDPOINT = "/api/logging/log" +const authMiddleware = new ApolloLink((operation, forward) => { + operation.setContext(({ headers = {} }) => { + headers = { + ...headers, + Accept: "application/json" + } + const [authHeaderName, authHeaderValue] = API._getAuthHeader() + if (authHeaderName && authHeaderValue) { + headers[authHeaderName] = authHeaderValue + } + return { headers } + }) + + return forward(operation) +}) + const API = { _fetch(url, data, accept) { const params = { @@ -18,10 +39,9 @@ const API = { Accept: accept || "application/json" } } - - const authHeader = API._getAuthHeader() - if (authHeader) { - params.headers[authHeader[0]] = authHeader[1] + const [authHeaderName, authHeaderValue] = API._getAuthHeader() + if (authHeaderName && authHeaderValue) { + params.headers[authHeaderName] = authHeaderValue } return window.fetch(url, params) @@ -111,11 +131,11 @@ const API = { }, _getAuthParams: function() { - const query = querystring.parse(window.location.search.slice(1)) - if (query.user && query.pass) { + const { user, pass } = querystring.parse(window.location.search.slice(1)) + if (user && pass) { window.ANET_DATA.creds = { - user: query.user, - pass: query.pass + user, + pass } } return window.ANET_DATA.creds @@ -138,43 +158,35 @@ const API = { Buffer.from(`${creds.user}:${creds.pass}`).toString("base64") ] } - return null + return [] }, client: new ApolloClient({ - uri: GRAPHQL_ENDPOINT, + link: from([ + authMiddleware, + new HttpLink({ + uri: GRAPHQL_ENDPOINT + }) + ]), cache: new InMemoryCache({ addTypename: false, dataIdFromObject: object => object.uuid || null }), + defaultOptions: { + query: { + fetchPolicy: "no-cache" + }, + watchQuery: { + fetchPolicy: "no-cache" + }, + mutate: { + fetchPolicy: "no-cache" + } + }, fetchOptions: { credentials: "same-origin" - }, - request: operation => { - const headers = { - Accept: "application/json" - } - const authHeader = API._getAuthHeader() - if (authHeader) { - headers[authHeader[0]] = authHeader[1] - } - operation.setContext({ headers }) } }) } -// Have to initialise this after creating the client -// (see https://github.com/apollographql/apollo-client/issues/3900) -API.client.defaultOptions = { - query: { - fetchPolicy: "no-cache" - }, - watchQuery: { - fetchPolicy: "no-cache" - }, - mutate: { - fetchPolicy: "no-cache" - } -} - export default API diff --git a/client/src/components/AdvisorReports/AdvisorReportsTable.js b/client/src/components/AdvisorReports/AdvisorReportsTable.js index d0729229e0..85eee5416a 100644 --- a/client/src/components/AdvisorReports/AdvisorReportsTable.js +++ b/client/src/components/AdvisorReports/AdvisorReportsTable.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import AdvisorReportsRow from "components/AdvisorReports/AdvisorReportsRow" import AdvisorReportsTableHead from "components/AdvisorReports/AdvisorReportsTableHead" import { diff --git a/client/src/components/AdvisorReports/FilterableAdvisorReportsTable.js b/client/src/components/AdvisorReports/FilterableAdvisorReportsTable.js index e0dd719b03..d1a265c211 100644 --- a/client/src/components/AdvisorReports/FilterableAdvisorReportsTable.js +++ b/client/src/components/AdvisorReports/FilterableAdvisorReportsTable.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import OrganizationAdvisorsTable from "components/AdvisorReports/OrganizationAdvisorsTable" import Toolbar from "components/AdvisorReports/Toolbar" import { PageDispatchersPropType, useBoilerplate } from "components/Page" diff --git a/client/src/components/AggregationWidget.js b/client/src/components/AggregationWidget.js deleted file mode 100644 index bccb6732db..0000000000 --- a/client/src/components/AggregationWidget.js +++ /dev/null @@ -1,92 +0,0 @@ -import LikertScale from "components/graphs/LikertScale" -import PropTypes from "prop-types" -import React from "react" -import { Col, ControlLabel, FormGroup } from "react-bootstrap" - -const aggregationPropTypes = { - values: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.array]) - ), - aggregationType: PropTypes.string -} - -const arrayOfNumbers = arr => - arr.filter(n => !isNaN(parseFloat(n)) && isFinite(n)).map(n => Number(n)) - -const NUMBER_AGG = { - sum: arr => arr.reduce((a, b) => a + b), - avg: arr => arr.reduce((a, b) => a + b) / arr.length, - min: arr => Math.min(...arr), - max: arr => Math.max(...arr) -} - -const NumberAggWidget = ({ values, aggregationType, ...otherWidgetProps }) => - values?.length ? ( -
{NUMBER_AGG[aggregationType](arrayOfNumbers(values))}
- ) : null -NumberAggWidget.propTypes = aggregationPropTypes - -const DefaultAggWidget = ({ values, ...otherWidgetProps }) => ( -
{`[${values}]`}
-) -DefaultAggWidget.propTypes = aggregationPropTypes - -const WIDGETS = { - likertScale: LikertScale, - numberAggregation: NumberAggWidget, - default: DefaultAggWidget -} - -const AggregationWidget = ({ - label, - widget, - values, - aggregationType, - vertical, - ...otherWidgetProps -}) => { - const Widget = (widget && WIDGETS[widget]) || WIDGETS.default - const widgetElem = ( - - ) - return ( - - {vertical ? ( - <> - {label !== null && {label}} - {widgetElem} - - ) : ( - <> - {label !== null && ( - - {label} - - )} - -
{widgetElem}
- - - )} -
- ) -} -AggregationWidget.propTypes = { - label: PropTypes.string, - widget: PropTypes.string, - vertical: PropTypes.bool, - ...aggregationPropTypes -} -AggregationWidget.defaultProps = { - label: "", - widget: "", - values: [], - aggregationType: "", - vertical: false -} - -export default AggregationWidget diff --git a/client/src/components/AssignPersonModal.js b/client/src/components/AssignPersonModal.js index aeb4f3eed7..b06f5b2312 100644 --- a/client/src/components/AssignPersonModal.js +++ b/client/src/components/AssignPersonModal.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import { PersonSimpleOverlayRow } from "components/advancedSelectWidget/AdvancedSelectOverlayRow" import AdvancedSingleSelect from "components/advancedSelectWidget/AdvancedSingleSelect" import LinkTo from "components/LinkTo" diff --git a/client/src/components/AssignPositionModal.js b/client/src/components/AssignPositionModal.js index 995af4da57..a563151955 100644 --- a/client/src/components/AssignPositionModal.js +++ b/client/src/components/AssignPositionModal.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import { PositionOverlayRow } from "components/advancedSelectWidget/AdvancedSelectOverlayRow" import AdvancedSingleSelect from "components/advancedSelectWidget/AdvancedSingleSelect" import AppContext from "components/AppContext" @@ -10,7 +10,13 @@ import _isEmpty from "lodash/isEmpty" import _isEqualWith from "lodash/isEqualWith" import { Person, Position } from "models" import PropTypes from "prop-types" -import React, { useCallback, useEffect, useRef, useState } from "react" +import React, { + useCallback, + useContext, + useEffect, + useRef, + useState +} from "react" import { Button, Col, @@ -34,13 +40,8 @@ const GQL_PUT_PERSON_IN_POSITION = gql` } ` -const BaseAssignPositionModal = ({ - person, - currentUser, - showModal, - onCancel, - onSuccess -}) => { +const AssignPositionModal = ({ person, showModal, onCancel, onSuccess }) => { + const { currentUser } = useContext(AppContext) const latestPersonProp = useRef(person) const personPropUnchanged = _isEqualWith( latestPersonProp.current, @@ -235,20 +236,11 @@ const BaseAssignPositionModal = ({ onCancel() } } -BaseAssignPositionModal.propTypes = { +AssignPositionModal.propTypes = { person: PropTypes.instanceOf(Person).isRequired, showModal: PropTypes.bool, onCancel: PropTypes.func.isRequired, - onSuccess: PropTypes.func.isRequired, - currentUser: PropTypes.instanceOf(Person) + onSuccess: PropTypes.func.isRequired } -const AssignPositionModal = props => ( - - {context => ( - - )} - -) - export default AssignPositionModal diff --git a/client/src/components/BarChart.js b/client/src/components/BarChart.js index 4fad434951..3dace558c4 100644 --- a/client/src/components/BarChart.js +++ b/client/src/components/BarChart.js @@ -3,6 +3,7 @@ import _isEmpty from "lodash/isEmpty" import PropTypes from "prop-types" import React, { useEffect, useRef } from "react" import ReactTooltip from "react-tooltip" +import utils from "utils" import "./BarChart.css" /* @@ -50,7 +51,11 @@ const BarChart = ({ const xScale = d3.scaleBand().domain( data.map(function(d) { - xLabels[getPropValue(d, xProp)] = getPropValue(d, label) + xLabels[getPropValue(d, xProp)] = utils.ellipsize( + // TODO: Make responsive + getPropValue(d, label), + 10 + ) return getPropValue(d, xProp) }) ) @@ -108,8 +113,8 @@ const BarChart = ({ let chart = d3.select(node.current) const chartBox = node.current.getBoundingClientRect() - const chartWidth = isNumeric(width) ? width : chartBox.width - const chartHeight = isNumeric(height) ? height : 0.7 * chartWidth + const chartWidth = utils.isNumeric(width) ? width : chartBox.width + const chartHeight = utils.isNumeric(height) ? height : 0.7 * chartWidth const xWidth = chartWidth - marginLeft - MARGIN.right const yHeight = chartHeight - MARGIN.top - marginBottom @@ -197,10 +202,6 @@ const BarChart = ({ )) || ) - - function isNumeric(value) { - return typeof value === "number" - } } BarChart.propTypes = { diff --git a/client/src/components/CancelledEngagementReports.js b/client/src/components/CancelledEngagementReports.js index e19376b428..ff3fb6edc3 100644 --- a/client/src/components/CancelledEngagementReports.js +++ b/client/src/components/CancelledEngagementReports.js @@ -1,14 +1,15 @@ +import { gql } from "@apollo/client" import { IconNames } from "@blueprintjs/icons" import API from "api" -import { gql } from "apollo-boost" import BarChart from "components/BarChart" import MosaicLayout from "components/MosaicLayout" import { PageDispatchersPropType, useBoilerplate } from "components/Page" import ReportCollection, { + FORMAT_CALENDAR, FORMAT_MAP, + FORMAT_STATISTICS, FORMAT_SUMMARY, - FORMAT_TABLE, - FORMAT_CALENDAR + FORMAT_TABLE } from "components/ReportCollection" import * as d3 from "d3" import _isEqual from "lodash/isEqual" @@ -262,7 +263,12 @@ const Collection = ({ id, queryParams }) => ( ) diff --git a/client/src/components/CreateButton.js b/client/src/components/CreateButton.js index d6830ff87a..6d50f4c6f5 100644 --- a/client/src/components/CreateButton.js +++ b/client/src/components/CreateButton.js @@ -1,7 +1,6 @@ import AppContext from "components/AppContext" import * as Models from "models" -import PropTypes from "prop-types" -import React from "react" +import React, { useContext } from "react" import { Button, DropdownButton, MenuItem } from "react-bootstrap" import { useHistory } from "react-router-dom" @@ -15,7 +14,8 @@ const ADMIN_ACTIONS = [ Models.AuthorizationGroup ] -const BaseCreateButton = ({ currentUser }) => { +const CreateButton = () => { + const { currentUser } = useContext(AppContext) const history = useHistory() const modelClasses = DEFAULT_ACTIONS.concat( @@ -65,16 +65,4 @@ const BaseCreateButton = ({ currentUser }) => { } } -BaseCreateButton.propTypes = { - currentUser: PropTypes.instanceOf(Models.Person) -} - -const CreateButton = props => ( - - {context => ( - - )} - -) - export default CreateButton diff --git a/client/src/components/CustomFields.js b/client/src/components/CustomFields.js index 88fe512500..f912cbdbdc 100644 --- a/client/src/components/CustomFields.js +++ b/client/src/components/CustomFields.js @@ -4,7 +4,9 @@ import Fieldset from "components/Fieldset" import LikertScale from "components/graphs/LikertScale" import Model, { CUSTOM_FIELD_TYPE, - createYupObjectShape + createYupObjectShape, + DEFAULT_CUSTOM_FIELDS_PARENT, + INVISIBLE_CUSTOM_FIELDS_FIELD } from "components/Model" import RichTextEditor from "components/RichTextEditor" import { FastField, FieldArray } from "formik" @@ -24,7 +26,7 @@ import { useDebouncedCallback } from "use-debounce" import utils from "utils" import { parseHtmlWithLinkTo } from "utils_links" -const SPECIAL_WIDGET_TYPES = { +export const SPECIAL_WIDGET_TYPES = { LIKERT_SCALE: "likertScale", RICH_TEXT_EDITOR: "richTextEditor" } @@ -34,8 +36,6 @@ const SPECIAL_WIDGET_COMPONENTS = { } const RENDERERS = {} -const DEFAULT_CUSTOM_FIELDS_PREFIX = "formCustomFields" - const SpecialField = ({ name, widget, formikProps, ...otherFieldProps }) => { const WidgetComponent = SPECIAL_WIDGET_COMPONENTS[widget] const widgetProps = {} @@ -44,6 +44,10 @@ const SpecialField = ({ name, widget, formikProps, ...otherFieldProps }) => { // validation will be done by setFieldValue formikProps.setFieldTouched(name, true, false) } + } else if (widget === SPECIAL_WIDGET_TYPES.LIKERT_SCALE) { + // Can't set it on the widgetProps directly as the onChange is required when + // editable (and onChange is set only while processing the SpecialField) + otherFieldProps.editable = true } return ( { if (widget === SPECIAL_WIDGET_TYPES.RICH_TEXT_EDITOR) { - const fieldValue = Object.get(values, name) // name might be a path for a nested prop + const fieldValue = Object.get(values, name) || "" // name might be a path for a nested prop return ( { const enumHumanValue = (choices, fieldVal) => { if (Array.isArray(fieldVal)) { - return fieldVal && fieldVal.map(k => choices[k].label).join(", ") + return fieldVal && fieldVal.map(k => choices[k]?.label).join(", ") } else { - return fieldVal && choices[fieldVal].label + return fieldVal && choices[fieldVal]?.label } } @@ -285,7 +289,7 @@ const ArrayObject = ({ invisibleFields={invisibleFields} updateInvisibleFields={updateInvisibleFields} vertical={vertical} - fieldNamePrefix={`${fieldName}.${index}`} + parentFieldName={`${fieldName}.${index}`} /> ) @@ -344,7 +348,7 @@ const ReadonlyArrayObject = ({
@@ -373,7 +377,7 @@ const FIELD_COMPONENTS = { function getInvisibleFields( invisibleFields, fieldsConfig, - fieldNamePrefix, + parentFieldName, formikValues ) { const prevInvisibleFields = _cloneDeep(invisibleFields) @@ -382,7 +386,7 @@ function getInvisibleFields( let curInvisibleFields = [] Object.keys(fieldsConfig).forEach(key => { const fieldConfig = fieldsConfig[key] - const fieldName = `${fieldNamePrefix}.${key}` + const fieldName = `${parentFieldName}.${key}` const isVisible = !fieldConfig.visibleWhen || (fieldConfig.visibleWhen && @@ -404,10 +408,10 @@ function getInvisibleFields( } export const CustomFieldsContainer = props => { - const { fieldNamePrefix, formikProps } = props + const { parentFieldName, formikProps } = props const [invisibleFields, setInvisibleFields] = useState([]) const { setFieldValue } = formikProps - const invisibleFieldsFieldName = `${fieldNamePrefix}.invisibleCustomFields` + const invisibleFieldsFieldName = `${parentFieldName}.${INVISIBLE_CUSTOM_FIELDS_FIELD}` useEffect(() => { setFieldValue(invisibleFieldsFieldName, invisibleFields, true) }, [invisibleFieldsFieldName, invisibleFields, setFieldValue]) @@ -431,11 +435,11 @@ export const CustomFieldsContainer = props => { CustomFieldsContainer.propTypes = { fieldsConfig: PropTypes.object, formikProps: PropTypes.object, - fieldNamePrefix: PropTypes.string.isRequired, + parentFieldName: PropTypes.string.isRequired, vertical: PropTypes.bool } CustomFieldsContainer.defaultProps = { - fieldNamePrefix: DEFAULT_CUSTOM_FIELDS_PREFIX, + parentFieldName: DEFAULT_CUSTOM_FIELDS_PARENT, vertical: false } @@ -469,7 +473,7 @@ const CustomField = ({ const handleChange = useMemo( () => (value, shouldValidate: true) => { const val = - typeof value === "object" && value.target ? value.target.value : value + value?.target?.value !== undefined ? value.target.value : value const sv = shouldValidate === undefined ? true : shouldValidate setFieldTouched(fieldName, true, false) setFieldValue(fieldName, val, sv) @@ -521,7 +525,7 @@ CustomField.propTypes = { const CustomFields = ({ fieldsConfig, formikProps, - fieldNamePrefix, + parentFieldName, invisibleFields, updateInvisibleFields, vertical @@ -539,10 +543,10 @@ const CustomFields = ({ getInvisibleFields( invisibleFields, fieldsConfig, - fieldNamePrefix, + parentFieldName, formikValues ), - [invisibleFields, fieldsConfig, fieldNamePrefix, formikValues] + [invisibleFields, fieldsConfig, parentFieldName, formikValues] ) const invisibleFieldsUnchanged = _isEqualWith( latestInvisibleFieldsProp.current, @@ -566,7 +570,7 @@ const CustomFields = ({ <> {Object.keys(fieldsConfig).map(key => { const fieldConfig = fieldsConfig[key] - const fieldName = `${fieldNamePrefix}.${key}` + const fieldName = `${parentFieldName}.${key}` return invisibleFields.includes(fieldName) ? null : ( { @@ -628,7 +632,7 @@ export const ReadonlyCustomFields = ({ return ( { - const customFieldsValues = Object.get(values, prefix) + const customFieldsValues = Object.get(values, parentFieldName) if (customFieldsValues && typeof customFieldsValues === "object") { const clonedValues = _cloneDeep(values) - const filteredCustomFieldsValues = Object.get(clonedValues, prefix) - if (filteredCustomFieldsValues.invisibleCustomFields) { - filteredCustomFieldsValues.invisibleCustomFields.forEach(f => + const filteredCustomFieldsValues = Object.get(clonedValues, parentFieldName) + if (filteredCustomFieldsValues[INVISIBLE_CUSTOM_FIELDS_FIELD]) { + filteredCustomFieldsValues[INVISIBLE_CUSTOM_FIELDS_FIELD].forEach(f => _set(clonedValues, f.split("."), undefined) ) if (forNoteText) { - delete filteredCustomFieldsValues.invisibleCustomFields + delete filteredCustomFieldsValues[INVISIBLE_CUSTOM_FIELDS_FIELD] } } return JSON.stringify(filteredCustomFieldsValues) diff --git a/client/src/components/DailyRollupChart.js b/client/src/components/DailyRollupChart.js index 6afb69fce6..e813ae55f5 100644 --- a/client/src/components/DailyRollupChart.js +++ b/client/src/components/DailyRollupChart.js @@ -2,6 +2,7 @@ import * as d3 from "d3" import PropTypes from "prop-types" import React, { useEffect, useRef } from "react" import ReactTooltip from "react-tooltip" +import utils from "utils" import "./BarChart.css" const DailyRollupChart = ({ @@ -27,7 +28,7 @@ const DailyRollupChart = ({ bottom: 20 // left and bottom MARGINs are dynamic, these are extra margins } const chartBox = node.current.getBoundingClientRect() - const chartWidth = (isNumeric(width) ? width : chartBox.width) - 30 + const chartWidth = (utils.isNumeric(width) ? width : chartBox.width) - 30 let chart = d3.select(node.current) const xLabels = [].concat.apply( [], @@ -167,10 +168,6 @@ const DailyRollupChart = ({ }, [node, width, height, data, onBarClick, tooltip, barColors]) return - - function isNumeric(value) { - return typeof value === "number" - } } DailyRollupChart.propTypes = { diff --git a/client/src/components/EditAssociatedPositionsModal.js b/client/src/components/EditAssociatedPositionsModal.js index e3886b1813..984d9be6c9 100644 --- a/client/src/components/EditAssociatedPositionsModal.js +++ b/client/src/components/EditAssociatedPositionsModal.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import AdvancedMultiSelect from "components/advancedSelectWidget/AdvancedMultiSelect" import { PositionOverlayRow } from "components/advancedSelectWidget/AdvancedSelectOverlayRow" import AppContext from "components/AppContext" @@ -11,7 +11,7 @@ import RECURSE_STRATEGY from "components/SearchFilters" import { FastField, Form, Formik } from "formik" import { Person, Position } from "models" import PropTypes from "prop-types" -import React, { useState } from "react" +import React, { useContext, useState } from "react" import { Button, Col, Grid, Modal, Row, Table } from "react-bootstrap" import POSITIONS_ICON from "resources/positions.png" import Settings from "settings" @@ -67,13 +67,13 @@ AssociatedPositionsTable.propTypes = { associatedPositions: PropTypes.array } -const BaseEditAssociatedPositionsModal = ({ +const EditAssociatedPositionsModal = ({ position, showModal, onCancel, - onSuccess, - currentUser + onSuccess }) => { + const { currentUser } = useContext(AppContext) const [error, setError] = useState(null) const assignedRole = position.type === Position.TYPE.PRINCIPAL @@ -183,7 +183,7 @@ const BaseEditAssociatedPositionsModal = ({ } function save(values, form) { - const newPosition = new Position(position) + const newPosition = Object.without(new Position(values), "notes") newPosition.associatedPositions = values.associatedPositions delete newPosition.previousPeople delete newPosition.person // prevent any changes to person. @@ -192,23 +192,11 @@ const BaseEditAssociatedPositionsModal = ({ }) } } -BaseEditAssociatedPositionsModal.propTypes = { +EditAssociatedPositionsModal.propTypes = { position: PropTypes.object.isRequired, showModal: PropTypes.bool, onCancel: PropTypes.func.isRequired, - onSuccess: PropTypes.func.isRequired, - currentUser: PropTypes.instanceOf(Person) + onSuccess: PropTypes.func.isRequired } -const EditAssociatedPositionsModal = props => ( - - {context => ( - - )} - -) - export default EditAssociatedPositionsModal diff --git a/client/src/components/FieldHelper.js b/client/src/components/FieldHelper.js index 7a3d10c06a..d89e6242cd 100644 --- a/client/src/components/FieldHelper.js +++ b/client/src/components/FieldHelper.js @@ -153,9 +153,7 @@ export const InputField = ({ () => ( ), @@ -196,9 +194,7 @@ export const InputFieldNoLabel = ({ () => ( ), @@ -487,7 +483,7 @@ export const FieldShortcuts = ({ shortcuts.length > 0 && (
{title}
- {shortcuts.map(shortcut => ( + {objectType.map(shortcuts, (shortcut, idx) => (
) diff --git a/client/src/components/GuidedTour.js b/client/src/components/GuidedTour.js index 59ce402e71..8887e0b6d8 100644 --- a/client/src/components/GuidedTour.js +++ b/client/src/components/GuidedTour.js @@ -1,9 +1,8 @@ import AppContext from "components/AppContext" import hopscotch from "hopscotch" import "hopscotch/dist/css/hopscotch.css" -import { Person } from "models" import PropTypes from "prop-types" -import React, { useCallback, useEffect, useState } from "react" +import React, { useCallback, useContext, useEffect, useState } from "react" import { Button } from "react-bootstrap" import { useHistory } from "react-router-dom" import TOUR_ICON from "resources/tour-icon.png" @@ -17,7 +16,8 @@ const HOPSCOTCH_CONFIG = { bubbleWidth: 400 } -const BaseGuidedTour = ({ autostart, currentUser, title, tour, onEnd }) => { +const GuidedTour = ({ autostart, title, tour, onEnd }) => { + const { currentUser } = useContext(AppContext) const history = useHistory() const [runningTour, setRunningTour] = useState(false) const startTour = useCallback(() => { @@ -64,18 +64,11 @@ const BaseGuidedTour = ({ autostart, currentUser, title, tour, onEnd }) => { ) } -BaseGuidedTour.propTypes = { +GuidedTour.propTypes = { tour: PropTypes.func.isRequired, autostart: PropTypes.bool, onEnd: PropTypes.func, - title: PropTypes.string, - currentUser: PropTypes.instanceOf(Person) + title: PropTypes.string } -const GuidedTour = props => ( - - {context => } - -) - export default GuidedTour diff --git a/client/src/components/HorizontalBarChart.js b/client/src/components/HorizontalBarChart.js index 0c634f07ca..a5622ee927 100644 --- a/client/src/components/HorizontalBarChart.js +++ b/client/src/components/HorizontalBarChart.js @@ -3,6 +3,7 @@ import _isEmpty from "lodash/isEmpty" import PropTypes from "prop-types" import React, { useEffect, useRef } from "react" import ReactTooltip from "react-tooltip" +import utils from "utils" import "./BarChart.css" /* @@ -86,7 +87,7 @@ const HorizontalBarChart = ({ bottom: 20 // left and bottom MARGINs are dynamic, these are extra margins } const chartBox = node.current.getBoundingClientRect() - const chartWidth = isNumeric(width) ? width : chartBox.width + const chartWidth = utils.isNumeric(width) ? width : chartBox.width const chartData = data.data const categoryLabels = data.categoryLabels const leavesLabels = data.leavesLabels @@ -293,10 +294,6 @@ const HorizontalBarChart = ({ )) || ) - function isNumeric(value) { - return typeof value === "number" - } - function bindElementOnClick(element, onClickHandler) { if (onClickHandler) { element.on("click", function(d) { diff --git a/client/src/components/Kanban.js b/client/src/components/Kanban.js index 731abd09fd..cbf9c0b8a5 100644 --- a/client/src/components/Kanban.js +++ b/client/src/components/Kanban.js @@ -6,6 +6,7 @@ import PropTypes from "prop-types" import React, { useState } from "react" import { Button, Glyphicon, Panel } from "react-bootstrap" import Settings from "settings" +import utils from "utils" const Kanban = ({ columns, allTasks }) => (
{ {task.longName && (
- {open || task.longName.length < 100 - ? task.longName - : task.longName.substring(0, 100) + "..."} + {open ? task.longName : utils.ellipsize(task.longName, 100)}
)} diff --git a/client/src/components/Leaflet.js b/client/src/components/Leaflet.js index 32dc27b00f..3af03ad9c8 100644 --- a/client/src/components/Leaflet.js +++ b/client/src/components/Leaflet.js @@ -1,4 +1,4 @@ -import { Control, CRS, Icon, Map, Marker, TileLayer } from "leaflet" +import { Control, CRS, DomUtil, Icon, Map, Marker, TileLayer } from "leaflet" import "leaflet-defaulticon-compatibility" import "leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.webpack.css" import { @@ -150,6 +150,18 @@ const Leaflet = ({ crs: CRS[Settings.imagery.mapOptions.crs] } ) + var container = DomUtil.get(mapId) + /* + * Prevent error "map container is already initialized" when mapId changed + * for the current map (which was already initialized). + * Note: this happens when the id of a map is not always the same but changes + * because of the use of _uniqueId (which we use for map aggregation widgets + * to make sure we don't have more maps with the same id on a page - like + * on the person show page for statistics of reports authored and attended) + */ + if (container !== null) { + container._leaflet_id = null + } const newMap = new Map(mapId, mapOptions).setView( Settings.imagery.mapOptions.homeView.location, Settings.imagery.mapOptions.homeView.zoomLevel diff --git a/client/src/components/LinkTo.js b/client/src/components/LinkTo.js index cf5ad770a1..319017e505 100644 --- a/client/src/components/LinkTo.js +++ b/client/src/components/LinkTo.js @@ -1,4 +1,5 @@ import AvatarDisplayComponent from "components/AvatarDisplayComponent" +import { OBJECT_TYPE_TO_MODEL } from "components/Model" import _isEmpty from "lodash/isEmpty" import * as Models from "models" import PropTypes from "prop-types" @@ -74,7 +75,8 @@ export default class LinkTo extends Component { return {whenUnspecified} } - const ModelClass = Models[modelType] + const ModelClass = + Models[modelType] || Models[OBJECT_TYPE_TO_MODEL[modelType]] const isModel = typeof model !== "string" const modelInstance = new ModelClass(isModel ? model : {}) diff --git a/client/src/components/Model.js b/client/src/components/Model.js index 071c2ebf75..0fe1d4b853 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -1,11 +1,14 @@ -import encodeQuery from "querystring/encode" +import { gql } from "@apollo/client" +import API from "api" import _forEach from "lodash/forEach" import _isEmpty from "lodash/isEmpty" +import * as Models from "models" import moment from "moment" +import { RECURRENCE_TYPE } from "periodUtils" import PropTypes from "prop-types" +import encodeQuery from "querystring/encode" import utils from "utils" import * as yup from "yup" -import { gql } from "apollo-boost" export const GRAPHQL_NOTE_FIELDS = /* GraphQL */ ` uuid @@ -23,6 +26,36 @@ export const GRAPHQL_NOTE_FIELDS = /* GraphQL */ ` noteUuid relatedObjectType relatedObjectUuid + relatedObject { + ... on AuthorizationGroup { + name + } + ... on Location { + name + } + ... on Organization { + shortName + } + ... on Person { + role + rank + name + avatar(size: 32) + } + ... on Position { + type + name + } + ... on Report { + intent + engagementDate + state + } + ... on Task { + shortName + longName + } + } } ` export const GRAPHQL_NOTES_FIELDS = /* GraphQL */ ` @@ -31,6 +64,16 @@ export const GRAPHQL_NOTES_FIELDS = /* GraphQL */ ` } ` +// Entity type --> GQL query +export const GRAPHQL_ENTITY_FIELDS = { + Report: "uuid intent", + Person: "uuid name role avatar(size: 32)", + Organization: "uuid shortName", + Position: "uuid name", + Location: "uuid name", + Task: "uuid shortName longName" +} + export const GQL_CREATE_NOTE = gql` mutation($note: NoteInput!) { createNote(note: $note) { @@ -46,12 +89,34 @@ export const GQL_UPDATE_NOTE = gql` } ` +export const MODEL_TO_OBJECT_TYPE = { + AuthorizationGroup: "authorizationGroups", + Location: "locations", + Organization: "organizations", + Person: "people", + Position: "positions", + Report: "reports", + Task: "tasks" +} +export const OBJECT_TYPE_TO_MODEL = {} +Object.entries(MODEL_TO_OBJECT_TYPE).forEach(([k, v]) => { + OBJECT_TYPE_TO_MODEL[v] = k +}) + export const NOTE_TYPE = { FREE_TEXT: "FREE_TEXT", CHANGE_RECORD: "CHANGE_RECORD", PARTNER_ASSESSMENT: "PARTNER_ASSESSMENT", ASSESSMENT: "ASSESSMENT" } + +export const DEFAULT_CUSTOM_FIELDS_PARENT = "formCustomFields" +export const INVISIBLE_CUSTOM_FIELDS_FIELD = "invisibleCustomFields" + +export const ASSESSMENTS_RELATED_OBJECT_TYPE = { + REPORT: "report" +} + export const yupDate = yup.date().transform(function(value, originalValue) { if (this.isType(value)) { return value @@ -73,7 +138,10 @@ export const CUSTOM_FIELD_TYPE = { const CUSTOM_FIELD_TYPE_SCHEMA = { [CUSTOM_FIELD_TYPE.TEXT]: yup.string().nullable().default(""), - [CUSTOM_FIELD_TYPE.NUMBER]: yup.number().nullable().default(null), + [CUSTOM_FIELD_TYPE.NUMBER]: yup.number().nullable().default(null).typeError( + // eslint-disable-next-line no-template-curly-in-string + "${path} must be a ${type} type, but the final value was ${originalValue}" + ), [CUSTOM_FIELD_TYPE.DATE]: yupDate.nullable().default(null), [CUSTOM_FIELD_TYPE.DATETIME]: yupDate.nullable().default(null), [CUSTOM_FIELD_TYPE.ENUM]: yup.string().nullable().default(""), @@ -82,14 +150,14 @@ const CUSTOM_FIELD_TYPE_SCHEMA = { [CUSTOM_FIELD_TYPE.SPECIAL_FIELD]: yup.mixed().nullable().default(null) } -const createFieldYupSchema = (fieldKey, fieldConfig, fieldPrefix) => { +const createFieldYupSchema = (fieldKey, fieldConfig, parentFieldName) => { const { label, validations, objectFields, typeError } = fieldConfig let fieldTypeYupSchema = CUSTOM_FIELD_TYPE_SCHEMA[fieldConfig.type] if (typeError) { fieldTypeYupSchema = fieldTypeYupSchema.typeError(typeError) } if (!_isEmpty(objectFields)) { - const objSchema = createYupObjectShape(objectFields, fieldPrefix) + const objSchema = createYupObjectShape(objectFields, parentFieldName) fieldTypeYupSchema = fieldTypeYupSchema.of(objSchema) } if (!_isEmpty(validations)) { @@ -109,16 +177,16 @@ const createFieldYupSchema = (fieldKey, fieldConfig, fieldPrefix) => { fieldYupSchema = fieldYupSchema.label(label) } // Field type specific validation not needed when the field is invisible or - // when invisibleCustomFields hasn't even been filled (like when the report + // when INVISIBLE_CUSTOM_FIELDS_FIELD hasn't even been filled (like when the report // has been created via sevrer side tests, or later maybe imported from an // external system (and never went through the edit/create form which normally - // fills the invisibleCustomFields) + // fills the INVISIBLE_CUSTOM_FIELDS_FIELD) fieldYupSchema = fieldYupSchema.when( - "invisibleCustomFields", + INVISIBLE_CUSTOM_FIELDS_FIELD, (invisibleCustomFields, schema) => { return invisibleCustomFields === null || (invisibleCustomFields && - invisibleCustomFields.includes(`${fieldPrefix}.${fieldKey}`)) + invisibleCustomFields.includes(`${parentFieldName}.${fieldKey}`)) ? schema : schema.concat(fieldTypeYupSchema) } @@ -126,19 +194,50 @@ const createFieldYupSchema = (fieldKey, fieldConfig, fieldPrefix) => { return fieldYupSchema } -export const createYupObjectShape = (config, prefix = "formCustomFields") => { +export const createYupObjectShape = ( + config, + parentFieldName = DEFAULT_CUSTOM_FIELDS_PARENT +) => { let objShape = {} if (config) { objShape = Object.fromEntries( Object.entries(config) - .map(([k, v]) => [k, createFieldYupSchema(k, config[k], prefix)]) + .map(([k, v]) => [ + k, + createFieldYupSchema(k, config[k], parentFieldName) + ]) .filter(([k, v]) => v !== null) ) - objShape.invisibleCustomFields = yup.mixed().nullable().default(null) + objShape[INVISIBLE_CUSTOM_FIELDS_FIELD] = yup + .mixed() + .nullable() + .default(null) } return yup.object().shape(objShape) } +export const ENTITY_ASSESSMENT_PARENT_FIELD = "entityAssessment" + +export const createAssessmentSchema = ( + assessmentConfig, + parentFieldName = ENTITY_ASSESSMENT_PARENT_FIELD +) => { + const assessmentSchemaShape = createYupObjectShape( + assessmentConfig, + parentFieldName + ) + return yup.object().shape({ + [parentFieldName]: assessmentSchemaShape + }) +} + +export const createCustomFieldsSchema = customFieldsConfig => + yup.object().shape({ + [DEFAULT_CUSTOM_FIELDS_PARENT]: createYupObjectShape( + customFieldsConfig + ).nullable() + }) + export default class Model { static schema = { notes: [] @@ -154,8 +253,7 @@ export default class Model { _forEach(yupSchema.fields, (value, key) => { if ( !Object.prototype.hasOwnProperty.call(obj, key) || - obj[key] === null || - obj[key] === undefined + utils.isNullOrUndefined(obj[key]) ) { obj[key] = value.default() } @@ -167,7 +265,18 @@ export default class Model { } } - static notePropTypes = PropTypes.shape({ + static relatedObjectPropType = PropTypes.shape({ + noteUuid: PropTypes.string, + relatedObjectType: PropTypes.string.isRequired, + relatedObjectUuid: PropTypes.string.isRequired, + relatedObject: PropTypes.object + }) + + static noteRelatedObjectsPropType = PropTypes.arrayOf( + Model.relatedObjectPropType + ) + + static notePropType = PropTypes.shape({ uuid: PropTypes.string, createdAt: PropTypes.number, text: PropTypes.string, @@ -177,13 +286,7 @@ export default class Model { rank: PropTypes.string, role: PropTypes.string }), - noteRelatedObjects: PropTypes.arrayOf( - PropTypes.shape({ - noteUuid: PropTypes.string, - relatedObjectType: PropTypes.string, - relatedObjectUuid: PropTypes.string - }) - ) + noteRelatedObjects: Model.noteRelatedObjectsPropType }) static resourceName = null @@ -264,6 +367,26 @@ export default class Model { return a && b && a.uuid === b.uuid } + static fetchByUuid(uuid, entityGqlFields) { + const fields = entityGqlFields[this.resourceName] + if (!fields) { + return Promise.resolve(null) + } + + return API.query( + gql` + query($uuid: String!) { + ${this.getInstanceName}(uuid: $uuid) { + ${fields} + } + } + `, + { + uuid: uuid + } + ).then(data => new Models[this.resourceName](data[this.getInstanceName])) + } + constructor(props) { Object.forEach(this.constructor.schema, (key, value) => { if (Array.isArray(value) && value.length === 0) { @@ -305,4 +428,133 @@ export default class Model { toString() { return this.name || this.uuid } + + static toConfigObject(value) { + switch (typeof value) { + case "object": + return value + case "string": + return utils.parseJsonSafe(value) + default: + return {} + } + } + + static parseAssessmentsConfig(assessmentsConfig) { + return Object.fromEntries( + assessmentsConfig.map(a => { + const recurrence = a.recurrence || RECURRENCE_TYPE.ONCE + const assessmentKey = a.relatedObjectType + ? `${a.relatedObjectType}_${recurrence}` + : recurrence + const questions = a.questions || {} + return [assessmentKey, Model.toConfigObject(questions)] + }) + ) + } + + generalAssessmentsConfig() { + // assessments configuration defined for more than one instance + return [] + } + + instanceAssessmentsConfig() { + // assessments configuration defined for one specific instance + return [] + } + + getAssessmentsConfig() { + return Object.assign( + Model.parseAssessmentsConfig(this.generalAssessmentsConfig()), + Model.parseAssessmentsConfig(this.instanceAssessmentsConfig()) + ) + } + + getInstantAssessmentConfig( + relatedObjectType = ASSESSMENTS_RELATED_OBJECT_TYPE.REPORT + ) { + return this.getAssessmentsConfig()[ + `${relatedObjectType}_${RECURRENCE_TYPE.ONCE}` + ] + } + + getPeriodicAssessmentDetails(recurrence = RECURRENCE_TYPE.MONTHLY) { + const assessmentConfig = this.getAssessmentsConfig()[recurrence] + return { + assessmentConfig: assessmentConfig, + assessmentYupSchema: + assessmentConfig && createAssessmentSchema(assessmentConfig) + } + } + + getPeriodAssessments(recurrence, period, currentUser) { + return this.notes + .filter(n => { + return ( + n.type === NOTE_TYPE.ASSESSMENT && n.noteRelatedObjects.length === 1 + ) + }) + .sort((a, b) => b.createdAt - a.createdAt) // desc sorted + .map(note => ({ note: note, assessment: utils.parseJsonSafe(note.text) })) + .filter( + obj => + // FIXME: make a nicer implementation of the check on period start + obj.assessment.__recurrence === recurrence && + obj.assessment.__periodStart === + utils.parseJsonSafe(JSON.stringify(period.start)) + ) + } + + static getInstantAssessmentsDetailsForEntities( + entities, + assessmentsParentField + ) { + const assessmentsConfig = {} + const assessmentsSchemaShape = {} + entities.forEach(entity => { + assessmentsConfig[entity.uuid] = entity.getInstantAssessmentConfig() + if (!_isEmpty(assessmentsConfig[entity.uuid])) { + assessmentsSchemaShape[entity.uuid] = createYupObjectShape( + assessmentsConfig[entity.uuid], + `${assessmentsParentField}.${entity.uuid}` + ) + } + }) + return { + assessmentsConfig: assessmentsConfig, + assessmentsSchema: yup.object().shape({ + [assessmentsParentField]: yup + .object() + .shape(assessmentsSchemaShape) + .nullable() + .default(null) + }) + } + } + + getInstantAssessmentResults( + dateRange, + relatedObjectType = ASSESSMENTS_RELATED_OBJECT_TYPE.REPORT + ) { + return this.notes + .filter( + n => + n.type === NOTE_TYPE.ASSESSMENT && + n.noteRelatedObjects.filter( + ro => + ro.relatedObject && + ro.relatedObjectType === Models.Report.relatedObjectType && + ro.relatedObject.state === Models.Report.STATE.PUBLISHED && + (!dateRange || + (ro.relatedObject.engagementDate <= dateRange.end && + ro.relatedObject.engagementDate >= dateRange.start)) + ).length + ) + .map(note => utils.parseJsonSafe(note.text)) + .filter( + obj => + obj.__recurrence === RECURRENCE_TYPE.ONCE && + obj.__relatedObjectType === relatedObjectType + ) + } } diff --git a/client/src/components/Nav.js b/client/src/components/Nav.js index 54a68ebe9b..fadc42befe 100644 --- a/client/src/components/Nav.js +++ b/client/src/components/Nav.js @@ -1,10 +1,10 @@ import { clearSearchQuery, resetPages } from "actions" import AppContext from "components/AppContext" import { ResponsiveLayoutContext } from "components/ResponsiveLayout" -import { Organization, Person } from "models" +import { Organization } from "models" import { INSIGHTS, INSIGHT_DETAILS } from "pages/insights/Show" import PropTypes from "prop-types" -import React, { useEffect } from "react" +import React, { useContext, useEffect } from "react" import { MenuItem, Nav as BSNav, NavDropdown, NavItem } from "react-bootstrap" import { connect } from "react-redux" import { @@ -61,14 +61,13 @@ SidebarLink.propTypes = { id: PropTypes.string } -const BaseNav = ({ - currentUser, +const Nav = ({ advisorOrganizations, principalOrganizations, - appSettings, resetPages, clearSearchQuery }) => { + const { appSettings, currentUser } = useContext(AppContext) useEffect(() => scrollSpy.update(), []) const externalDocumentationUrl = appSettings.EXTERNAL_DOCUMENTATION_LINK_URL @@ -172,12 +171,6 @@ const BaseNav = ({ Daily rollup - {process.env.NODE_ENV === "development" && ( - - GraphQL - - )} - {currentUser.isAdmin() && ( Admin @@ -192,6 +185,9 @@ const BaseNav = ({ Authorization groups + + GraphQL + )} @@ -236,17 +232,14 @@ const BaseNav = ({ ) } -BaseNav.propTypes = { - currentUser: PropTypes.instanceOf(Person), - appSettings: PropTypes.object, +Nav.propTypes = { advisorOrganizations: PropTypes.array, principalOrganizations: PropTypes.array, clearSearchQuery: PropTypes.func.isRequired, resetPages: PropTypes.func.isRequired } -BaseNav.defaultProps = { - appSettings: {}, +Nav.defaultProps = { advisorOrganizations: [], principalOrganizations: [] } @@ -260,18 +253,6 @@ const mapDispatchToProps = (dispatch, ownProps) => dispatch ) -const Nav = props => ( - - {context => ( - - )} - -) - export default connect(null, mapDispatchToProps, null, { pure: false })(Nav) diff --git a/client/src/components/OrganizationTable.js b/client/src/components/OrganizationTable.js index 5a920809d6..4e9b609c37 100644 --- a/client/src/components/OrganizationTable.js +++ b/client/src/components/OrganizationTable.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import LinkTo from "components/LinkTo" import { PageDispatchersPropType, diff --git a/client/src/components/PendingApprovalReports.js b/client/src/components/PendingApprovalReports.js index 2079ec3b19..20df41bdf8 100644 --- a/client/src/components/PendingApprovalReports.js +++ b/client/src/components/PendingApprovalReports.js @@ -1,14 +1,15 @@ +import { gql } from "@apollo/client" import { IconNames } from "@blueprintjs/icons" import API from "api" -import { gql } from "apollo-boost" import BarChart from "components/BarChart" import MosaicLayout from "components/MosaicLayout" import { PageDispatchersPropType, useBoilerplate } from "components/Page" import ReportCollection, { + FORMAT_CALENDAR, FORMAT_MAP, + FORMAT_STATISTICS, FORMAT_SUMMARY, - FORMAT_TABLE, - FORMAT_CALENDAR + FORMAT_TABLE } from "components/ReportCollection" import * as d3 from "d3" import _isEqual from "lodash/isEqual" @@ -139,7 +140,12 @@ const Collection = ({ id, queryParams }) => (
) diff --git a/client/src/components/PeriodsNavigation.js b/client/src/components/PeriodsNavigation.js new file mode 100644 index 0000000000..c81fa0dac8 --- /dev/null +++ b/client/src/components/PeriodsNavigation.js @@ -0,0 +1,33 @@ +import { Icon } from "@blueprintjs/core" +import { IconNames } from "@blueprintjs/icons" +import PropTypes from "prop-types" +import React from "react" +import { Button } from "react-bootstrap" + +const PeriodsNavigation = ({ offset, onChange }) => ( +
+ + +
+) +PeriodsNavigation.propTypes = { + offset: PropTypes.number, + onChange: PropTypes.func.isRequired +} +PeriodsNavigation.defaultProps = { + offset: 0 +} + +export default PeriodsNavigation diff --git a/client/src/components/PositionTable.js b/client/src/components/PositionTable.js index d8e56e8115..9d7a47e49e 100644 --- a/client/src/components/PositionTable.js +++ b/client/src/components/PositionTable.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import LinkTo from "components/LinkTo" import { PageDispatchersPropType, diff --git a/client/src/components/RelatedObjectNoteModal.js b/client/src/components/RelatedObjectNoteModal.js index 7684e6d8cc..c8ab773bb1 100644 --- a/client/src/components/RelatedObjectNoteModal.js +++ b/client/src/components/RelatedObjectNoteModal.js @@ -1,23 +1,30 @@ import API from "api" +import ConfirmDelete from "components/ConfirmDelete" import * as FieldHelper from "components/FieldHelper" import Messages from "components/Messages" import Model, { GQL_CREATE_NOTE, GQL_UPDATE_NOTE, + MODEL_TO_OBJECT_TYPE, NOTE_TYPE } from "components/Model" +import RelatedObjectsTable from "components/RelatedObjectsTable" import RichTextEditor from "components/RichTextEditor" import { Field, Form, Formik } from "formik" +import _isEmpty from "lodash/isEmpty" import PropTypes from "prop-types" import React, { useState } from "react" import { Button, Modal } from "react-bootstrap" +import utils from "utils" import * as yup from "yup" const RelatedObjectNoteModal = ({ note, + currentObject, showModal, onCancel, onSuccess, + onDelete, questions }) => { const yupSchema = yup.object().shape({ @@ -25,6 +32,9 @@ const RelatedObjectNoteModal = ({ text: yup.string().default("") }) const [error, setError] = useState(null) + const [relatedObjects, setRelatedObjects] = useState( + note.noteRelatedObjects || [] + ) const edit = !!note.uuid return ( @@ -44,7 +54,8 @@ const RelatedObjectNoteModal = ({ submitForm }) => { const isJson = note.type !== NOTE_TYPE.FREE_TEXT - const jsonFields = isJson && note.text ? JSON.parse(note.text) : {} + const jsonFields = + isJson && note.text ? utils.parseJsonSafe(note.text) : {} const noteText = isJson ? jsonFields.text : note.text const typeName = note.type === NOTE_TYPE.PARTNER_ASSESSMENT || @@ -68,7 +79,6 @@ const RelatedObjectNoteModal = ({ }} > - {note.type === NOTE_TYPE.PARTNER_ASSESSMENT && ( <> {questions.map(question => ( @@ -89,7 +99,6 @@ const RelatedObjectNoteModal = ({ ))} )} - + - + {_isEmpty(relatedObjects) && onDelete && ( + onDelete(note.uuid)} + objectType="note" + objectDisplay={"#" + note.uuid} + bsStyle="warning" + buttonLabel="Delete note" + /> + )} + {!_isEmpty(relatedObjects) && ( + + )} ) @@ -126,6 +153,26 @@ const RelatedObjectNoteModal = ({ ) + + function handleRelatedObjectSelect(value, model) { + const relatedObjectsUuids = relatedObjects.map(o => o.relatedObjectUuid) + if (!relatedObjectsUuids.includes(value.uuid)) { + const newRelatedObject = { + relatedObjectType: MODEL_TO_OBJECT_TYPE[model], + relatedObjectUuid: value.uuid, + relatedObject: value + } + setRelatedObjects([...relatedObjects, newRelatedObject]) + } + } + + function handleRelatedObjectDelete(relatedObject) { + const newRelatedObjects = relatedObjects.filter( + item => item.relatedObjectUuid !== relatedObject.relatedObjectUuid + ) + setRelatedObjects(newRelatedObjects) + } + function onSubmit(values, form) { return save(values, form) .then(response => onSubmitSuccess(response, values, form)) @@ -141,11 +188,15 @@ const RelatedObjectNoteModal = ({ } function save(values, form) { + const noteRelatedObjects = relatedObjects.map(o => ({ + relatedObjectType: o.relatedObjectType, + relatedObjectUuid: o.relatedObjectUuid + })) const updatedNote = { uuid: values.uuid, author: values.author, type: values.type, - noteRelatedObjects: values.noteRelatedObjects, + noteRelatedObjects, text: values.text } const isJson = updatedNote.type !== NOTE_TYPE.FREE_TEXT @@ -161,14 +212,17 @@ const RelatedObjectNoteModal = ({ function close() { // Reset state before closing (cancel) setError(null) + setRelatedObjects(note.noteRelatedObjects || []) onCancel() } } RelatedObjectNoteModal.propTypes = { - note: Model.notePropTypes, + note: Model.notePropType, + currentObject: Model.relatedObjectPropType, showModal: PropTypes.bool, onCancel: PropTypes.func.isRequired, onSuccess: PropTypes.func.isRequired, + onDelete: PropTypes.func, questions: PropTypes.array } diff --git a/client/src/components/RelatedObjectNotes.js b/client/src/components/RelatedObjectNotes.js index 89a591780e..aa4d0fa477 100644 --- a/client/src/components/RelatedObjectNotes.js +++ b/client/src/components/RelatedObjectNotes.js @@ -1,13 +1,17 @@ -import API from "api" -import { gql } from "apollo-boost" +import { gql } from "@apollo/client" import { Icon } from "@blueprintjs/core" import "@blueprintjs/core/lib/css/blueprint.css" import { IconNames } from "@blueprintjs/icons" +import API from "api" import AppContext from "components/AppContext" import ConfirmDelete from "components/ConfirmDelete" import Pie from "components/graphs/Pie" import LinkTo from "components/LinkTo" -import Model, { NOTE_TYPE } from "components/Model" +import Messages from "components/Messages" +import Model, { + INVISIBLE_CUSTOM_FIELDS_FIELD, + NOTE_TYPE +} from "components/Model" import RelatedObjectNoteModal from "components/RelatedObjectNoteModal" import { JSONPath } from "jsonpath-plus" import _isEmpty from "lodash/isEmpty" @@ -15,7 +19,7 @@ import _isEqualWith from "lodash/isEqualWith" import { Person } from "models" import moment from "moment" import PropTypes from "prop-types" -import React, { useEffect, useRef, useState } from "react" +import React, { useContext, useEffect, useRef, useState } from "react" import { Button, Panel } from "react-bootstrap" import ReactDOM from "react-dom" import NotificationBadge from "react-notification-badge" @@ -33,13 +37,20 @@ const GQL_DELETE_NOTE = gql` export { GRAPHQL_NOTES_FIELDS } from "components/Model" -const BaseRelatedObjectNotes = ({ - currentUser, +export const EXCLUDED_ASSESSMENT_FIELDS = [ + "__recurrence", + "__periodStart", + "__relatedObjectType", + INVISIBLE_CUSTOM_FIELDS_FIELD +] + +const RelatedObjectNotes = ({ notesElemId, relatedObject, relatedObjectValue, notes: notesProp }) => { + const { currentUser } = useContext(AppContext) const latestNotesProp = useRef(notesProp) const notesPropUnchanged = _isEqualWith( latestNotesProp.current, @@ -47,9 +58,7 @@ const BaseRelatedObjectNotes = ({ utils.treatFunctionsAsEqual ) - // TODO: display somewhere the error state - // eslint-disable-next-line no-unused-vars - const [error, setError] = useState(null) // lgtm[js/unused-local-variable] + const [error, setError] = useState(null) const [hidden, setHidden] = useState(true) const [ showRelatedObjectNoteModalKey, @@ -88,7 +97,7 @@ const BaseRelatedObjectNotes = ({ ) const partnerAssessmentsSummary = partnerAssessments.reduce( (counters, assessment) => { - const assessmentJson = JSON.parse(assessment.text) + const assessmentJson = utils.parseJsonSafe(assessment.text) questions.forEach(question => { if (!counters[question.id]) { @@ -140,6 +149,7 @@ const BaseRelatedObjectNotes = ({ +
deleteNote(note.uuid)} @@ -348,7 +362,9 @@ const BaseRelatedObjectNotes = ({ {Object.keys(jsonFields) - .filter(field => field !== "text") + .filter( + field => !EXCLUDED_ASSESSMENT_FIELDS.includes(field) + ) .map(field => (

{field}: {jsonFields[field]} @@ -402,13 +418,21 @@ const BaseRelatedObjectNotes = ({ function hideEditRelatedObjectNoteModal(note) { const newNotes = notes.filter(item => item.uuid !== note.uuid) // remove old note - newNotes.unshift(note) // add updated note at the front + const roUuids = note?.noteRelatedObjects.map(nro => nro.relatedObjectUuid) + if (roUuids?.includes(relatedObject?.relatedObjectUuid)) { + newNotes.unshift(note) // add updated note at the front + } setError(null) setShowRelatedObjectNoteModalKey(null) setNoteType(null) setNotes(newNotes) } + function hideDeleteRelatedObjectNoteModal(uuid) { + setShowRelatedObjectNoteModalKey(null) + deleteNote(uuid) + } + function deleteNote(uuid) { const newNotes = notes.filter(item => item.uuid !== uuid) // remove note API.mutation(GQL_DELETE_NOTE, { uuid }) @@ -421,31 +445,19 @@ const BaseRelatedObjectNotes = ({ }) } } -BaseRelatedObjectNotes.propTypes = { - currentUser: PropTypes.instanceOf(Person), +RelatedObjectNotes.propTypes = { notesElemId: PropTypes.string.isRequired, - notes: PropTypes.arrayOf(Model.notePropTypes), - relatedObject: PropTypes.shape({ - relatedObjectType: PropTypes.string.isRequired, - relatedObjectUuid: PropTypes.string.isRequired - }), + notes: PropTypes.arrayOf(Model.notePropType), + relatedObject: Model.relatedObjectPropType, relatedObjectValue: PropTypes.shape({ role: PropTypes.string.isRequired, rank: PropTypes.string.isRequired, name: PropTypes.string.isRequired }) } -BaseRelatedObjectNotes.defaultProps = { +RelatedObjectNotes.defaultProps = { notesElemId: "notes-view", notes: [] } -const RelatedObjectNotes = props => ( - - {context => ( - - )} - -) - export default RelatedObjectNotes diff --git a/client/src/components/RelatedObjectsTable.js b/client/src/components/RelatedObjectsTable.js new file mode 100644 index 0000000000..fad40a5fc4 --- /dev/null +++ b/client/src/components/RelatedObjectsTable.js @@ -0,0 +1,94 @@ +import LinkTo from "components/LinkTo" +import Model from "components/Model" +import MultiTypeAdvancedSelectComponent from "components/advancedSelectWidget/MultiTypeAdvancedSelectComponent" +import _get from "lodash/get" +import PropTypes from "prop-types" +import React from "react" +import { Table } from "react-bootstrap" +import REMOVE_ICON from "resources/delete.png" +import utils from "utils" + +const RelatedObjectsTable = ({ + currentObject, + relatedObjects, + onSelect, + showDelete, + onDelete +}) => { + const relatedObjectsExist = _get(relatedObjects, "length", 0) > 0 + + return ( +

+ ) +} + +RelatedObjectsTable.propTypes = { + currentObject: Model.relatedObjectPropType, + relatedObjects: Model.noteRelatedObjectsPropType.isRequired, + onSelect: PropTypes.func.isRequired, + showDelete: PropTypes.bool, + onDelete: utils.fnRequiredWhen.bind(null, "showDelete") +} + +RelatedObjectsTable.defaultProps = { + showDelete: false +} + +export default RelatedObjectsTable diff --git a/client/src/components/ReportCalendar.js b/client/src/components/ReportCalendar.js index 81a54733a9..4b3a7415bd 100644 --- a/client/src/components/ReportCalendar.js +++ b/client/src/components/ReportCalendar.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import Calendar from "components/Calendar" import { PageDispatchersPropType } from "components/Page" import _isEqual from "lodash/isEqual" diff --git a/client/src/components/ReportCollection.js b/client/src/components/ReportCollection.js index 013a87c922..088bd6795b 100644 --- a/client/src/components/ReportCollection.js +++ b/client/src/components/ReportCollection.js @@ -6,8 +6,10 @@ import { } from "components/Page" import ReportCalendar from "components/ReportCalendar" import ReportMap from "components/ReportMap" +import ReportStatistics from "components/ReportStatistics" import ReportSummary from "components/ReportSummary" import ReportTable from "components/ReportTable" +import { RECURRENCE_TYPE } from "periodUtils" import PropTypes from "prop-types" import React, { useState } from "react" import { Button } from "react-bootstrap" @@ -17,6 +19,7 @@ export const FORMAT_CALENDAR = "calendar" export const FORMAT_SUMMARY = "summary" export const FORMAT_TABLE = "table" export const FORMAT_MAP = "map" +export const FORMAT_STATISTICS = "statistics" const ReportCollection = ({ pageDispatchers, @@ -34,7 +37,7 @@ const ReportCollection = ({ }) => { const [viewFormat, setViewFormat] = useState(viewFormats[0]) const showHeader = viewFormats.length > 1 || reportsFilter - + const statisticsRecurrence = [RECURRENCE_TYPE.MONTHLY] return (
@@ -58,6 +61,9 @@ const ReportCollection = ({ {viewFormats.includes(FORMAT_MAP) && ( )} + {viewFormats.includes(FORMAT_STATISTICS) && ( + + )} )} @@ -107,6 +113,22 @@ const ReportCollection = ({ marginBottom={marginBottom} /> )} + {viewFormat === FORMAT_STATISTICS && ( + <> + {statisticsRecurrence.map(recurrence => ( + + ))} + + )}
@@ -129,7 +151,13 @@ ReportCollection.propTypes = { } ReportCollection.defaultProps = { - viewFormats: [FORMAT_SUMMARY, FORMAT_TABLE, FORMAT_CALENDAR, FORMAT_MAP] + viewFormats: [ + FORMAT_STATISTICS, + FORMAT_SUMMARY, + FORMAT_TABLE, + FORMAT_CALENDAR, + FORMAT_MAP + ] } const mapDispatchToProps = (dispatch, ownProps) => { diff --git a/client/src/components/ReportMap.js b/client/src/components/ReportMap.js index c0ae8170b1..d2b5a0bad0 100644 --- a/client/src/components/ReportMap.js +++ b/client/src/components/ReportMap.js @@ -1,15 +1,13 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" -import Leaflet from "components/Leaflet" +import ReportsMapWidget from "components/aggregations/ReportsMapWidget" import { PageDispatchersPropType, mapPageDispatchersToProps, useBoilerplate } from "components/Page" -import _escape from "lodash/escape" -import { Location } from "models" import PropTypes from "prop-types" -import React, { useEffect, useMemo } from "react" +import React, { useEffect } from "react" import { connect } from "react-redux" const GQL_GET_REPORT_LIST = gql` @@ -50,26 +48,6 @@ const ReportMap = ({ error, pageDispatchers }) - const markers = useMemo(() => { - const reports = data ? data.reportList.list : [] - if (!reports.length) { - return [] - } - const markerArray = [] - reports.forEach(report => { - if (Location.hasCoordinates(report.location)) { - let label = _escape(report.intent || "") // escape HTML in intent! - label += `
@ ${_escape(report.location.name)}` // escape HTML in locationName! - markerArray.push({ - id: report.uuid, - lat: report.location.lat, - lng: report.location.lng, - name: label - }) - } - }) - return markerArray - }, [data]) // Update the total count const totalCount = done ? null : data?.reportList?.totalCount useEffect(() => setTotalCount && setTotalCount(totalCount), [ @@ -79,10 +57,10 @@ const ReportMap = ({ if (done) { return result } - + const reports = data ? data.reportList.list : [] return ( - { + const choices = {} + Object.forEach(values, val => { + choices[val] = { label: labels[val] } + if (colors) { + choices[val].color = colors[val] + } + }) + return choices +} + +const REPORT_FIELDS_FOR_STATISTICS = { + engagementDate: { + type: CUSTOM_FIELD_TYPE.DATE + }, + location: { + aggregation: { + widget: AGGERGATION_WIDGET_TYPE.REPORTS_MAP + } + }, + state: { + type: CUSTOM_FIELD_TYPE.ENUM, + choices: choicesFactory( + Report.STATE, + Report.STATE_LABELS, + Report.STATE_COLORS + ) + }, + engagementStatus: { + type: CUSTOM_FIELD_TYPE.ENUMSET, + choices: choicesFactory( + Report.ENGAGEMENT_STATUS, + Report.ENGAGEMENT_STATUS_LABELS + ) + }, + tasks: { + aggregation: { + aggregationType: AGGREGATION_TYPE.REPORTS_BY_TASK, + widget: AGGERGATION_WIDGET_TYPE.REPORTS_BY_TASK + }, + label: pluralize(Settings.fields.task.subLevel.shortLabel) + }, + atmosphere: { + type: CUSTOM_FIELD_TYPE.ENUM, + label: Settings.fields.report.atmosphere, + choices: choicesFactory(Report.ATMOSPHERE, Report.ATMOSPHERE_LABELS) + } +} + +const GQL_GET_REPORT_LIST = gql` + query($reportQuery: ReportSearchQueryInput) { + reportList(query: $reportQuery) { + pageNum + pageSize + totalCount + list { + uuid + intent + engagementDate + location { + uuid + name + lat + lng + } + atmosphere + state + engagementStatus + tasks { + uuid + shortName + } + customFields + } + } + } +` + +const FieldStatisticsRow = ({ + fieldConfig, + fieldName, + periods, + periodsData, + isFirstRow +}) => { + const aggregationWidget = getAggregationWidget(fieldConfig) + if (_isEmpty(periods) || !aggregationWidget) { + return null + } + return ( + + {periods.map((period, index) => ( + + {_isEmpty(periodsData[index]) ? ( + isFirstRow ? ( + No reports found + ) : null + ) : ( + + )} + + ))} + + ) +} +FieldStatisticsRow.propTypes = { + fieldConfig: PropTypes.object, + fieldName: PropTypes.string, + periods: PeriodsPropType.isRequired, + periodsData: PropTypes.arrayOf(PropTypes.array).isRequired, + isFirstRow: PropTypes.bool +} + +const NoStatisticsRow = ({ periods }) => ( + + {periods.map((period, index) => ( + + No reports found + + ))} + +) +NoStatisticsRow.propTypes = { + periods: PeriodsPropType.isRequired +} + +const ReportStatistics = ({ + pageDispatchers, + periodsDetails, + setTotalCount, + queryParams +}) => { + const [offset, setOffset] = useState(0) + const { recurrence, numberOfPeriods } = periodsDetails + const periodsConfig = getPeriodsConfig(recurrence, numberOfPeriods, offset) + const { periods } = periodsConfig + const dateSortAsc = datesArray => datesArray.sort((a, b) => a - b) + const statisticsStartDate = + !_isEmpty(periods) && dateSortAsc(periods.map(p => p.start))[0] + const statisticsEndDate = + !_isEmpty(periods) && + dateSortAsc(periods.map(p => p.end))[periods.length - 1] + const reportQuery = Object.assign({}, queryParams, { pageSize: 0 }) + if ( + statisticsStartDate && + (!queryParams.engagementDateStart || + queryParams.engagementDateStart < statisticsStartDate) + ) { + reportQuery.engagementDateStart = statisticsStartDate + } + if ( + statisticsEndDate && + (!queryParams.engagementDateEnd || + queryParams.engagementDateEnd > statisticsEndDate) + ) { + reportQuery.engagementDateEnd = statisticsEndDate + } + const { loading, error, data } = API.useApiQuery(GQL_GET_REPORT_LIST, { + reportQuery + }) + const { done, result } = useBoilerplate({ + loading, + error, + pageDispatchers + }) + // Update the total count + const totalCount = done ? null : data?.reportList?.totalCount + useEffect(() => setTotalCount && setTotalCount(totalCount), [ + setTotalCount, + totalCount + ]) + if (done) { + return result + } + if (_isEmpty(periods)) { + return null + } + + const reports = data ? Report.fromArray(data.reportList.list) : [] + const CUSTOM_FIELDS_KEY = "customFieldsJson" + const getPeriodData = (reports, dateRange) => { + const reportsForDateRange = reports.filter( + elem => + elem.engagementDate <= dateRange.end && + elem.engagementDate >= dateRange.start + ) + reportsForDateRange.map( + report => + (report[CUSTOM_FIELDS_KEY] = utils.parseJsonSafe(report.customFields)) + ) + return reportsForDateRange + } + const dataPerPeriod = [] + periods.forEach(period => dataPerPeriod.push(getPeriodData(reports, period))) + const hasStatistics = !_isEmpty(dataPerPeriod.filter(data => !_isEmpty(data))) + const customFieldsConfig = Settings.fields.report.customFields + + return ( + <> + + + + + <> + {!hasStatistics && } + {hasStatistics && + Object.keys(REPORT_FIELDS_FOR_STATISTICS).map((key, index) => ( + + ))} + {hasStatistics && + Object.keys(customFieldsConfig || {}).map((key, index) => ( + + ))} + + +
+ + ) +} + +ReportStatistics.propTypes = { + pageDispatchers: PageDispatchersPropType, + periodsDetails: PeriodsDetailsPropType.isRequired, + setTotalCount: PropTypes.func, + queryParams: PropTypes.object +} + +export default ReportStatistics diff --git a/client/src/components/ReportSummary.js b/client/src/components/ReportSummary.js index 29efd4c38c..965dd52dfb 100644 --- a/client/src/components/ReportSummary.js +++ b/client/src/components/ReportSummary.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import LinkTo from "components/LinkTo" import { PageDispatchersPropType, useBoilerplate } from "components/Page" import { ReportCompactWorkflow } from "components/ReportWorkflow" diff --git a/client/src/components/ReportTable.js b/client/src/components/ReportTable.js index 4468a8e339..6a489910e7 100644 --- a/client/src/components/ReportTable.js +++ b/client/src/components/ReportTable.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import LinkTo from "components/LinkTo" import { PageDispatchersPropType, useBoilerplate } from "components/Page" import UltimatePaginationTopDown from "components/UltimatePaginationTopDown" diff --git a/client/src/components/ReportTags.js b/client/src/components/ReportTags.js index a8d556b4a0..337015886c 100644 --- a/client/src/components/ReportTags.js +++ b/client/src/components/ReportTags.js @@ -19,6 +19,7 @@ const ReportTags = ({ value, suggestions, onChange }) => { handleFilterSuggestions={handleTagSuggestions} handleDelete={handleTagDelete} handleAddition={handleTagAddition} + renderSuggestion={item => {item.text}} /> ) diff --git a/client/src/components/ReportsByDayOfWeek.js b/client/src/components/ReportsByDayOfWeek.js index 3aeb6d6b05..4978113b32 100644 --- a/client/src/components/ReportsByDayOfWeek.js +++ b/client/src/components/ReportsByDayOfWeek.js @@ -1,14 +1,15 @@ +import { gql } from "@apollo/client" import { IconNames } from "@blueprintjs/icons" import API from "api" -import { gql } from "apollo-boost" import BarChart from "components/BarChart" import MosaicLayout from "components/MosaicLayout" import { PageDispatchersPropType, useBoilerplate } from "components/Page" import ReportCollection, { + FORMAT_CALENDAR, FORMAT_MAP, + FORMAT_STATISTICS, FORMAT_SUMMARY, - FORMAT_TABLE, - FORMAT_CALENDAR + FORMAT_TABLE } from "components/ReportCollection" import * as d3 from "d3" import _isEqual from "lodash/isEqual" @@ -134,7 +135,12 @@ const Collection = ({ id, queryParams }) => ( ) diff --git a/client/src/components/ReportsByTask.js b/client/src/components/ReportsByTask.js index 5ba8e64444..d000a052ce 100644 --- a/client/src/components/ReportsByTask.js +++ b/client/src/components/ReportsByTask.js @@ -1,14 +1,16 @@ +import { gql } from "@apollo/client" import { IconNames } from "@blueprintjs/icons" import API from "api" -import { gql } from "apollo-boost" +import { getReportsByTasks } from "components/aggregations/utils" import BarChart from "components/BarChart" import MosaicLayout from "components/MosaicLayout" import { PageDispatchersPropType, useBoilerplate } from "components/Page" import ReportCollection, { + FORMAT_CALENDAR, FORMAT_MAP, + FORMAT_STATISTICS, FORMAT_SUMMARY, - FORMAT_TABLE, - FORMAT_CALENDAR + FORMAT_TABLE } from "components/ReportCollection" import * as d3 from "d3" import _isEqual from "lodash/isEqual" @@ -53,46 +55,11 @@ const Chart = ({ if (!data) { return [] } - const noTaskMessage = `No ${Settings.fields.task.subLevel.shortLabel}` - const noTask = { - uuid: "-1", - shortName: noTaskMessage, - longName: noTaskMessage - } - const reportsList = data.reportList.list || [] - if (!reportsList.length) { - return [] - } - const simplifiedValues = reportsList.map(d => { - return { reportUuid: d.uuid, tasks: d.tasks.map(p => p.uuid) } - }) - let tasks = reportsList.map(d => d.tasks) - tasks = [].concat - .apply([], tasks) - .filter( - (item, index, d) => - d.findIndex(t => { - return t.uuid === item.uuid - }) === index - ) - .sort((a, b) => a.shortName.localeCompare(b.shortName)) - // add No Task item, in order to relate to reports without Tasks - tasks.push(noTask) - return tasks.map(d => { - const r = {} - r.task = d - r.reportsCount = - d.uuid === noTask.uuid - ? simplifiedValues.filter(item => item.tasks.length === 0).length - : simplifiedValues.filter(item => item.tasks.indexOf(d.uuid) > -1) - .length - return r - }) + return getReportsByTasks(data.reportList.list) }, [data]) if (done) { return result } - return (
@@ -135,7 +102,12 @@ const Collection = ({ id, queryParams }) => (
) diff --git a/client/src/components/SavedSearchTable.js b/client/src/components/SavedSearchTable.js index 6b8a76360c..d745cf6746 100644 --- a/client/src/components/SavedSearchTable.js +++ b/client/src/components/SavedSearchTable.js @@ -1,7 +1,14 @@ import { SEARCH_OBJECT_TYPES } from "actions" -import ReportCollection from "components/ReportCollection" +import ReportCollection, { + FORMAT_CALENDAR, + FORMAT_MAP, + FORMAT_STATISTICS, + FORMAT_SUMMARY, + FORMAT_TABLE +} from "components/ReportCollection" import PropTypes from "prop-types" import React from "react" +import utils from "utils" const SavedSearchTable = props => { const objType = @@ -11,14 +18,26 @@ const SavedSearchTable = props => { return No reports found } - const query = JSON.parse(props.search.query) + const query = utils.parseJsonSafe(props.search.query) // Add default sorting (if not specified/saved in the query); see SEARCH_CONFIG in pages/Search.js query.sortBy = query.sortBy || "ENGAGEMENT_DATE" query.sortOrder = query.sortOrder || "DESC" query.pageNum = query.pageNum || 0 query.pageSize = query.pageSize || 10 - return + return ( + + ) } SavedSearchTable.propTypes = { diff --git a/client/src/components/SearchFilters.js b/client/src/components/SearchFilters.js index a2709b6f1c..f3252cfd26 100644 --- a/client/src/components/SearchFilters.js +++ b/client/src/components/SearchFilters.js @@ -351,7 +351,11 @@ const searchFilters = function() { deserializer: deserializeSelectFilter, props: { queryKey: "atmosphere", - options: ["POSITIVE", "NEUTRAL", "NEGATIVE"] + options: [ + Report.ATMOSPHERE.POSITIVE, + Report.ATMOSPHERE.NEUTRAL, + Report.ATMOSPHERE.NEGATIVE + ] } }, Tag: { diff --git a/client/src/components/SecurityBanner.js b/client/src/components/SecurityBanner.js index 347f7d6583..cd942dd0ee 100644 --- a/client/src/components/SecurityBanner.js +++ b/client/src/components/SecurityBanner.js @@ -1,8 +1,6 @@ import AppContext from "components/AppContext" import LinkTo from "components/LinkTo" -import { Person } from "models" -import PropTypes from "prop-types" -import React from "react" +import React, { useContext } from "react" const SETTING_KEY_TEXT = "SECURITY_BANNER_TEXT" const SETTING_KEY_COLOR = "SECURITY_BANNER_COLOR" @@ -16,40 +14,24 @@ const aCss = { fontSize: "0.7em" } -const BaseSecurityBanner = ({ currentUser, appSettings }) => ( -
- {appSettings[SETTING_KEY_TEXT]} || {currentUser.name}{" "} - { + const { appSettings, currentUser } = useContext(AppContext) + return ( +
- (edit) - -
-) -BaseSecurityBanner.propTypes = { - currentUser: PropTypes.instanceOf(Person), - appSettings: PropTypes.object + {appSettings[SETTING_KEY_TEXT]} || {currentUser.name}{" "} + + (edit) + +
+ ) } -BaseSecurityBanner.defaultProps = { - appSettings: {} -} - -const SecurityBanner = props => ( - - {context => ( - - )} - -) export default SecurityBanner diff --git a/client/src/components/TopBar.js b/client/src/components/TopBar.js index c25327060a..87afe38415 100644 --- a/client/src/components/TopBar.js +++ b/client/src/components/TopBar.js @@ -4,9 +4,8 @@ import GeneralBanner from "components/GeneralBanner" import Header from "components/Header" import NoPositionBanner from "components/NoPositionBanner" import SecurityBanner from "components/SecurityBanner" -import { Person } from "models" import PropTypes from "prop-types" -import React, { useEffect, useRef, useState } from "react" +import React, { useContext, useEffect, useRef, useState } from "react" import { connect } from "react-redux" const GENERAL_BANNER_LEVEL = "GENERAL_BANNER_LEVEL" @@ -19,14 +18,13 @@ const visible = { USERS_AND_SUPER_USERS: 3 } -const BaseTopBar = ({ - currentUser, - appSettings, +const TopBar = ({ handleTopbarHeight, resetPages, minimalHeader, toggleMenuAction }) => { + const { appSettings, currentUser } = useContext(AppContext) const [bannerVisibility, setBannerVisibility] = useState(false) const [height, setHeight] = useState(0) const topbarDiv = useRef() @@ -102,27 +100,13 @@ const BaseTopBar = ({ ) } -BaseTopBar.propTypes = { - currentUser: PropTypes.instanceOf(Person), - appSettings: PropTypes.object, +TopBar.propTypes = { handleTopbarHeight: PropTypes.func.isRequired, resetPages: PropTypes.func.isRequired, minimalHeader: PropTypes.bool, toggleMenuAction: PropTypes.func } -const TopBar = props => ( - - {context => ( - - )} - -) - const mapDispatchToProps = dispatch => ({ resetPages: () => dispatch(resetPages()) }) diff --git a/client/src/components/advancedSearch/AdvancedSelectFilter.js b/client/src/components/advancedSearch/AdvancedSelectFilter.js index 580d443e97..8472abd4ad 100644 --- a/client/src/components/advancedSearch/AdvancedSelectFilter.js +++ b/client/src/components/advancedSearch/AdvancedSelectFilter.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import useSearchFilter from "components/advancedSearch/hooks" import AdvancedSingleSelect from "components/advancedSelectWidget/AdvancedSingleSelect" import PropTypes from "prop-types" diff --git a/client/src/components/advancedSearch/OrganizationFilter.js b/client/src/components/advancedSearch/OrganizationFilter.js index 901980266c..16bce1b1f5 100644 --- a/client/src/components/advancedSearch/OrganizationFilter.js +++ b/client/src/components/advancedSearch/OrganizationFilter.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import useSearchFilter from "components/advancedSearch/hooks" import { OrganizationOverlayRow } from "components/advancedSelectWidget/AdvancedSelectOverlayRow" import AdvancedSingleSelect from "components/advancedSelectWidget/AdvancedSingleSelect" diff --git a/client/src/components/advancedSearch/ReportStateFilter.js b/client/src/components/advancedSearch/ReportStateFilter.js index fe775110f3..bba7d28d1b 100644 --- a/client/src/components/advancedSearch/ReportStateFilter.js +++ b/client/src/components/advancedSearch/ReportStateFilter.js @@ -5,14 +5,6 @@ import PropTypes from "prop-types" import React from "react" import { FormGroup } from "react-bootstrap" -const STATE_LABELS = { - [Report.STATE.DRAFT]: "Draft", - [Report.STATE.PENDING_APPROVAL]: "Pending Approval", - [Report.STATE.APPROVED]: "Approved", - [Report.STATE.PUBLISHED]: "Published", - [Report.STATE.CANCELLED]: "Cancelled", - [Report.STATE.REJECTED]: "Changes requested" -} const CANCELLATION_REASON_LABELS = { [Report.CANCELLATION_REASON.CANCELLED_BY_ADVISOR]: "Advisor", [Report.CANCELLATION_REASON.CANCELLED_BY_PRINCIPAL]: "Principal", @@ -55,7 +47,7 @@ const ReportStateFilter = ({ toQuery ) - const labels = value.state.map(s => STATE_LABELS[s]) + const labels = value.state.map(s => Report.STATE_LABELS[s]) const onlyCancelled = isOnlyCancelled(value) let stateDisplay = labels.join(" or ") if (onlyCancelled && value.cancelledReason) { @@ -79,9 +71,9 @@ const ReportStateFilter = ({ onChange={handleChangeState} multiple > - {Object.keys(STATE_LABELS).map(key => ( + {Object.keys(Report.STATE_LABELS).map(key => ( ))} diff --git a/client/src/components/advancedSelectWidget/AdvancedSelect.js b/client/src/components/advancedSelectWidget/AdvancedSelect.js index cd4250c8b5..3df40e5e81 100644 --- a/client/src/components/advancedSelectWidget/AdvancedSelect.js +++ b/client/src/components/advancedSelectWidget/AdvancedSelect.js @@ -1,6 +1,6 @@ +import { gql } from "@apollo/client" import { Popover, PopoverInteractionKind, Position } from "@blueprintjs/core" import API from "api" -import { gql } from "apollo-boost" import * as FieldHelper from "components/FieldHelper" import UltimatePagination from "components/UltimatePagination" import _isEmpty from "lodash/isEmpty" diff --git a/client/src/components/advancedSelectWidget/AdvancedSelectOverlayTable.js b/client/src/components/advancedSelectWidget/AdvancedSelectOverlayTable.js index ed41a16d17..035933ef48 100644 --- a/client/src/components/advancedSelectWidget/AdvancedSelectOverlayTable.js +++ b/client/src/components/advancedSelectWidget/AdvancedSelectOverlayTable.js @@ -34,10 +34,14 @@ const AdvancedSelectOverlayTable = ({ isSelected ? handleRemoveItem(item) : handleAddItem(item) const renderSelectComponent = React.cloneElement( selectItemComponent, - { name: fieldName, checked: isSelected, onChange: handleClick } + { name: fieldName, checked: isSelected, onChange: () => null } ) return ( - + {renderSelectComponent} {renderRow(item)} diff --git a/client/src/components/advancedSelectWidget/MultiTypeAdvancedSelectComponent.js b/client/src/components/advancedSelectWidget/MultiTypeAdvancedSelectComponent.js new file mode 100644 index 0000000000..fab4cf08ad --- /dev/null +++ b/client/src/components/advancedSelectWidget/MultiTypeAdvancedSelectComponent.js @@ -0,0 +1,173 @@ +import { SEARCH_OBJECT_LABELS, SEARCH_OBJECT_TYPES } from "actions" +import { + LocationOverlayRow, + OrganizationOverlayRow, + PersonDetailedOverlayRow, + PositionOverlayRow, + ReportDetailedOverlayRow, + TaskSimpleOverlayRow +} from "components/advancedSelectWidget/AdvancedSelectOverlayRow" +import AdvancedSingleSelect from "components/advancedSelectWidget/AdvancedSingleSelect" +import ButtonToggleGroup from "components/ButtonToggleGroup" +import * as Models from "models" +import PropTypes from "prop-types" +import React, { useState } from "react" +import { Button } from "react-bootstrap" +import LOCATIONS_ICON from "resources/locations.png" +import ORGANIZATIONS_ICON from "resources/organizations.png" +import PEOPLE_ICON from "resources/people.png" +import POSITIONS_ICON from "resources/positions.png" +import REPORTS_ICON from "resources/reports.png" +import TASKS_ICON from "resources/tasks.png" +import { ENTITY_TYPES } from "utils_links" + +const entityFilters = { + allEntities: { + label: "All entities", + queryVars: {} + } +} + +const peopleFilters = { + allEntities: { + label: "All", + queryVars: { matchPositionName: true } + }, + activeAdvisors: { + label: "All advisors", + queryVars: { role: Models.Person.ROLE.ADVISOR, matchPositionName: true } + }, + activePrincipals: { + label: "All principals", + queryVars: { role: Models.Person.ROLE.PRINCIPAL } + } +} + +const widgetPropsReport = { + objectType: Models.Report, + overlayRenderRow: ReportDetailedOverlayRow, + overlayColumns: ["Goal", "Author", "Updated"], + filterDefs: entityFilters, + queryParams: {}, + fields: Models.Report.autocompleteQuery, + addon: REPORTS_ICON +} + +const widgetPropsPeople = { + objectType: Models.Person, + overlayRenderRow: PersonDetailedOverlayRow, + overlayColumns: ["Name", "Position", "Location", "Organization"], + filterDefs: peopleFilters, + queryParams: {}, + fields: Models.Person.autocompleteQueryWithNotes, + addon: PEOPLE_ICON +} + +const widgetPropsOrganization = { + objectType: Models.Organization, + overlayRenderRow: OrganizationOverlayRow, + overlayColumns: ["Name"], + filterDefs: entityFilters, + queryParams: {}, + fields: Models.Organization.autocompleteQuery, + addon: ORGANIZATIONS_ICON +} + +const widgetPropsPosition = { + objectType: Models.Position, + overlayRenderRow: PositionOverlayRow, + overlayColumns: ["Position", "Organization", "Current Occupant"], + filterDefs: entityFilters, + queryParams: {}, + fields: Models.Position.autocompleteQuery, + addon: POSITIONS_ICON +} + +const widgetPropsLocation = { + objectType: Models.Location, + overlayRenderRow: LocationOverlayRow, + overlayColumns: ["Name"], + filterDefs: entityFilters, + queryParams: { status: Models.Location.STATUS.ACTIVE }, + fields: Models.Location.autocompleteQuery, + addon: LOCATIONS_ICON +} + +const widgetPropsTask = { + objectType: Models.Task, + overlayRenderRow: TaskSimpleOverlayRow, + overlayColumns: ["Name"], + filterDefs: entityFilters, + queryParams: { status: Models.Task.STATUS.ACTIVE }, + fields: Models.Task.autocompleteQueryWithNotes, + addon: TASKS_ICON +} + +const widgetTypeMapping = { + [ENTITY_TYPES.REPORTS]: widgetPropsReport, + [ENTITY_TYPES.PEOPLE]: widgetPropsPeople, + [ENTITY_TYPES.ORGANIZATIONS]: widgetPropsOrganization, + [ENTITY_TYPES.POSITIONS]: widgetPropsPosition, + [ENTITY_TYPES.LOCATIONS]: widgetPropsLocation, + [ENTITY_TYPES.TASKS]: widgetPropsTask +} + +const MultiTypeAdvancedSelectComponent = ({ + onConfirm, + objectType: entityTypeArg +}) => { + const [entityType, setEntityType] = useState(entityTypeArg) + const [advancedSelectProps, setAdvancedSelectProps] = useState( + widgetTypeMapping[entityType] + ) + function changeEntityType(newEntityType) { + setEntityType(newEntityType) + setAdvancedSelectProps(widgetTypeMapping[newEntityType]) + } + let searchPlaceholder = "" + return ( + <> + + {Object.entries(ENTITY_TYPES).map((key, value) => { + const entityName = key[1] + const entityLabel = SEARCH_OBJECT_LABELS[SEARCH_OBJECT_TYPES[key[0]]] + if (entityName === entityType) { + searchPlaceholder = "Find " + entityLabel.toLowerCase() + } + return ( + + ) + })} + + + onConfirm(value, entityType)} + objectType={advancedSelectProps.objectType} + queryParams={advancedSelectProps.queryParams} + fields={advancedSelectProps.fields} + addon={advancedSelectProps.addon} + /> + + ) +} + +MultiTypeAdvancedSelectComponent.propTypes = { + onConfirm: PropTypes.func, + objectType: PropTypes.string +} +MultiTypeAdvancedSelectComponent.defaultProps = { + objectType: ENTITY_TYPES.REPORTS +} + +export default MultiTypeAdvancedSelectComponent diff --git a/client/src/components/aggregations/AggregationWidgetContainer.js b/client/src/components/aggregations/AggregationWidgetContainer.js new file mode 100644 index 0000000000..e745e11d89 --- /dev/null +++ b/client/src/components/aggregations/AggregationWidgetContainer.js @@ -0,0 +1,215 @@ +import CalendarWidget from "components/aggregations/CalendarWidget" +import DefaultAggWidget from "components/aggregations/DefaultAggWidget" +import LikertScaleAndPieWidget from "components/aggregations/LikertScaleAndPieWidget" +import PieWidget from "components/aggregations/PieWidget" +import ReportsByTaskWidget from "components/aggregations/ReportsByTaskWidget" +import ReportsMapWidget from "components/aggregations/ReportsMapWidget" +import { + countPerDateAggregation, + countPerValueAggregation, + likertScaleAndPieAggregation, + numbersListAggregation, + objectsListAggregation, + reportsByTaskAggregation, + valuesListAggregation +} from "components/aggregations/utils" +import { + getFieldPropsFromFieldConfig, + SPECIAL_WIDGET_TYPES +} from "components/CustomFields" +import IqrBoxPlot from "components/graphs/IqrBoxPlot" +import LikertScale from "components/graphs/LikertScale" +import { CUSTOM_FIELD_TYPE } from "components/Model" +import { AssessmentPeriodPropType, PeriodPropType } from "periodUtils" +import PropTypes from "prop-types" +import React from "react" +import { Col, ControlLabel, FormGroup } from "react-bootstrap" +import utils from "utils" + +export const AGGERGATION_WIDGET_TYPE = { + LIKERT_SCALE: "likertScale", + PIE: "pie", + LIKERT_SCALE_AND_PIE: "likertScaleAndPie", + REPORTS_BY_TASK: "reportsByTask", + IQR_BOX_PLOT: "iqrBoxPlot", + CALENDAR: "calendar", + REPORTS_MAP: "reportsMap", + DEFAULT: "default" +} + +const AGGREGATION_WIDGET_COMPONENTS = { + [AGGERGATION_WIDGET_TYPE.LIKERT_SCALE]: LikertScale, + [AGGERGATION_WIDGET_TYPE.PIE]: PieWidget, + [AGGERGATION_WIDGET_TYPE.LIKERT_SCALE_AND_PIE]: LikertScaleAndPieWidget, + [AGGERGATION_WIDGET_TYPE.IQR_BOX_PLOT]: IqrBoxPlot, + [AGGERGATION_WIDGET_TYPE.REPORTS_BY_TASK]: ReportsByTaskWidget, + [AGGERGATION_WIDGET_TYPE.REPORTS_MAP]: ReportsMapWidget, + [AGGERGATION_WIDGET_TYPE.CALENDAR]: CalendarWidget, + [AGGERGATION_WIDGET_TYPE.DEFAULT]: DefaultAggWidget +} + +const DEFAULT_AGGREGATION_WIDGET_PER_FIELD_TYPE = { + [CUSTOM_FIELD_TYPE.TEXT]: AGGERGATION_WIDGET_TYPE.DEFAULT, + [CUSTOM_FIELD_TYPE.NUMBER]: AGGERGATION_WIDGET_TYPE.IQR_BOX_PLOT, + [CUSTOM_FIELD_TYPE.DATE]: AGGERGATION_WIDGET_TYPE.CALENDAR, + [CUSTOM_FIELD_TYPE.DATETIME]: AGGERGATION_WIDGET_TYPE.CALENDAR, + [CUSTOM_FIELD_TYPE.ENUM]: AGGERGATION_WIDGET_TYPE.PIE, + [CUSTOM_FIELD_TYPE.ENUMSET]: AGGERGATION_WIDGET_TYPE.PIE, + [CUSTOM_FIELD_TYPE.SPECIAL_FIELD]: { + [SPECIAL_WIDGET_TYPES.LIKERT_SCALE]: + AGGERGATION_WIDGET_TYPE.LIKERT_SCALE_AND_PIE, + [SPECIAL_WIDGET_TYPES.RICH_TEXT_EDITOR]: AGGERGATION_WIDGET_TYPE.DEFAULT + } +} + +export const AGGREGATION_TYPE = { + REPORTS_BY_TASK: "countReportsByTask", + COUNT_PER_DATE: "countPerDate", + COUNT_PER_VALUE: "countPerValue", + NUMBERS_LIST: "numbersList", + VALUES_LIST: "valuesList", + OBJECTS_LIST: "objectsList", + LIKERT_SCALE_AND_PIE_AGG: "likertScaleAndPieAgg" +} + +const DEFAULT_AGGREGATION_TYPE_PER_WIDGET_TYPE = { + [AGGERGATION_WIDGET_TYPE.LIKERT_SCALE]: AGGREGATION_TYPE.VALUES_LIST, + [AGGERGATION_WIDGET_TYPE.PIE]: AGGREGATION_TYPE.COUNT_PER_VALUE, + [AGGERGATION_WIDGET_TYPE.LIKERT_SCALE_AND_PIE]: + AGGREGATION_TYPE.LIKERT_SCALE_AND_PIE_AGG, + [AGGERGATION_WIDGET_TYPE.REPORTS_BY_TASK]: AGGREGATION_TYPE.REPORTS_BY_TASK, + [AGGERGATION_WIDGET_TYPE.REPORTS_MAP]: AGGREGATION_TYPE.OBJECTS_LIST, + [AGGERGATION_WIDGET_TYPE.IQR_BOX_PLOT]: AGGREGATION_TYPE.NUMBERS_LIST, + [AGGERGATION_WIDGET_TYPE.CALENDAR]: AGGREGATION_TYPE.COUNT_PER_DATE, + [AGGERGATION_WIDGET_TYPE.DEFAULT]: AGGREGATION_TYPE.VALUES_LIST +} + +const AGGREGATION_TYPE_FUNCTION = { + [AGGREGATION_TYPE.REPORTS_BY_TASK]: reportsByTaskAggregation, + [AGGREGATION_TYPE.COUNT_PER_VALUE]: countPerValueAggregation, + [AGGREGATION_TYPE.COUNT_PER_DATE]: countPerDateAggregation, + [AGGREGATION_TYPE.NUMBERS_LIST]: numbersListAggregation, + [AGGREGATION_TYPE.VALUES_LIST]: valuesListAggregation, + [AGGREGATION_TYPE.OBJECTS_LIST]: objectsListAggregation, + [AGGREGATION_TYPE.LIKERT_SCALE_AND_PIE_AGG]: likertScaleAndPieAggregation +} + +export const getAggregationWidget = ( + fieldConfig, + defaultWidgetPerFieldType = DEFAULT_AGGREGATION_WIDGET_PER_FIELD_TYPE, + ignoreFieldConfigWidget = false +) => { + const widget = !ignoreFieldConfigWidget && fieldConfig.aggregation?.widget + const defaultWidget = defaultWidgetPerFieldType[fieldConfig.type] + const defaultWidgetIsObject = typeof defaultWidget === "object" + return ( + widget || + (defaultWidget && + defaultWidgetIsObject && + defaultWidget[fieldConfig.widget]) || + (!defaultWidgetIsObject && defaultWidget) || + null + ) +} + +const getAggregationFunction = (fieldConfig, aggregationWidget) => { + const aggregationType = + fieldConfig.aggregation?.aggregationType || + DEFAULT_AGGREGATION_TYPE_PER_WIDGET_TYPE[aggregationWidget] + return AGGREGATION_TYPE_FUNCTION[aggregationType] +} + +const AggregationWidgetContainer = ({ + data, + fieldConfig, + fieldName, + period, + vertical, + widget, + widgetId, + ...otherWidgetProps +}) => { + const WHEN_UNSPECIFIED = ( +
+ Not specified +
+ ) + const aggregationWidget = widget || getAggregationWidget(fieldConfig) + const aggregationFunction = getAggregationFunction( + fieldConfig, + aggregationWidget + ) + if (!aggregationFunction) { + return null + } + + const { values, ...otherAggregationDetails } = aggregationFunction( + fieldName, + fieldConfig, + data + ) + const fieldProps = getFieldPropsFromFieldConfig(fieldConfig) + let label = fieldProps.label + // label not provided, calculate it from fieldName, which is a required prop + // (label of null would mean we don't want to display a label) + if (label === undefined) { + label = utils.sentenceCase(fieldName) + } + const WidgetComponent = + (aggregationWidget && AGGREGATION_WIDGET_COMPONENTS[aggregationWidget]) || + AGGREGATION_WIDGET_COMPONENTS.default + if (WidgetComponent === ReportsMapWidget) { + otherWidgetProps.mapId = `map-${widgetId}` + } + const widgetElem = ( + + ) + return ( + +
+ {vertical ? ( + <> + {label !== null && {label}} + {widgetElem} + + ) : ( + <> + {label !== null && ( + + {label} + + )} + +
{widgetElem}
+ + + )} +
+
+ ) +} +AggregationWidgetContainer.propTypes = { + data: PropTypes.any, + fieldConfig: PropTypes.object.isRequired, + fieldName: PropTypes.string.isRequired, + period: PropTypes.oneOfType([AssessmentPeriodPropType, PeriodPropType]), + vertical: PropTypes.bool, + widget: PropTypes.string, + widgetId: PropTypes.string.isRequired +} +AggregationWidgetContainer.defaultProps = { + vertical: true, + widget: "" +} + +export default AggregationWidgetContainer diff --git a/client/src/components/aggregations/CalendarWidget.js b/client/src/components/aggregations/CalendarWidget.js new file mode 100644 index 0000000000..f8bf8586e5 --- /dev/null +++ b/client/src/components/aggregations/CalendarWidget.js @@ -0,0 +1,80 @@ +import "@fullcalendar/core/main.css" +import dayGridPlugin from "@fullcalendar/daygrid" +import "@fullcalendar/daygrid/main.css" +import FullCalendar from "@fullcalendar/react" +import { + aggregationWidgetDefaultProps, + aggregationWidgetPropTypes +} from "components/aggregations/utils" +import _isEmpty from "lodash/isEmpty" +import PropTypes from "prop-types" +import React, { useRef } from "react" + +const DATE_FORMAT = "YYYY-MM-DD" + +const CalendarWidget = ({ + values, + fieldConfig, + fieldName, + period, + whenUnspecified, + hasPrevNext, + ...otherWidgetProps +}) => { + const calendarComponentRef = useRef(null) + const events = Object.entries(Object.without(values, null)).map( + ([key, value]) => { + return { + title: `${value} events`, + start: key, + end: key + } + } + ) + if (_isEmpty(events)) { + return whenUnspecified + } + return ( + + ) +} +CalendarWidget.propTypes = { + hasPrevNext: PropTypes.bool, + ...aggregationWidgetPropTypes +} +CalendarWidget.defaultProps = { + hasPrevNext: false, + ...aggregationWidgetDefaultProps +} + +export default CalendarWidget diff --git a/client/src/components/aggregations/DefaultAggWidget.js b/client/src/components/aggregations/DefaultAggWidget.js new file mode 100644 index 0000000000..0de8a94d91 --- /dev/null +++ b/client/src/components/aggregations/DefaultAggWidget.js @@ -0,0 +1,47 @@ +import { + aggregationWidgetDefaultProps, + aggregationWidgetPropTypes +} from "components/aggregations/utils" +import _isEmpty from "lodash/isEmpty" +import _uniqueId from "lodash/uniqueId" +import React, { useState } from "react" +import { Button, Collapse, Table } from "react-bootstrap" +import utils from "utils" + +const DefaultAggWidget = ({ values, whenUnspecified, ...otherWidgetProps }) => { + const [showValues, setShowValues] = useState(false) + const filteredValues = values.filter(value => !utils.isNullOrUndefined(value)) + if (_isEmpty(filteredValues)) { + return whenUnspecified + } + return ( +
+ + + + + {filteredValues.map(val => { + const keyValue = _uniqueId("value_") + return ( + + + + ) + })} + +
{JSON.stringify(val)}
+
+
+ ) +} +DefaultAggWidget.propTypes = aggregationWidgetPropTypes +DefaultAggWidget.defaultProps = aggregationWidgetDefaultProps + +export default DefaultAggWidget diff --git a/client/src/components/aggregations/LikertScaleAndPieWidget.js b/client/src/components/aggregations/LikertScaleAndPieWidget.js new file mode 100644 index 0000000000..5a4cc0c492 --- /dev/null +++ b/client/src/components/aggregations/LikertScaleAndPieWidget.js @@ -0,0 +1,46 @@ +import { + aggregationWidgetDefaultProps, + aggregationWidgetPropTypes +} from "components/aggregations/utils" +import PieWidget from "components/aggregations/PieWidget" +import LikertScale from "components/graphs/LikertScale" +import _isEmpty from "lodash/isEmpty" +import React from "react" + +const LikertScaleAndPieWidget = ({ values, ...otherWidgetProps }) => { + const { likertScaleValues, pieValues } = values + return ( +
+
+ +
+ {!_isEmpty(likertScaleValues) && ( +
+ +
+ )} +
+ ) +} +LikertScaleAndPieWidget.propTypes = aggregationWidgetPropTypes +LikertScaleAndPieWidget.defaultProps = aggregationWidgetDefaultProps + +export default LikertScaleAndPieWidget diff --git a/client/src/components/aggregations/PieWidget.js b/client/src/components/aggregations/PieWidget.js new file mode 100644 index 0000000000..3a72f6f166 --- /dev/null +++ b/client/src/components/aggregations/PieWidget.js @@ -0,0 +1,48 @@ +import { + aggregationWidgetDefaultProps, + aggregationWidgetPropTypes +} from "components/aggregations/utils" +import Pie from "components/graphs/Pie" +import PropTypes from "prop-types" +import React from "react" + +const PieWidget = ({ + values, + entitiesCount, + legend, + showLegend = true, + ...otherWidgetProps +}) => { + return ( + <> + legend[entity.data.key]?.color} + segmentLabel={d => d.data.value} + /> + {showLegend && ( +
+ {Object.map(legend, (key, choice) => ( + + + {choice.label}{" "} + + + ))} +
+ )} + + ) +} +PieWidget.propTypes = { + entitiesCount: PropTypes.number, + legend: PropTypes.object, + showLegend: PropTypes.bool, + ...aggregationWidgetPropTypes +} +PieWidget.defaultProps = aggregationWidgetDefaultProps + +export default PieWidget diff --git a/client/src/components/aggregations/ReportsByTaskWidget.js b/client/src/components/aggregations/ReportsByTaskWidget.js new file mode 100644 index 0000000000..b0ddc5418d --- /dev/null +++ b/client/src/components/aggregations/ReportsByTaskWidget.js @@ -0,0 +1,27 @@ +import { + aggregationWidgetDefaultProps, + aggregationWidgetPropTypes +} from "components/aggregations/utils" +import BarChart from "components/BarChart" +import _uniqueId from "lodash/uniqueId" +import React from "react" + +const ReportsByTaskWidget = ({ values, ...otherWidgetProps }) => ( +
+ ` +

${d.task.shortName}

+

${d.reportsCount}

+ `} + /> +
+) +ReportsByTaskWidget.propTypes = aggregationWidgetPropTypes +ReportsByTaskWidget.defaultProps = aggregationWidgetDefaultProps + +export default ReportsByTaskWidget diff --git a/client/src/components/aggregations/ReportsMapWidget.js b/client/src/components/aggregations/ReportsMapWidget.js new file mode 100644 index 0000000000..6d05414346 --- /dev/null +++ b/client/src/components/aggregations/ReportsMapWidget.js @@ -0,0 +1,65 @@ +import { + aggregationWidgetDefaultProps, + aggregationWidgetPropTypes +} from "components/aggregations/utils" +import Leaflet from "components/Leaflet" +import _escape from "lodash/escape" +import _isEmpty from "lodash/isEmpty" +import { Location } from "models" +import PropTypes from "prop-types" +import React, { useMemo } from "react" + +const ReportsMapWidget = ({ + values, + mapId, + width, + height, + whenUnspecified, + ...otherWidgetProps +}) => { + const markers = useMemo(() => { + if (!values.length) { + return [] + } + const markerArray = [] + values.forEach(report => { + if (Location.hasCoordinates(report.location)) { + let label = _escape(report.intent || "") // escape HTML in intent! + label += `
@ ${_escape(report.location.name)}` // escape HTML in locationName! + markerArray.push({ + id: report.uuid, + lat: report.location.lat, + lng: report.location.lng, + name: label + }) + } + }) + return markerArray + }, [values]) + if (_isEmpty(markers)) { + return whenUnspecified + } + return ( +
+ +
+ ) +} +ReportsMapWidget.propTypes = { + ...aggregationWidgetPropTypes, + mapId: PropTypes.string, + width: PropTypes.number, + height: PropTypes.number +} +ReportsMapWidget.defaultProps = { + values: [], + ...aggregationWidgetDefaultProps +} + +export default ReportsMapWidget diff --git a/client/src/components/aggregations/utils.js b/client/src/components/aggregations/utils.js new file mode 100644 index 0000000000..94f3aacb55 --- /dev/null +++ b/client/src/components/aggregations/utils.js @@ -0,0 +1,190 @@ +import _clone from "lodash/clone" +import _isEmpty from "lodash/isEmpty" +import moment from "moment" +import { AssessmentPeriodPropType, PeriodPropType } from "periodUtils" +import PropTypes from "prop-types" +import Settings from "settings" + +export const aggregationWidgetPropTypes = { + values: PropTypes.oneOfType([ + PropTypes.object, + PropTypes.arrayOf( + PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number, + PropTypes.array, + PropTypes.object + ]) + ) + ]), + fieldConfig: PropTypes.object, + fieldName: PropTypes.string, + vertical: PropTypes.bool, + period: PropTypes.oneOfType([AssessmentPeriodPropType, PeriodPropType]), + whenUnspecified: PropTypes.oneOfType([PropTypes.string, PropTypes.object]) +} +export const aggregationWidgetDefaultProps = { + whenUnspecified: null +} + +export const countPerDateAggregation = (fieldName, fieldConfig, data) => { + const values = data.reduce((counter, entity) => { + const dateFieldValue = Object.get(entity, fieldName) + const value = dateFieldValue + ? moment(dateFieldValue).format("YYYY-MM-DD") + : null + counter[value] = ++counter[value] || 1 + return counter + }, {}) + return { values: values } +} + +// TODO: maybe use a library for a list of colors +// For now, used this list of colors: https://gist.github.com/mikebmou/1323655 +const CHART_COLORS = [ + "#3366cc", + "#dc3912", + "#ff9900", + "#109618", + "#990099", + "#0099c6", + "#dd4477", + "#66aa00", + "#b82e2e", + "#316395", + "#3366cc", + "#994499", + "#22aa99", + "#aaaa11", + "#6633cc", + "#e67300", + "#8b0707", + "#651067", + "#329262", + "#5574a6", + "#3b3eac", + "#b77322", + "#16d620", + "#b91383", + "#f4359e", + "#9c5935", + "#a9c413", + "#2a778d", + "#668d1c", + "#bea413", + "#0c5922", + "#743411" +] + +export const countPerValueAggregation = (fieldName, fieldConfig, data) => { + const counters = data.reduce((counter, entity) => { + const value = Object.get(entity, fieldName) || null + const values = Array.isArray(value) ? value : [value] + values.forEach(choice => (counter[choice] = ++counter[choice] || 1)) + return counter + }, {}) + const legendColors = _clone(CHART_COLORS) + const legend = fieldConfig?.choices || {} + const legendKeys = !_isEmpty(legend) + ? Object.keys(legend) + : Object.keys(counters) + legendKeys.forEach( + key => + (legend[key] = { + label: legend[key]?.label || key, + color: legend[key]?.color || legendColors.shift() + }) + ) + legend.null = { label: "Unspecified", color: "#bbbbbb" } + return { values: counters, entitiesCount: data.length, legend: legend } +} + +const arrayOfNumbers = arr => + arr.filter(n => !isNaN(parseFloat(n)) && isFinite(n)).map(n => Number(n)) + +export const numbersListAggregation = (fieldName, fieldConfig, data) => { + const values = data.map(item => Object.get(item, fieldName)) + const numberValues = arrayOfNumbers(values) + return { values: numberValues } +} + +const noTaskMessage = `No ${Settings.fields.task.subLevel.shortLabel}` +const noTask = { + uuid: "-1", + shortName: noTaskMessage, + longName: noTaskMessage +} + +export const getReportsByTasks = reportsList => { + if (_isEmpty(reportsList)) { + return [] + } + const simplifiedValues = reportsList.map(d => { + return { reportUuid: d.uuid, tasks: d.tasks.map(p => p.uuid) } + }) + let tasks = reportsList.map(d => d.tasks) + tasks = [].concat + .apply([], tasks) + .filter( + (item, index, d) => + d.findIndex(t => { + return t.uuid === item.uuid + }) === index + ) + .sort((a, b) => a.shortName.localeCompare(b.shortName)) + // add No Task item, in order to relate to reports without Tasks + tasks.push(noTask) + return tasks.map(d => ({ + task: d, + reportsCount: + d.uuid === noTask.uuid + ? simplifiedValues.filter(item => _isEmpty(item.tasks)).length + : simplifiedValues.filter(item => item.tasks.indexOf(d.uuid) > -1) + .length + })) +} + +export const reportsByTaskAggregation = (fieldName, fieldConfig, data) => ({ + values: getReportsByTasks(data) +}) + +export const valuesListAggregation = (fieldName, fieldConfig, data) => ({ + values: data.map(item => Object.get(item, fieldName)) +}) + +export const objectsListAggregation = (fieldName, fieldConfig, data) => ({ + values: data +}) + +export const countPerLevelAggregation = (fieldName, fieldConfig, data) => { + const levels = fieldConfig.levels + if (_isEmpty(levels)) { + return null + } + const levelsEndValues = levels.map(level => level.endValue) + levelsEndValues.sort((a, b) => a - b) + const counters = data.reduce((counter, entity) => { + const value = Object.get(entity, fieldName) || null + const levelEndValue = + value !== null + ? levelsEndValues.filter(endVal => endVal >= value)[0] + : null + counter[levelEndValue] = ++counter[levelEndValue] || 1 + return counter + }, {}) + const legend = levels.reduce((res, level) => { + res[level.endValue] = level + return res + }, {}) + legend.null = { label: "Unspecified", color: "#bbbbbb" } + return { values: counters, entitiesCount: data.length, legend: legend } +} + +export const likertScaleAndPieAggregation = (fieldName, fieldConfig, data) => { + return { + values: { + likertScaleValues: valuesListAggregation(fieldName, fieldConfig, data), + pieValues: countPerLevelAggregation(fieldName, fieldConfig, data) + } + } +} diff --git a/client/src/components/approvals/ApprovalsDefinition.js b/client/src/components/approvals/ApprovalsDefinition.js index 7b682a97c1..d6b7002a58 100644 --- a/client/src/components/approvals/ApprovalsDefinition.js +++ b/client/src/components/approvals/ApprovalsDefinition.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import AdvancedMultiSelect from "components/advancedSelectWidget/AdvancedMultiSelect" import { ApproverOverlayRow } from "components/advancedSelectWidget/AdvancedSelectOverlayRow" import * as FieldHelper from "components/FieldHelper" diff --git a/client/src/components/assessments/AddAssessmentModal.js b/client/src/components/assessments/AddAssessmentModal.js deleted file mode 100644 index 1a10cf7e3c..0000000000 --- a/client/src/components/assessments/AddAssessmentModal.js +++ /dev/null @@ -1,141 +0,0 @@ -import API from "api" -import { - CustomFieldsContainer, - customFieldsJSONString -} from "components/CustomFields" -import Model, { GQL_CREATE_NOTE, NOTE_TYPE } from "components/Model" -import Messages from "components/Messages" -import { Form, Formik } from "formik" -import { Task } from "models" -import PropTypes from "prop-types" -import React, { useMemo, useState } from "react" -import { Button, Modal } from "react-bootstrap" - -const AddAssessmentModal = ({ - entity, - entityType, - yupSchema, - assessmentConfig, - title, - showModal, - onCancel, - onSuccess -}) => { - const [assessmentError, setAssessmentError] = useState(null) - const initialValues = useMemo(() => Model.fillObject({}, yupSchema), [ - yupSchema - ]) - return ( - - - {({ - isSubmitting, - isValid, - setFieldValue, - setFieldTouched, - validateForm, - values, - submitForm - }) => { - return ( -
- - {title} - - -
- - -
-
- - - - -
- ) - }} -
-
- ) - - function closeModal() { - setAssessmentError(null) - onCancel() - } - - function onAssessmentSubmit(values, form) { - return saveAssessment(values, form) - .then(response => onSubmitSuccess(response, values, form)) - .catch(error => { - setAssessmentError(error) - form.setSubmitting(false) - }) - } - - function onSubmitSuccess(response, values, form) { - onSuccess() - } - - function saveAssessment(values, form) { - const updatedNote = { - type: NOTE_TYPE.ASSESSMENT, - noteRelatedObjects: [ - { - relatedObjectType: entityType.relatedObjectType, - relatedObjectUuid: entity.uuid - } - ] - } - updatedNote.text = customFieldsJSONString(values, true, "entityAssessment") - return API.mutation(GQL_CREATE_NOTE, { - note: updatedNote - }) - } -} -AddAssessmentModal.propTypes = { - entity: PropTypes.oneOfType([PropTypes.instanceOf(Task)]).isRequired, - entityType: PropTypes.func.isRequired, - yupSchema: PropTypes.object.isRequired, - assessmentConfig: PropTypes.object.isRequired, - title: PropTypes.string, - showModal: PropTypes.bool, - onCancel: PropTypes.func.isRequired, - onSuccess: PropTypes.func.isRequired -} -AddAssessmentModal.defaultProps = { - title: "Assessment", - showModal: false -} - -export default AddAssessmentModal diff --git a/client/src/components/assessments/AssessmentModal.js b/client/src/components/assessments/AssessmentModal.js new file mode 100644 index 0000000000..2c37b1c216 --- /dev/null +++ b/client/src/components/assessments/AssessmentModal.js @@ -0,0 +1,168 @@ +import API from "api" +import { + CustomFieldsContainer, + customFieldsJSONString +} from "components/CustomFields" +import Model, { + ENTITY_ASSESSMENT_PARENT_FIELD, + GQL_CREATE_NOTE, + GQL_UPDATE_NOTE +} from "components/Model" +import Messages from "components/Messages" +import { Form, Formik } from "formik" +import _cloneDeep from "lodash/cloneDeep" +import _isEmpty from "lodash/isEmpty" +import PropTypes from "prop-types" +import React, { useMemo, useState } from "react" +import { Button, Modal } from "react-bootstrap" + +const AssessmentModal = ({ + showModal, + note, + assessment, + assessmentYupSchema, + assessmentConfig, + assessmentPeriod, + recurrence, + title, + onSuccess, + onCancel +}) => { + const [assessmentError, setAssessmentError] = useState(null) + const edit = !!note.uuid + const initialValues = useMemo( + () => + _isEmpty(assessment) + ? Model.fillObject({}, assessmentYupSchema) + : { [ENTITY_ASSESSMENT_PARENT_FIELD]: assessment }, + [assessment, assessmentYupSchema] + ) + return ( + <> + + + {({ + isSubmitting, + isValid, + setFieldValue, + setFieldTouched, + validateForm, + values, + submitForm + }) => { + return ( +
+ + {title} + + +
+ + +
+
+ + + + +
+ ) + }} +
+
+ + ) + + function closeModal() { + setAssessmentError(null) + onCancel() + } + + function onAssessmentSubmit(values, form) { + return saveAssessment(values, form) + .then(response => onSubmitSuccess(response, values, form)) + .catch(error => { + setAssessmentError(error) + form.setSubmitting(false) + }) + } + + function onSubmitSuccess(response, values, form) { + const operation = edit ? "updateNote" : "createNote" + onSuccess(response[operation]) + } + + function saveAssessment(values, form) { + const noteRelatedObjects = note.noteRelatedObjects.map(o => ({ + relatedObjectType: o.relatedObjectType, + relatedObjectUuid: o.relatedObjectUuid + })) + const updatedNote = { + uuid: note.uuid, + author: note.author, + type: note.type, + noteRelatedObjects + } + // values contains the assessment fields + const clonedValues = _cloneDeep(values) + clonedValues[ENTITY_ASSESSMENT_PARENT_FIELD].__recurrence = recurrence + clonedValues[ENTITY_ASSESSMENT_PARENT_FIELD].__periodStart = + assessmentPeriod.start + updatedNote.text = customFieldsJSONString( + clonedValues, + true, + ENTITY_ASSESSMENT_PARENT_FIELD + ) + return API.mutation(edit ? GQL_UPDATE_NOTE : GQL_CREATE_NOTE, { + note: updatedNote + }) + } +} +AssessmentModal.propTypes = { + showModal: PropTypes.bool, + note: Model.notePropType, + assessment: PropTypes.object, + assessmentYupSchema: PropTypes.object.isRequired, + assessmentConfig: PropTypes.object.isRequired, + assessmentPeriod: PropTypes.object.isRequired, + recurrence: PropTypes.string.isRequired, + title: PropTypes.string, + onSuccess: PropTypes.func.isRequired, + onCancel: PropTypes.func.isRequired +} +AssessmentModal.defaultProps = { + showModal: false, + title: "Assessment" +} + +export default AssessmentModal diff --git a/client/src/components/assessments/AssessmentResultsContainer.js b/client/src/components/assessments/AssessmentResultsContainer.js new file mode 100644 index 0000000000..9a28247399 --- /dev/null +++ b/client/src/components/assessments/AssessmentResultsContainer.js @@ -0,0 +1,49 @@ +import AssessmentResultsTable from "components/assessments/AssessmentResultsTable" +import Model from "components/Model" +import { PERIOD_FACTORIES } from "periodUtils" +import PropTypes from "prop-types" +import React from "react" + +const AssessmentResultsContainer = ({ + entity, + entityType, + subEntities, + canAddAssessment, + onUpdateAssessment +}) => { + if (!entity) { + return null + } + const assessmentsTypes = Object.keys(entity.getAssessmentsConfig()) + return ( + <> + {assessmentsTypes.map( + assessmentsType => + PERIOD_FACTORIES[assessmentsType] && ( + + ) + )} + + ) +} +AssessmentResultsContainer.propTypes = { + entity: PropTypes.instanceOf(Model), + entityType: PropTypes.func.isRequired, + subEntities: PropTypes.array, + onUpdateAssessment: PropTypes.func.isRequired, + canAddAssessment: PropTypes.bool +} + +export default AssessmentResultsContainer diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index 306a5c1e59..20bd9368b6 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -1,259 +1,85 @@ -import AggregationWidget from "components/AggregationWidget" -import AddAssessmentModal from "components/assessments/AddAssessmentModal" -import { - getFieldPropsFromFieldConfig, - ReadonlyCustomFields -} from "components/CustomFields" +import { PeriodicAssessmentsRows } from "components/assessments/PeriodicAssessmentResults" +import { InstantAssessmentsRow } from "components/assessments/InstantAssessmentResults" import Fieldset from "components/Fieldset" -import { Formik } from "formik" import LinkTo from "components/LinkTo" +import PeriodsNavigation from "components/PeriodsNavigation" import _isEmpty from "lodash/isEmpty" +import { + AssessmentPeriodsConfigPropType, + getPeriodsConfig, + PeriodsDetailsPropType, + PeriodsTableHeader +} from "periodUtils" import PropTypes from "prop-types" import React, { useState } from "react" -import { Button, Table } from "react-bootstrap" +import { Table } from "react-bootstrap" import "components/assessments/AssessmentResultsTable.css" /* The AssessmentResultsTable component displays the results of two types of * assessments made on a given entity and subentities: - * - aggregation of the measurements made on the entity/subentities when + * - instant assessments => made on the entity/subentities when * working on them in relation to another type of entity (example: - * assessments made on tasks, while filling report related to the tasks); - * the definition of these assessments is to be found in - * entity.customFields.assessmentDefinition - * - display of the last monthly assessment made on the entity/subentities - * as a conclusion about the given period of time; - * the definition of these assessments is to be found in - * entity.periodAssessmentConfig() + * assessments made on tasks, while filling report related to the tasks) or + * assessments made on the entity/subentity itself; + * the configuration of these assessments can be retrieved using + * entity.getInstantAssessmentConfig() + * - periodic assessments => made on the entity/subentities periodically, + * as a measurement of the given period of time; + * the config and yupSchema for these assessments is to be found in + * entity.getPeriodicAssessmentDetails(recurrence) */ -const PERIOD_FORMAT = "MMM-YYYY" - -const AssessmentsTableHeader = ({ periods }) => ( - - - <> - {periods.map(period => ( - {period.start.format(PERIOD_FORMAT)} - ))} - - - -) -AssessmentsTableHeader.propTypes = { - periods: PropTypes.array -} - -const MeasurementRow = ({ - measurementKey, - measurementDef, - entity, - assessmentPeriods -}) => { - const aggWidgetProps = { - widget: measurementDef.aggregation?.widget || measurementDef.widget, - aggregationType: measurementDef.aggregation?.aggregationType, - vertical: true - } - const fieldProps = getFieldPropsFromFieldConfig(measurementDef) - return ( - - {assessmentPeriods.map((assessmentPeriod, index) => ( - - - - ))} - - ) -} -MeasurementRow.propTypes = { - entity: PropTypes.object, - assessmentPeriods: PropTypes.arrayOf( - PropTypes.shape({ - start: PropTypes.object, - end: PropTypes.object, - allowNewAssessments: PropTypes.bool - }) - ), - measurementKey: PropTypes.string, - measurementDef: PropTypes.object -} - -const MonthlyAssessmentRows = ({ - entity, - entityType, - assessmentPeriods, - canAddAssessment, - onAddAssessment -}) => { - const periodAssessmentConfig = entity.periodAssessmentConfig() - const [showAssessmentModal, setShowAssessmentModal] = useState(false) - const periodsLastAssessment = [] - const periodsAllowNewAssessment = [] - assessmentPeriods.forEach(period => { - // TODO: rethink assessments for a period: should we also save the period - // in the assessment? For now we assume that the dateRange is a month and - // that assessments for a given month will have been made in the next month. - periodsLastAssessment.push( - entity.getLastAssessment({ - start: period.start.clone().add(1, "months"), - end: period.start.clone().add(1, "months").endOf("month") - }) - ) - periodsAllowNewAssessment.push( - periodAssessmentConfig && canAddAssessment && period.allowNewAssessments - ) - }) - const hasLastAssessments = !_isEmpty( - periodsLastAssessment.filter(x => !_isEmpty(x)) - ) - const hasAddAssessment = !_isEmpty(periodsAllowNewAssessment.filter(x => x)) - return ( - <> - {hasLastAssessments && ( - - {periodsLastAssessment.map((lastAssessment, index) => { - const lastAssessmentPrefix = `lastAssessment-${entity.uuid}-${index}` - return ( - - {periodAssessmentConfig && lastAssessment && ( - - {({ values }) => ( - - )} - - )} - - ) - })} - - )} - {hasAddAssessment && ( - - {assessmentPeriods.map((period, index) => { - const assessmentLabelPrefix = periodsLastAssessment[index] - ? "Add a" - : "Make a new" - const addAssessmentLabel = `${assessmentLabelPrefix} ${entity?.toString()} assessment for the month of ${period.start.format( - PERIOD_FORMAT - )}` - return ( - - {periodsAllowNewAssessment[index] && ( - <> - - setShowAssessmentModal(false)} - onSuccess={() => { - setShowAssessmentModal(false) - onAddAssessment() - }} - /> - - )} - - ) - })} - - )} - - ) -} -MonthlyAssessmentRows.propTypes = { - entity: PropTypes.object, - entityType: PropTypes.func.isRequired, - assessmentPeriods: PropTypes.arrayOf( - PropTypes.shape({ - start: PropTypes.object, - end: PropTypes.object, - allowNewAssessments: PropTypes.bool - }) - ), - canAddAssessment: PropTypes.bool, - onAddAssessment: PropTypes.func -} - const EntityAssessmentResults = ({ entity, entityType, style, - assessmentPeriods, + periodsConfig, canAddAssessment, - onAddAssessment + onUpdateAssessment }) => { if (!entity) { return null } - const assessmentDefinition = JSON.parse( - JSON.parse(entity.customFields || "{}").assessmentDefinition || "{}" + const instantAssessmentConfig = entity.getInstantAssessmentConfig() + const { periods } = periodsConfig + const dataPerPeriod = [] + periods.forEach(period => + dataPerPeriod.push(entity.getInstantAssessmentResults(period)) ) return ( <> - - + + - {Object.keys(assessmentDefinition || {}).map(key => ( - ( + ))} - ) } EntityAssessmentResults.propTypes = { style: PropTypes.object, - entity: PropTypes.object, + entity: PropTypes.object.isRequired, entityType: PropTypes.func.isRequired, - assessmentPeriods: PropTypes.arrayOf( - PropTypes.shape({ - start: PropTypes.object, - end: PropTypes.object, - allowNewAssessments: PropTypes.bool - }) - ), - onAddAssessment: PropTypes.func, + periodsConfig: AssessmentPeriodsConfigPropType.isRequired, + onUpdateAssessment: PropTypes.func.isRequired, canAddAssessment: PropTypes.bool } @@ -262,58 +88,84 @@ const AssessmentResultsTable = ({ entityType, subEntities, style, - assessmentPeriods, + periodsDetails, canAddAssessment, - onAddAssessment + onUpdateAssessment }) => { + const [offset, setOffset] = useState(0) if (!entity) { return null } + const { recurrence, numberOfPeriods } = periodsDetails + const periodsConfig = getPeriodsConfig( + recurrence, + numberOfPeriods, + offset, + true + ) + if (_isEmpty(periodsConfig?.periods)) { + return null + } + const entityInstantAssessmentConfig = entity.getInstantAssessmentConfig() + const subentitiesInstantAssessmentConfig = subEntities + ?.map(s => s.getInstantAssessmentConfig()) + .filter(mc => !_isEmpty(mc)) + const { assessmentConfig } = entity.getPeriodicAssessmentDetails(recurrence) + const showAssessmentResults = + !_isEmpty(entityInstantAssessmentConfig) || + !_isEmpty(subentitiesInstantAssessmentConfig) || + !_isEmpty(assessmentConfig) return ( -
-
- - - - {!_isEmpty(subEntities) && ( - <> - {subEntities?.map(subEntity => ( - - ))} - - )} - - -
-
-
+ <> + {showAssessmentResults && ( +
+
+ + + + + <> + {subEntities?.map(subEntity => ( + + ))} + + + +
+
+
+ )} + ) } AssessmentResultsTable.propTypes = { style: PropTypes.object, - entity: PropTypes.object, + entity: PropTypes.object.isRequired, entityType: PropTypes.func.isRequired, subEntities: PropTypes.array, - assessmentPeriods: PropTypes.arrayOf( - PropTypes.shape({ - start: PropTypes.object, - end: PropTypes.object, - allowNewAssessments: PropTypes.bool - }) - ), - onAddAssessment: PropTypes.func, + periodsDetails: PeriodsDetailsPropType.isRequired, + onUpdateAssessment: PropTypes.func.isRequired, canAddAssessment: PropTypes.bool } diff --git a/client/src/components/assessments/InstantAssessmentResults.js b/client/src/components/assessments/InstantAssessmentResults.js new file mode 100644 index 0000000000..e66c1e22b2 --- /dev/null +++ b/client/src/components/assessments/InstantAssessmentResults.js @@ -0,0 +1,61 @@ +import AggregationWidgetContainer, { + getAggregationWidget +} from "components/aggregations/AggregationWidgetContainer" +import _isEmpty from "lodash/isEmpty" +import _uniqueId from "lodash/uniqueId" +import { PeriodsPropType } from "periodUtils" +import PropTypes from "prop-types" +import React from "react" + +/* The InstantAssessmentsRow component displays the results of the aggregation + * of the assessments made on a given question (as part of the instant + * assessments made on a given entity), grouped per period of time: + * - instant assessments => made on the entity/subentities when + * working on them in relation to another type of entity (example: + * assessments made on tasks, while filling report related to the tasks) or + * assessments made on the entity/subentity itself; + */ + +export const InstantAssessmentsRow = ({ + questionKey, + questionConfig, + entity, + periods, + periodsData, + isFirstRow +}) => { + const aggregationWidget = getAggregationWidget(questionConfig) + if (_isEmpty(periods) || !aggregationWidget) { + return null + } + return ( + + {periods.map((period, index) => ( + + {_isEmpty(periodsData[index]) ? ( + isFirstRow ? ( + No assessments + ) : null + ) : ( + + )} + + ))} + + ) +} +InstantAssessmentsRow.propTypes = { + entity: PropTypes.object.isRequired, + periods: PeriodsPropType.isRequired, + periodsData: PropTypes.arrayOf(PropTypes.array).isRequired, + questionKey: PropTypes.string.isRequired, + questionConfig: PropTypes.object.isRequired, + isFirstRow: PropTypes.bool +} diff --git a/client/src/components/assessments/InstantAssessmentsContainerField.js b/client/src/components/assessments/InstantAssessmentsContainerField.js new file mode 100644 index 0000000000..0f6fdc20fe --- /dev/null +++ b/client/src/components/assessments/InstantAssessmentsContainerField.js @@ -0,0 +1,81 @@ +import { + CustomFieldsContainer, + ReadonlyCustomFields +} from "components/CustomFields" +import LinkTo from "components/LinkTo" +import Model from "components/Model" +import _isEmpty from "lodash/isEmpty" +import PropTypes from "prop-types" +import React from "react" +import { Table } from "react-bootstrap" + +const InstantAssessmentsContainerField = ({ + entityType, + entities, + entitiesInstantAssessmentsConfig, + parentFieldName, + formikProps, + readonly +}) => { + const { values } = formikProps + return ( + + + {entities.map(entity => { + const entityInstantAssessmentConfig = !_isEmpty( + entitiesInstantAssessmentsConfig + ) + ? entitiesInstantAssessmentsConfig[entity.uuid] + : entity.getInstantAssessmentConfig() + if (!entityInstantAssessmentConfig) { + return null + } + return ( + + + + + + + + + ) + })} + +
+ +
+ {readonly ? ( + + ) : ( + + )} +
+ ) +} +InstantAssessmentsContainerField.propTypes = { + entityType: PropTypes.func.isRequired, + entities: PropTypes.arrayOf(PropTypes.instanceOf(Model)), + entitiesInstantAssessmentsConfig: PropTypes.object, + parentFieldName: PropTypes.string.isRequired, + formikProps: PropTypes.shape({ + setFieldTouched: PropTypes.func, + setFieldValue: PropTypes.func, + values: PropTypes.object.isRequired, + validateForm: PropTypes.func + }), + readonly: PropTypes.bool +} +InstantAssessmentsContainerField.defaultProps = { + entities: [], + readonly: false +} +export default InstantAssessmentsContainerField diff --git a/client/src/components/assessments/PeriodicAssessmentResults.js b/client/src/components/assessments/PeriodicAssessmentResults.js new file mode 100644 index 0000000000..ca04436bda --- /dev/null +++ b/client/src/components/assessments/PeriodicAssessmentResults.js @@ -0,0 +1,260 @@ +import { Icon } from "@blueprintjs/core" +import { IconNames } from "@blueprintjs/icons" +import AppContext from "components/AppContext" +import AssessmentModal from "components/assessments/AssessmentModal" +import { ReadonlyCustomFields } from "components/CustomFields" +import { Formik } from "formik" +import LinkTo from "components/LinkTo" +import Model, { NOTE_TYPE } from "components/Model" +import _isEmpty from "lodash/isEmpty" +import { Person } from "models" +import moment from "moment" +import { + AssessmentPeriodPropType, + AssessmentPeriodsConfigPropType, + periodToString +} from "periodUtils" +import PropTypes from "prop-types" +import React, { useContext, useState } from "react" +import { Button, Panel } from "react-bootstrap" + +const PeriodicAssessment = ({ + assessment, + assessmentYupSchema, + assessmentConfig, + note, + entity, + period, + recurrence, + onUpdateAssessment +}) => { + const { currentUser } = useContext(AppContext) + const [showAssessmentModalKey, setShowAssessmentModalKey] = useState(null) + + const byMe = Person.isEqual(currentUser, note.author) + const parentFieldName = `assessment-${note.uuid}` + const periodDisplay = periodToString(period) + + return ( + + + <> + {moment(note.updatedAt).fromNow()}{" "} + + {byMe && ( + <> + + { + setShowAssessmentModalKey(null) + onUpdateAssessment() + }} + onCancel={() => setShowAssessmentModalKey(null)} + /> + + )} + + + +
+ + {({ values }) => { + return ( + + ) + }} + +
+
+
+ ) +} +PeriodicAssessment.propTypes = { + assessment: PropTypes.object.isRequired, + assessmentConfig: PropTypes.object.isRequired, + assessmentYupSchema: PropTypes.object.isRequired, + note: Model.notePropType.isRequired, + entity: PropTypes.object.isRequired, + period: AssessmentPeriodPropType.isRequired, + recurrence: PropTypes.string.isRequired, + onUpdateAssessment: PropTypes.func.isRequired +} + +export const PeriodicAssessmentsRows = ({ + entity, + entityType, + periodsConfig, + canAddAssessment, + onUpdateAssessment +}) => { + const { currentUser } = useContext(AppContext) + const [showAssessmentModalKey, setShowAssessmentModalKey] = useState(null) + const { recurrence, periods } = periodsConfig + if (_isEmpty(periods)) { + return null + } + + const { + assessmentConfig, + assessmentYupSchema + } = entity.getPeriodicAssessmentDetails(recurrence) + if (!assessmentConfig) { + return null + } + + const periodsAssessments = [] + const periodsAllowNewAssessment = [] + periods.forEach(period => { + const periodAssessments = entity.getPeriodAssessments( + recurrence, + period, + currentUser + ) + const myPeriodAssessments = periodAssessments.filter( + ({ note, assessment }) => Person.isEqual(currentUser, note.author) + ) + periodsAssessments.push(periodAssessments) + // Only allow adding new assessments for a period if the user has the rights + // for it, if the period is configured to allow adding new assessments and + // if the current user didn't already made an assessment for the period + periodsAllowNewAssessment.push( + canAddAssessment && + period.allowNewAssessments && + _isEmpty(myPeriodAssessments) + ) + }) + const hasPeriodicAssessmentsRow = !_isEmpty( + periodsAssessments.filter(x => !_isEmpty(x)) + ) + const hasAddAssessmentRow = !_isEmpty( + periodsAllowNewAssessment.filter(x => x) + ) + return ( + <> + {hasPeriodicAssessmentsRow && ( + + {periodsAssessments.map((periodAssessments, index) => { + return ( + + {periodAssessments && + periodAssessments.map(({ note, assessment }, i) => ( +
+ +
+ ))} + + ) + })} + + )} + {hasAddAssessmentRow && ( + + {periods.map((period, index) => { + const periodDisplay = periodToString(period) + const addAssessmentLabel = `Make a new ${entity?.toString()} assessment for ${periodDisplay}` + const modalKey = `${entity.uuid}-${periodDisplay}` + return ( + + {periodsAllowNewAssessment[index] && ( + <> + + { + setShowAssessmentModalKey(null) + onUpdateAssessment() + }} + onCancel={() => setShowAssessmentModalKey(null)} + /> + + )} + + ) + })} + + )} + + ) +} +PeriodicAssessmentsRows.propTypes = { + entity: PropTypes.object.isRequired, + entityType: PropTypes.func.isRequired, + periodsConfig: AssessmentPeriodsConfigPropType.isRequired, + canAddAssessment: PropTypes.bool, + onUpdateAssessment: PropTypes.func.isRequired +} diff --git a/client/src/components/editor/LinkAnetEntity.js b/client/src/components/editor/LinkAnetEntity.js index 52ab87e97a..8ab3a70f30 100644 --- a/client/src/components/editor/LinkAnetEntity.js +++ b/client/src/components/editor/LinkAnetEntity.js @@ -1,16 +1,18 @@ import LinkTo from "components/LinkTo" +import { GRAPHQL_ENTITY_FIELDS } from "components/Model" +import * as Models from "models" import PropTypes from "prop-types" import React, { useEffect, useState } from "react" -import { getEntityByUuid } from "utils_links" const LinkAnetEntity = ({ type, uuid, children }) => { const [entity, setEntity] = useState() useEffect(() => { - const response = getEntityByUuid(type, uuid) - if (response) { - response.then(data => setEntity(data)) - } + const modelClass = Models[type] + modelClass && + modelClass + .fetchByUuid(uuid, GRAPHQL_ENTITY_FIELDS) + .then(data => setEntity(data)) }, [type, uuid]) return ( diff --git a/client/src/components/editor/LinkSourceAnet.js b/client/src/components/editor/LinkSourceAnet.js index 01d1eb2e08..007e3945f4 100644 --- a/client/src/components/editor/LinkSourceAnet.js +++ b/client/src/components/editor/LinkSourceAnet.js @@ -1,126 +1,13 @@ -import { SEARCH_OBJECT_LABELS } from "actions" -import { - LocationOverlayRow, - OrganizationOverlayRow, - PersonDetailedOverlayRow, - PositionOverlayRow, - ReportDetailedOverlayRow, - TaskSimpleOverlayRow -} from "components/advancedSelectWidget/AdvancedSelectOverlayRow" -import AdvancedSingleSelect from "components/advancedSelectWidget/AdvancedSingleSelect" -import ButtonToggleGroup from "components/ButtonToggleGroup" import * as Models from "models" import PropTypes from "prop-types" -import React, { useState } from "react" -import { Button, Modal } from "react-bootstrap" -import LOCATIONS_ICON from "resources/locations.png" -import ORGANIZATIONS_ICON from "resources/organizations.png" -import PEOPLE_ICON from "resources/people.png" -import POSITIONS_ICON from "resources/positions.png" -import REPORTS_ICON from "resources/reports.png" -import TASKS_ICON from "resources/tasks.png" -import { ENTITY_TYPES } from "utils_links" +import React from "react" +import { Modal } from "react-bootstrap" import "./LinkSource.css" +import MultiTypeAdvancedSelectComponent from "components/advancedSelectWidget/MultiTypeAdvancedSelectComponent" import createEntity from "./utils/createEntity" -const entityFilters = { - allEntities: { - label: "All entities", - queryVars: {} - } -} - -const peopleFilters = { - allEntities: { - label: "All", - queryVars: { matchPositionName: true } - }, - activeAdvisors: { - label: "All advisors", - queryVars: { role: Models.Person.ROLE.ADVISOR, matchPositionName: true } - }, - activePrincipals: { - label: "All principals", - queryVars: { role: Models.Person.ROLE.PRINCIPAL } - } -} - -const widgetPropsReport = { - objectType: Models.Report, - overlayRenderRow: ReportDetailedOverlayRow, - overlayColumns: ["Goal", "Author", "Updated"], - filterDefs: entityFilters, - queryParams: {}, - fields: Models.Report.autocompleteQuery, - addon: REPORTS_ICON -} - -const widgetPropsPeople = { - objectType: Models.Person, - overlayRenderRow: PersonDetailedOverlayRow, - overlayColumns: ["Name", "Position", "Location", "Organization"], - filterDefs: peopleFilters, - queryParams: {}, - fields: Models.Person.autocompleteQuery, - addon: PEOPLE_ICON -} - -const widgetPropsOrganization = { - objectType: Models.Organization, - overlayRenderRow: OrganizationOverlayRow, - overlayColumns: ["Name"], - filterDefs: entityFilters, - queryParams: {}, - fields: Models.Organization.autocompleteQuery, - addon: ORGANIZATIONS_ICON -} - -const widgetPropsPosition = { - objectType: Models.Position, - overlayRenderRow: PositionOverlayRow, - overlayColumns: ["Position", "Organization", "Current Occupant"], - filterDefs: entityFilters, - queryParams: {}, - fields: Models.Position.autocompleteQuery, - addon: POSITIONS_ICON -} - -const widgetPropsLocation = { - objectType: Models.Location, - overlayRenderRow: LocationOverlayRow, - overlayColumns: ["Name"], - filterDefs: entityFilters, - queryParams: { status: Models.Location.STATUS.ACTIVE }, - fields: Models.Location.autocompleteQuery, - addon: LOCATIONS_ICON -} - -const widgetPropsTask = { - objectType: Models.Task, - overlayRenderRow: TaskSimpleOverlayRow, - overlayColumns: ["Name"], - filterDefs: entityFilters, - queryParams: { status: Models.Task.STATUS.ACTIVE }, - fields: Models.Task.autocompleteQuery, - addon: TASKS_ICON -} - -const widgetTypeMapping = { - [ENTITY_TYPES.REPORTS]: widgetPropsReport, - [ENTITY_TYPES.PEOPLE]: widgetPropsPeople, - [ENTITY_TYPES.ORGANIZATIONS]: widgetPropsOrganization, - [ENTITY_TYPES.POSITIONS]: widgetPropsPosition, - [ENTITY_TYPES.LOCATIONS]: widgetPropsLocation, - [ENTITY_TYPES.TASKS]: widgetPropsTask -} - const LinkSourceAnet = ({ editorState, entityType, onComplete, onClose }) => { - const [objectType, setObjectType] = useState(ENTITY_TYPES.REPORTS) - const [advancedSelectProps, setAdvancedSelectProps] = useState( - widgetTypeMapping[objectType] - ) - - function onConfirm(value) { + function onConfirm(value, objectType) { // Retrieve entity URL and label const ModelClass = Models[objectType] const modelInstance = new ModelClass(value) @@ -140,49 +27,14 @@ const LinkSourceAnet = ({ editorState, entityType, onComplete, onClose }) => { onComplete(nextState) } - function changeObjectType(newObjectType) { - setObjectType(newObjectType) - setAdvancedSelectProps(widgetTypeMapping[newObjectType]) - } - return ( Link to ANET entity - - - {Object.entries(ENTITY_TYPES).map((key, value) => { - const entityName = key[1] - const entityLabel = SEARCH_OBJECT_LABELS[key[0]] - return ( - - ) - })} - + - - - onConfirm(value)} - objectType={advancedSelectProps.objectType} - queryParams={advancedSelectProps.queryParams} - fields={advancedSelectProps.fields} - addon={advancedSelectProps.addon} - /> - ) } diff --git a/client/src/components/graphs/IqrBoxPlot.js b/client/src/components/graphs/IqrBoxPlot.js new file mode 100644 index 0000000000..5fb2560b82 --- /dev/null +++ b/client/src/components/graphs/IqrBoxPlot.js @@ -0,0 +1,133 @@ +import { TRAFFIC_LIGHTS_LEVELS } from "components/graphs/utils" +import * as d3 from "d3" +import _isEmpty from "lodash/isEmpty" +import PropTypes from "prop-types" +import React, { useEffect, useRef } from "react" +import useDimensions from "react-use-dimensions" + +const IqrBoxPlot = ({ values, levels, width, height, whenUnspecified }) => { + const cursorRef = useRef(null) + const axisRef = useRef(null) + const [containerRef, containerBox] = useDimensions() + const containerHeight = containerBox.height || 0 + const containerWidth = containerBox.width || 0 + const MARGIN = 13 + const scaleYPosition = containerHeight - 30 + + const sortedValues = values.sort((a, b) => a - b) + const valuesStats = { + min: Math.min(...values), + max: Math.max(...values), + q1: getQuartile(sortedValues, 1), + q2: getQuartile(sortedValues, 2), + q3: getQuartile(sortedValues, 3) + } + + function getQuartile(sortedData, quartileNumber) { + const index = quartileNumber * (sortedData.length / 4) + const idx = Math.floor(index) + return idx === index + ? (sortedData[idx - 1] + sortedData[idx]) / 2 + : sortedData[idx] + } + + const scale = d3 + .scaleLinear() + .domain([valuesStats.min, valuesStats.max]) + .range([MARGIN, containerWidth - 2 * MARGIN]) + const x = scale(50) + + useEffect(() => { + d3.select(cursorRef.current).attr( + "transform", + `translate(${x} ${scaleYPosition})` + ) + }, [x, scaleYPosition]) + + useEffect(() => { + const axis = d3.axisBottom(scale) + d3.select(axisRef.current).call(axis) + }, [scale]) + + const fillColor = d3.color("lightGray") + fillColor.opacity = 0.4 + + if (_isEmpty(values)) { + return whenUnspecified + } + return ( + + {values?.length > 1 && ( + + + + + + + + + )} + + + ) +} + +IqrBoxPlot.propTypes = { + values: PropTypes.arrayOf(PropTypes.number), + levels: PropTypes.arrayOf( + PropTypes.shape({ + color: PropTypes.string, + endValue: PropTypes.number.isRequired, + tooltip: PropTypes.string, + label: PropTypes.string + }) + ).isRequired, + width: PropTypes.string.isRequired, + height: PropTypes.string.isRequired, + whenUnspecified: PropTypes.oneOfType([PropTypes.string, PropTypes.object]) +} + +IqrBoxPlot.defaultProps = { + levels: TRAFFIC_LIGHTS_LEVELS, + height: "65", + width: "100%", + whenUnspecified: null +} + +export default IqrBoxPlot diff --git a/client/src/components/graphs/LikertScale.js b/client/src/components/graphs/LikertScale.js index 59f0cb3f1f..d506e8191b 100644 --- a/client/src/components/graphs/LikertScale.js +++ b/client/src/components/graphs/LikertScale.js @@ -1,8 +1,11 @@ -import React, { useEffect, useRef } from "react" +import { TRAFFIC_LIGHTS_LEVELS } from "components/graphs/utils" import * as d3 from "d3" +import _isEmpty from "lodash/isEmpty" import PropTypes from "prop-types" +import React, { useCallback, useEffect, useRef } from "react" import Text from "react-svg-text" import useDimensions from "react-use-dimensions" +import utils from "utils" const LikertScale = ({ onChange, @@ -11,7 +14,8 @@ const LikertScale = ({ levels, width, height, - readonly + editable, + whenUnspecified }) => { const cursorRef = useRef(null) const axisRef = useRef(null) @@ -19,30 +23,50 @@ const LikertScale = ({ const containerHeight = containerBox.height || 0 const containerWidth = containerBox.width || 0 const containerX = containerBox.x || 0 - const MARGIN = 13 + const MARGIN_LEFT = editable ? 25 : 13 + const MARGIN_RIGHT = 13 const scaleYPosition = containerHeight - 30 - const scale = d3 .scaleLinear() .domain([0, 10]) - .range([MARGIN, containerWidth - 2 * MARGIN]) - const x = scale(Number(value !== undefined ? value : 50)) + .range([MARGIN_LEFT, containerWidth - MARGIN_RIGHT]) + const x = utils.isNumeric(value) ? scale(value) : MARGIN_LEFT / 2 + + const calculateNewX = useCallback( + eventX => { + return Math.min( + Math.max(eventX, scale.range()[0] - MARGIN_LEFT / 2), + scale.range()[1] + ) + }, + [scale, MARGIN_LEFT] + ) + + const xToValue = useCallback( + newX => (newX >= scale.range()[0] ? scale.invert(newX) : null), + [scale] + ) useEffect(() => { - if (readonly) { + if (!editable) { return } const handleDrag = d3.drag().on("drag", function() { const me = d3.select(cursorRef.current) - const newX = Math.min( - Math.max(d3.event.x, scale.range()[0]), - scale.range()[1] - ) + const newX = calculateNewX(d3.event.x) me.attr("transform", `translate(${newX} ${scaleYPosition})`) - onChange(scale.invert(newX)) + onChange(xToValue(newX)) }) handleDrag(d3.select(cursorRef.current)) - }, [onChange, scale, scaleYPosition, readonly]) + }, [ + onChange, + scale, + scaleYPosition, + editable, + MARGIN_LEFT, + calculateNewX, + xToValue + ]) useEffect(() => { d3.select(cursorRef.current).attr( @@ -58,25 +82,31 @@ const LikertScale = ({ let activeColor = null let valuesStats = null - if (values?.length) { + const numberValues = utils.arrayOfNumbers(values) + if (numberValues !== undefined && _isEmpty(numberValues)) { + return whenUnspecified + } + if (numberValues?.length) { valuesStats = { - min: Math.min(...values), - max: Math.max(...values), - avg: values.reduce((a, b) => a + b, 0) / values.length + min: Math.min(...numberValues), + max: Math.max(...numberValues), + avg: numberValues.reduce((a, b) => a + b, 0) / numberValues.length } valuesStats.avgColor = levels.find( level => level.endValue > valuesStats.avg )?.color } - return ( - !readonly && e.clientX && onChange(scale.invert(e.clientX - containerX))} + onClick={e => { + if (editable && e.clientX) { + const newX = calculateNewX(e.clientX - containerX) + onChange(xToValue(newX)) + } + }} > {levels.map((level, index) => { const startX = scale(index === 0 ? 0 : levels[index - 1].endValue) @@ -108,7 +138,7 @@ const LikertScale = ({ ) })} - {values?.map((xValue, index) => ( + {numberValues?.map((xValue, index) => ( ))} - {values?.length > 1 && ( + {numberValues?.length > 1 && ( )} - {values?.length > 0 && ( + {numberValues?.length > 0 && ( - avg:{" "} - {Number(valuesStats.avg).toFixed(value < scale.domain()[1] ? 1 : 0)} + avg: {valuesStats.avg.toFixed(value < scale.domain()[1] ? 1 : 0)} )} - {onChange && ( + {onChange && (editable || (value && value >= scale.domain()[0])) && ( - {Number(value).toFixed(value < scale.domain()[1] ? 1 : 0)} + {utils.isNumeric(value) && value >= scale.domain()[0] + ? value.toFixed(value < scale.domain()[1] ? 1 : 0) + : null} )} @@ -201,7 +232,7 @@ const LikertScale = ({ LikertScale.propTypes = { value: PropTypes.number, values: PropTypes.arrayOf(PropTypes.number), - onChange: PropTypes.func, + onChange: utils.fnRequiredWhen.bind(null, "editable"), levels: PropTypes.arrayOf( PropTypes.shape({ color: PropTypes.string, @@ -212,27 +243,17 @@ LikertScale.propTypes = { ).isRequired, width: PropTypes.string.isRequired, height: PropTypes.string.isRequired, - readonly: PropTypes.bool + editable: PropTypes.bool, + whenUnspecified: PropTypes.oneOfType([PropTypes.string, PropTypes.object]) } LikertScale.defaultProps = { - value: 0, - levels: [ - { - color: "red", - endValue: 3 - }, - { - color: "#FFBF00", - endValue: 7 - }, - { - color: "green", - endValue: 10 - } - ], + value: null, + levels: TRAFFIC_LIGHTS_LEVELS, height: "65", - width: "100%" + width: "100%", + editable: false, + whenUnspecified: null } export default LikertScale diff --git a/client/src/components/graphs/OrganizationalChart.js b/client/src/components/graphs/OrganizationalChart.js index 7e41560e47..7eddb4bb00 100644 --- a/client/src/components/graphs/OrganizationalChart.js +++ b/client/src/components/graphs/OrganizationalChart.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import SVGCanvas from "components/graphs/SVGCanvas" import { PageDispatchersPropType, @@ -18,6 +18,7 @@ import DEFAULT_AVATAR from "resources/default_avatar.svg" import COLLAPSE_ICON from "resources/organizations.png" import EXPAND_ICON from "resources/plus.png" import Settings from "settings" +import utils from "utils" const GQL_GET_CHART_DATA = gql` query($uuid: String!) { @@ -91,7 +92,6 @@ const OrganizationalChart = ({ const [personnelDepth, setPersonnelDepth] = useState(5) const history = useHistory() const canvasRef = useRef(null) - const svgRef = useRef(null) const linkRef = useRef(null) const nodeRef = useRef(null) const tree = useRef(d3.tree()) @@ -373,7 +373,7 @@ const OrganizationalChart = ({ const result = `${d.person ? d.person.rank : ""} ${ d.person ? d.person.name : "unfilled" } ${d.name}` - return result.length > 31 ? result.substring(0, 28) + "..." : result + return utils.ellipsize(result, 31) }) }, [data, expanded, history, personnelDepth, root, link, node]) @@ -383,7 +383,6 @@ const OrganizationalChart = ({ return ( { +const SVGCanvas = ({ width, height, exportTitle, zoomFn, children }) => { + const svgRef = useRef(null) const exportSvg = () => { var svgBlob = new Blob( ['', svgRef.current.outerHTML], @@ -62,12 +56,7 @@ const SVGCanvas = ({ )} - + {children} @@ -79,7 +68,6 @@ SVGCanvas.propTypes = { height: PropTypes.number.isRequired, exportTitle: PropTypes.string, zoomFn: PropTypes.func, - svgRef: PropTypes.object.isRequired, children: PropTypes.node } diff --git a/client/src/components/graphs/utils.js b/client/src/components/graphs/utils.js new file mode 100644 index 0000000000..0a9b31334c --- /dev/null +++ b/client/src/components/graphs/utils.js @@ -0,0 +1,15 @@ +export const TRAFFIC_LIGHTS_LEVELS = [ + { + color: "red", + endValue: 3 + }, + { + // amber + color: "#FFBF00", + endValue: 7 + }, + { + color: "green", + endValue: 10 + } +] diff --git a/client/src/exportUtils.js b/client/src/exportUtils.js index b3b208ef30..45bd1ec1dc 100644 --- a/client/src/exportUtils.js +++ b/client/src/exportUtils.js @@ -1,6 +1,6 @@ +import { gql } from "@apollo/client" import { SEARCH_OBJECT_TYPES } from "actions" import API from "api" -import { gql } from "apollo-boost" import FileSaver from "file-saver" const GQL_GET_ORGANIZATION_LIST = gql` diff --git a/client/src/index.js b/client/src/index.js index fd584bc186..cea9bac3b8 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -1,4 +1,4 @@ -import { ApolloProvider } from "@apollo/react-hooks" +import { ApolloProvider } from "@apollo/client" import API from "api" import "bootstrap/dist/css/bootstrap.css" import { jumpToTop } from "components/Page" diff --git a/client/src/models/Person.js b/client/src/models/Person.js index 3950b02aee..4b0b0f6f33 100644 --- a/client/src/models/Person.js +++ b/client/src/models/Person.js @@ -1,4 +1,8 @@ -import Model, { createYupObjectShape, yupDate } from "components/Model" +import Model, { + createCustomFieldsSchema, + GRAPHQL_NOTES_FIELDS, + yupDate +} from "components/Model" import _isEmpty from "lodash/isEmpty" import { Organization, Position } from "models" import AFG_ICON from "resources/afg_small.png" @@ -30,8 +34,13 @@ export default class Person extends Model { static nameDelimiter = "," + static advisorAssessmentConfig = Settings.fields.advisor.person.assessments + + static principalAssessmentConfig = + Settings.fields.principal.person.assessments + // create yup schema for the customFields, based on the customFields config - static customFieldsSchema = createYupObjectShape( + static customFieldsSchema = createCustomFieldsSchema( Settings.fields.person.customFields ) @@ -142,15 +151,17 @@ export default class Person extends Model { status: yup .string() .nullable() - .default(() => Person.STATUS.ACTIVE), - // not actually in the database, the database contains the JSON customFields - formCustomFields: Person.customFieldsSchema.nullable() + .default(() => Person.STATUS.ACTIVE) }) + // not actually in the database, the database contains the JSON customFields + .concat(Person.customFieldsSchema) .concat(Model.yupSchema) static autocompleteQuery = "uuid, name, rank, role, status, endOfTourDate, avatar(size: 32), position { uuid, name, type, code, status, organization { uuid, shortName }, location {uuid, name} }" + static autocompleteQueryWithNotes = `${this.autocompleteQuery} ${GRAPHQL_NOTES_FIELDS}` + static humanNameOfRole(role) { if (role === Person.ROLE.ADVISOR) { return Settings.fields.advisor.person.name @@ -316,4 +327,14 @@ export default class Person extends Model { firstName: firstName.trim() } } + + generalAssessmentsConfig() { + let config + if (this.isAdvisor()) { + config = Person.advisorAssessmentConfig + } else if (this.isPrincipal()) { + config = Person.principalAssessmentConfig + } + return config || [] + } } diff --git a/client/src/models/Report.js b/client/src/models/Report.js index 95c3577de2..4f90c18b2b 100644 --- a/client/src/models/Report.js +++ b/client/src/models/Report.js @@ -1,5 +1,5 @@ import Model, { - createYupObjectShape, + createCustomFieldsSchema, NOTE_TYPE, yupDate } from "components/Model" @@ -26,12 +26,36 @@ export default class Report extends Model { CANCELLED: "CANCELLED" } + static STATE_LABELS = { + [Report.STATE.DRAFT]: "Draft", + [Report.STATE.PENDING_APPROVAL]: "Pending Approval", + [Report.STATE.APPROVED]: "Approved", + [Report.STATE.PUBLISHED]: "Published", + [Report.STATE.CANCELLED]: "Cancelled", + [Report.STATE.REJECTED]: "Changes requested" + } + + static STATE_COLORS = { + [Report.STATE.DRAFT]: "#bdbdaf", + [Report.STATE.PENDING_APPROVAL]: "#848478", + [Report.STATE.APPROVED]: "#75eb75", + [Report.STATE.PUBLISHED]: "#5cb85c", + [Report.STATE.CANCELLED]: "#ec971f", + [Report.STATE.REJECTED]: "#c23030" + } + static ENGAGEMENT_STATUS = { HAPPENED: "HAPPENED", FUTURE: "FUTURE", CANCELLED: "CANCELLED" } + static ENGAGEMENT_STATUS_LABELS = { + [Report.ENGAGEMENT_STATUS.HAPPENED]: "Happened", + [Report.ENGAGEMENT_STATUS.FUTURE]: "Future", + [Report.ENGAGEMENT_STATUS.CANCELLED]: "Cancelled" + } + static CANCELLATION_REASON = { CANCELLED_BY_ADVISOR: "CANCELLED_BY_ADVISOR", CANCELLED_BY_PRINCIPAL: "CANCELLED_BY_PRINCIPAL", @@ -49,8 +73,19 @@ export default class Report extends Model { NEUTRAL: "NEUTRAL" } + static ATMOSPHERE_LABELS = { + [Report.ATMOSPHERE.POSITIVE]: "Positive", + [Report.ATMOSPHERE.NEGATIVE]: "Negative", + [Report.ATMOSPHERE.NEUTRAL]: "Neutral" + } + + static TASKS_ASSESSMENTS_PARENT_FIELD = "tasksAssessments" + static TASKS_ASSESSMENTS_UUIDS_FIELD = "tasksAssessmentsUuids" + static ATTENDEES_ASSESSMENTS_PARENT_FIELD = "attendeesAssessments" + static ATTENDEES_ASSESSMENTS_UUIDS_FIELD = "attendeesAssessmentsUuids" + // create yup schema for the customFields, based on the customFields config - static customFieldsSchema = createYupObjectShape( + static customFieldsSchema = createCustomFieldsSchema( Settings.fields.report.customFields ) @@ -238,10 +273,10 @@ export default class Report extends Model { .default([]) .label(Settings.fields.report.reportTags), reportSensitiveInformation: yup.object().nullable().default({}), // null? - authorizationGroups: yup.array().nullable().default([]), - // not actually in the database, the database contains the JSON customFields - formCustomFields: Report.customFieldsSchema.nullable() + authorizationGroups: yup.array().nullable().default([]) }) + // not actually in the database, the database contains the JSON customFields + .concat(Report.customFieldsSchema) .concat(Model.yupSchema) static yupWarningSchema = yup.object().shape({ @@ -382,32 +417,53 @@ export default class Report extends Model { } } - getTaskAssessments() { + getRelatedObjectsEngagementAssessments( + entityType, + entitiesAssessmentsFieldName, + entitiesAssessmentsUuidsFieldName + ) { const notesToAssessments = this.notes .filter( - n => - n.type === NOTE_TYPE.ASSESSMENT && - n.noteRelatedObjects.filter( - ro => ro.relatedObjectType === Task.relatedObjectType - ).length + n => n.type === NOTE_TYPE.ASSESSMENT && n.noteRelatedObjects.length > 1 ) - .map(ta => ({ - taskUuid: [ - ta.noteRelatedObjects.filter( - ro => ro.relatedObjectType === Task.relatedObjectType - )[0].relatedObjectUuid - ], - assessmentUuid: ta.uuid, - assessment: JSON.parse(ta.text) + .map(n => ({ + entityUuids: n.noteRelatedObjects + .filter(ro => ro.relatedObjectType === entityType.relatedObjectType) + .map(ro => ro.relatedObjectUuid), + assessmentUuid: n.uuid, + assessment: utils.parseJsonSafe(n.text) })) - // When updating the assessments, we need for each task the uuid of the related assessment - const taskToAssessmentUuid = {} - // Get initial task assessments values - const taskAssessments = {} - notesToAssessments.forEach(ta => { - taskToAssessmentUuid[ta.taskUuid] = ta.assessmentUuid - taskAssessments[ta.taskUuid] = ta.assessment + .filter(n => !_isEmpty(n.entityUuids)) + // When updating the instant assessments, we need for each entity the uuid of the + // related instant assessment + const entitiesAssessmentsUuids = {} + // Get initial entities assessments values + const entitiesAssessments = {} + notesToAssessments.forEach(m => { + m.entityUuids.forEach(entityUuid => { + entitiesAssessmentsUuids[entityUuid] = m.assessmentUuid + entitiesAssessments[entityUuid] = m.assessment + }) }) - return { taskToAssessmentUuid, taskAssessments } + return { + [entitiesAssessmentsUuidsFieldName]: entitiesAssessmentsUuids, + [entitiesAssessmentsFieldName]: entitiesAssessments + } + } + + getTasksEngagementAssessments() { + return this.getRelatedObjectsEngagementAssessments( + Task, + Report.TASKS_ASSESSMENTS_PARENT_FIELD, + Report.TASKS_ASSESSMENTS_UUIDS_FIELD + ) + } + + getAttendeesEngagementAssessments() { + return this.getRelatedObjectsEngagementAssessments( + Person, + Report.ATTENDEES_ASSESSMENTS_PARENT_FIELD, + Report.ATTENDEES_ASSESSMENTS_UUIDS_FIELD + ) } } diff --git a/client/src/models/Tag.js b/client/src/models/Tag.js index ac713f4b0b..58f109a1fa 100644 --- a/client/src/models/Tag.js +++ b/client/src/models/Tag.js @@ -11,7 +11,7 @@ export default class Tag extends Model { ...Model.schema } - static autocompleteQuery = "uuid, name" + static autocompleteQuery = "uuid, name, description" toString() { return this.name diff --git a/client/src/models/Task.js b/client/src/models/Task.js index 47285fd128..aa584ba62b 100644 --- a/client/src/models/Task.js +++ b/client/src/models/Task.js @@ -1,25 +1,14 @@ import Model, { - createYupObjectShape, - NOTE_TYPE, + createCustomFieldsSchema, + GRAPHQL_NOTES_FIELDS, yupDate } from "components/Model" import _isEmpty from "lodash/isEmpty" -import { Report } from "models" import TASKS_ICON from "resources/tasks.png" import Settings from "settings" import utils from "utils" import * as yup from "yup" -function createTaskAssessmentSchema(customFieldsConfig) { - const taskAssessmentSchemaShape = createYupObjectShape( - customFieldsConfig, - "entityAssessment" - ) - return yup.object().shape({ - entityAssessment: taskAssessmentSchemaShape - }) -} - export const { shortLabel, longLabel, @@ -53,18 +42,10 @@ export default class Task extends Model { } // create yup schema for the customFields, based on the customFields config - static customFieldsSchema = createYupObjectShape( + static customFieldsSchema = createCustomFieldsSchema( Settings.fields.task.customFields ) - static topLevelAssessmentCustomFieldsSchema = createTaskAssessmentSchema( - Settings.fields.task.topLevel.assessment.customFields - ) - - static subLevelAssessmentCustomFieldsSchema = createTaskAssessmentSchema( - Settings.fields.task.subLevel.assessment.customFields - ) - static yupSchema = yup .object() .shape({ @@ -163,15 +144,17 @@ export default class Task extends Model { }) ) .nullable() - .default([]), - // not actually in the database, the database contains the JSON customFields - formCustomFields: Task.customFieldsSchema.nullable() + .default([]) }) + // not actually in the database, the database contains the JSON customFields + .concat(Task.customFieldsSchema) .concat(Model.yupSchema) static autocompleteQuery = "uuid, shortName, longName, customFieldRef1 { uuid, shortName } taskedOrganizations { uuid, shortName }, customFields" + static autocompleteQueryWithNotes = `${this.autocompleteQuery} ${GRAPHQL_NOTES_FIELDS}` + static humanNameOfStatus(status) { return utils.sentenceCase(status) } @@ -190,16 +173,6 @@ export default class Task extends Model { : Settings.fields.task.subLevel } - periodAssessmentYupSchema() { - return this.isTopLevelTask() - ? Task.topLevelAssessmentCustomFieldsSchema - : Task.subLevelAssessmentCustomFieldsSchema - } - - periodAssessmentConfig() { - return this.fieldSettings().assessment?.customFields - } - iconUrl() { return TASKS_ICON } @@ -208,49 +181,12 @@ export default class Task extends Model { return `${this.shortName}` } - getAssessmentResults(dateRange) { - const publishedReportsUuids = this.publishedReports.map(r => r.uuid) - const taskAssessmentNotes = this.notes - .filter( - n => - n.type === NOTE_TYPE.ASSESSMENT && - n.noteRelatedObjects.length === 2 && - n.noteRelatedObjects.filter( - ro => - ro.relatedObjectType === Report.relatedObjectType && - publishedReportsUuids.includes(ro.relatedObjectUuid) - ).length && - (!dateRange || - (n.createdAt <= dateRange.end && n.createdAt >= dateRange.start)) - ) - .map(ta => JSON.parse(ta.text)) - const assessmentResults = {} - taskAssessmentNotes.forEach(o => - Object.keys(o).forEach(k => { - if (!Object.prototype.hasOwnProperty.call(assessmentResults, k)) { - assessmentResults[k] = [] - } - assessmentResults[k].push(o[k]) - }) - ) - return assessmentResults + generalAssessmentsConfig() { + return this.fieldSettings().assessments || [] } - getLastAssessment(dateRange) { - const notesToAssessments = this.notes - .filter(n => { - return ( - n.type === NOTE_TYPE.ASSESSMENT && - n.noteRelatedObjects.length === 1 && - (!dateRange || - (n.createdAt <= dateRange.end && n.createdAt >= dateRange.start)) - ) - }) - .sort((a, b) => b.createdAt - a.createdAt) // desc sorted - .map(ta => ({ - uuid: ta.uuid, - assessment: JSON.parse(ta.text) - })) - return notesToAssessments.length ? notesToAssessments[0].assessment : null + instanceAssessmentsConfig() { + // The given task instance might have a specific assessments config + return utils.parseJsonSafe(this.customFields).assessments || [] } } diff --git a/client/src/pages/App.js b/client/src/pages/App.js index b6c23bd63b..3802b26ba8 100644 --- a/client/src/pages/App.js +++ b/client/src/pages/App.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import AppContext from "components/AppContext" import Messages from "components/Messages" import { diff --git a/client/src/pages/GraphiQL.js b/client/src/pages/GraphiQL.js index 6693cf7590..85b0d64dc0 100644 --- a/client/src/pages/GraphiQL.js +++ b/client/src/pages/GraphiQL.js @@ -1,6 +1,6 @@ +import { gql } from "@apollo/client" import { DEFAULT_SEARCH_PROPS, PAGE_PROPS_NO_NAV } from "actions" import API from "api" -import { gql } from "apollo-boost" import { PageDispatchersPropType, mapPageDispatchersToProps, diff --git a/client/src/pages/Help.js b/client/src/pages/Help.js index 88dad5c6d2..5a47659635 100644 --- a/client/src/pages/Help.js +++ b/client/src/pages/Help.js @@ -1,6 +1,6 @@ +import { gql } from "@apollo/client" import { DEFAULT_PAGE_PROPS, DEFAULT_SEARCH_PROPS } from "actions" import API from "api" -import { gql } from "apollo-boost" import AppContext from "components/AppContext" import Fieldset from "components/Fieldset" import { @@ -10,7 +10,7 @@ import { } from "components/Page" import { Person, Position } from "models" import PropTypes from "prop-types" -import React from "react" +import React, { useContext } from "react" import { connect } from "react-redux" import TOUR_SCREENSHOT from "resources/tour-screenshot.png" import Settings from "settings" @@ -37,14 +37,15 @@ const screenshotCss = { boxShadow: "0px 0px 10px #aaa" } -const BaseHelp = ({ appSettings, currentUser, pageDispatchers }) => { +const Help = ({ pageDispatchers }) => { + const { appSettings, currentUser } = useContext(AppContext) if ( currentUser.uuid && currentUser.position && currentUser.position.organization ) { return ( - { ) } return ( - { ) } -BaseHelp.propTypes = { - appSettings: PropTypes.object, - currentUser: PropTypes.instanceOf(Person), +Help.propTypes = { pageDispatchers: PageDispatchersPropType } -const BaseHelpFetchSuperUsers = ({ +const HelpFetchSuperUsers = ({ orgUuid, appSettings, currentUser, @@ -84,7 +83,7 @@ const BaseHelpFetchSuperUsers = ({ positionQuery }) return ( - ( - - {context => ( - - )} - -) - export default connect(null, mapPageDispatchersToProps)(Help) diff --git a/client/src/pages/Home.js b/client/src/pages/Home.js index 304d72731b..a4a35c5d49 100644 --- a/client/src/pages/Home.js +++ b/client/src/pages/Home.js @@ -1,3 +1,4 @@ +import { gql } from "@apollo/client" import { DEFAULT_PAGE_PROPS, DEFAULT_SEARCH_PROPS, @@ -5,7 +6,6 @@ import { setSearchQuery } from "actions" import API from "api" -import { gql } from "apollo-boost" import AppContext from "components/AppContext" import ConfirmDelete from "components/ConfirmDelete" import Fieldset from "components/Fieldset" @@ -24,7 +24,7 @@ import _isEmpty from "lodash/isEmpty" import { Person, Report } from "models" import { superUserTour, userTour } from "pages/HopscotchTour" import PropTypes from "prop-types" -import React, { useState } from "react" +import React, { useContext, useState } from "react" import { Button, ControlLabel, @@ -37,6 +37,7 @@ import { connect } from "react-redux" import { useHistory, useLocation } from "react-router-dom" import { deserializeQueryParams } from "searchUtils" import Settings from "settings" +import utils from "utils" const GQL_GET_SAVED_SEARCHES = gql` query { @@ -369,7 +370,7 @@ const SavedSearches = ({ setSearchQuery, pageDispatchers }) => { function showSearch() { if (selectedSearch) { const objType = SEARCH_OBJECT_TYPES[selectedSearch.objectType] - const queryParams = JSON.parse(selectedSearch.query) + const queryParams = utils.parseJsonSafe(selectedSearch.query) deserializeQueryParams(objType, queryParams, deserializeCallback) } } @@ -401,7 +402,8 @@ SavedSearches.propTypes = { pageDispatchers: PageDispatchersPropType } -const BaseHome = ({ currentUser, setSearchQuery, pageDispatchers }) => { +const Home = ({ setSearchQuery, pageDispatchers }) => { + const { currentUser } = useContext(AppContext) const routerLocation = useLocation() const stateSuccess = routerLocation.state && routerLocation.state.success const alertStyle = { top: 132, marginBottom: "1rem", textAlign: "center" } @@ -472,9 +474,8 @@ const BaseHome = ({ currentUser, setSearchQuery, pageDispatchers }) => { ) } -BaseHome.propTypes = { +Home.propTypes = { setSearchQuery: PropTypes.func.isRequired, - currentUser: PropTypes.instanceOf(Person), pageDispatchers: PageDispatchersPropType } @@ -486,10 +487,4 @@ const mapDispatchToProps = (dispatch, ownProps) => { } } -const Home = props => ( - - {context => } - -) - export default connect(null, mapDispatchToProps)(Home) diff --git a/client/src/pages/Routing.js b/client/src/pages/Routing.js index c89c60710c..bfdff6a9e2 100644 --- a/client/src/pages/Routing.js +++ b/client/src/pages/Routing.js @@ -1,11 +1,11 @@ import AppContext from "components/AppContext" -import { Person } from "models" import AuthorizationGroupEdit from "pages/admin/authorizationgroup/Edit" import AuthorizationGroupNew from "pages/admin/authorizationgroup/New" import AuthorizationGroupShow from "pages/admin/authorizationgroup/Show" import AuthorizationGroups from "pages/admin/AuthorizationGroups" import AdminIndex from "pages/admin/Index" import MergePeople from "pages/admin/MergePeople" +import BoardDashboard from "pages/dashboards/BoardDashboard" import DecisivesDashboard from "pages/dashboards/DecisivesDashboard" import KanbanDashboard from "pages/dashboards/KanbanDashboard" import GraphiQL from "pages/GraphiQL" @@ -38,154 +38,159 @@ import TaskEdit from "pages/tasks/Edit" import TaskNew from "pages/tasks/New" import TaskShow from "pages/tasks/Show" import { PAGE_URLS } from "pages/util" -import PropTypes from "prop-types" -import React from "react" +import React, { useContext } from "react" import { Redirect, Route, Switch } from "react-router-dom" -const BaseRouting = ({ currentUser }) => ( - - - - - - - ( - - - - - - - - )} - /> - ( - - - - - - )} - /> - ( - - - - - - )} - /> - ( - - - - - - )} - /> - ( - - - - - - )} - /> - ( - - - - - - )} - /> - ( - - - - - - - - - )} - /> - ( - - - - )} - /> - ( - - - - )} - /> - ( - - - +const Routing = () => { + const { currentUser } = useContext(AppContext) + return ( + + + + + + ( + + + + + + + + )} + /> + ( + + + + + + )} + /> + ( + + + + + + )} + /> + ( + + + + + + )} + /> + ( + + + + + + )} + /> + ( + + + + + + )} + /> + {currentUser.isAdmin() && ( + ( + + + + + + + + + + )} + /> )} - /> - - currentUser.isNewUser() ? ( + ( - - + - ) : ( - // Redirect to home if user account exists already. Some users bookmark the onboarding - the very first page they hit - )} - /> - - -) - -BaseRouting.propTypes = { - currentUser: PropTypes.instanceOf(Person) + /> + ( + + + + )} + /> + ( + + + + )} + /> + ( + + + + )} + /> + + currentUser.isNewUser() ? ( + + + + + ) : ( + // Redirect to home if user account exists already. Some users bookmark the onboarding - the very first page they hit + + )} + /> + + + ) } -const Routing = props => ( - - {context => } - -) - export default Routing diff --git a/client/src/pages/Search.js b/client/src/pages/Search.js index 01100c2758..d2a1c1a1a6 100644 --- a/client/src/pages/Search.js +++ b/client/src/pages/Search.js @@ -1,3 +1,4 @@ +import { gql } from "@apollo/client" import { DEFAULT_PAGE_PROPS, DEFAULT_SEARCH_PROPS, @@ -6,7 +7,6 @@ import { setPagination } from "actions" import API from "api" -import { gql } from "apollo-boost" import * as FieldHelper from "components/FieldHelper" import Fieldset from "components/Fieldset" import LinkTo from "components/LinkTo" @@ -19,7 +19,13 @@ import { useBoilerplate } from "components/Page" import PositionTable from "components/PositionTable" -import ReportCollection from "components/ReportCollection" +import ReportCollection, { + FORMAT_CALENDAR, + FORMAT_MAP, + FORMAT_STATISTICS, + FORMAT_SUMMARY, + FORMAT_TABLE +} from "components/ReportCollection" import { SearchDescription, SearchQueryPropType, @@ -893,6 +899,13 @@ const Search = ({ queryParams={reportsSearchQueryParams} setTotalCount={setNumReports} paginationKey="SEARCH_reports" + viewFormats={[ + FORMAT_SUMMARY, + FORMAT_TABLE, + FORMAT_CALENDAR, + FORMAT_MAP, + FORMAT_STATISTICS + ]} />
)} diff --git a/client/src/pages/admin/AuthorizationGroups.js b/client/src/pages/admin/AuthorizationGroups.js index 3d44d0c3ab..b6130637e8 100644 --- a/client/src/pages/admin/AuthorizationGroups.js +++ b/client/src/pages/admin/AuthorizationGroups.js @@ -1,6 +1,6 @@ +import { gql } from "@apollo/client" import { DEFAULT_PAGE_PROPS, DEFAULT_SEARCH_PROPS } from "actions" import API from "api" -import { gql } from "apollo-boost" import Fieldset from "components/Fieldset" import { PageDispatchersPropType, diff --git a/client/src/pages/admin/Index.js b/client/src/pages/admin/Index.js index dc266b38c1..40cc41c1a0 100644 --- a/client/src/pages/admin/Index.js +++ b/client/src/pages/admin/Index.js @@ -1,6 +1,6 @@ +import { gql } from "@apollo/client" import { DEFAULT_PAGE_PROPS, DEFAULT_SEARCH_PROPS } from "actions" import API from "api" -import { gql } from "apollo-boost" import AppContext from "components/AppContext" import * as FieldHelper from "components/FieldHelper" import Fieldset from "components/Fieldset" @@ -12,8 +12,7 @@ import { useBoilerplate } from "components/Page" import { Field, Form, Formik } from "formik" -import PropTypes from "prop-types" -import React, { useState } from "react" +import React, { useContext, useState } from "react" import { Button } from "react-bootstrap" import { connect } from "react-redux" @@ -31,7 +30,8 @@ const GQL_SAVE_ADMIN_SETTINGS = gql` } ` -const BaseAdminIndex = ({ pageDispatchers, loadAppData }) => { +const AdminIndex = ({ pageDispatchers }) => { + const { loadAppData } = useContext(AppContext) const [saveError, setSaveError] = useState(null) const [saveSuccess, setSaveSuccess] = useState(null) const { loading, error, data, refetch } = API.useApiQuery( @@ -120,15 +120,8 @@ const BaseAdminIndex = ({ pageDispatchers, loadAppData }) => { } } -BaseAdminIndex.propTypes = { - pageDispatchers: PageDispatchersPropType, - loadAppData: PropTypes.func +AdminIndex.propTypes = { + pageDispatchers: PageDispatchersPropType } -const AdminIndex = props => ( - - {context => } - -) - export default connect(null, mapPageDispatchersToProps)(AdminIndex) diff --git a/client/src/pages/admin/MergePeople.js b/client/src/pages/admin/MergePeople.js index 55957874ee..d89d282d7b 100644 --- a/client/src/pages/admin/MergePeople.js +++ b/client/src/pages/admin/MergePeople.js @@ -1,6 +1,6 @@ +import { gql } from "@apollo/client" import { DEFAULT_PAGE_PROPS, DEFAULT_SEARCH_PROPS } from "actions" import API from "api" -import { gql } from "apollo-boost" import { PersonSimpleOverlayRow } from "components/advancedSelectWidget/AdvancedSelectOverlayRow" import AdvancedSingleSelect from "components/advancedSelectWidget/AdvancedSingleSelect" import * as FieldHelper from "components/FieldHelper" diff --git a/client/src/pages/admin/authorizationgroup/Edit.js b/client/src/pages/admin/authorizationgroup/Edit.js index 12a7e200b6..bcc3426e80 100644 --- a/client/src/pages/admin/authorizationgroup/Edit.js +++ b/client/src/pages/admin/authorizationgroup/Edit.js @@ -1,6 +1,6 @@ +import { gql } from "@apollo/client" import { DEFAULT_SEARCH_PROPS, PAGE_PROPS_NO_NAV } from "actions" import API from "api" -import { gql } from "apollo-boost" import { PageDispatchersPropType, mapPageDispatchersToProps, @@ -75,7 +75,8 @@ const AuthorizationGroupEdit = ({ pageDispatchers }) => { relatedObject={ authorizationGroup.uuid && { relatedObjectType: AuthorizationGroup.relatedObjectType, - relatedObjectUuid: authorizationGroup.uuid + relatedObjectUuid: authorizationGroup.uuid, + relatedObject: authorizationGroup } } /> diff --git a/client/src/pages/admin/authorizationgroup/Form.js b/client/src/pages/admin/authorizationgroup/Form.js index 9069215771..c8e2ed2f4f 100644 --- a/client/src/pages/admin/authorizationgroup/Form.js +++ b/client/src/pages/admin/authorizationgroup/Form.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import AdvancedMultiSelect from "components/advancedSelectWidget/AdvancedMultiSelect" import { PositionOverlayRow } from "components/advancedSelectWidget/AdvancedSelectOverlayRow" import * as FieldHelper from "components/FieldHelper" diff --git a/client/src/pages/admin/authorizationgroup/Show.js b/client/src/pages/admin/authorizationgroup/Show.js index 8f296cb270..d9fe1ad1b3 100644 --- a/client/src/pages/admin/authorizationgroup/Show.js +++ b/client/src/pages/admin/authorizationgroup/Show.js @@ -1,6 +1,6 @@ +import { gql } from "@apollo/client" import { DEFAULT_PAGE_PROPS, DEFAULT_SEARCH_PROPS } from "actions" import API from "api" -import { gql } from "apollo-boost" import AppContext from "components/AppContext" import * as FieldHelper from "components/FieldHelper" import Fieldset from "components/Fieldset" @@ -15,11 +15,16 @@ import PositionTable from "components/PositionTable" import RelatedObjectNotes, { GRAPHQL_NOTES_FIELDS } from "components/RelatedObjectNotes" -import ReportCollection from "components/ReportCollection" +import ReportCollection, { + FORMAT_CALENDAR, + FORMAT_MAP, + FORMAT_STATISTICS, + FORMAT_SUMMARY, + FORMAT_TABLE +} from "components/ReportCollection" import { Field, Form, Formik } from "formik" -import { AuthorizationGroup, Person } from "models" -import PropTypes from "prop-types" -import React from "react" +import { AuthorizationGroup } from "models" +import React, { useContext } from "react" import { connect } from "react-redux" import { useLocation, useParams } from "react-router-dom" @@ -53,7 +58,8 @@ const GQL_GET_AUTHORIZATION_GROUP = gql` } ` -const BaseAuthorizationGroupShow = ({ pageDispatchers, currentUser }) => { +const AuthorizationGroupShow = ({ pageDispatchers }) => { + const { currentUser } = useContext(AppContext) const { uuid } = useParams() const routerLocation = useLocation() const { loading, error, data } = API.useApiQuery( @@ -100,7 +106,8 @@ const BaseAuthorizationGroupShow = ({ pageDispatchers, currentUser }) => { relatedObject={ authorizationGroup.uuid && { relatedObjectType: AuthorizationGroup.relatedObjectType, - relatedObjectUuid: authorizationGroup.uuid + relatedObjectUuid: authorizationGroup.uuid, + relatedObject: authorizationGroup } } /> @@ -136,6 +143,13 @@ const BaseAuthorizationGroupShow = ({ pageDispatchers, currentUser }) => { authorizationGroupUuid: uuid }} mapId="reports" + viewFormats={[ + FORMAT_SUMMARY, + FORMAT_TABLE, + FORMAT_CALENDAR, + FORMAT_MAP, + FORMAT_STATISTICS + ]} /> @@ -146,20 +160,8 @@ const BaseAuthorizationGroupShow = ({ pageDispatchers, currentUser }) => { ) } -BaseAuthorizationGroupShow.propTypes = { - pageDispatchers: PageDispatchersPropType, - currentUser: PropTypes.instanceOf(Person) +AuthorizationGroupShow.propTypes = { + pageDispatchers: PageDispatchersPropType } -const AuthorizationGroupShow = props => ( - - {context => ( - - )} - -) - export default connect(null, mapPageDispatchersToProps)(AuthorizationGroupShow) diff --git a/client/src/pages/dashboards/BoardDashboard.css b/client/src/pages/dashboards/BoardDashboard.css new file mode 100644 index 0000000000..e4c4dc52a2 --- /dev/null +++ b/client/src/pages/dashboards/BoardDashboard.css @@ -0,0 +1,39 @@ +.diagram-container { + width: 100%; + height: 100%; + background: white; +} + +.custom-node { + border: solid 2px gray; + border-radius: 5px; + width: 50px; + height: 50px; + display: flex; + align-items: flex-start; + justify-content: space-between; + position: relative; +} + +.custom-node-color { + position: absolute; + top: 50%; + left: 50%; + width: 20px; + height: 20px; + transform: translate(-50%, -50%); + border-radius: 10px; +} + +.circle-port { + width: 12px; + height: 12px; + margin: 2px; + border-radius: 4px; + background: darkgray; + cursor: pointer; +} + +.circle-port:hover { + background: mediumpurple; +} diff --git a/client/src/pages/dashboards/BoardDashboard.js b/client/src/pages/dashboards/BoardDashboard.js new file mode 100644 index 0000000000..c68d6141ed --- /dev/null +++ b/client/src/pages/dashboards/BoardDashboard.js @@ -0,0 +1,334 @@ +import { Icon } from "@blueprintjs/core" +import { IconNames } from "@blueprintjs/icons" +import { + CanvasWidget, + SelectionBoxLayerFactory +} from "@projectstorm/react-canvas-core" +import { + DefaultDiagramState, + DiagramEngine, + DiagramModel, + LinkLayerFactory, + NodeLayerFactory, + PortModelAlignment +} from "@projectstorm/react-diagrams-core" +import { DefaultLabelFactory } from "@projectstorm/react-diagrams-defaults" +import { + PathFindingLinkFactory, + DagreEngine +} from "@projectstorm/react-diagrams-routing" +import LinkTo from "components/LinkTo" +import MultiTypeAdvancedSelectComponent from "components/advancedSelectWidget/MultiTypeAdvancedSelectComponent" +import { mapPageDispatchersToProps } from "components/Page" +import FileSaver from "file-saver" +import * as Models from "models" +import PropTypes from "prop-types" +import React, { useEffect, useRef, useState } from "react" +import { Badge, Button, Modal, Panel } from "react-bootstrap" +import { connect } from "react-redux" +import { useParams } from "react-router-dom" +import DOWNLOAD_ICON from "resources/download.png" +import Settings from "settings" +import utils from "utils" +import "./BoardDashboard.css" +import { + DiagramLinkFactory, + DiagramNodeFactory, + DiagramNodeModel, + DiagramPortModel, + SimplePortFactory +} from "./DiagramNode" + +const createEngine = options => { + const engine = new DiagramEngine({}) + engine.getLayerFactories().registerFactory(new NodeLayerFactory()) + engine.getLayerFactories().registerFactory(new LinkLayerFactory()) + engine.getLayerFactories().registerFactory(new SelectionBoxLayerFactory()) + + engine.getLabelFactories().registerFactory(new DefaultLabelFactory()) + engine.getNodeFactories().registerFactory(new DiagramNodeFactory()) + engine.getLinkFactories().registerFactory(new DiagramLinkFactory()) + engine.getLinkFactories().registerFactory(new PathFindingLinkFactory()) + engine + .getPortFactories() + .registerFactory( + new SimplePortFactory( + "anet", + config => new DiagramPortModel(PortModelAlignment.LEFT) + ) + ) + + engine.getStateMachine().pushState(new DefaultDiagramState()) + return engine +} + +const PrototypeNode = ({ name, model, onClick }) => ( + +
{ + event.dataTransfer.setData( + "storm-diagram-node", + JSON.stringify({ anetObjectType: model.constructor.resourceName }) + ) + }} + style={{ textAlign: "left", cursor: "grab" }} + > + + {name} +
+
+) + +PrototypeNode.propTypes = { + name: PropTypes.string, + model: PropTypes.object, + onClick: PropTypes.func +} + +const BoardDashboard = () => { + const { dashboard } = useParams() + const dashboardSettings = Settings.dashboards.find(o => o.label === dashboard) + const [dropEvent, setDropEvent] = useState(null) + const engineRef = useRef(createEngine()) + const [model, setModel] = useState(null) + const [edit, setEdit] = useState(false) + const [selectingEntity, setSelectingEntity] = useState(false) + const [editedNode, setEditedNode] = useState(null) + const dagreEngineRef = useRef( + new DagreEngine({ + graph: { + rankdir: "RL", + ranker: "longest-path", + marginx: 25, + marginy: 25 + }, + includeLinks: true + }) + ) + + useEffect(() => { + setModel(new DiagramModel()) + return () => setModel(null) + }, []) + + useEffect(() => { + const previousModel = engineRef.current.getModel() + if (previousModel) { + previousModel.clearListeners() + previousModel.getNodes().forEach(node => node.clearListeners()) + } + engineRef.current.setModel(model) + if (model) { + const selectionListener = { + selectionChanged: () => + setEditedNode( + model.getSelectedEntities().length === 1 + ? model.getSelectedEntities()[0] + : null + ) + } + model.registerListener({ + nodesUpdated: function(event) { + if (event.isCreated) { + event.node.registerListener(selectionListener) + } else { + if ( + editedNode?.options.anetObject.uuid === + event.node.anetObject?.uuid + ) { + setEditedNode(null) + } + } + } + }) + model.getNodes().forEach(node => node.registerListener(selectionListener)) + } + }, [editedNode, model]) + + useEffect(() => { + model && model.setLocked(!edit) + }, [model, edit]) + + useEffect(() => { + async function fetchData() { + await fetch(dashboardSettings.data) + .then(response => response.json()) + .then(data => { + const model = new DiagramModel() + model.deserializeModel(data, engineRef.current) + setModel(model) + }) + } + fetchData() + }, [dashboardSettings.data]) + + useEffect(() => { + if (dropEvent) { + const { data, point } = dropEvent + const node = new DiagramNodeModel(data) + + node.setPosition(point) + model.getSelectedEntities().forEach(entity => entity.setSelected(false)) + node.setSelected(true) + setEditedNode(node) + engineRef.current.getModel().addNode(node) + setDropEvent(null) + } + }, [model, dropEvent]) + + return ( +
+
{ + event.persist() + const data = utils.parseJsonSafe( + event.dataTransfer.getData("storm-diagram-node") + ) + const point = engineRef.current.getRelativeMousePoint(event) + setDropEvent({ data, point }) + }} + onDragOver={event => { + event.preventDefault() + }} + > + {engineRef.current.getModel() && ( + + )} +
+
+ + + + {edit && ( + <> + + + + + )} + + + {edit && ( + <> + + Node palette + + {Object.values(Models).map(Model => { + const instance = new Model() + const modelName = instance.constructor.resourceName + return ( + instance.iconUrl() && ( + { + const data = { anetObjectType: modelName } + const point = { x: 150, y: 150 } + setDropEvent({ data, point }) + }} + /> + ) + ) + })} + + Click or drag into diagram + + + + + Node editor + + {editedNode ? ( + <> + ANET entity: +
+ + + ) : ( + + Select an item on diagram + + )} +
+ setSelectingEntity(false)} + > + + Edit diagram node + + + { + editedNode.options.anetObject = value + editedNode.options.anetObjectType = objectType + setSelectingEntity(false) + }} + objectType={editedNode?.options.anetObjectType} + /> + + +
+ + )} +
+
+ ) +} + +export default connect(null, mapPageDispatchersToProps)(BoardDashboard) diff --git a/client/src/pages/dashboards/DecisivesDashboard.js b/client/src/pages/dashboards/DecisivesDashboard.js index 4211f963ee..60cdcb4bc1 100644 --- a/client/src/pages/dashboards/DecisivesDashboard.js +++ b/client/src/pages/dashboards/DecisivesDashboard.js @@ -1,3 +1,4 @@ +import { gql } from "@apollo/client" import { DEFAULT_PAGE_PROPS, DEFAULT_SEARCH_PROPS, @@ -6,7 +7,6 @@ import { setSearchQuery } from "actions" import API from "api" -import { gql } from "apollo-boost" import LinkTo from "components/LinkTo" import { PageDispatchersPropType, diff --git a/client/src/pages/dashboards/DiagramNode.js b/client/src/pages/dashboards/DiagramNode.js new file mode 100644 index 0000000000..7bfeb44186 --- /dev/null +++ b/client/src/pages/dashboards/DiagramNode.js @@ -0,0 +1,309 @@ +import { css, keyframes } from "@emotion/core" +import styled from "@emotion/styled" +import { + AbstractModelFactory, + AbstractReactFactory +} from "@projectstorm/react-canvas-core" +import { + NodeModel, + PortModel, + PortModelAlignment, + PortWidget +} from "@projectstorm/react-diagrams-core" +import { + DefaultLinkFactory, + DefaultLinkModel, + DefaultLinkWidget +} from "@projectstorm/react-diagrams-defaults" +import AggregationWidgetContainer, { + AGGERGATION_WIDGET_TYPE, + getAggregationWidget +} from "components/aggregations/AggregationWidgetContainer" +import AvatarDisplayComponent from "components/AvatarDisplayComponent" +import { SPECIAL_WIDGET_TYPES } from "components/CustomFields" +import LinkTo from "components/LinkTo" +import { CUSTOM_FIELD_TYPE, GRAPHQL_ENTITY_FIELDS } from "components/Model" +import { GRAPHQL_NOTES_FIELDS } from "components/RelatedObjectNotes" +import _uniqueId from "lodash/uniqueId" +import * as Models from "models" +import moment from "moment" +import { PERIOD_FACTORIES, RECURRENCE_TYPE } from "periodUtils" +import PropTypes from "prop-types" +import * as React from "react" + +const ENTITY_GQL_FIELDS = { + Report: GRAPHQL_ENTITY_FIELDS.Report, + Person: `uuid, name, role, avatar(size: 64), ${GRAPHQL_NOTES_FIELDS}`, + Organization: GRAPHQL_ENTITY_FIELDS.Organization, + Position: GRAPHQL_ENTITY_FIELDS.Position, + Location: GRAPHQL_ENTITY_FIELDS.Location, + Task: `${GRAPHQL_ENTITY_FIELDS.Task} ${GRAPHQL_NOTES_FIELDS}` +} + +const DIAGRAM_AGGREGATION_WIDGET_PER_FIELD_TYPE = { + [CUSTOM_FIELD_TYPE.SPECIAL_FIELD]: { + [SPECIAL_WIDGET_TYPES.LIKERT_SCALE]: AGGERGATION_WIDGET_TYPE.PIE + } +} + +export class DiagramPortModel extends PortModel { + constructor(alignment) { + super({ + type: "anet", + name: alignment, + alignment: alignment + }) + } + + createLinkModel = () => new DiagramLinkModel() +} + +export class DiagramLinkModel extends DefaultLinkModel { + constructor() { + super({ + type: "anet" + }) + } +} +export class DiagramNodeModel extends NodeModel { + constructor(options) { + super({ + type: "anet", + ...options + }) + this.addPort(new DiagramPortModel(PortModelAlignment.TOP)) + this.addPort(new DiagramPortModel(PortModelAlignment.LEFT)) + this.addPort(new DiagramPortModel(PortModelAlignment.BOTTOM)) + this.addPort(new DiagramPortModel(PortModelAlignment.RIGHT)) + } + + deserialize = event => { + super.deserialize(event) + const options = this.options + options.anetObjectType = event.data.anetObjectType + options.color = event.data.color + // TODO: batch-process all queries as one + const modelClass = Models[event.data.anetObjectType] + modelClass && + modelClass + .fetchByUuid(event.data.anetObjectUuid, ENTITY_GQL_FIELDS) + .then(function(entity) { + options.anetObject = entity + // TODO: fire an event instead + event.engine.repaintCanvas() + }) + } + + serialize = () => ({ + ...super.serialize(), + anetObjectUuid: this.options.anetObject?.uuid, + anetObjectType: this.options.anetObjectType, + color: this.options.color + }) +} + +const Port = styled.div` + width: 16px; + height: 16px; + z-index: 10; + border: 2px solid rgba(255, 255, 255, 0.5); + background: rgba(0, 0, 0, 0.1); + border-radius: 8px; + cursor: pointer; + &:hover { + background: rgba(0, 0, 0, 0.4); + } +` + +export const DiagramNodeWidget = ({ size, node, engine }) => { + const { anetObjectType, anetObject } = node.options + const ModelClass = anetObjectType && Models[anetObjectType] + const modelInstance = anetObject && ModelClass && new ModelClass(anetObject) + const now = moment() + const period = PERIOD_FACTORIES[RECURRENCE_TYPE.MONTHLY](now, 0) + const instantAssessmentConfig = + anetObject && anetObject.getInstantAssessmentConfig() + const instantAssessmentResults = + instantAssessmentConfig && anetObject.getInstantAssessmentResults(period) + return ( +
+ {modelInstance && + Object.prototype.hasOwnProperty.call(modelInstance, "avatar") ? ( + + ) : ( + + )} + {anetObjectType && anetObject && ( +
+ + <> + {instantAssessmentConfig && + Object.keys(instantAssessmentConfig || {}).map(questionKey => { + const questionConfig = instantAssessmentConfig[questionKey] + const aggregationWidget = getAggregationWidget( + questionConfig, + DIAGRAM_AGGREGATION_WIDGET_PER_FIELD_TYPE, + true + ) + questionConfig.showLegend = false + return aggregationWidget ? ( + + ) : null + })} + +
+ )} + + + + + + + + + + + + +
+ ) +} + +DiagramNodeWidget.propTypes = { + size: PropTypes.number, + node: PropTypes.object, + engine: PropTypes.object +} + +export class SimplePortFactory extends AbstractModelFactory { + constructor(type, cb) { + super(type) + this.cb = cb + } + + generateModel = event => this.cb(event.initialConfig) +} + +export const Keyframes = keyframes` +from { + stroke-dashoffset: 24; +} +to { + stroke-dashoffset: 0; +} +` + +const selected = css` + stroke-dasharray: 10, 2; + animation: ${Keyframes} 1s linear infinite; +` + +export const Path = styled.path` + ${p => p.selected && selected}; + fill: none; + pointer-events: all; +` + +export class DiagramLinkFactory extends DefaultLinkFactory { + constructor() { + super("anet") + } + + generateReactWidget(event) { + return + } + + generateModel() { + return new DiagramLinkModel() + } + + generateLinkSegment(model, selected, path) { + return ( + + ) + } +} + +export class DiagramNodeFactory extends AbstractReactFactory { + constructor() { + super("anet") + } + + generateReactWidget = event => { + return ( + + ) + } + + generateModel = event => new DiagramNodeModel() +} diff --git a/client/src/pages/dashboards/KanbanDashboard.js b/client/src/pages/dashboards/KanbanDashboard.js index 595a6ad5f1..602ea2944b 100644 --- a/client/src/pages/dashboards/KanbanDashboard.js +++ b/client/src/pages/dashboards/KanbanDashboard.js @@ -1,6 +1,6 @@ +import { gql } from "@apollo/client" import { DEFAULT_PAGE_PROPS, DEFAULT_SEARCH_PROPS } from "actions" import API from "api" -import { gql } from "apollo-boost" import Kanban from "components/Kanban" import { PageDispatchersPropType, diff --git a/client/src/pages/insights/Show.js b/client/src/pages/insights/Show.js index 57cc9e6e1e..1e0117fdfa 100644 --- a/client/src/pages/insights/Show.js +++ b/client/src/pages/insights/Show.js @@ -24,7 +24,7 @@ import _isEmpty from "lodash/isEmpty" import { Report } from "models" import moment from "moment" import PropTypes from "prop-types" -import React from "react" +import React, { useContext } from "react" import { connect } from "react-redux" import { useParams } from "react-router-dom" import { deserializeQueryParams } from "searchUtils" @@ -90,18 +90,15 @@ export const INSIGHT_DETAILS = { } } -const BaseInsightsShow = ({ - pageDispatchers, - appSettings, - searchQuery, - setSearchQuery -}) => { +const InsightsShow = ({ pageDispatchers, searchQuery, setSearchQuery }) => { + const { appSettings } = useContext(AppContext) const { insight } = useParams() const flexStyle = { display: "flex", flexDirection: "column", flex: "1 1 auto", - height: "100%" + height: "100%", + overflow: "auto" } const mosaicLayoutStyle = { display: "flex", @@ -212,11 +209,10 @@ const BaseInsightsShow = ({ } } -BaseInsightsShow.propTypes = { +InsightsShow.propTypes = { pageDispatchers: PageDispatchersPropType, searchQuery: SearchQueryPropType, - setSearchQuery: PropTypes.func.isRequired, - appSettings: PropTypes.object + setSearchQuery: PropTypes.func.isRequired } const mapStateToProps = (state, ownProps) => ({ @@ -231,12 +227,4 @@ const mapDispatchToProps = (dispatch, ownProps) => { } } -const InsightsShow = props => ( - - {context => ( - - )} - -) - export default connect(mapStateToProps, mapDispatchToProps)(InsightsShow) diff --git a/client/src/pages/locations/Edit.js b/client/src/pages/locations/Edit.js index 9f18895a86..7cb1646026 100644 --- a/client/src/pages/locations/Edit.js +++ b/client/src/pages/locations/Edit.js @@ -1,6 +1,6 @@ +import { gql } from "@apollo/client" import { DEFAULT_SEARCH_PROPS, PAGE_PROPS_NO_NAV } from "actions" import API from "api" -import { gql } from "apollo-boost" import { PageDispatchersPropType, mapPageDispatchersToProps, @@ -85,7 +85,8 @@ const LocationEdit = ({ pageDispatchers }) => { relatedObject={ location.uuid && { relatedObjectType: Location.relatedObjectType, - relatedObjectUuid: location.uuid + relatedObjectUuid: location.uuid, + relatedObject: location } } /> diff --git a/client/src/pages/locations/Form.js b/client/src/pages/locations/Form.js index 60623989f9..125ed701a6 100644 --- a/client/src/pages/locations/Form.js +++ b/client/src/pages/locations/Form.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import AppContext from "components/AppContext" import ApprovalsDefinition from "components/approvals/ApprovalsDefinition" import * as FieldHelper from "components/FieldHelper" @@ -10,9 +10,9 @@ import NavigationWarning from "components/NavigationWarning" import { jumpToTop } from "components/Page" import { FastField, Form, Formik } from "formik" import _escape from "lodash/escape" -import { Location, Person, Position } from "models" +import { Location, Position } from "models" import PropTypes from "prop-types" -import React, { useState } from "react" +import React, { useContext, useState } from "react" import { Button } from "react-bootstrap" import { useHistory } from "react-router-dom" import GeoLocation from "./GeoLocation" @@ -30,7 +30,8 @@ const GQL_UPDATE_LOCATION = gql` } ` -const BaseLocationForm = ({ currentUser, edit, title, initialValues }) => { +const LocationForm = ({ edit, title, initialValues }) => { + const { currentUser } = useContext(AppContext) const history = useHistory() const [error, setError] = useState(null) const canEditName = @@ -247,25 +248,16 @@ const BaseLocationForm = ({ currentUser, edit, title, initialValues }) => { } } -BaseLocationForm.propTypes = { +LocationForm.propTypes = { initialValues: PropTypes.instanceOf(Location).isRequired, title: PropTypes.string, - edit: PropTypes.bool, - currentUser: PropTypes.instanceOf(Person) + edit: PropTypes.bool } -BaseLocationForm.defaultProps = { +LocationForm.defaultProps = { initialValues: new Location(), title: "", edit: false } -const LocationForm = props => ( - - {context => ( - - )} - -) - export default LocationForm diff --git a/client/src/pages/locations/Show.js b/client/src/pages/locations/Show.js index 5fa3c50f47..d45c056508 100644 --- a/client/src/pages/locations/Show.js +++ b/client/src/pages/locations/Show.js @@ -1,6 +1,6 @@ +import { gql } from "@apollo/client" import { DEFAULT_PAGE_PROPS, DEFAULT_SEARCH_PROPS } from "actions" import API from "api" -import { gql } from "apollo-boost" import AppContext from "components/AppContext" import Approvals from "components/approvals/Approvals" import * as FieldHelper from "components/FieldHelper" @@ -16,17 +16,11 @@ import { import RelatedObjectNotes, { GRAPHQL_NOTES_FIELDS } from "components/RelatedObjectNotes" -import ReportCollection, { - FORMAT_MAP, - FORMAT_SUMMARY, - FORMAT_TABLE, - FORMAT_CALENDAR -} from "components/ReportCollection" +import ReportCollection from "components/ReportCollection" import { Field, Form, Formik } from "formik" import _escape from "lodash/escape" -import { Location, Person } from "models" -import PropTypes from "prop-types" -import React from "react" +import { Location } from "models" +import React, { useContext } from "react" import { connect } from "react-redux" import { useLocation, useParams } from "react-router-dom" import GeoLocation, { GEO_LOCATION_DISPLAY_TYPE } from "./GeoLocation" @@ -74,7 +68,8 @@ const GQL_GET_LOCATION = gql` } ` -const BaseLocationShow = ({ pageDispatchers, currentUser }) => { +const LocationShow = ({ pageDispatchers }) => { + const { currentUser } = useContext(AppContext) const { uuid } = useParams() const routerLocation = useLocation() const { loading, error, data } = API.useApiQuery(GQL_GET_LOCATION, { @@ -129,7 +124,8 @@ const BaseLocationShow = ({ pageDispatchers, currentUser }) => { relatedObject={ location.uuid && { relatedObjectType: Location.relatedObjectType, - relatedObjectUuid: location.uuid + relatedObjectUuid: location.uuid, + relatedObject: location } } /> @@ -162,12 +158,6 @@ const BaseLocationShow = ({ pageDispatchers, currentUser }) => { paginationKey={`r_${uuid}`} queryParams={{ locationUuid: uuid }} mapId="reports" - viewFormats={[ - FORMAT_CALENDAR, - FORMAT_SUMMARY, - FORMAT_TABLE, - FORMAT_MAP - ]} /> @@ -177,17 +167,8 @@ const BaseLocationShow = ({ pageDispatchers, currentUser }) => { ) } -BaseLocationShow.propTypes = { - pageDispatchers: PageDispatchersPropType, - currentUser: PropTypes.instanceOf(Person) +LocationShow.propTypes = { + pageDispatchers: PageDispatchersPropType } -const LocationShow = props => ( - - {context => ( - - )} - -) - export default connect(null, mapPageDispatchersToProps)(LocationShow) diff --git a/client/src/pages/onboarding/Edit.js b/client/src/pages/onboarding/Edit.js index cbf330ba06..64a6c1cd3d 100644 --- a/client/src/pages/onboarding/Edit.js +++ b/client/src/pages/onboarding/Edit.js @@ -1,6 +1,6 @@ +import { gql } from "@apollo/client" import { DEFAULT_SEARCH_PROPS, PAGE_PROPS_MIN_HEAD } from "actions" import API from "api" -import { gql } from "apollo-boost" import AppContext from "components/AppContext" import { PageDispatchersPropType, @@ -10,8 +10,7 @@ import { import { Person } from "models" import moment from "moment" import PersonForm from "pages/people/Form" -import PropTypes from "prop-types" -import React from "react" +import React, { useContext } from "react" import { connect } from "react-redux" const GQL_GET_PERSON = gql` @@ -40,7 +39,10 @@ const GQL_GET_PERSON = gql` } ` -const BaseOnboardingEdit = ({ pageDispatchers, currentUser: { uuid } }) => { +const OnboardingEdit = ({ pageDispatchers }) => { + const { + currentUser: { uuid } + } = useContext(AppContext) const { loading, error, data } = API.useApiQuery(GQL_GET_PERSON, { uuid }) @@ -78,17 +80,8 @@ const BaseOnboardingEdit = ({ pageDispatchers, currentUser: { uuid } }) => { ) } -BaseOnboardingEdit.propTypes = { - pageDispatchers: PageDispatchersPropType, - currentUser: PropTypes.instanceOf(Person) +OnboardingEdit.propTypes = { + pageDispatchers: PageDispatchersPropType } -const OnboardingEdit = props => ( - - {context => ( - - )} - -) - export default connect(null, mapPageDispatchersToProps)(OnboardingEdit) diff --git a/client/src/pages/organizations/Edit.js b/client/src/pages/organizations/Edit.js index 011e3a4e6c..9a88ccfe0a 100644 --- a/client/src/pages/organizations/Edit.js +++ b/client/src/pages/organizations/Edit.js @@ -1,6 +1,6 @@ +import { gql } from "@apollo/client" import { DEFAULT_SEARCH_PROPS, PAGE_PROPS_NO_NAV } from "actions" import API from "api" -import { gql } from "apollo-boost" import { PageDispatchersPropType, mapPageDispatchersToProps, @@ -97,7 +97,8 @@ const OrganizationEdit = ({ pageDispatchers }) => { relatedObject={ organization.uuid && { relatedObjectType: Organization.relatedObjectType, - relatedObjectUuid: organization.uuid + relatedObjectUuid: organization.uuid, + relatedObject: organization } } /> diff --git a/client/src/pages/organizations/Form.js b/client/src/pages/organizations/Form.js index ac3ddd6b73..617f95e04b 100644 --- a/client/src/pages/organizations/Form.js +++ b/client/src/pages/organizations/Form.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import AdvancedMultiSelect from "components/advancedSelectWidget/AdvancedMultiSelect" import { OrganizationOverlayRow, @@ -16,10 +16,10 @@ import NavigationWarning from "components/NavigationWarning" import { jumpToTop } from "components/Page" import TaskTable from "components/TaskTable" import { FastField, Form, Formik } from "formik" -import { Organization, Person, Position, Task } from "models" +import { Organization, Position, Task } from "models" import pluralize from "pluralize" import PropTypes from "prop-types" -import React, { useState } from "react" +import React, { useContext, useState } from "react" import { Button } from "react-bootstrap" import { useHistory } from "react-router-dom" import ORGANIZATIONS_ICON from "resources/organizations.png" @@ -41,7 +41,8 @@ const GQL_UPDATE_ORGANIZATION = gql` } ` -const BaseOrganizationForm = ({ currentUser, edit, title, initialValues }) => { +const OrganizationForm = ({ edit, title, initialValues }) => { + const { currentUser } = useContext(AppContext) const history = useHistory() const [error, setError] = useState(null) const statusButtons = [ @@ -420,24 +421,15 @@ const BaseOrganizationForm = ({ currentUser, edit, title, initialValues }) => { } } -BaseOrganizationForm.propTypes = { +OrganizationForm.propTypes = { initialValues: PropTypes.instanceOf(Organization).isRequired, title: PropTypes.string, - edit: PropTypes.bool, - currentUser: PropTypes.instanceOf(Person) + edit: PropTypes.bool } -BaseOrganizationForm.defaultProps = { +OrganizationForm.defaultProps = { title: "", edit: false } -const OrganizationForm = props => ( - - {context => ( - - )} - -) - export default OrganizationForm diff --git a/client/src/pages/organizations/Laydown.js b/client/src/pages/organizations/Laydown.js index 3d3ae4b263..9886d2b98d 100644 --- a/client/src/pages/organizations/Laydown.js +++ b/client/src/pages/organizations/Laydown.js @@ -4,13 +4,14 @@ import OrganizationalChart from "components/graphs/OrganizationalChart" import LinkTo from "components/LinkTo" import { Organization, Person, Position } from "models" import PropTypes from "prop-types" -import React, { useState } from "react" +import React, { useContext, useState } from "react" import { Button, Table } from "react-bootstrap" import ContainerDimensions from "react-container-dimensions" import { Element } from "react-scroll" import Settings from "settings" -const BaseOrganizationLaydown = ({ currentUser, organization }) => { +const OrganizationLaydown = ({ organization }) => { + const { currentUser } = useContext(AppContext) const [showInactivePositions, setShowInactivePositions] = useState(false) const isSuperUser = currentUser && currentUser.isSuperUserForOrg(organization) @@ -227,17 +228,8 @@ const BaseOrganizationLaydown = ({ currentUser, organization }) => { } } -BaseOrganizationLaydown.propTypes = { - organization: PropTypes.instanceOf(Organization).isRequired, - currentUser: PropTypes.instanceOf(Person) +OrganizationLaydown.propTypes = { + organization: PropTypes.instanceOf(Organization).isRequired } -const OrganizationLaydown = props => ( - - {context => ( - - )} - -) - export default OrganizationLaydown diff --git a/client/src/pages/organizations/New.js b/client/src/pages/organizations/New.js index dc1acac6f8..85bcd40c92 100644 --- a/client/src/pages/organizations/New.js +++ b/client/src/pages/organizations/New.js @@ -1,6 +1,6 @@ +import { gql } from "@apollo/client" import { DEFAULT_SEARCH_PROPS, PAGE_PROPS_NO_NAV } from "actions" import API from "api" -import { gql } from "apollo-boost" import { PageDispatchersPropType, mapPageDispatchersToProps, diff --git a/client/src/pages/organizations/OrganizationTasks.js b/client/src/pages/organizations/OrganizationTasks.js index 4ff1374aee..b9f2d54867 100644 --- a/client/src/pages/organizations/OrganizationTasks.js +++ b/client/src/pages/organizations/OrganizationTasks.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import AppContext from "components/AppContext" import Fieldset from "components/Fieldset" import LinkTo from "components/LinkTo" @@ -10,10 +10,10 @@ import { } from "components/Page" import UltimatePaginationTopDown from "components/UltimatePaginationTopDown" import _get from "lodash/get" -import { Person, Task } from "models" +import { Task } from "models" import pluralize from "pluralize" import PropTypes from "prop-types" -import React, { useState } from "react" +import React, { useContext, useState } from "react" import { Table } from "react-bootstrap" import { connect } from "react-redux" import Settings from "settings" @@ -33,12 +33,8 @@ const GQL_GET_TASK_LIST = gql` } ` -const BaseOrganizationTasks = ({ - pageDispatchers, - queryParams, - currentUser, - organization -}) => { +const OrganizationTasks = ({ pageDispatchers, queryParams, organization }) => { + const { currentUser } = useContext(AppContext) const [pageNum, setPageNum] = useState(0) const taskQuery = Object.assign({}, queryParams, { pageNum }) const { loading, error, data } = API.useApiQuery(GQL_GET_TASK_LIST, { @@ -120,19 +116,10 @@ const BaseOrganizationTasks = ({ ) } -BaseOrganizationTasks.propTypes = { +OrganizationTasks.propTypes = { pageDispatchers: PageDispatchersPropType, - currentUser: PropTypes.instanceOf(Person), organization: PropTypes.object.isRequired, queryParams: PropTypes.object } -const OrganizationTasks = props => ( - - {context => ( - - )} - -) - export default connect(null, mapPageDispatchersToProps)(OrganizationTasks) diff --git a/client/src/pages/organizations/Show.js b/client/src/pages/organizations/Show.js index cab7ffc1e0..750c3032b3 100644 --- a/client/src/pages/organizations/Show.js +++ b/client/src/pages/organizations/Show.js @@ -1,6 +1,6 @@ +import { gql } from "@apollo/client" import { DEFAULT_PAGE_PROPS, DEFAULT_SEARCH_PROPS } from "actions" import API from "api" -import { gql } from "apollo-boost" import Approvals from "components/approvals/Approvals" import AppContext from "components/AppContext" import * as FieldHelper from "components/FieldHelper" @@ -17,20 +17,21 @@ import { import RelatedObjectNotes, { GRAPHQL_NOTES_FIELDS } from "components/RelatedObjectNotes" -import ReportCollection, { - FORMAT_MAP, - FORMAT_SUMMARY, - FORMAT_TABLE, - FORMAT_CALENDAR -} from "components/ReportCollection" +import ReportCollection from "components/ReportCollection" +import { RECURSE_STRATEGY } from "components/SearchFilters" import SubNav from "components/SubNav" import { Field, Form, Formik } from "formik" -import { Organization, Person, Position, Report, Task } from "models" +import { Organization, Position, Report, Task } from "models" import { orgTour } from "pages/HopscotchTour" import pluralize from "pluralize" -import PropTypes from "prop-types" -import React, { useState } from "react" -import { ListGroup, ListGroupItem, Nav, Button } from "react-bootstrap" +import React, { useContext, useState } from "react" +import { + Checkbox, + ListGroup, + ListGroupItem, + Nav, + Button +} from "react-bootstrap" import { connect } from "react-redux" import { useLocation, useParams } from "react-router-dom" import Settings from "settings" @@ -124,9 +125,11 @@ const GQL_GET_ORGANIZATION = gql` } ` -const BaseOrganizationShow = ({ pageDispatchers, currentUser }) => { +const OrganizationShow = ({ pageDispatchers }) => { + const { currentUser } = useContext(AppContext) const routerLocation = useLocation() const [filterPendingApproval, setFilterPendingApproval] = useState(false) + const [includeChildrenOrgs, setIncludeChildrenOrgs] = useState(false) const { uuid } = useParams() const { loading, error, data } = API.useApiQuery(GQL_GET_ORGANIZATION, { uuid @@ -192,6 +195,10 @@ const BaseOrganizationShow = ({ pageDispatchers, currentUser }) => { if (filterPendingApproval) { reportQueryParams.state = Report.STATE.PENDING_APPROVAL } + if (includeChildrenOrgs) { + reportQueryParams.orgRecurseStrategy = RECURSE_STRATEGY.CHILDREN + } + return ( {({ values }) => { @@ -253,7 +260,8 @@ const BaseOrganizationShow = ({ pageDispatchers, currentUser }) => { relatedObject={ organization.uuid && { relatedObjectType: Organization.relatedObjectType, - relatedObjectUuid: organization.uuid + relatedObjectUuid: organization.uuid, + relatedObject: organization } } /> @@ -385,23 +393,27 @@ const BaseOrganizationShow = ({ pageDispatchers, currentUser }) => { - {filterPendingApproval - ? "Show all reports" - : "Show pending approval"} - + <> + + + setIncludeChildrenOrgs(!includeChildrenOrgs)} + > + include reports from sub-orgs + + ) } /> @@ -412,29 +424,16 @@ const BaseOrganizationShow = ({ pageDispatchers, currentUser }) => { }} ) - - function togglePendingApprovalFilter() { - setFilterPendingApproval(!filterPendingApproval) - } } -BaseOrganizationShow.propTypes = { - pageDispatchers: PageDispatchersPropType, - currentUser: PropTypes.instanceOf(Person) +OrganizationShow.propTypes = { + pageDispatchers: PageDispatchersPropType } const mapStateToProps = (state, ownProps) => ({ pagination: state.pagination }) -const OrganizationShow = props => ( - - {context => ( - - )} - -) - export default connect( mapStateToProps, mapPageDispatchersToProps diff --git a/client/src/pages/people/Edit.js b/client/src/pages/people/Edit.js index 489754b436..7ff18c05b9 100644 --- a/client/src/pages/people/Edit.js +++ b/client/src/pages/people/Edit.js @@ -1,9 +1,10 @@ +import { gql } from "@apollo/client" import { DEFAULT_SEARCH_PROPS, PAGE_PROPS_NO_NAV } from "actions" import API from "api" -import { gql } from "apollo-boost" +import { DEFAULT_CUSTOM_FIELDS_PARENT } from "components/Model" import { - PageDispatchersPropType, mapPageDispatchersToProps, + PageDispatchersPropType, useBoilerplate } from "components/Page" import RelatedObjectNotes, { @@ -14,6 +15,7 @@ import moment from "moment" import React from "react" import { connect } from "react-redux" import { useParams } from "react-router-dom" +import utils from "utils" import PersonForm from "./Form" const GQL_GET_PERSON = gql` @@ -74,7 +76,9 @@ const PersonEdit = ({ pageDispatchers }) => { const parsedFullName = Person.parseFullName(data.person.name) data.person.firstName = parsedFullName.firstName data.person.lastName = parsedFullName.lastName - data.person.formCustomFields = JSON.parse(data.person.customFields) + data.person[DEFAULT_CUSTOM_FIELDS_PARENT] = utils.parseJsonSafe( + data.person.customFields + ) } const person = new Person(data ? data.person : {}) const legendText = person.isNewUser() @@ -89,7 +93,8 @@ const PersonEdit = ({ pageDispatchers }) => { relatedObject={ person.uuid && { relatedObjectType: Person.relatedObjectType, - relatedObjectUuid: person.uuid + relatedObjectUuid: person.uuid, + relatedObject: person } } relatedObjectValue={person} diff --git a/client/src/pages/people/Form.js b/client/src/pages/people/Form.js index d901d868bd..bac87d615e 100644 --- a/client/src/pages/people/Form.js +++ b/client/src/pages/people/Form.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import AppContext from "components/AppContext" import AvatarDisplayComponent from "components/AvatarDisplayComponent" import AvatarEditModal from "components/AvatarEditModal" @@ -11,6 +11,7 @@ import { import * as FieldHelper from "components/FieldHelper" import Fieldset from "components/Fieldset" import Messages from "components/Messages" +import { DEFAULT_CUSTOM_FIELDS_PARENT } from "components/Model" import "components/NameInput.css" import NavigationWarning from "components/NavigationWarning" import OptionListModal from "components/OptionListModal" @@ -22,7 +23,7 @@ import _isEmpty from "lodash/isEmpty" import { Person } from "models" import pluralize from "pluralize" import PropTypes from "prop-types" -import React, { useRef, useState } from "react" +import React, { useContext, useRef, useState } from "react" import { Alert, Button, @@ -48,14 +49,8 @@ const GQL_UPDATE_PERSON = gql` } ` -const BasePersonForm = ({ - loadAppData, - currentUser, - edit, - title, - saveText, - initialValues -}) => { +const PersonForm = ({ edit, title, saveText, initialValues }) => { + const { loadAppData, currentUser } = useContext(AppContext) const history = useHistory() const confirmHasReplacementButton = useRef(null) const [error, setError] = useState(null) @@ -595,7 +590,7 @@ const BasePersonForm = ({ "firstName", "lastName", "customFields", // initial JSON from the db - "formCustomFields" + DEFAULT_CUSTOM_FIELDS_PARENT ) if (values.status === Person.STATUS.NEW_USER) { person.status = Person.STATUS.ACTIVE @@ -633,31 +628,17 @@ const BasePersonForm = ({ } } -BasePersonForm.propTypes = { +PersonForm.propTypes = { initialValues: PropTypes.instanceOf(Person).isRequired, title: PropTypes.string, edit: PropTypes.bool, - saveText: PropTypes.string, - currentUser: PropTypes.instanceOf(Person), - loadAppData: PropTypes.func + saveText: PropTypes.string } -BasePersonForm.defaultProps = { +PersonForm.defaultProps = { title: "", edit: false, saveText: "Save Person" } -const PersonForm = props => ( - - {context => ( - - )} - -) - export default PersonForm diff --git a/client/src/pages/people/Show.js b/client/src/pages/people/Show.js index ebd31ac8c8..38ed7a52a5 100644 --- a/client/src/pages/people/Show.js +++ b/client/src/pages/people/Show.js @@ -1,7 +1,8 @@ +import { gql } from "@apollo/client" import { DEFAULT_PAGE_PROPS, DEFAULT_SEARCH_PROPS } from "actions" import API from "api" -import { gql } from "apollo-boost" import AppContext from "components/AppContext" +import AssessmentResultsContainer from "components/assessments/AssessmentResultsContainer" import AssignPositionModal from "components/AssignPositionModal" import AvatarDisplayComponent from "components/AvatarDisplayComponent" import { ReadonlyCustomFields } from "components/CustomFields" @@ -11,31 +12,27 @@ import Fieldset from "components/Fieldset" import GuidedTour from "components/GuidedTour" import LinkTo from "components/LinkTo" import Messages from "components/Messages" +import { DEFAULT_CUSTOM_FIELDS_PARENT } from "components/Model" import { - PageDispatchersPropType, mapPageDispatchersToProps, + PageDispatchersPropType, useBoilerplate } from "components/Page" import RelatedObjectNotes, { GRAPHQL_NOTES_FIELDS } from "components/RelatedObjectNotes" -import ReportCollection, { - FORMAT_MAP, - FORMAT_SUMMARY, - FORMAT_TABLE, - FORMAT_CALENDAR -} from "components/ReportCollection" +import ReportCollection from "components/ReportCollection" import { Field, Form, Formik } from "formik" import _isEmpty from "lodash/isEmpty" import { Person, Position } from "models" import moment from "moment" import { personTour } from "pages/HopscotchTour" -import PropTypes from "prop-types" -import React, { useState } from "react" +import React, { useContext, useState } from "react" import { Button, Col, ControlLabel, FormGroup, Table } from "react-bootstrap" import { connect } from "react-redux" import { useLocation, useParams } from "react-router-dom" import Settings from "settings" +import utils from "utils" import { parseHtmlWithLinkTo } from "utils_links" const GQL_GET_PERSON = gql` @@ -95,7 +92,8 @@ const GQL_GET_PERSON = gql` } ` -const BasePersonShow = ({ pageDispatchers, currentUser }) => { +const PersonShow = ({ pageDispatchers }) => { + const { currentUser } = useContext(AppContext) const routerLocation = useLocation() const [showAssignPositionModal, setShowAssignPositionModal] = useState(false) const [ @@ -119,7 +117,9 @@ const BasePersonShow = ({ pageDispatchers, currentUser }) => { return result } if (data) { - data.person.formCustomFields = JSON.parse(data.person.customFields) + data.person[DEFAULT_CUSTOM_FIELDS_PARENT] = utils.parseJsonSafe( + data.person.customFields + ) } const person = new Person(data ? data.person : {}) const stateSuccess = routerLocation.state && routerLocation.state.success @@ -147,7 +147,10 @@ const BasePersonShow = ({ pageDispatchers, currentUser }) => { (!hasPosition && currentUser.isSuperUser()) || (hasPosition && currentUser.isSuperUserForOrg(position.organization)) || (person.role === Person.ROLE.PRINCIPAL && currentUser.isSuperUser()) - + const canAddAssessment = currentUser.position.associatedPositions + .filter(ap => ap.person) + .map(ap => ap.person.uuid) + .includes(person.uuid) return ( {({ values }) => { @@ -189,7 +192,8 @@ const BasePersonShow = ({ pageDispatchers, currentUser }) => { relatedObject={ person.uuid && { relatedObjectType: Person.relatedObjectType, - relatedObjectUuid: person.uuid + relatedObjectUuid: person.uuid, + relatedObject: person } } relatedObjectValue={person} @@ -347,12 +351,6 @@ const BasePersonShow = ({ pageDispatchers, currentUser }) => { queryParams={{ authorUuid: uuid }} - viewFormats={[ - FORMAT_CALENDAR, - FORMAT_SUMMARY, - FORMAT_TABLE, - FORMAT_MAP - ]} mapId="reports-authored" /> @@ -414,6 +412,13 @@ const BasePersonShow = ({ pageDispatchers, currentUser }) => { )} + + ) }} @@ -526,15 +531,8 @@ const BasePersonShow = ({ pageDispatchers, currentUser }) => { } } -BasePersonShow.propTypes = { - pageDispatchers: PageDispatchersPropType, - currentUser: PropTypes.instanceOf(Person) +PersonShow.propTypes = { + pageDispatchers: PageDispatchersPropType } -const PersonShow = props => ( - - {context => } - -) - export default connect(null, mapPageDispatchersToProps)(PersonShow) diff --git a/client/src/pages/positions/Edit.js b/client/src/pages/positions/Edit.js index ae16ce59c3..5671552e45 100644 --- a/client/src/pages/positions/Edit.js +++ b/client/src/pages/positions/Edit.js @@ -1,6 +1,6 @@ +import { gql } from "@apollo/client" import { DEFAULT_SEARCH_PROPS, PAGE_PROPS_NO_NAV } from "actions" import API from "api" -import { gql } from "apollo-boost" import { PageDispatchersPropType, mapPageDispatchersToProps, @@ -85,7 +85,8 @@ const PositionEdit = ({ pageDispatchers }) => { relatedObject={ position.uuid && { relatedObjectType: Position.relatedObjectType, - relatedObjectUuid: position.uuid + relatedObjectUuid: position.uuid, + relatedObject: position } } /> diff --git a/client/src/pages/positions/Form.js b/client/src/pages/positions/Form.js index 98b1c1f2a3..a853d53796 100644 --- a/client/src/pages/positions/Form.js +++ b/client/src/pages/positions/Form.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import { LocationOverlayRow, OrganizationOverlayRow @@ -15,9 +15,9 @@ import { jumpToTop } from "components/Page" import { RECURSE_STRATEGY } from "components/SearchFilters" import { FastField, Field, Form, Formik } from "formik" import DictionaryField from "HOC/DictionaryField" -import { Location, Organization, Person, Position } from "models" +import { Location, Organization, Position } from "models" import PropTypes from "prop-types" -import React, { useState } from "react" +import React, { useContext, useState } from "react" import { Button, HelpBlock } from "react-bootstrap" import { useHistory } from "react-router-dom" import LOCATIONS_ICON from "resources/locations.png" @@ -38,7 +38,8 @@ const GQL_UPDATE_POSITION = gql` } ` -const BasePositionForm = ({ currentUser, edit, title, initialValues }) => { +const PositionForm = ({ edit, title, initialValues }) => { + const { currentUser } = useContext(AppContext) const history = useHistory() const [error, setError] = useState(null) const statusButtons = [ @@ -370,24 +371,15 @@ const BasePositionForm = ({ currentUser, edit, title, initialValues }) => { } } -BasePositionForm.propTypes = { +PositionForm.propTypes = { initialValues: PropTypes.instanceOf(Position).isRequired, title: PropTypes.string, - edit: PropTypes.bool, - currentUser: PropTypes.instanceOf(Person) + edit: PropTypes.bool } -BasePositionForm.defaultProps = { +PositionForm.defaultProps = { title: "", edit: false } -const PositionForm = props => ( - - {context => ( - - )} - -) - export default PositionForm diff --git a/client/src/pages/positions/New.js b/client/src/pages/positions/New.js index cdecae7bf3..e47a250a77 100644 --- a/client/src/pages/positions/New.js +++ b/client/src/pages/positions/New.js @@ -1,6 +1,6 @@ +import { gql } from "@apollo/client" import { DEFAULT_SEARCH_PROPS, PAGE_PROPS_NO_NAV } from "actions" import API from "api" -import { gql } from "apollo-boost" import { PageDispatchersPropType, mapPageDispatchersToProps, diff --git a/client/src/pages/positions/Show.js b/client/src/pages/positions/Show.js index d75ea60a7d..f4c6c7b010 100644 --- a/client/src/pages/positions/Show.js +++ b/client/src/pages/positions/Show.js @@ -1,6 +1,6 @@ +import { gql } from "@apollo/client" import { DEFAULT_PAGE_PROPS, DEFAULT_SEARCH_PROPS } from "actions" import API from "api" -import { gql } from "apollo-boost" import AppContext from "components/AppContext" import AssignPersonModal from "components/AssignPersonModal" import ConfirmDelete from "components/ConfirmDelete" @@ -21,11 +21,10 @@ import RelatedObjectNotes, { } from "components/RelatedObjectNotes" import { Field, Form, Formik } from "formik" import DictionaryField from "HOC/DictionaryField" -import { Person, Position } from "models" +import { Position } from "models" import moment from "moment" import { positionTour } from "pages/HopscotchTour" -import PropTypes from "prop-types" -import React, { useState } from "react" +import React, { useContext, useState } from "react" import { Button, Table } from "react-bootstrap" import { connect } from "react-redux" import { useHistory, useLocation, useParams } from "react-router-dom" @@ -94,7 +93,8 @@ const GQL_DELETE_POSITION = gql` } ` -const BasePositionShow = ({ pageDispatchers, currentUser }) => { +const PositionShow = ({ pageDispatchers }) => { + const { currentUser } = useContext(AppContext) const history = useHistory() const [showAssignPersonModal, setShowAssignPersonModal] = useState(false) const [ @@ -182,7 +182,8 @@ const BasePositionShow = ({ pageDispatchers, currentUser }) => { relatedObject={ position.uuid && { relatedObjectType: Position.relatedObjectType, - relatedObjectUuid: position.uuid + relatedObjectUuid: position.uuid, + relatedObject: position } } /> @@ -433,17 +434,8 @@ const BasePositionShow = ({ pageDispatchers, currentUser }) => { } } -const PositionShow = props => ( - - {context => ( - - )} - -) - -BasePositionShow.propTypes = { - pageDispatchers: PageDispatchersPropType, - currentUser: PropTypes.instanceOf(Person) +PositionShow.propTypes = { + pageDispatchers: PageDispatchersPropType } export default connect(null, mapPageDispatchersToProps)(PositionShow) diff --git a/client/src/pages/reports/Edit.js b/client/src/pages/reports/Edit.js index ce053a647a..a3fbecb8a5 100644 --- a/client/src/pages/reports/Edit.js +++ b/client/src/pages/reports/Edit.js @@ -1,18 +1,20 @@ +import { gql } from "@apollo/client" import { DEFAULT_SEARCH_PROPS, PAGE_PROPS_NO_NAV } from "actions" import API from "api" -import { gql } from "apollo-boost" +import { DEFAULT_CUSTOM_FIELDS_PARENT } from "components/Model" import { - PageDispatchersPropType, mapPageDispatchersToProps, + PageDispatchersPropType, useBoilerplate } from "components/Page" import RelatedObjectNotes, { GRAPHQL_NOTES_FIELDS } from "components/RelatedObjectNotes" -import { Report } from "models" +import { Person, Report, Task } from "models" import React from "react" import { connect } from "react-redux" import { useParams } from "react-router-dom" +import utils from "utils" import ReportForm from "./Form" const GQL_GET_REPORT = gql` @@ -119,10 +121,20 @@ const ReportEdit = ({ pageDispatchers }) => { id: tag.uuid.toString(), text: tag.name })) - data.report.formCustomFields = JSON.parse(data.report.customFields) + data.report[DEFAULT_CUSTOM_FIELDS_PARENT] = utils.parseJsonSafe( + data.report.customFields + ) } const report = new Report(data ? data.report : {}) - const reportInitialValues = Object.assign(report, report.getTaskAssessments()) + const reportInitialValues = Object.assign( + report, + report.getTasksEngagementAssessments(), + report.getAttendeesEngagementAssessments() + ) + reportInitialValues.tasks = Task.fromArray(reportInitialValues.tasks) + reportInitialValues.attendees = Person.fromArray( + reportInitialValues.attendees + ) return (
@@ -131,7 +143,8 @@ const ReportEdit = ({ pageDispatchers }) => { relatedObject={ report.uuid && { relatedObjectType: Report.relatedObjectType, - relatedObjectUuid: report.uuid + relatedObjectUuid: report.uuid, + relatedObject: report } } /> diff --git a/client/src/pages/reports/Form.js b/client/src/pages/reports/Form.js index 3cf5d62e80..c065353799 100644 --- a/client/src/pages/reports/Form.js +++ b/client/src/pages/reports/Form.js @@ -1,7 +1,7 @@ +import { gql } from "@apollo/client" import { Icon } from "@blueprintjs/core" import { IconNames } from "@blueprintjs/icons" import API from "api" -import { gql } from "apollo-boost" import AdvancedMultiSelect from "components/advancedSelectWidget/AdvancedMultiSelect" import { AuthorizationGroupOverlayRow, @@ -11,6 +11,7 @@ import { } from "components/advancedSelectWidget/AdvancedSelectOverlayRow" import AdvancedSingleSelect from "components/advancedSelectWidget/AdvancedSingleSelect" import AppContext from "components/AppContext" +import InstantAssessmentsContainerField from "components/assessments/InstantAssessmentsContainerField" import ConfirmDelete from "components/ConfirmDelete" import CustomDateInput from "components/CustomDateInput" import { @@ -20,7 +21,11 @@ import { import * as FieldHelper from "components/FieldHelper" import Fieldset from "components/Fieldset" import Messages from "components/Messages" -import { createYupObjectShape, NOTE_TYPE } from "components/Model" +import { + ASSESSMENTS_RELATED_OBJECT_TYPE, + DEFAULT_CUSTOM_FIELDS_PARENT, + NOTE_TYPE +} from "components/Model" import NavigationWarning from "components/NavigationWarning" import { jumpToTop, @@ -28,6 +33,7 @@ import { PageDispatchersPropType, useBoilerplate } from "components/Page" +import { EXCLUDED_ASSESSMENT_FIELDS } from "components/RelatedObjectNotes" import ReportTags from "components/ReportTags" import RichTextEditor from "components/RichTextEditor" import { RECURSE_STRATEGY } from "components/SearchFilters" @@ -37,11 +43,12 @@ import _cloneDeep from "lodash/cloneDeep" import _debounce from "lodash/debounce" import _isEmpty from "lodash/isEmpty" import _upperFirst from "lodash/upperFirst" -import { AuthorizationGroup, Location, Person, Report, Task } from "models" +import { AuthorizationGroup, Location, Person, Report, Tag, Task } from "models" import moment from "moment" +import { RECURRENCE_TYPE } from "periodUtils" import pluralize from "pluralize" import PropTypes from "prop-types" -import React, { useEffect, useState } from "react" +import React, { useContext, useEffect, useState } from "react" import { Button, Checkbox, Collapse, HelpBlock } from "react-bootstrap" import { connect } from "react-redux" import { useHistory } from "react-router-dom" @@ -51,7 +58,6 @@ import PEOPLE_ICON from "resources/people.png" import TASKS_ICON from "resources/tasks.png" import Settings from "settings" import utils from "utils" -import * as yup from "yup" import AttendeesTable from "./AttendeesTable" import AuthorizationGroupTable from "./AuthorizationGroupTable" @@ -67,8 +73,7 @@ const GQL_GET_RECENTS = gql` } ) { list { - uuid - name + ${Location.autocompleteQuery} } } personList( @@ -81,43 +86,12 @@ const GQL_GET_RECENTS = gql` } ) { list { - uuid - name - rank - role - status - endOfTourDate - avatar(size: 32) - position { - uuid - name - type - status - organization { - uuid - shortName - } - location { - uuid - name - } - } + ${Person.autocompleteQuery} } } taskList(query: $taskQuery) { list { - uuid - shortName - longName - customFieldRef1 { - uuid - shortName - } - taskedOrganizations { - uuid - shortName - } - customFields + ${Task.autocompleteQuery} } } authorizationGroupList( @@ -130,9 +104,7 @@ const GQL_GET_RECENTS = gql` } ) { list { - uuid - name - description + ${AuthorizationGroup.autocompleteQuery} } } tagList( @@ -141,9 +113,7 @@ const GQL_GET_RECENTS = gql` } ) { list { - uuid - name - description + ${Tag.autocompleteQuery} } } } @@ -189,20 +159,24 @@ const GQL_UPDATE_REPORT_ASSESSMENTS = gql` } ` -const BaseReportForm = ({ +const ReportForm = ({ pageDispatchers, - currentUser, edit, title, initialValues, showSensitiveInfo: ssi }) => { + const { currentUser } = useContext(AppContext) const history = useHistory() const [showSensitiveInfo, setShowSensitiveInfo] = useState(ssi) const [saveError, setSaveError] = useState(null) const [autoSavedAt, setAutoSavedAt] = useState(null) - // We need the report tasks in order to be able to dynamically update the yup schema for the selected task assessments + // We need the report tasks/attendees in order to be able to dynamically + // update the yup schema for the selected tasks/attendees instant assessments const [reportTasks, setReportTasks] = useState(initialValues.tasks) + const [reportAttendees, setReportAttendees] = useState( + initialValues.attendees + ) // some autosave settings const defaultTimeout = moment.duration(30, "seconds") const autoSaveSettings = { @@ -242,7 +216,6 @@ const BaseReportForm = ({ text: "__should_not_match_anything__" // TODO: Do this more gracefully } } - const { loading, error, data } = API.useApiQuery(GQL_GET_RECENTS, { taskQuery: recentTasksVarUser }) @@ -269,17 +242,17 @@ const BaseReportForm = ({ { id: "positiveAtmos", value: Report.ATMOSPHERE.POSITIVE, - label: "Positive" + label: Report.ATMOSPHERE_LABELS[Report.ATMOSPHERE.POSITIVE] }, { id: "neutralAtmos", value: Report.ATMOSPHERE.NEUTRAL, - label: "Neutral" + label: Report.ATMOSPHERE_LABELS[Report.ATMOSPHERE.NEUTRAL] }, { id: "negativeAtmos", value: Report.ATMOSPHERE.NEGATIVE, - label: "Negative" + label: Report.ATMOSPHERE_LABELS[Report.ATMOSPHERE.NEGATIVE] } ] const cancelledReasonOptions = [ @@ -329,27 +302,29 @@ const BaseReportForm = ({ })) } - // Update the task assessments schema according to the selected report tasks - const taskAssessmentsSchemaShape = {} - reportTasks - .filter(t => t.customFields) - .forEach(t => { - taskAssessmentsSchemaShape[t.uuid] = createYupObjectShape( - JSON.parse(JSON.parse(t.customFields).assessmentDefinition), - `taskAssessments.${t.uuid}` - ) - }) - const reportSchema = _isEmpty(taskAssessmentsSchemaShape) - ? Report.yupSchema - : Report.yupSchema.concat( - yup.object().shape({ - taskAssessments: yup - .object() - .shape(taskAssessmentsSchemaShape) - .nullable() - .default(null) - }) - ) + // Update the report schema according to the selected report tasks and attendees + // instant assessments schema + const { + assessmentsConfig: tasksInstantAssessmentsConfig, + assessmentsSchema: tasksInstantAssessmentsSchema + } = Task.getInstantAssessmentsDetailsForEntities( + reportTasks, + Report.TASKS_ASSESSMENTS_PARENT_FIELD + ) + const { + assessmentsConfig: attendeesInstantAssessmentsConfig, + assessmentsSchema: attendeesInstantAssessmentsSchema + } = Person.getInstantAssessmentsDetailsForEntities( + reportAttendees, + Report.ATTENDEES_ASSESSMENTS_PARENT_FIELD + ) + let reportSchema = Report.yupSchema + if (!_isEmpty(tasksInstantAssessmentsConfig)) { + reportSchema = reportSchema.concat(tasksInstantAssessmentsSchema) + } + if (!_isEmpty(attendeesInstantAssessmentsConfig)) { + reportSchema = reportSchema.concat(attendeesInstantAssessmentsSchema) + } let validateFieldDebounced return ( @@ -634,7 +609,7 @@ const BaseReportForm = ({ title="Recent Locations" shortcuts={recents.locations} fieldName="location" - objectType="Location" + objectType={Location} curValue={values.location} onChange={value => { // validation will be done by setFieldValue @@ -721,7 +696,9 @@ const BaseReportForm = ({ validateFieldDebounced("atmosphereDetails") }} placeholder={`Why was this engagement ${values.atmosphere.toLowerCase()}? ${ - values.atmosphere === "POSITIVE" ? "(optional)" : "" + values.atmosphere === Report.ATMOSPHERE.POSITIVE + ? "(optional)" + : "" }`} className="atmosphere-details" /> @@ -750,9 +727,12 @@ const BaseReportForm = ({ name="attendees" component={FieldHelper.SpecialField} onChange={value => { - // validation will be done by setFieldValue - setFieldTouched("attendees", true, false) // onBlur doesn't work when selecting an option - updateAttendees(setFieldValue, "attendees", value) + updateAttendees( + setFieldValue, + setFieldTouched, + "attendees", + value + ) }} widget={ { - // validation will be done by setFieldValue - setFieldTouched("attendees", true, false) // onBlur doesn't work when selecting an option - updateAttendees(setFieldValue, "attendees", value) + updateAttendees( + setFieldValue, + setFieldTouched, + "attendees", + value + ) }} handleAddItem={FieldHelper.handleMultiSelectAddItem} /> @@ -850,12 +833,13 @@ const BaseReportForm = ({ title={`Recent ${tasksLabel}`} shortcuts={recents.tasks} fieldName="tasks" - objectType="Task" + objectType={Task} curValue={values.tasks} onChange={value => { // validation will be done by setFieldValue setFieldTouched("tasks", true, false) // onBlur doesn't work when selecting an option setFieldValue("tasks", value, true) + setReportTasks(value) }} handleAddItem={FieldHelper.handleMultiSelectAddItem} /> @@ -1040,7 +1024,7 @@ const BaseReportForm = ({ title="Recent Authorization Groups" shortcuts={recents.authorizationGroups} fieldName="authorizationGroups" - objectType="AuthorizationGroup" + objectType={AuthorizationGroup} curValue={values.authorizationGroups} onChange={value => { // validation will be done by setFieldValue @@ -1068,34 +1052,43 @@ const BaseReportForm = ({
- {values.tasks.map(task => { - if (!task.customFields) { - return null + +
+ +
+ - ) - })} + parentFieldName={Report.TASKS_ASSESSMENTS_PARENT_FIELD} + formikProps={{ + setFieldTouched, + setFieldValue, + values, + validateForm + }} + />
@@ -1151,7 +1144,9 @@ const BaseReportForm = ({ return _upperFirst(getReportType(values)) } - function updateAttendees(setFieldValue, field, attendees) { + function updateAttendees(setFieldValue, setFieldTouched, field, attendees) { + // validation will be done by setFieldValue + setFieldTouched(field, true, false) // onBlur doesn't work when selecting an option attendees.forEach(attendee => { if (!attendees.find(a2 => attendee.role === a2.role && a2.primary)) { attendee.primary = true @@ -1161,6 +1156,7 @@ const BaseReportForm = ({ } }) setFieldValue(field, attendees, true) + setReportAttendees(attendees) } function countCharsLeft(elemId, maxChars, event) { @@ -1275,28 +1271,43 @@ const BaseReportForm = ({ }) } - function isEmptyTaskAssessment(assessment) { + function isEmptyAssessment(assessment) { return ( - (Object.keys(assessment).length === 1 && - Object.keys(assessment)[0] === "invisibleCustomFields") || - _isEmpty(assessment) + Object.entries(assessment).filter( + ([key, value]) => + !EXCLUDED_ASSESSMENT_FIELDS.includes(key) && + value !== null && + value !== undefined && + !utils.isEmptyHtml(value) + ).length < 1 ) } - function createTaskAssessmentsNotes(values, reportUuid) { - const selectedTasksUuids = values.tasks.map(t => t.uuid) - return Object.keys(values.taskAssessments) + function createInstantAssessments( + entityType, + entities, + values, + asessmentsFieldName, + assessmentsUuidsFieldName, + reportUuid + ) { + const entitiesUuids = entities.map(e => e.uuid) + const entitiesAssessments = values[asessmentsFieldName] + return Object.keys(entitiesAssessments) .filter( key => - selectedTasksUuids.includes(key) && - !isEmptyTaskAssessment(values.taskAssessments[key]) + entitiesUuids.includes(key) && + !isEmptyAssessment(entitiesAssessments[key]) ) .map(key => { + entitiesAssessments[key].__recurrence = RECURRENCE_TYPE.ONCE + entitiesAssessments[key].__relatedObjectType = + ASSESSMENTS_RELATED_OBJECT_TYPE.REPORT const noteObj = { type: NOTE_TYPE.ASSESSMENT, noteRelatedObjects: [ { - relatedObjectType: Task.relatedObjectType, + relatedObjectType: entityType.relatedObjectType, relatedObjectUuid: key }, { @@ -1304,9 +1315,13 @@ const BaseReportForm = ({ relatedObjectUuid: reportUuid } ], - text: customFieldsJSONString(values, true, `taskAssessments.${key}`) + text: customFieldsJSONString( + values, + true, + `${asessmentsFieldName}.${key}` + ) } - const initialAssessmentUuid = values.taskToAssessmentUuid[key] + const initialAssessmentUuid = values[assessmentsUuidsFieldName][key] if (initialAssessmentUuid) { noteObj.uuid = initialAssessmentUuid } @@ -1323,9 +1338,11 @@ const BaseReportForm = ({ "attendees", "tasks", "customFields", // initial JSON from the db - "formCustomFields", - "taskAssessments", - "taskToAssessmentUuid" + DEFAULT_CUSTOM_FIELDS_PARENT, + Report.TASKS_ASSESSMENTS_PARENT_FIELD, + Report.ATTENDEES_ASSESSMENTS_PARENT_FIELD, + Report.TASKS_ASSESSMENTS_UUIDS_FIELD, + Report.ATTENDEES_ASSESSMENTS_UUIDS_FIELD ) if (Report.isFuture(values.engagementDate)) { // Empty fields which should not be set for future reports. @@ -1355,7 +1372,7 @@ const BaseReportForm = ({ "lastName", "position", "customFields", - "formCustomFields" + DEFAULT_CUSTOM_FIELDS_PARENT ) ) // strip tasks fields not in data model @@ -1368,10 +1385,23 @@ const BaseReportForm = ({ return _saveReport(edit, variables, sendEmail).then(response => { const report = response[operation] const updateNotesVariables = { report } - updateNotesVariables.notes = createTaskAssessmentsNotes( + const tasksNotes = createInstantAssessments( + Task, + values.tasks, values, + Report.TASKS_ASSESSMENTS_PARENT_FIELD, + Report.TASKS_ASSESSMENTS_UUIDS_FIELD, report.uuid ) + const attendeesNotes = createInstantAssessments( + Person, + values.attendees, + values, + Report.ATTENDEES_ASSESSMENTS_PARENT_FIELD, + Report.ATTENDEES_ASSESSMENTS_UUIDS_FIELD, + report.uuid + ) + updateNotesVariables.notes = tasksNotes.concat(attendeesNotes) return API.mutation( GQL_UPDATE_REPORT_ASSESSMENTS, updateNotesVariables @@ -1382,7 +1412,6 @@ const BaseReportForm = ({ function _saveReport(edit, variables, sendEmail) { if (edit) { variables.sendEditEmail = sendEmail - // Add an additional mutation to create notes for the taskAssessments return API.mutation(GQL_UPDATE_REPORT, variables) } else { return API.mutation(GQL_CREATE_REPORT, variables) @@ -1390,25 +1419,18 @@ const BaseReportForm = ({ } } -BaseReportForm.propTypes = { +ReportForm.propTypes = { pageDispatchers: PageDispatchersPropType, initialValues: PropTypes.instanceOf(Report).isRequired, title: PropTypes.string, edit: PropTypes.bool, - showSensitiveInfo: PropTypes.bool, - currentUser: PropTypes.instanceOf(Person) + showSensitiveInfo: PropTypes.bool } -BaseReportForm.defaultProps = { +ReportForm.defaultProps = { title: "", edit: false, showSensitiveInfo: false } -const ReportForm = props => ( - - {context => } - -) - export default connect(null, mapPageDispatchersToProps)(ReportForm) diff --git a/client/src/pages/reports/Minimal.js b/client/src/pages/reports/Minimal.js index 2a28de4560..ed774c4cd4 100644 --- a/client/src/pages/reports/Minimal.js +++ b/client/src/pages/reports/Minimal.js @@ -1,6 +1,6 @@ +import { gql } from "@apollo/client" import { DEFAULT_SEARCH_PROPS, PAGE_PROPS_MIN_HEAD } from "actions" import API from "api" -import { gql } from "apollo-boost" import * as FieldHelper from "components/FieldHelper" import Fieldset from "components/Fieldset" import LinkTo from "components/LinkTo" diff --git a/client/src/pages/reports/MyReports.js b/client/src/pages/reports/MyReports.js index 2bf5bb3be4..ac4469b633 100644 --- a/client/src/pages/reports/MyReports.js +++ b/client/src/pages/reports/MyReports.js @@ -5,20 +5,24 @@ import { PageDispatchersPropType, mapPageDispatchersToProps } from "components/Page" -import ReportCollection from "components/ReportCollection" +import ReportCollection, { + FORMAT_CALENDAR, + FORMAT_MAP, + FORMAT_STATISTICS, + FORMAT_SUMMARY, + FORMAT_TABLE +} from "components/ReportCollection" import { SearchQueryPropType, getSearchQuery } from "components/SearchFilters" import SubNav from "components/SubNav" -import { Person, Report } from "models" -import PropTypes from "prop-types" -import React from "react" +import { Report } from "models" +import React, { useContext } from "react" import { Nav } from "react-bootstrap" import { connect } from "react-redux" -const BaseMyReports = ({ - pageDispatchers, - searchQuery, - currentUser: { uuid } -}) => { +const MyReports = ({ pageDispatchers, searchQuery }) => { + const { + currentUser: { uuid } + } = useContext(AppContext) const sectionQueryParams = { draft: { state: [Report.STATE.DRAFT, Report.STATE.REJECTED] @@ -83,15 +87,21 @@ const BaseMyReports = ({ paginationKey={`r_${id}_${uuid}`} queryParams={queryParams} mapId={id} + viewFormats={[ + FORMAT_SUMMARY, + FORMAT_TABLE, + FORMAT_CALENDAR, + FORMAT_MAP, + FORMAT_STATISTICS + ]} /> ) } } -BaseMyReports.propTypes = { +MyReports.propTypes = { pageDispatchers: PageDispatchersPropType, - currentUser: PropTypes.instanceOf(Person), searchQuery: SearchQueryPropType } @@ -99,10 +109,4 @@ const mapStateToProps = (state, ownProps) => ({ searchQuery: state.searchQuery }) -const MyReports = props => ( - - {context => } - -) - export default connect(mapStateToProps, mapPageDispatchersToProps)(MyReports) diff --git a/client/src/pages/reports/New.js b/client/src/pages/reports/New.js index e6e818cfa3..da6748e109 100644 --- a/client/src/pages/reports/New.js +++ b/client/src/pages/reports/New.js @@ -8,12 +8,12 @@ import { } from "components/Page" import { Person, Report } from "models" import { reportTour } from "pages/HopscotchTour" -import PropTypes from "prop-types" -import React from "react" +import React, { useContext } from "react" import { connect } from "react-redux" import ReportForm from "./Form" -const BaseReportNew = ({ pageDispatchers, currentUser }) => { +const ReportNew = ({ pageDispatchers }) => { + const { currentUser } = useContext(AppContext) useBoilerplate({ pageProps: PAGE_PROPS_NO_NAV, searchProps: DEFAULT_SEARCH_PROPS, @@ -26,7 +26,11 @@ const BaseReportNew = ({ pageDispatchers, currentUser }) => { person.primary = true report.attendees.push(person) } - const reportInitialValues = Object.assign(report, report.getTaskAssessments()) + const reportInitialValues = Object.assign( + report, + report.getTasksEngagementAssessments(), + report.getAttendeesEngagementAssessments() + ) return (
@@ -50,15 +54,8 @@ const BaseReportNew = ({ pageDispatchers, currentUser }) => { ) } -BaseReportNew.propTypes = { - pageDispatchers: PageDispatchersPropType, - currentUser: PropTypes.instanceOf(Person) +ReportNew.propTypes = { + pageDispatchers: PageDispatchersPropType } -const ReportNew = props => ( - - {context => } - -) - export default connect(null, mapPageDispatchersToProps)(ReportNew) diff --git a/client/src/pages/reports/Show.js b/client/src/pages/reports/Show.js index 0ac0d26605..ba7980966a 100644 --- a/client/src/pages/reports/Show.js +++ b/client/src/pages/reports/Show.js @@ -1,3 +1,4 @@ +import { gql } from "@apollo/client" import { DEFAULT_PAGE_PROPS, DEFAULT_SEARCH_PROPS, @@ -5,14 +6,15 @@ import { setSearchQuery } from "actions" import API from "api" -import { gql } from "apollo-boost" import AppContext from "components/AppContext" +import InstantAssessmentsContainerField from "components/assessments/InstantAssessmentsContainerField" import ConfirmDelete from "components/ConfirmDelete" import { ReadonlyCustomFields } from "components/CustomFields" import * as FieldHelper from "components/FieldHelper" import Fieldset from "components/Fieldset" import LinkTo from "components/LinkTo" import Messages from "components/Messages" +import { DEFAULT_CUSTOM_FIELDS_PARENT } from "components/Model" import { AnchorLink, PageDispatchersPropType, @@ -30,11 +32,11 @@ import { Field, Form, Formik } from "formik" import _concat from "lodash/concat" import _isEmpty from "lodash/isEmpty" import _upperFirst from "lodash/upperFirst" -import { Comment, Person, Position, Report } from "models" +import { Comment, Person, Position, Report, Task } from "models" import moment from "moment" import pluralize from "pluralize" import PropTypes from "prop-types" -import React, { useState } from "react" +import React, { useContext, useState } from "react" import { Alert, Button, Col, HelpBlock, Modal } from "react-bootstrap" import Confirm from "react-confirm-bootstrap" import { connect } from "react-redux" @@ -268,7 +270,8 @@ const GQL_APPROVE_REPORT = gql` } ` -const BaseReportShow = ({ currentUser, setSearchQuery, pageDispatchers }) => { +const ReportShow = ({ setSearchQuery, pageDispatchers }) => { + const { currentUser } = useContext(AppContext) const history = useHistory() const [saveSuccess, setSaveSuccess] = useState(null) const [saveError, setSaveError] = useState(null) @@ -299,8 +302,12 @@ const BaseReportShow = ({ currentUser, setSearchQuery, pageDispatchers }) => { id: tag.uuid.toString(), text: tag.name })) + data.report.tasks = Task.fromArray(data.report.tasks) + data.report.attendees = Person.fromArray(data.report.attendees) data.report.to = "" - data.report.formCustomFields = JSON.parse(data.report.customFields) + data.report[DEFAULT_CUSTOM_FIELDS_PARENT] = utils.parseJsonSafe( + data.report.customFields + ) report = new Report(data.report) try { Report.yupSchema.validateSync(report, { abortEarly: false }) @@ -351,8 +358,9 @@ const BaseReportShow = ({ currentUser, setSearchQuery, pageDispatchers }) => { const hasAuthorizationGroups = report.authorizationGroups && report.authorizationGroups.length > 0 - // Get initial task assessments values - report = Object.assign(report, report.getTaskAssessments()) + // Get initial tasks/attendees instant assessments values + report = Object.assign(report, report.getTasksEngagementAssessments()) + report = Object.assign(report, report.getAttendeesEngagementAssessments()) return ( { relatedObject={ uuid && { relatedObjectType: Report.relatedObjectType, - relatedObjectUuid: uuid + relatedObjectUuid: uuid, + relatedObject: report } } /> @@ -654,29 +663,32 @@ const BaseReportShow = ({ currentUser, setSearchQuery, pageDispatchers }) => { )}
- {values.tasks.map(task => { - if (!task.customFields) { - return null - } - const taskCustomFields = JSON.parse(task.customFields) - if (!taskCustomFields.assessmentDefinition) { - return null - } - const taskAssessmentDefinition = JSON.parse( - taskCustomFields.assessmentDefinition - ) - return ( - - ) - })} + +
+
+
{report.showWorkflow() && ( @@ -1112,10 +1124,13 @@ const BaseReportShow = ({ currentUser, setSearchQuery, pageDispatchers }) => { confirmHandler, cancelHandler ) { - const validationWarnings = warnApproveOwnReport - ? [`You are requesting changes to your own ${reportType}`] - : [] - return _isEmpty(validationWarnings) ? ( + const warnings = _concat( + validationWarnings || [], + warnApproveOwnReport + ? [`You are requesting changes to your own ${reportType}`] + : [] + ) + return _isEmpty(warnings) ? ( @@ -1124,7 +1139,7 @@ const BaseReportShow = ({ currentUser, setSearchQuery, pageDispatchers }) => { onConfirm={confirmHandler} onClose={cancelHandler} title="Request changes?" - body={renderValidationWarnings(validationWarnings, "rejecting")} + body={renderValidationWarnings(warnings, "rejecting")} confirmText="Request changes anyway" cancelText="Cancel change request" dialogClassName="react-confirm-bootstrap-modal" @@ -1208,13 +1223,11 @@ const BaseReportShow = ({ currentUser, setSearchQuery, pageDispatchers }) => { id, className ) { - let validationWarnings = warnApproveOwnReport - ? [`You are approving your own ${reportType}`] - : [] - if (!_isEmpty(validationWarnings)) { - validationWarnings = _concat(validationWarnings, validationWarnings) - } - return _isEmpty(validationWarnings) ? ( + const warnings = _concat( + validationWarnings || [], + warnApproveOwnReport ? [`You are approving your own ${reportType}`] : [] + ) + return _isEmpty(warnings) ? (
) @@ -252,7 +258,8 @@ Map.propTypes = { queryParams: PropTypes.object } -const BaseRollupShow = ({ pageDispatchers, appSettings, searchQuery }) => { +const RollupShow = ({ pageDispatchers, searchQuery }) => { + const { appSettings } = useContext(AppContext) const history = useHistory() const routerLocation = useLocation() const { startDate, endDate } = getDateRangeFromQS(routerLocation.search) @@ -648,8 +655,7 @@ const BaseRollupShow = ({ pageDispatchers, appSettings, searchQuery }) => { } } -BaseRollupShow.propTypes = { - appSettings: PropTypes.object, +RollupShow.propTypes = { searchQuery: SearchQueryPropType, pageDispatchers: PageDispatchersPropType } @@ -658,10 +664,4 @@ const mapStateToProps = (state, ownProps) => ({ searchQuery: state.searchQuery }) -const RollupShow = props => ( - - {context => } - -) - export default connect(mapStateToProps, mapPageDispatchersToProps)(RollupShow) diff --git a/client/src/pages/tasks/Edit.js b/client/src/pages/tasks/Edit.js index e324af3172..c031778417 100644 --- a/client/src/pages/tasks/Edit.js +++ b/client/src/pages/tasks/Edit.js @@ -1,9 +1,10 @@ +import { gql } from "@apollo/client" import { DEFAULT_SEARCH_PROPS, PAGE_PROPS_NO_NAV } from "actions" import API from "api" -import { gql } from "apollo-boost" +import { DEFAULT_CUSTOM_FIELDS_PARENT } from "components/Model" import { - PageDispatchersPropType, mapPageDispatchersToProps, + PageDispatchersPropType, useBoilerplate } from "components/Page" import RelatedObjectNotes, { @@ -14,6 +15,7 @@ import React from "react" import { connect } from "react-redux" import { useParams } from "react-router-dom" import Settings from "settings" +import utils from "utils" import TaskForm from "./Form" const GQL_GET_TASK = gql` @@ -113,7 +115,9 @@ const TaskEdit = ({ pageDispatchers }) => { return result } if (data) { - data.task.formCustomFields = JSON.parse(data.task.customFields) + data.task[DEFAULT_CUSTOM_FIELDS_PARENT] = utils.parseJsonSafe( + data.task.customFields + ) } const task = new Task(data ? data.task : {}) @@ -124,7 +128,8 @@ const TaskEdit = ({ pageDispatchers }) => { relatedObject={ task.uuid && { relatedObjectType: Task.relatedObjectType, - relatedObjectUuid: task.uuid + relatedObjectUuid: task.uuid, + relatedObject: task } } /> diff --git a/client/src/pages/tasks/Form.js b/client/src/pages/tasks/Form.js index 2312af4afb..63a094223b 100644 --- a/client/src/pages/tasks/Form.js +++ b/client/src/pages/tasks/Form.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import AdvancedMultiSelect from "components/advancedSelectWidget/AdvancedMultiSelect" import { OrganizationOverlayRow, @@ -17,16 +17,20 @@ import { import * as FieldHelper from "components/FieldHelper" import Fieldset from "components/Fieldset" import Messages from "components/Messages" -import { GRAPHQL_NOTE_FIELDS, NOTE_TYPE } from "components/Model" +import { + DEFAULT_CUSTOM_FIELDS_PARENT, + GRAPHQL_NOTE_FIELDS, + NOTE_TYPE +} from "components/Model" import NavigationWarning from "components/NavigationWarning" import { jumpToTop } from "components/Page" import PositionTable from "components/PositionTable" import OrganizationTable from "components/OrganizationTable" import RichTextEditor from "components/RichTextEditor" import { FastField, Field, Form, Formik } from "formik" -import { Organization, Person, Position, Task } from "models" +import { Organization, Position, Task } from "models" import PropTypes from "prop-types" -import React, { useState } from "react" +import React, { useContext, useState } from "react" import { Button } from "react-bootstrap" import { useHistory } from "react-router-dom" import ORGANIZATIONS_ICON from "resources/organizations.png" @@ -52,7 +56,8 @@ const GQL_UPDATE_TASK = gql` } ` -const BaseTaskForm = ({ currentUser, edit, title, initialValues }) => { +const TaskForm = ({ edit, title, initialValues }) => { + const { currentUser } = useContext(AppContext) const history = useHistory() const [error, setError] = useState(null) const statusButtons = [ @@ -496,7 +501,7 @@ const BaseTaskForm = ({ currentUser, edit, title, initialValues }) => { "notes", "assessment_customFieldEnum1", "customFields", // initial JSON from the db - "formCustomFields" + DEFAULT_CUSTOM_FIELDS_PARENT ) task.customFieldRef1 = utils.getReference(task.customFieldRef1) task.customFields = customFieldsJSONString(values) @@ -533,22 +538,15 @@ const BaseTaskForm = ({ currentUser, edit, title, initialValues }) => { } } -BaseTaskForm.propTypes = { +TaskForm.propTypes = { initialValues: PropTypes.instanceOf(Task).isRequired, title: PropTypes.string, - edit: PropTypes.bool, - currentUser: PropTypes.instanceOf(Person) + edit: PropTypes.bool } -BaseTaskForm.defaultProps = { +TaskForm.defaultProps = { title: "", edit: false } -const TaskForm = props => ( - - {context => } - -) - export default TaskForm diff --git a/client/src/pages/tasks/New.js b/client/src/pages/tasks/New.js index 9bd46b5447..8192de4090 100644 --- a/client/src/pages/tasks/New.js +++ b/client/src/pages/tasks/New.js @@ -1,6 +1,6 @@ +import { gql } from "@apollo/client" import { DEFAULT_SEARCH_PROPS, PAGE_PROPS_NO_NAV } from "actions" import API from "api" -import { gql } from "apollo-boost" import { PageDispatchersPropType, mapPageDispatchersToProps, diff --git a/client/src/pages/tasks/Show.js b/client/src/pages/tasks/Show.js index 03414fd257..9ed7d2fbff 100644 --- a/client/src/pages/tasks/Show.js +++ b/client/src/pages/tasks/Show.js @@ -1,13 +1,14 @@ +import { gql } from "@apollo/client" import { DEFAULT_PAGE_PROPS, DEFAULT_SEARCH_PROPS } from "actions" import API from "api" -import { gql } from "apollo-boost" import AppContext from "components/AppContext" import Approvals from "components/approvals/Approvals" -import AssessmentResultsTable from "components/assessments/AssessmentResultsTable" +import AssessmentResultsContainer from "components/assessments/AssessmentResultsContainer" import * as FieldHelper from "components/FieldHelper" import Fieldset from "components/Fieldset" import LinkTo from "components/LinkTo" import Messages from "components/Messages" +import { DEFAULT_CUSTOM_FIELDS_PARENT, NOTE_TYPE } from "components/Model" import { mapPageDispatchersToProps, PageDispatchersPropType, @@ -20,13 +21,13 @@ import RelatedObjectNotes, { import ReportCollection from "components/ReportCollection" import { Field, Form, Formik } from "formik" import _isEmpty from "lodash/isEmpty" -import { Person, Report, Task } from "models" +import { Task } from "models" import moment from "moment" -import PropTypes from "prop-types" -import React from "react" +import React, { useContext } from "react" import { connect } from "react-redux" import { useLocation, useParams } from "react-router-dom" import Settings from "settings" +import utils from "utils" import DictionaryField from "../../HOC/DictionaryField" const GQL_GET_TASK = gql` @@ -104,12 +105,6 @@ const GQL_GET_TASK = gql` } customFields ${GRAPHQL_NOTES_FIELDS} - publishedReports: reports(query: { - pageSize: 0 - state: [${Report.STATE.PUBLISHED}] - }) { - uuid - } } subTasks: taskList(query: { pageSize: 0 @@ -126,18 +121,13 @@ const GQL_GET_TASK = gql` } customFields ${GRAPHQL_NOTES_FIELDS} - publishedReports: reports(query: { - pageSize: 0 - state: [${Report.STATE.PUBLISHED}] - }) { - uuid - } } } } ` -const BaseTaskShow = ({ pageDispatchers, currentUser }) => { +const TaskShow = ({ pageDispatchers }) => { + const { currentUser } = useContext(AppContext) const { uuid } = useParams() const routerLocation = useLocation() const { loading, error, data, refetch } = API.useApiQuery(GQL_GET_TASK, { @@ -159,15 +149,25 @@ const BaseTaskShow = ({ pageDispatchers, currentUser }) => { } if (data) { - data.task.formCustomFields = JSON.parse(data.task.customFields) // TODO: Maybe move this code to Task() - data.task.notes.forEach(note => (note.customFields = JSON.parse(note.text))) // TODO: Maybe move this code to Task() + data.task[DEFAULT_CUSTOM_FIELDS_PARENT] = utils.parseJsonSafe( + data.task.customFields + ) + data.task.notes.forEach( + note => + note.type !== NOTE_TYPE.FREE_TEXT && + (note.customFields = utils.parseJsonSafe(note.text)) + ) // TODO: Maybe move this code to Task() } const task = new Task(data ? data.task : {}) const subTasks = [] data && data.subTasks.list.forEach(subTask => { - subTask.notes.forEach(note => (note.customFields = JSON.parse(note.text))) // TODO: Maybe move this code to Task() + subTask.notes.forEach( + note => + note.type !== NOTE_TYPE.FREE_TEXT && + (note.customFields = utils.parseJsonSafe(note.text)) + ) // TODO: Maybe move this code to Task() subTasks.push(new Task(subTask)) }) @@ -193,24 +193,6 @@ const BaseTaskShow = ({ pageDispatchers, currentUser }) => { position => currentUser.position.uuid === position.uuid ) )) - const now = moment() - const assessmentPeriods = [ - { - start: now.clone().subtract(2, "months").startOf("month"), - end: now.clone().subtract(2, "months").endOf("month"), - allowNewAssessments: false - }, - { - start: now.clone().subtract(1, "months").startOf("month"), - end: now.clone().subtract(1, "months").endOf("month"), - allowNewAssessments: true - }, - { - start: now.clone().startOf("month"), - end: now.clone().endOf("month"), - allowNewAssessments: false - } - ] return ( {({ values }) => { @@ -226,7 +208,8 @@ const BaseTaskShow = ({ pageDispatchers, currentUser }) => { relatedObject={ task.uuid && { relatedObjectType: Task.relatedObjectType, - relatedObjectUuid: task.uuid + relatedObjectUuid: task.uuid, + relatedObject: task } } /> @@ -351,14 +334,12 @@ const BaseTaskShow = ({ pageDispatchers, currentUser }) => {
-
@@ -386,15 +367,8 @@ const BaseTaskShow = ({ pageDispatchers, currentUser }) => { ) } -BaseTaskShow.propTypes = { - pageDispatchers: PageDispatchersPropType, - currentUser: PropTypes.instanceOf(Person) +TaskShow.propTypes = { + pageDispatchers: PageDispatchersPropType } -const TaskShow = props => ( - - {context => } - -) - export default connect(null, mapPageDispatchersToProps)(TaskShow) diff --git a/client/src/pages/util.js b/client/src/pages/util.js index 002e5e84f6..698ce41292 100644 --- a/client/src/pages/util.js +++ b/client/src/pages/util.js @@ -7,7 +7,6 @@ export const PAGE_URLS = { HOME: "/", SEARCH: "/search", ROLLUP: "/rollup", - GRAPHIQL: "/graphiql", HELP: "/help", REPORTS: "/reports", PEOPLE: "/people", @@ -17,6 +16,7 @@ export const PAGE_URLS = { TASKS: "/tasks", ADMIN: "/admin", INSIGHTS: "/insights", + BOARD: "/dashboards/board", KANBAN: "/dashboards/kanban", DECISIVES: "/dashboards/decisives", ONBOARDING: "/onboarding", diff --git a/client/src/periodUtils.js b/client/src/periodUtils.js new file mode 100644 index 0000000000..9f09b0cb45 --- /dev/null +++ b/client/src/periodUtils.js @@ -0,0 +1,156 @@ +import moment from "moment" +import PropTypes from "prop-types" +import React from "react" +import { momentObj } from "react-moment-proptypes" + +const now = moment() + +export const RECURRENCE_TYPE = { + ONCE: "once", + DAILY: "daily", + WEEKLY: "weekly", + BIWEEKLY: "biweekly", + SEMIMONTHLY: "semimonthly", + MONTHLY: "monthly", + QUARTERLY: "quarterly", + SEMIANNUALY: "semiannualy" +} + +const PERIOD_FORMAT = { + START_SHORT: "D", + START_MIDDLE: "D MMMM", + START_LONG: "D MMMM YYYY", + END_LONG: "D MMMM YYYY" +} + +export const PERIOD_FACTORIES = { + [RECURRENCE_TYPE.DAILY]: (date, offset) => ({ + start: date.clone().subtract(offset, "days").startOf("day"), + end: date.clone().subtract(offset, "days").endOf("day") + }), + [RECURRENCE_TYPE.WEEKLY]: (date, offset) => ({ + start: date.clone().subtract(offset, "weeks").startOf("week"), + end: date.clone().subtract(offset, "weeks").endOf("week") + }), + // FIXME: biweekly calculation should be changed, first agree on what it means + [RECURRENCE_TYPE.BIWEEKLY]: (date, offset) => ({ + start: date + .clone() + .subtract(2 * offset, "weeks") + .startOf("week"), + end: date + .clone() + .subtract(2 * offset, "weeks") + .endOf("week") + }), + [RECURRENCE_TYPE.SEMIMONTHLY]: (date, offset) => ({ + start: + date.date() < 15 + ? date.clone().subtract(offset, "months").startOf("month") + : date.clone().subtract(offset, "months").startOf("month").date(15), + end: + date.date() < 15 + ? date.clone().subtract(offset, "months").startOf("month").date(14) + : date.clone().subtract(offset, "months").endOf("month") + }), + [RECURRENCE_TYPE.MONTHLY]: (date, offset) => ({ + start: date.clone().subtract(offset, "months").startOf("month"), + end: date.clone().subtract(offset, "months").endOf("month") + }), + [RECURRENCE_TYPE.QUARTERLY]: (date, offset) => ({ + start: date.clone().subtract(offset, "quarters").startOf("quarter"), + end: date.clone().subtract(offset, "quarters").endOf("quarter") + }), + [RECURRENCE_TYPE.SEMIANNUALY]: (date, offset) => ({ + start: date + .clone() + .subtract(2 * offset, "quarters") + .startOf("quarter"), + end: date + .clone() + .subtract(2 * offset, "quarters") + .endOf("quarter") + }) +} + +export const getPeriodsConfig = ( + recurrence, + numberOfperiods, + offset, + forAssessments = false +) => { + const periods = [] + for (var i = numberOfperiods - 1; i >= 0; i--) { + const periodDetails = { ...PERIOD_FACTORIES[recurrence](now, offset + i) } + if (forAssessments) { + periodDetails.allowNewAssessments = offset + i !== 0 + } + periods.push(periodDetails) + } + return { + recurrence: recurrence, + periods: periods + } +} + +export const PeriodsDetailsPropType = PropTypes.shape({ + recurrence: PropTypes.string.isRequired, + numberOfPeriods: PropTypes.number.isRequired +}) + +export const PeriodPropType = PropTypes.shape({ + start: momentObj.isRequired, + end: momentObj.isRequired +}) +export const PeriodsPropType = PropTypes.arrayOf(PeriodPropType) +export const PeriodsConfigPropType = PropTypes.shape({ + recurrence: PropTypes.string.isRequired, + periods: PeriodsPropType.isRequired +}) + +export const AssessmentPeriodPropType = PropTypes.shape({ + start: momentObj.isRequired, + end: momentObj.isRequired, + allowNewAssessments: PropTypes.bool +}) +export const AssessmentPeriodsPropType = PropTypes.arrayOf( + AssessmentPeriodPropType +) +export const AssessmentPeriodsConfigPropType = PropTypes.shape({ + recurrence: PropTypes.string.isRequired, + periods: AssessmentPeriodsPropType.isRequired +}) + +export const periodToString = period => { + if (period.start.isSame(period.end, "day")) { + return period.end.format(PERIOD_FORMAT.END_LONG) + } else { + const periodStartFormat = + period.start.year() !== period.end.year() + ? PERIOD_FORMAT.START_LONG + : period.start.month() !== period.end.month() + ? PERIOD_FORMAT.START_MIDDLE + : PERIOD_FORMAT.START_SHORT + return `${period.start.format(periodStartFormat)} - ${period.end.format( + PERIOD_FORMAT.END_LONG + )}` + } +} + +export const PeriodsTableHeader = ({ periodsConfig }) => ( + + + <> + {periodsConfig.periods.map(period => ( + {periodToString(period)} + ))} + + + +) +PeriodsTableHeader.propTypes = { + periodsConfig: PropTypes.oneOfType([ + AssessmentPeriodsConfigPropType, + PeriodsConfigPropType + ]) +} diff --git a/client/src/utils.js b/client/src/utils.js index 811963168f..814fa3ad8a 100644 --- a/client/src/utils.js +++ b/client/src/utils.js @@ -22,9 +22,29 @@ Object.keys(changeCase) !input ? "" : changeCase[c](input, options) }) +const isNullOrUndefined = value => { + return value === null || value === undefined +} + +const fnRequiredWhen = (boolPropName, props, propName, componentName) => { + if (props[boolPropName] && typeof props[propName] !== "function") { + return new Error( + `Prop "${componentName}.${propName}" is a required function if "${boolPropName}" is true` + ) + } +} + +const ellipsize = (value, maxLength) => + value.length > maxLength + ? value.substring(0, maxLength - 1) + "\u2026" + : value + export default { ...wrappedChangeCase, pluralize, + isNullOrUndefined, + fnRequiredWhen, + ellipsize, resourceize: function(string) { return pluralize(wrappedChangeCase.camelCase(string)) }, @@ -138,6 +158,10 @@ export default { return _isEmpty(text) }, + isNumeric: function(value) { + return typeof value === "number" + }, + pushHash: function(hash) { const { history, location } = window hash = hash ? (hash.indexOf("#") === 0 ? hash : "#" + hash) : "" @@ -151,6 +175,24 @@ export default { } else { location.hash = hash } + }, + + parseJsonSafe: function(jsonString) { + // TODO: Improve error handling so that consuming widgets can display an error w/o crashing + let result + try { + result = JSON.parse(jsonString || "{}") + } catch (error) { + console.error(`unable to parse JSON: ${jsonString}`) + } + return typeof result === "object" ? result || {} : {} + }, + + arrayOfNumbers: function(arr) { + return ( + arr && + arr.filter(n => !isNaN(parseFloat(n)) && isFinite(n)).map(n => Number(n)) + ) } } @@ -172,7 +214,7 @@ Object.get = function(source, keypath) { while (keys[0]) { const key = keys.shift() source = source[key] - if (source === undefined || source === null) { + if (isNullOrUndefined(source)) { return source } } diff --git a/client/src/utils_links.js b/client/src/utils_links.js index 20f1996ca3..e36221613e 100644 --- a/client/src/utils_links.js +++ b/client/src/utils_links.js @@ -1,78 +1,20 @@ -import API from "api" -import { gql } from "apollo-boost" import LinkAnet from "components/editor/LinkAnet" import parse from "html-react-parser" +import * as Models from "models" import { PAGE_URLS } from "pages/util" import React from "react" const UUID_REGEX = "^[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}$" -const GQL_GET_REPORT = gql` - query($uuid: String!) { - entity: report(uuid: $uuid) { - uuid - intent - } - } -` - -const GQL_GET_PERSON = gql` - query($uuid: String!) { - entity: person(uuid: $uuid) { - uuid - name - role - avatar(size: 32) - } - } -` - -const GQL_GET_ORGANIZATION = gql` - query($uuid: String!) { - entity: organization(uuid: $uuid) { - uuid - shortName - } - } -` - -const GQL_GET_POSITION = gql` - query($uuid: String!) { - entity: position(uuid: $uuid) { - uuid - name - } - } -` - -const GQL_GET_LOCATION = gql` - query($uuid: String!) { - entity: location(uuid: $uuid) { - uuid - name - } - } -` - -const GQL_GET_TASK = gql` - query($uuid: String!) { - entity: task(uuid: $uuid) { - uuid - shortName - longName - } - } -` - // Entity type --> entity name export const ENTITY_TYPES = { - REPORTS: "Report", - PEOPLE: "Person", - ORGANIZATIONS: "Organization", - POSITIONS: "Position", - LOCATIONS: "Location", - TASKS: "Task" + REPORTS: Models.Report.resourceName, + PEOPLE: Models.Person.resourceName, + ORGANIZATIONS: Models.Organization.resourceName, + POSITIONS: Models.Position.resourceName, + LOCATIONS: Models.Location.resourceName, + TASKS: Models.Task.resourceName } // Entity URL --> Entity type @@ -85,16 +27,6 @@ const ENTITY_URL_TYPES = { [PAGE_URLS.TASKS]: ENTITY_TYPES.TASKS } -// Entity type --> GQL query -const ENTITY_GQL_QUERIES = { - [ENTITY_TYPES.REPORTS]: GQL_GET_REPORT, - [ENTITY_TYPES.PEOPLE]: GQL_GET_PERSON, - [ENTITY_TYPES.ORGANIZATIONS]: GQL_GET_ORGANIZATION, - [ENTITY_TYPES.POSITIONS]: GQL_GET_POSITION, - [ENTITY_TYPES.LOCATIONS]: GQL_GET_LOCATION, - [ENTITY_TYPES.TASKS]: GQL_GET_TASK -} - export function getEntityInfoFromUrl(url) { const splittedUrl = url.split(/[\\/]/) @@ -112,7 +44,10 @@ export function getEntityInfoFromUrl(url) { } // Enhanced HTML so that links will be converted to LinkTo components -export function parseHtmlWithLinkTo(html, report) { +export function parseHtmlWithLinkTo(html) { + if (!html) { + return null + } return parse(html, { replace: domNode => { if (domNode.attribs && domNode.attribs.href) { @@ -121,15 +56,3 @@ export function parseHtmlWithLinkTo(html, report) { } }) } - -// If entity could not retrieved a null will be returned -export function getEntityByUuid(type, uuid) { - const entityQuery = ENTITY_GQL_QUERIES[type] - if (!entityQuery) { - return null - } - - return API.query(entityQuery, { - uuid: uuid - }).then(data => data.entity) -} diff --git a/client/tests/sim/simutils.js b/client/tests/sim/simutils.js index 245f715201..99b079c78b 100644 --- a/client/tests/sim/simutils.js +++ b/client/tests/sim/simutils.js @@ -235,7 +235,8 @@ function populate(instance, scheme, context) { return populator } -const specialUser = { name: "erin", password: "erin" } +// Our initial admin, should always be there +const specialUser = { name: "arthur", password: "arthur" } export { runGQL, diff --git a/client/tests/sim/stories/NoteStories.js b/client/tests/sim/stories/NoteStories.js index fe638d9d69..b11ea22d8c 100644 --- a/client/tests/sim/stories/NoteStories.js +++ b/client/tests/sim/stories/NoteStories.js @@ -30,7 +30,7 @@ export async function getRandomObject( type, variables, fields = "uuid", - ignoredUuids = [] + ignoreCallback = randomObject => false ) { const [listEndpoint, queryType] = getListEndpoint(type) const objectQuery = Object.assign({}, variables, { @@ -77,7 +77,7 @@ export async function getRandomObject( return null } const randomObject = list[0] - if (ignoredUuids.includes(randomObject?.uuid)) { + if (ignoreCallback(randomObject)) { attempt++ } else { return randomObject diff --git a/client/tests/sim/stories/PositionStories.js b/client/tests/sim/stories/PositionStories.js index f6887545fa..cde13214ee 100644 --- a/client/tests/sim/stories/PositionStories.js +++ b/client/tests/sim/stories/PositionStories.js @@ -197,7 +197,9 @@ const _createPosition = async function(user) { role: getPersonRole(organization.type) }, "uuid", - [user.uuid] + randomObject => + randomObject?.uuid === user.uuid || + randomObject?.domainUsername === specialUser.name ) const location = await getRandomObject(user, "locations") const template = { diff --git a/client/tests/webdriver/pages/home.page.js b/client/tests/webdriver/pages/home.page.js index 9ce88ea9f1..1497e28787 100644 --- a/client/tests/webdriver/pages/home.page.js +++ b/client/tests/webdriver/pages/home.page.js @@ -24,6 +24,10 @@ class Home extends Page { return browser.$("#topbar #searchBarSubmit") } + get myOrgLink() { + return browser.$("#my-organization") + } + waitForSecurityBannerValue(value) { this.securityBanner.waitForExist() this.securityBanner.waitForDisplayed() diff --git a/client/tests/webdriver/pages/myOrg.page.js b/client/tests/webdriver/pages/myOrg.page.js new file mode 100644 index 0000000000..96c6009733 --- /dev/null +++ b/client/tests/webdriver/pages/myOrg.page.js @@ -0,0 +1,29 @@ +import Page from "./page" + +class MyOrg extends Page { + get engagementDateStatistics() { + return browser.$("[id^=engagementDate-statistics]").$(".fc") + } + + get locationStatistics() { + return browser.$("[id^=map-map-location-statistics]") + } + + get engagementStatus() { + return browser.$("[id^=engagementStatus-statistics]") + } + + get tasks() { + return browser.$("[id^=tasks-statistics]") + } + + get trainingEvent() { + return browser.$("[id*=trainingEvent-statistics]") + } + + get numberTrained() { + return browser.$("[id*=numberTrained-statistics]") + } +} + +export default new MyOrg() diff --git a/client/tests/webdriver/pages/myReports.page.js b/client/tests/webdriver/pages/myReports.page.js new file mode 100644 index 0000000000..660a15e252 --- /dev/null +++ b/client/tests/webdriver/pages/myReports.page.js @@ -0,0 +1,19 @@ +import Page from "./page" + +const PAGE_URL = "/reports/mine" + +class MyReports extends Page { + open() { + super.openAsAdminUser(PAGE_URL) + } + + get reportWithAssessmentsUrl() { + const tableTab = browser.$( + "#published-reports .report-collection div header div button[value='table']" + ) + tableTab.click() + return $("*=A test report from Arthur").getAttribute("href") + } +} + +export default new MyReports() diff --git a/client/tests/webdriver/pages/page.js b/client/tests/webdriver/pages/page.js index f50ab7a9fe..ad46ada0e1 100644 --- a/client/tests/webdriver/pages/page.js +++ b/client/tests/webdriver/pages/page.js @@ -8,7 +8,11 @@ class Page { _buildUrl(pathName, credentials) { const credSep = pathName.includes("?") ? "&" : "?" - return `${browser.options.baseUrl}${pathName}${credSep}user=${credentials}&pass=${credentials}` + const baseUrl = browser.options.baseUrl + const url = pathName.startsWith(baseUrl) + ? pathName + : `${baseUrl}${pathName}` + return `${url}${credSep}user=${credentials}&pass=${credentials}` } _open(pathName, credentials) { diff --git a/client/tests/webdriver/pages/showReport.page.js b/client/tests/webdriver/pages/showReport.page.js new file mode 100644 index 0000000000..294cc1b6ab --- /dev/null +++ b/client/tests/webdriver/pages/showReport.page.js @@ -0,0 +1,13 @@ +import Page from "./page" + +class ShowReport extends Page { + get tasksEngagementAssessments() { + return browser.$("#tasks-engagement-assessments") + } + + get task12BUrl() { + return browser.$("*=1.2.B").getAttribute("href") + } +} + +export default new ShowReport() diff --git a/client/tests/webdriver/pages/showTask.page.js b/client/tests/webdriver/pages/showTask.page.js new file mode 100644 index 0000000000..dc17c0136d --- /dev/null +++ b/client/tests/webdriver/pages/showTask.page.js @@ -0,0 +1,13 @@ +import Page from "./page" + +class ShowTask extends Page { + get assessmentResultsMonthly() { + return browser.$("#entity-assessments-results-monthly") + } + + get assessmentResultsWeekly() { + return browser.$("#entity-assessments-results-weekly") + } +} + +export default new ShowTask() diff --git a/client/tests/webdriver/specs/myOrg.spec.js b/client/tests/webdriver/specs/myOrg.spec.js new file mode 100644 index 0000000000..a28f659006 --- /dev/null +++ b/client/tests/webdriver/specs/myOrg.spec.js @@ -0,0 +1,60 @@ +import { expect } from "chai" +import Home from "../pages/home.page" +import MyOrg from "../pages/myOrg.page" + +describe("My organization page", () => { + beforeEach("Open the my organization page", () => { + Home.openAsAdminUser() + const myOrgUrl = Home.myOrgLink.getAttribute("href") + MyOrg.openAsAdminUser(myOrgUrl) + }) + + describe("When checking the report statistics part of the page", () => { + it("Should see different types of fields statistics", () => { + // Note: checks like length.above are being made because the wdio tests + // might also be run after the jacocoTestReport, without resetting the + // database, and in that case we have more reports in the statistics + MyOrg.engagementDateStatistics.waitForDisplayed() + const daysWithEvent = MyOrg.engagementDateStatistics.$$( + ".fc-event-container" + ) + // There is at least one date with events in the calendar + expect(daysWithEvent).to.have.length.above(0) + + // Location statistics map is being loaded + MyOrg.locationStatistics.waitForDisplayed() + + MyOrg.engagementStatus.waitForDisplayed() + // There are 4 engagement status options + const engagementStatusLegend = MyOrg.engagementStatus + .$(".pieLegend") + .$$("span") + expect(engagementStatusLegend).to.have.length(4) + + MyOrg.tasks.waitForDisplayed() + // There are 4 tasks on the x-axis + const tasks = MyOrg.tasks.$("svg g").$$(".bars-group") + expect(tasks).to.have.length(4) + let countTasksBars = 0 + tasks.forEach(bar => { + if (+bar.$("rect").getAttribute("height") > 0) { + countTasksBars++ + } + }) + // There is at least one bar + expect(countTasksBars).to.be.above(0) + + MyOrg.trainingEvent.waitForDisplayed() + // There are 3 training event options + const trainingEventLegend = MyOrg.trainingEvent.$(".pieLegend").$$("span") + expect(trainingEventLegend).to.have.length(3) + // Total number of reports is bigger than 0 + const trainignEventTotal = MyOrg.trainingEvent.$("svg g text") + expect(+trainignEventTotal.getText()).to.be.above(0) + + MyOrg.numberTrained.waitForDisplayed() + const numberTrained = MyOrg.numberTrained.$("div em") + expect(numberTrained.getText()).to.equal("Not specified") + }) + }) +}) diff --git a/client/tests/webdriver/specs/showReport.spec.js b/client/tests/webdriver/specs/showReport.spec.js new file mode 100644 index 0000000000..c1cc0bb61d --- /dev/null +++ b/client/tests/webdriver/specs/showReport.spec.js @@ -0,0 +1,27 @@ +import { expect } from "chai" +import MyReports from "../pages/myReports.page" +import ShowReport from "../pages/showReport.page" + +describe("Show report page", () => { + beforeEach("Open the show report page", () => { + MyReports.open() + ShowReport.openAsAdminUser(MyReports.reportWithAssessmentsUrl) + }) + describe("When on the show page of a report with assessments", () => { + it("We should see a table of tasks instant assessments related to the current report", () => { + ShowReport.tasksEngagementAssessments.waitForDisplayed() + // Both 1.2.A as 1.2.B tasks on the page have an svg type of assessment (LikertScale widgets) + const svgAssessments = ShowReport.tasksEngagementAssessments.$$("svg") + expect(svgAssessments).to.have.length(2) + // Check on assessments of task 1.2.A + const question2Assessments = ShowReport.tasksEngagementAssessments.$$( + "[name*=question2]" + ) + expect(question2Assessments).to.have.length(1) + const question3Assessments = ShowReport.tasksEngagementAssessments.$$( + "[name*=question3]" + ) + expect(question3Assessments).to.have.length(1) + }) + }) +}) diff --git a/client/tests/webdriver/specs/showTask.spec.js b/client/tests/webdriver/specs/showTask.spec.js new file mode 100644 index 0000000000..a3124d686b --- /dev/null +++ b/client/tests/webdriver/specs/showTask.spec.js @@ -0,0 +1,28 @@ +import { expect } from "chai" +import MyReports from "../pages/myReports.page" +import ShowReport from "../pages/showReport.page" +import ShowTask from "../pages/showTask.page" + +describe("Show task page", () => { + beforeEach("Open the show task page", () => { + MyReports.open() + ShowReport.openAsAdminUser(MyReports.reportWithAssessmentsUrl) + ShowTask.openAsAdminUser(ShowReport.task12BUrl) + }) + + describe("When on the show page of a task with assessments", () => { + it("We should see a table of assessments related to the current task", () => { + ShowTask.assessmentResultsMonthly.waitForDisplayed() + const frenchFlagAssessmentMonthly = ShowTask.assessmentResultsMonthly.$( + "id*=frenchFlag-assessment" + ) + expect(frenchFlagAssessmentMonthly.isExisting()) + + ShowTask.assessmentResultsWeekly.waitForDisplayed() + const frenchFlagAssessmentWeekly = ShowTask.assessmentResultsWeekly.$( + "id*=levels-assessment" + ) + expect(frenchFlagAssessmentWeekly.isExisting()) + }) + }) +}) diff --git a/client/yarn.lock b/client/yarn.lock index 476782c5d8..17c291ad5a 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -2,23 +2,23 @@ # yarn lockfile v1 -"@apollo/react-common@^3.1.4": - version "3.1.4" - resolved "https://registry.yarnpkg.com/@apollo/react-common/-/react-common-3.1.4.tgz#ec13c985be23ea8e799c9ea18e696eccc97be345" - integrity sha512-X5Kyro73bthWSCBJUC5XYQqMnG0dLWuDZmVkzog9dynovhfiVCV4kPSdgSIkqnb++cwCzOVuQ4rDKVwo2XRzQA== - dependencies: - ts-invariant "^0.4.4" - tslib "^1.10.0" - -"@apollo/react-hooks@3.1.5": - version "3.1.5" - resolved "https://registry.yarnpkg.com/@apollo/react-hooks/-/react-hooks-3.1.5.tgz#7e710be52461255ae7fc0b3b9c2ece64299c10e6" - integrity sha512-y0CJ393DLxIIkksRup4nt+vSjxalbZBXnnXxYbviq/woj+zKa431zy0yT4LqyRKpFy9ahMIwxBnBwfwIoupqLQ== +"@apollo/client@3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.1.2.tgz#e384f691706c46aef4d9234b63a03ccc06e9c33c" + integrity sha512-GaA/J0CDSSNe0HVm1abeOIJA3M4fs9Ih7wF2z1AI2SLqv5TBLvwBxh0+0+jCSntPZ3gnDQvR7MHjmXota5V1LQ== dependencies: - "@apollo/react-common" "^3.1.4" - "@wry/equality" "^0.1.9" + "@types/zen-observable" "^0.8.0" + "@wry/context" "^0.5.2" + "@wry/equality" "^0.2.0" + fast-json-stable-stringify "^2.0.0" + graphql-tag "^2.11.0" + hoist-non-react-statics "^3.3.2" + optimism "^0.12.1" + prop-types "^15.7.2" + symbol-observable "^1.2.0" ts-invariant "^0.4.4" tslib "^1.10.0" + zen-observable "^0.8.14" "@babel/code-frame@7.5.5": version "7.5.5" @@ -27,47 +27,40 @@ dependencies: "@babel/highlight" "^7.0.0" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.1", "@babel/code-frame@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.1.tgz#d5481c5095daa1c57e16e54c6f9198443afb49ff" - integrity sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" + integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== dependencies: - "@babel/highlight" "^7.10.1" + "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.3.tgz#324bcfd8d35cd3d47dae18cde63d752086435e9a" - integrity sha512-fDx9eNW0qz0WkUeqL6tXEXzVlPh6Y5aCDEZesl0xBGA8ndRukX91Uk44ZqnkECp01NAZUdCAl+aiQNGi0k88Eg== - dependencies: - "@babel/highlight" "^7.10.3" - -"@babel/compat-data@^7.10.1", "@babel/compat-data@^7.9.0": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.10.1.tgz#b1085ffe72cd17bf2c0ee790fc09f9626011b2db" - integrity sha512-CHvCj7So7iCkGKPRFUfryXIkU2gSBw7VSZFYLsqVhrS47269VK2Hfi9S/YcublPMW8k1u2bQBlbDruoQEm4fgw== +"@babel/compat-data@^7.10.4", "@babel/compat-data@^7.11.0", "@babel/compat-data@^7.9.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.11.0.tgz#e9f73efe09af1355b723a7f39b11bad637d7c99c" + integrity sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ== dependencies: browserslist "^4.12.0" invariant "^2.2.4" semver "^5.5.0" -"@babel/core@7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.3.tgz#73b0e8ddeec1e3fdd7a2de587a60e17c440ec77e" - integrity sha512-5YqWxYE3pyhIi84L84YcwjeEgS+fa7ZjK6IBVGTjDVfm64njkR2lfDhVR5OudLk8x2GK59YoSyVv+L/03k1q9w== - dependencies: - "@babel/code-frame" "^7.10.3" - "@babel/generator" "^7.10.3" - "@babel/helper-module-transforms" "^7.10.1" - "@babel/helpers" "^7.10.1" - "@babel/parser" "^7.10.3" - "@babel/template" "^7.10.3" - "@babel/traverse" "^7.10.3" - "@babel/types" "^7.10.3" +"@babel/core@7.11.1": + version "7.11.1" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.1.tgz#2c55b604e73a40dc21b0e52650b11c65cf276643" + integrity sha512-XqF7F6FWQdKGGWAzGELL+aCO1p+lRY5Tj5/tbT3St1G8NaH70jhhDIKknIZaDans0OQBG5wRAldROLHSt44BgQ== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.0" + "@babel/helper-module-transforms" "^7.11.0" + "@babel/helpers" "^7.10.4" + "@babel/parser" "^7.11.1" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.11.0" + "@babel/types" "^7.11.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" + lodash "^4.17.19" resolve "^1.3.2" semver "^5.4.1" source-map "^0.5.0" @@ -95,353 +88,297 @@ source-map "^0.5.0" "@babel/core@^7.1.0", "@babel/core@^7.4.5", "@babel/core@^7.7.5": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.2.tgz#bd6786046668a925ac2bd2fd95b579b92a23b36a" - integrity sha512-KQmV9yguEjQsXqyOUGKjS4+3K8/DlOCE2pZcq4augdQmtTy5iv5EHtmMSJ7V4c1BIPjuwtZYqYLCq9Ga+hGBRQ== - dependencies: - "@babel/code-frame" "^7.10.1" - "@babel/generator" "^7.10.2" - "@babel/helper-module-transforms" "^7.10.1" - "@babel/helpers" "^7.10.1" - "@babel/parser" "^7.10.2" - "@babel/template" "^7.10.1" - "@babel/traverse" "^7.10.1" - "@babel/types" "^7.10.2" + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.0.tgz#73b9c33f1658506887f767c26dae07798b30df76" + integrity sha512-mkLq8nwaXmDtFmRkQ8ED/eA2CnVw4zr7dCztKalZXBvdK5EeNUAesrrwUqjQEzFgomJssayzB0aqlOsP1vGLqg== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.0" + "@babel/helper-module-transforms" "^7.11.0" + "@babel/helpers" "^7.10.4" + "@babel/parser" "^7.11.0" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.11.0" + "@babel/types" "^7.11.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" + lodash "^4.17.19" resolve "^1.3.2" semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.10.1", "@babel/generator@^7.10.2", "@babel/generator@^7.9.0": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.2.tgz#0fa5b5b2389db8bfdfcc3492b551ee20f5dd69a9" - integrity sha512-AxfBNHNu99DTMvlUPlt1h2+Hn7knPpH5ayJ8OqDWSeLld+Fi2AYBTC/IejWDM9Edcii4UzZRCsbUt0WlSDsDsA== +"@babel/eslint-parser@7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.11.0.tgz#b123924edd44508782c030066c926f1b807151cd" + integrity sha512-dJDM2Pc01D9TwKL3Mmz2xgVF9X953RBHq9H4gywbN1q8MrfvXmNHfsCt06vvByBVQqm+9WxMs+doEH/R09TwWQ== dependencies: - "@babel/types" "^7.10.2" - jsesc "^2.5.1" - lodash "^4.17.13" - source-map "^0.5.0" + eslint-scope "5.1.0" + eslint-visitor-keys "^1.3.0" + semver "^6.3.0" -"@babel/generator@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.3.tgz#32b9a0d963a71d7a54f5f6c15659c3dbc2a523a5" - integrity sha512-drt8MUHbEqRzNR0xnF8nMehbY11b1SDkRw03PSNH/3Rb2Z35oxkddVSi3rcaak0YJQ86PCuE7Qx1jSFhbLNBMA== +"@babel/generator@^7.11.0", "@babel/generator@^7.9.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.0.tgz#4b90c78d8c12825024568cbe83ee6c9af193585c" + integrity sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ== dependencies: - "@babel/types" "^7.10.3" + "@babel/types" "^7.11.0" jsesc "^2.5.1" - lodash "^4.17.13" source-map "^0.5.0" -"@babel/helper-annotate-as-pure@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.1.tgz#f6d08acc6f70bbd59b436262553fb2e259a1a268" - integrity sha512-ewp3rvJEwLaHgyWGe4wQssC2vjks3E80WiUe2BpMb0KhreTjMROCbxXcEovTrbeGVdQct5VjQfrv9EgC+xMzCw== +"@babel/helper-annotate-as-pure@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3" + integrity sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA== dependencies: - "@babel/types" "^7.10.1" + "@babel/types" "^7.10.4" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.1.tgz#0ec7d9be8174934532661f87783eb18d72290059" - integrity sha512-cQpVq48EkYxUU0xozpGCLla3wlkdRRqLWu1ksFMXA9CM5KQmyyRpSEsYXbao7JUkOw/tAaYKCaYyZq6HOFYtyw== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" + integrity sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg== dependencies: - "@babel/helper-explode-assignable-expression" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/helper-explode-assignable-expression" "^7.10.4" + "@babel/types" "^7.10.4" -"@babel/helper-builder-react-jsx-experimental@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.10.1.tgz#9a7d58ad184d3ac3bafb1a452cec2bad7e4a0bc8" - integrity sha512-irQJ8kpQUV3JasXPSFQ+LCCtJSc5ceZrPFVj6TElR6XCHssi3jV8ch3odIrNtjJFRZZVbrOEfJMI79TPU/h1pQ== +"@babel/helper-builder-react-jsx-experimental@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.10.5.tgz#f35e956a19955ff08c1258e44a515a6d6248646b" + integrity sha512-Buewnx6M4ttG+NLkKyt7baQn7ScC/Td+e99G914fRU8fGIUivDDgVIQeDHFa5e4CRSJQt58WpNHhsAZgtzVhsg== dependencies: - "@babel/helper-annotate-as-pure" "^7.10.1" - "@babel/helper-module-imports" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-module-imports" "^7.10.4" + "@babel/types" "^7.10.5" -"@babel/helper-builder-react-jsx@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.10.1.tgz#a327f0cf983af5554701b1215de54a019f09b532" - integrity sha512-KXzzpyWhXgzjXIlJU1ZjIXzUPdej1suE6vzqgImZ/cpAsR/CC8gUcX4EWRmDfWz/cs6HOCPMBIJ3nKoXt3BFuw== +"@babel/helper-builder-react-jsx@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.10.4.tgz#8095cddbff858e6fa9c326daee54a2f2732c1d5d" + integrity sha512-5nPcIZ7+KKDxT1427oBivl9V9YTal7qk0diccnh7RrcgrT/pGFOjgGw1dgryyx1GvHEpXVfoDF6Ak3rTiWh8Rg== dependencies: - "@babel/helper-annotate-as-pure" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/types" "^7.10.4" -"@babel/helper-compilation-targets@^7.10.2", "@babel/helper-compilation-targets@^7.8.7": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.2.tgz#a17d9723b6e2c750299d2a14d4637c76936d8285" - integrity sha512-hYgOhF4To2UTB4LTaZepN/4Pl9LD4gfbJx8A34mqoluT8TLbof1mhUlYuNWTEebONa8+UlCC4X0TEXu7AOUyGA== +"@babel/helper-compilation-targets@^7.10.4", "@babel/helper-compilation-targets@^7.8.7": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz#804ae8e3f04376607cc791b9d47d540276332bd2" + integrity sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ== dependencies: - "@babel/compat-data" "^7.10.1" + "@babel/compat-data" "^7.10.4" browserslist "^4.12.0" invariant "^2.2.4" levenary "^1.1.1" semver "^5.5.0" -"@babel/helper-create-class-features-plugin@^7.10.1", "@babel/helper-create-class-features-plugin@^7.8.3": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.2.tgz#7474295770f217dbcf288bf7572eb213db46ee67" - integrity sha512-5C/QhkGFh1vqcziq1vAL6SI9ymzUp8BCYjFpvYVhWP4DlATIb3u5q3iUd35mvlyGs8fO7hckkW7i0tmH+5+bvQ== - dependencies: - "@babel/helper-function-name" "^7.10.1" - "@babel/helper-member-expression-to-functions" "^7.10.1" - "@babel/helper-optimise-call-expression" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/helper-replace-supers" "^7.10.1" - "@babel/helper-split-export-declaration" "^7.10.1" - -"@babel/helper-create-class-features-plugin@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.3.tgz#2783daa6866822e3d5ed119163b50f0fc3ae4b35" - integrity sha512-iRT9VwqtdFmv7UheJWthGc/h2s7MqoweBF9RUj77NFZsg9VfISvBTum3k6coAhJ8RWv2tj3yUjA03HxPd0vfpQ== - dependencies: - "@babel/helper-function-name" "^7.10.3" - "@babel/helper-member-expression-to-functions" "^7.10.3" - "@babel/helper-optimise-call-expression" "^7.10.3" - "@babel/helper-plugin-utils" "^7.10.3" - "@babel/helper-replace-supers" "^7.10.1" - "@babel/helper-split-export-declaration" "^7.10.1" - -"@babel/helper-create-regexp-features-plugin@^7.10.1", "@babel/helper-create-regexp-features-plugin@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.1.tgz#1b8feeab1594cbcfbf3ab5a3bbcabac0468efdbd" - integrity sha512-Rx4rHS0pVuJn5pJOqaqcZR4XSgeF9G/pO/79t+4r7380tXFJdzImFnxMU19f83wjSrmKHq6myrM10pFHTGzkUA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.1" - "@babel/helper-regex" "^7.10.1" +"@babel/helper-create-class-features-plugin@^7.10.4", "@babel/helper-create-class-features-plugin@^7.10.5", "@babel/helper-create-class-features-plugin@^7.8.3": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz#9f61446ba80e8240b0a5c85c6fdac8459d6f259d" + integrity sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-member-expression-to-functions" "^7.10.5" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" + +"@babel/helper-create-regexp-features-plugin@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz#fdd60d88524659a0b6959c0579925e425714f3b8" + integrity sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-regex" "^7.10.4" regexpu-core "^4.7.0" -"@babel/helper-define-map@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.1.tgz#5e69ee8308648470dd7900d159c044c10285221d" - integrity sha512-+5odWpX+OnvkD0Zmq7panrMuAGQBu6aPUgvMzuMGo4R+jUOvealEj2hiqI6WhxgKrTpFoFj0+VdsuA8KDxHBDg== - dependencies: - "@babel/helper-function-name" "^7.10.1" - "@babel/types" "^7.10.1" - lodash "^4.17.13" - -"@babel/helper-explode-assignable-expression@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.1.tgz#e9d76305ee1162ca467357ae25df94f179af2b7e" - integrity sha512-vcUJ3cDjLjvkKzt6rHrl767FeE7pMEYfPanq5L16GRtrXIoznc0HykNW2aEYkcnP76P0isoqJ34dDMFZwzEpJg== - dependencies: - "@babel/traverse" "^7.10.1" - "@babel/types" "^7.10.1" - -"@babel/helper-function-name@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.1.tgz#92bd63829bfc9215aca9d9defa85f56b539454f4" - integrity sha512-fcpumwhs3YyZ/ttd5Rz0xn0TpIwVkN7X0V38B9TWNfVF42KEkhkAAuPCQ3oXmtTRtiPJrmZ0TrfS0GKF0eMaRQ== - dependencies: - "@babel/helper-get-function-arity" "^7.10.1" - "@babel/template" "^7.10.1" - "@babel/types" "^7.10.1" - -"@babel/helper-function-name@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.3.tgz#79316cd75a9fa25ba9787ff54544307ed444f197" - integrity sha512-FvSj2aiOd8zbeqijjgqdMDSyxsGHaMt5Tr0XjQsGKHD3/1FP3wksjnLAWzxw7lvXiej8W1Jt47SKTZ6upQNiRw== - dependencies: - "@babel/helper-get-function-arity" "^7.10.3" - "@babel/template" "^7.10.3" - "@babel/types" "^7.10.3" - -"@babel/helper-get-function-arity@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.1.tgz#7303390a81ba7cb59613895a192b93850e373f7d" - integrity sha512-F5qdXkYGOQUb0hpRaPoetF9AnsXknKjWMZ+wmsIRsp5ge5sFh4c3h1eH2pRTTuy9KKAA2+TTYomGXAtEL2fQEw== - dependencies: - "@babel/types" "^7.10.1" - -"@babel/helper-get-function-arity@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.3.tgz#3a28f7b28ccc7719eacd9223b659fdf162e4c45e" - integrity sha512-iUD/gFsR+M6uiy69JA6fzM5seno8oE85IYZdbVVEuQaZlEzMO2MXblh+KSPJgsZAUx0EEbWXU0yJaW7C9CdAVg== - dependencies: - "@babel/types" "^7.10.3" - -"@babel/helper-hoist-variables@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.1.tgz#7e77c82e5dcae1ebf123174c385aaadbf787d077" - integrity sha512-vLm5srkU8rI6X3+aQ1rQJyfjvCBLXP8cAGeuw04zeAM2ItKb1e7pmVmLyHb4sDaAYnLL13RHOZPLEtcGZ5xvjg== - dependencies: - "@babel/types" "^7.10.1" - -"@babel/helper-member-expression-to-functions@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.1.tgz#432967fd7e12a4afef66c4687d4ca22bc0456f15" - integrity sha512-u7XLXeM2n50gb6PWJ9hoO5oO7JFPaZtrh35t8RqKLT1jFKj9IWeD1zrcrYp1q1qiZTdEarfDWfTIP8nGsu0h5g== - dependencies: - "@babel/types" "^7.10.1" - -"@babel/helper-member-expression-to-functions@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.3.tgz#bc3663ac81ac57c39148fef4c69bf48a77ba8dd6" - integrity sha512-q7+37c4EPLSjNb2NmWOjNwj0+BOyYlssuQ58kHEWk1Z78K5i8vTUsteq78HMieRPQSl/NtpQyJfdjt3qZ5V2vw== - dependencies: - "@babel/types" "^7.10.3" - -"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.10.1", "@babel/helper-module-imports@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.1.tgz#dd331bd45bccc566ce77004e9d05fe17add13876" - integrity sha512-SFxgwYmZ3HZPyZwJRiVNLRHWuW2OgE5k2nrVs6D9Iv4PPnXVffuEHy83Sfx/l4SqF+5kyJXjAyUmrG7tNm+qVg== - dependencies: - "@babel/types" "^7.10.1" - -"@babel/helper-module-transforms@^7.10.1", "@babel/helper-module-transforms@^7.9.0": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz#24e2f08ee6832c60b157bb0936c86bef7210c622" - integrity sha512-RLHRCAzyJe7Q7sF4oy2cB+kRnU4wDZY/H2xJFGof+M+SJEGhZsb+GFj5j1AD8NiSaVBJ+Pf0/WObiXu/zxWpFg== - dependencies: - "@babel/helper-module-imports" "^7.10.1" - "@babel/helper-replace-supers" "^7.10.1" - "@babel/helper-simple-access" "^7.10.1" - "@babel/helper-split-export-declaration" "^7.10.1" - "@babel/template" "^7.10.1" - "@babel/types" "^7.10.1" - lodash "^4.17.13" - -"@babel/helper-optimise-call-expression@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.1.tgz#b4a1f2561870ce1247ceddb02a3860fa96d72543" - integrity sha512-a0DjNS1prnBsoKx83dP2falChcs7p3i8VMzdrSbfLhuQra/2ENC4sbri34dz/rWmDADsmF1q5GbfaXydh0Jbjg== - dependencies: - "@babel/types" "^7.10.1" - -"@babel/helper-optimise-call-expression@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.3.tgz#f53c4b6783093195b0f69330439908841660c530" - integrity sha512-kT2R3VBH/cnSz+yChKpaKRJQJWxdGoc6SjioRId2wkeV3bK0wLLioFpJROrX0U4xr/NmxSSAWT/9Ih5snwIIzg== - dependencies: - "@babel/types" "^7.10.3" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.1", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.1.tgz#ec5a5cf0eec925b66c60580328b122c01230a127" - integrity sha512-fvoGeXt0bJc7VMWZGCAEBEMo/HAjW2mP8apF5eXK0wSqwLAVHAISCWRoLMBMUs2kqeaG77jltVqu4Hn8Egl3nA== - -"@babel/helper-plugin-utils@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.3.tgz#aac45cccf8bc1873b99a85f34bceef3beb5d3244" - integrity sha512-j/+j8NAWUTxOtx4LKHybpSClxHoq6I91DQ/mKgAXn5oNUPIUiGppjPIX3TDtJWPrdfP9Kfl7e4fgVMiQR9VE/g== - -"@babel/helper-regex@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.1.tgz#021cf1a7ba99822f993222a001cc3fec83255b96" - integrity sha512-7isHr19RsIJWWLLFn21ubFt223PjQyg1HY7CZEMRr820HttHPpVvrsIN3bUOo44DEfFV4kBXO7Abbn9KTUZV7g== +"@babel/helper-define-map@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30" + integrity sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/types" "^7.10.5" + lodash "^4.17.19" + +"@babel/helper-explode-assignable-expression@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.4.tgz#40a1cd917bff1288f699a94a75b37a1a2dbd8c7c" + integrity sha512-4K71RyRQNPRrR85sr5QY4X3VwG4wtVoXZB9+L3r1Gp38DhELyHCtovqydRi7c1Ovb17eRGiQ/FD5s8JdU0Uy5A== + dependencies: + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-function-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" + integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== dependencies: - lodash "^4.17.13" - -"@babel/helper-remap-async-to-generator@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.1.tgz#bad6aaa4ff39ce8d4b82ccaae0bfe0f7dbb5f432" - integrity sha512-RfX1P8HqsfgmJ6CwaXGKMAqbYdlleqglvVtht0HGPMSsy2V6MqLlOJVF/0Qyb/m2ZCi2z3q3+s6Pv7R/dQuZ6A== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.1" - "@babel/helper-wrap-function" "^7.10.1" - "@babel/template" "^7.10.1" - "@babel/traverse" "^7.10.1" - "@babel/types" "^7.10.1" - -"@babel/helper-replace-supers@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.1.tgz#ec6859d20c5d8087f6a2dc4e014db7228975f13d" - integrity sha512-SOwJzEfpuQwInzzQJGjGaiG578UYmyi2Xw668klPWV5n07B73S0a9btjLk/52Mlcxa+5AdIYqws1KyXRfMoB7A== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.10.1" - "@babel/helper-optimise-call-expression" "^7.10.1" - "@babel/traverse" "^7.10.1" - "@babel/types" "^7.10.1" - -"@babel/helper-simple-access@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz#08fb7e22ace9eb8326f7e3920a1c2052f13d851e" - integrity sha512-VSWpWzRzn9VtgMJBIWTZ+GP107kZdQ4YplJlCmIrjoLVSi/0upixezHCDG8kpPVTBJpKfxTH01wDhh+jS2zKbw== - dependencies: - "@babel/template" "^7.10.1" - "@babel/types" "^7.10.1" - -"@babel/helper-split-export-declaration@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz#c6f4be1cbc15e3a868e4c64a17d5d31d754da35f" - integrity sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g== - dependencies: - "@babel/types" "^7.10.1" - -"@babel/helper-validator-identifier@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz#5770b0c1a826c4f53f5ede5e153163e0318e94b5" - integrity sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw== - -"@babel/helper-validator-identifier@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.3.tgz#60d9847f98c4cea1b279e005fdb7c28be5412d15" - integrity sha512-bU8JvtlYpJSBPuj1VUmKpFGaDZuLxASky3LhaKj3bmpSTY6VWooSM8msk+Z0CZoErFye2tlABF6yDkT3FOPAXw== - -"@babel/helper-wrap-function@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.1.tgz#956d1310d6696257a7afd47e4c42dfda5dfcedc9" - integrity sha512-C0MzRGteVDn+H32/ZgbAv5r56f2o1fZSA/rj/TYo8JEJNHg+9BdSmKBUND0shxWRztWhjlT2cvHYuynpPsVJwQ== - dependencies: - "@babel/helper-function-name" "^7.10.1" - "@babel/template" "^7.10.1" - "@babel/traverse" "^7.10.1" - "@babel/types" "^7.10.1" - -"@babel/helpers@^7.10.1", "@babel/helpers@^7.9.0": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.1.tgz#a6827b7cb975c9d9cef5fd61d919f60d8844a973" - integrity sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw== - dependencies: - "@babel/template" "^7.10.1" - "@babel/traverse" "^7.10.1" - "@babel/types" "^7.10.1" - -"@babel/highlight@^7.0.0", "@babel/highlight@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.1.tgz#841d098ba613ba1a427a2b383d79e35552c38ae0" - integrity sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg== - dependencies: - "@babel/helper-validator-identifier" "^7.10.1" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/highlight@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.3.tgz#c633bb34adf07c5c13156692f5922c81ec53f28d" - integrity sha512-Ih9B/u7AtgEnySE2L2F0Xm0GaM729XqqLfHkalTsbjXGyqmf/6M0Cu0WpvqueUlW+xk88BHw9Nkpj49naU+vWw== - dependencies: - "@babel/helper-validator-identifier" "^7.10.3" + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-get-function-arity@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" + integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-hoist-variables@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e" + integrity sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-member-expression-to-functions@^7.10.4", "@babel/helper-member-expression-to-functions@^7.10.5": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz#ae69c83d84ee82f4b42f96e2a09410935a8f26df" + integrity sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q== + dependencies: + "@babel/types" "^7.11.0" + +"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620" + integrity sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-module-transforms@^7.10.4", "@babel/helper-module-transforms@^7.10.5", "@babel/helper-module-transforms@^7.11.0", "@babel/helper-module-transforms@^7.9.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz#b16f250229e47211abdd84b34b64737c2ab2d359" + integrity sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg== + dependencies: + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/template" "^7.10.4" + "@babel/types" "^7.11.0" + lodash "^4.17.19" + +"@babel/helper-optimise-call-expression@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" + integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" + integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== + +"@babel/helper-regex@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.5.tgz#32dfbb79899073c415557053a19bd055aae50ae0" + integrity sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg== + dependencies: + lodash "^4.17.19" + +"@babel/helper-remap-async-to-generator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.4.tgz#fce8bea4e9690bbe923056ded21e54b4e8b68ed5" + integrity sha512-86Lsr6NNw3qTNl+TBcF1oRZMaVzJtbWTyTko+CQL/tvNvcGYEFKbLXDPxtW0HKk3McNOk4KzY55itGWCAGK5tg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-wrap-function" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-replace-supers@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz#d585cd9388ea06e6031e4cd44b6713cbead9e6cf" + integrity sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-simple-access@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz#0f5ccda2945277a2a7a2d3a821e15395edcf3461" + integrity sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw== + dependencies: + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-skip-transparent-expression-wrappers@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz#eec162f112c2f58d3af0af125e3bb57665146729" + integrity sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q== + dependencies: + "@babel/types" "^7.11.0" + +"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" + integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== + dependencies: + "@babel/types" "^7.11.0" + +"@babel/helper-validator-identifier@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" + integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== + +"@babel/helper-wrap-function@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" + integrity sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helpers@^7.10.4", "@babel/helpers@^7.9.0": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.4.tgz#2abeb0d721aff7c0a97376b9e1f6f65d7a475044" + integrity sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA== + dependencies: + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/highlight@^7.0.0", "@babel/highlight@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" + integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.10.1", "@babel/parser@^7.10.2", "@babel/parser@^7.7.0", "@babel/parser@^7.9.0": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.2.tgz#871807f10442b92ff97e4783b9b54f6a0ca812d0" - integrity sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ== +"@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.11.0", "@babel/parser@^7.9.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.0.tgz#a9d7e11aead25d3b422d17b2c6502c8dddef6a5d" + integrity sha512-qvRvi4oI8xii8NllyEc4MDJjuZiNaRzyb7Y7lup1NqJV8TZHF4O27CcP+72WPn/k1zkgJ6WJfnIbk4jTsVAZHw== -"@babel/parser@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.3.tgz#7e71d892b0d6e7d04a1af4c3c79d72c1f10f5315" - integrity sha512-oJtNJCMFdIMwXGmx+KxuaD7i3b8uS7TTFYW/FNG2BT8m+fmGHoiPYoH0Pe3gya07WuFmM5FCDIr1x0irkD/hyA== +"@babel/parser@^7.11.1": + version "7.11.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.2.tgz#0882ab8a455df3065ea2dcb4c753b2460a24bead" + integrity sha512-Vuj/+7vLo6l1Vi7uuO+1ngCDNeVmNbTngcJFKCR/oEtz8tKz0CJxZEGmPt9KcIloZhOZ3Zit6xbpXT2MDlS9Vw== -"@babel/plugin-proposal-async-generator-functions@^7.10.1", "@babel/plugin-proposal-async-generator-functions@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.1.tgz#6911af5ba2e615c4ff3c497fe2f47b35bf6d7e55" - integrity sha512-vzZE12ZTdB336POZjmpblWfNNRpMSua45EYnRigE2XsZxcXcIyly2ixnTJasJE4Zq3U7t2d8rRF7XRUuzHxbOw== +"@babel/plugin-proposal-async-generator-functions@^7.10.4", "@babel/plugin-proposal-async-generator-functions@^7.8.3": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz#3491cabf2f7c179ab820606cec27fed15e0e8558" + integrity sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/helper-remap-async-to-generator" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.10.4" "@babel/plugin-syntax-async-generators" "^7.8.0" -"@babel/plugin-proposal-class-properties@7.10.1", "@babel/plugin-proposal-class-properties@^7.10.1", "@babel/plugin-proposal-class-properties@^7.7.0": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.1.tgz#046bc7f6550bb08d9bd1d4f060f5f5a4f1087e01" - integrity sha512-sqdGWgoXlnOdgMXU+9MbhzwFRgxVLeiGBqTrnuS7LC2IBU31wSsESbTUreT2O418obpfPdGUR2GbEufZF1bpqw== +"@babel/plugin-proposal-class-properties@7.10.4", "@babel/plugin-proposal-class-properties@^7.10.4", "@babel/plugin-proposal-class-properties@^7.7.0": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz#a33bf632da390a59c7a8c570045d1115cd778807" + integrity sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg== dependencies: - "@babel/helper-create-class-features-plugin" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-create-class-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-proposal-class-properties@7.8.3": version "7.8.3" @@ -451,14 +388,14 @@ "@babel/helper-create-class-features-plugin" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-proposal-decorators@7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.10.3.tgz#2fc6b5696028adccfcd14bc826c184c578b857f8" - integrity sha512-Rzwn5tcYFTdWWK3IrhMZkMDjzFQLIGYqHvv9XuzNnEB91Y6gHr/JjazYV1Yec9g0yMLhy1p/21eiW1P7f5UN4A== +"@babel/plugin-proposal-decorators@7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.10.5.tgz#42898bba478bc4b1ae242a703a953a7ad350ffb4" + integrity sha512-Sc5TAQSZuLzgY0664mMDn24Vw2P8g/VhyLyGPaWiHahhgLqeZvcGeyBZOrJW0oSKIK2mvQ22a1ENXBIQLhrEiQ== dependencies: - "@babel/helper-create-class-features-plugin" "^7.10.3" - "@babel/helper-plugin-utils" "^7.10.3" - "@babel/plugin-syntax-decorators" "^7.10.1" + "@babel/helper-create-class-features-plugin" "^7.10.5" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-decorators" "^7.10.4" "@babel/plugin-proposal-decorators@7.8.3": version "7.8.3" @@ -469,69 +406,69 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-decorators" "^7.8.3" -"@babel/plugin-proposal-do-expressions@7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-do-expressions/-/plugin-proposal-do-expressions-7.10.1.tgz#ef99f594320f38c300ed2404d6ca83b00c858905" - integrity sha512-rjAoAQl6YLsY9C60zQBVTBsDP8YUWlgSv7qRdG8rapQYl+WL1LIVq23SHDCPllaNrE8bqO9csBooTL4yXr7FnA== +"@babel/plugin-proposal-do-expressions@7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-do-expressions/-/plugin-proposal-do-expressions-7.10.4.tgz#9a5190f3bf4818f83e41d673ee517ff76cf8e4ed" + integrity sha512-Gcc2wLVeMceRdP6m9tdDygP01lbUVmaQGBRoIRJZxzPfB5VTiUgmn1jGfORgqbEVgUpG0IQm/z4q5Y/qzG+8JQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-do-expressions" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-do-expressions" "^7.10.4" -"@babel/plugin-proposal-dynamic-import@^7.10.1", "@babel/plugin-proposal-dynamic-import@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.1.tgz#e36979dc1dc3b73f6d6816fc4951da2363488ef0" - integrity sha512-Cpc2yUVHTEGPlmiQzXj026kqwjEQAD9I4ZC16uzdbgWgitg/UHKHLffKNCQZ5+y8jpIZPJcKcwsr2HwPh+w3XA== +"@babel/plugin-proposal-dynamic-import@^7.10.4", "@babel/plugin-proposal-dynamic-import@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz#ba57a26cb98b37741e9d5bca1b8b0ddf8291f17e" + integrity sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-dynamic-import" "^7.8.0" -"@babel/plugin-proposal-export-default-from@7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.10.1.tgz#59ea2a4f09dbb0358c73dab27def3d21a27bd370" - integrity sha512-Xfc1CfHapIkwZ/+AI+j4Ha3g233ol0EEdy6SmnUuQQiZX78SfQXHd8tmntc5zqCkwPnIHoiZa6l6p0OAvxYXHw== +"@babel/plugin-proposal-export-default-from@7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.10.4.tgz#08f66eef0067cbf6a7bc036977dcdccecaf0c6c5" + integrity sha512-G1l00VvDZ7Yk2yRlC5D8Ybvu3gmeHS3rCHoUYdjrqGYUtdeOBoRypnvDZ5KQqxyaiiGHWnVDeSEzA5F9ozItig== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-export-default-from" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-export-default-from" "^7.10.4" -"@babel/plugin-proposal-export-namespace-from@7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.1.tgz#512ee069cd866256600bdf89639cf7e1b51fbfe9" - integrity sha512-eR4CoYb6mh5y9LWjnb4CyUatuhtZ8pNLXLDi46GkqtF7WPafFqXycHdvF5qWviozZVGRSAmHzdayc8wUReCdjA== +"@babel/plugin-proposal-export-namespace-from@7.10.4", "@babel/plugin-proposal-export-namespace-from@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz#570d883b91031637b3e2958eea3c438e62c05f54" + integrity sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-proposal-function-sent@7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-function-sent/-/plugin-proposal-function-sent-7.10.1.tgz#e9ffe9df5348e2694d6679f8fd0897acf14326d7" - integrity sha512-mpfEbRcwHvDA6k19ZFsGkW4Q+AF7DekafKTTfn2Ihz1cs6/qL+KgAJlcHBY6XnW1OW1zDaNCR0i28Blonl8/Bg== +"@babel/plugin-proposal-function-sent@7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-function-sent/-/plugin-proposal-function-sent-7.10.4.tgz#05f2daef7b3f09b6c74c9e8a85b430272d206ac4" + integrity sha512-aBtve/DhQsVPAGnSDcgt33gF36rO0TK+KtHp9Hwtj3KwH+o1Cii9vfVVYeB9c6Jo1SXOgTRwRD7ljpTS0qbN8w== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/helper-wrap-function" "^7.10.1" - "@babel/plugin-syntax-function-sent" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-wrap-function" "^7.10.4" + "@babel/plugin-syntax-function-sent" "^7.10.4" -"@babel/plugin-proposal-json-strings@7.10.1", "@babel/plugin-proposal-json-strings@^7.10.1", "@babel/plugin-proposal-json-strings@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.1.tgz#b1e691ee24c651b5a5e32213222b2379734aff09" - integrity sha512-m8r5BmV+ZLpWPtMY2mOKN7wre6HIO4gfIiV+eOmsnZABNenrt/kzYBwrh+KOfgumSWpnlGs5F70J8afYMSJMBg== +"@babel/plugin-proposal-json-strings@7.10.4", "@babel/plugin-proposal-json-strings@^7.10.4", "@babel/plugin-proposal-json-strings@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz#593e59c63528160233bd321b1aebe0820c2341db" + integrity sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.0" -"@babel/plugin-proposal-logical-assignment-operators@7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.10.3.tgz#efae900a91f76ad07dbd50142108e8cd602fee44" - integrity sha512-9uievCCgqOa7VDyMDXlTp5U+0bXu0ubMQL2ek5M1mrwQIY2T9Fx6PUpx/0Eh/8XZice1hzZZo3CJx0wHcDVqNQ== +"@babel/plugin-proposal-logical-assignment-operators@7.11.0", "@babel/plugin-proposal-logical-assignment-operators@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz#9f80e482c03083c87125dee10026b58527ea20c8" + integrity sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q== dependencies: - "@babel/helper-plugin-utils" "^7.10.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-proposal-nullish-coalescing-operator@7.10.1", "@babel/plugin-proposal-nullish-coalescing-operator@^7.10.1", "@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.1.tgz#02dca21673842ff2fe763ac253777f235e9bbf78" - integrity sha512-56cI/uHYgL2C8HVuHOuvVowihhX0sxb3nnfVRzUeVHTWmRHTZrKuAh/OBIMggGU/S1g/1D2CRCXqP+3u7vX7iA== +"@babel/plugin-proposal-nullish-coalescing-operator@7.10.4", "@babel/plugin-proposal-nullish-coalescing-operator@^7.10.4", "@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz#02a7e961fc32e6d5b2db0649e01bf80ddee7e04a" + integrity sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" "@babel/plugin-proposal-nullish-coalescing-operator@7.8.3": @@ -542,13 +479,13 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" -"@babel/plugin-proposal-numeric-separator@7.10.1", "@babel/plugin-proposal-numeric-separator@^7.10.1", "@babel/plugin-proposal-numeric-separator@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.1.tgz#a9a38bc34f78bdfd981e791c27c6fdcec478c123" - integrity sha512-jjfym4N9HtCiNfyyLAVD8WqPYeHUrw4ihxuAynWj6zzp2gf9Ey2f7ImhFm6ikB3CLf5Z/zmcJDri6B4+9j9RsA== +"@babel/plugin-proposal-numeric-separator@7.10.4", "@babel/plugin-proposal-numeric-separator@^7.10.4", "@babel/plugin-proposal-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz#ce1590ff0a65ad12970a609d78855e9a4c1aef06" + integrity sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-numeric-separator" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@babel/plugin-proposal-numeric-separator@7.8.3": version "7.8.3" @@ -558,29 +495,30 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-numeric-separator" "^7.8.3" -"@babel/plugin-proposal-object-rest-spread@^7.10.1", "@babel/plugin-proposal-object-rest-spread@^7.6.2", "@babel/plugin-proposal-object-rest-spread@^7.9.0": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.10.1.tgz#cba44908ac9f142650b4a65b8aa06bf3478d5fb6" - integrity sha512-Z+Qri55KiQkHh7Fc4BW6o+QBuTagbOp9txE+4U1i79u9oWlf2npkiDx+Rf3iK3lbcHBuNy9UOkwuR5wOMH3LIQ== +"@babel/plugin-proposal-object-rest-spread@^7.11.0", "@babel/plugin-proposal-object-rest-spread@^7.6.2", "@babel/plugin-proposal-object-rest-spread@^7.9.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz#bd81f95a1f746760ea43b6c2d3d62b11790ad0af" + integrity sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-transform-parameters" "^7.10.1" + "@babel/plugin-transform-parameters" "^7.10.4" -"@babel/plugin-proposal-optional-catch-binding@^7.10.1", "@babel/plugin-proposal-optional-catch-binding@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.1.tgz#c9f86d99305f9fa531b568ff5ab8c964b8b223d2" - integrity sha512-VqExgeE62YBqI3ogkGoOJp1R6u12DFZjqwJhqtKc2o5m1YTUuUWnos7bZQFBhwkxIFpWYJ7uB75U7VAPPiKETA== +"@babel/plugin-proposal-optional-catch-binding@^7.10.4", "@babel/plugin-proposal-optional-catch-binding@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz#31c938309d24a78a49d68fdabffaa863758554dd" + integrity sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.3.tgz#9a726f94622b653c0a3a7a59cdce94730f526f7c" - integrity sha512-yyG3n9dJ1vZ6v5sfmIlMMZ8azQoqx/5/nZTSWX1td6L1H1bsjzA8TInDChpafCZiJkeOFzp/PtrfigAQXxI1Ng== +"@babel/plugin-proposal-optional-chaining@7.11.0", "@babel/plugin-proposal-optional-chaining@^7.11.0", "@babel/plugin-proposal-optional-chaining@^7.9.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz#de5866d0646f6afdaab8a566382fe3a221755076" + integrity sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA== dependencies: - "@babel/helper-plugin-utils" "^7.10.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" "@babel/plugin-syntax-optional-chaining" "^7.8.0" "@babel/plugin-proposal-optional-chaining@7.9.0": @@ -591,45 +529,37 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@^7.10.1", "@babel/plugin-proposal-optional-chaining@^7.9.0": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.1.tgz#15f5d6d22708629451a91be28f8facc55b0e818c" - integrity sha512-dqQj475q8+/avvok72CF3AOSV/SGEcH29zT5hhohqqvvZ2+boQoOr7iGldBG5YXTO2qgCgc2B3WvVLUdbeMlGA== +"@babel/plugin-proposal-pipeline-operator@7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-pipeline-operator/-/plugin-proposal-pipeline-operator-7.10.5.tgz#0fa2871dbfb74efe19eeb17722032056cb5697f3" + integrity sha512-tCpZ46KUAHgFoXsH593k9sX/ZKsNb4NlTGNif8PdlmkGbtYdbTQi6zNv8yibpRf+3sQFElOBLyNo3I5ZwVu90g== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - -"@babel/plugin-proposal-pipeline-operator@7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-pipeline-operator/-/plugin-proposal-pipeline-operator-7.10.1.tgz#d7129bf1b170efef250759b82b64ce9a9b29d335" - integrity sha512-P+WKKsi7XBEvvTaregnYZIF+aLoCTNt0T21tbzeGlOdERmR1X0iFXJKqZbxsJooa+a3f/tKYFhbJYqnKt70x2w== - dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-pipeline-operator" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-pipeline-operator" "^7.10.4" -"@babel/plugin-proposal-private-methods@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.1.tgz#ed85e8058ab0fe309c3f448e5e1b73ca89cdb598" - integrity sha512-RZecFFJjDiQ2z6maFprLgrdnm0OzoC23Mx89xf1CcEsxmHuzuXOdniEuI+S3v7vjQG4F5sa6YtUp+19sZuSxHg== +"@babel/plugin-proposal-private-methods@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz#b160d972b8fdba5c7d111a145fc8c421fc2a6909" + integrity sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-create-class-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-proposal-throw-expressions@7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-throw-expressions/-/plugin-proposal-throw-expressions-7.10.1.tgz#89bde971b6081bfecff832c811ad76c2337c6970" - integrity sha512-wyhTn1ebUbbphDJVVUpg1wikUOIW8Lg93ng0aDGv07+MxINPS4d0ju68JVH06W4oMnZTwgELA5AImrah9RULYA== +"@babel/plugin-proposal-throw-expressions@7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-throw-expressions/-/plugin-proposal-throw-expressions-7.10.4.tgz#501154a3c1b33cb1ad5b899204481fa2859cd3f3" + integrity sha512-m7K9duXeH/rko36i9G9seLOg2AVdeVTn65k8nnTxgozex0hkDSUr6cktJxTO7jElGEpmMz410pTs0Jn8+empxw== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-throw-expressions" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-throw-expressions" "^7.10.4" -"@babel/plugin-proposal-unicode-property-regex@^7.10.1", "@babel/plugin-proposal-unicode-property-regex@^7.4.4", "@babel/plugin-proposal-unicode-property-regex@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.1.tgz#dc04feb25e2dd70c12b05d680190e138fa2c0c6f" - integrity sha512-JjfngYRvwmPwmnbRZyNiPFI8zxCZb8euzbCG/LxyKdeTb59tVciKo9GK9bi6JYKInk1H11Dq9j/zRqIH4KigfQ== +"@babel/plugin-proposal-unicode-property-regex@^7.10.4", "@babel/plugin-proposal-unicode-property-regex@^7.4.4", "@babel/plugin-proposal-unicode-property-regex@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz#4483cda53041ce3413b7fe2f00022665ddfaa75d" + integrity sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-async-generators@^7.8.0", "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -645,26 +575,26 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-class-properties@^7.10.1", "@babel/plugin-syntax-class-properties@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.1.tgz#d5bc0645913df5b17ad7eda0fa2308330bde34c5" - integrity sha512-Gf2Yx/iRs1JREDtVZ56OrjjgFHCaldpTnuy9BHla10qyVT3YkIIGEtoDWhyop0ksu1GvNjHIoYRBqm3zoR1jyQ== +"@babel/plugin-syntax-class-properties@^7.10.4", "@babel/plugin-syntax-class-properties@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz#6644e6a0baa55a61f9e3231f6c9eeb6ee46c124c" + integrity sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-decorators@^7.10.1", "@babel/plugin-syntax-decorators@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.10.1.tgz#16b869c4beafc9a442565147bda7ce0967bd4f13" - integrity sha512-a9OAbQhKOwSle1Vr0NJu/ISg1sPfdEkfRKWpgPuzhnWWzForou2gIeUIIwjAMHRekhhpJ7eulZlYs0H14Cbi+g== +"@babel/plugin-syntax-decorators@^7.10.4", "@babel/plugin-syntax-decorators@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.10.4.tgz#6853085b2c429f9d322d02f5a635018cdeb2360c" + integrity sha512-2NaoC6fAk2VMdhY1eerkfHV+lVYC1u8b+jmRJISqANCJlTxYy19HGdIkkQtix2UtkcPuPu+IlDgrVseZnU03bw== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-do-expressions@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-do-expressions/-/plugin-syntax-do-expressions-7.10.1.tgz#18ad0be2e2808991101c708e56d2ca5e7a9f96d9" - integrity sha512-Me/wISm2f76puo3Heyu01tthw7/8HSTn2aaiDahWD1K9oRPfzygW0eBcLIrTUdhr58MUyrSLduhUM7uZry6vzg== +"@babel/plugin-syntax-do-expressions@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-do-expressions/-/plugin-syntax-do-expressions-7.10.4.tgz#0c7ebb749500c6bfa99a9f926db3bfd6cdbaded9" + integrity sha512-HyvaTg1aiwGo2I+Pu0nyurRMjIP7J89GpuZ2mcQ0fhO6Jt3BnyhEPbNJFG1hRE99NAPNfPYh93/7HO+GPVkTKg== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-dynamic-import@7.8.3", "@babel/plugin-syntax-dynamic-import@^7.2.0", "@babel/plugin-syntax-dynamic-import@^7.8.0": version "7.8.3" @@ -673,12 +603,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-export-default-from@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.10.1.tgz#634f58f36b5d6320d80f75441fdc61e1c05c33b0" - integrity sha512-+rcL4S/mN1Ss4zhSCbxzv1Wsf12eauvgTjWi0krXEeX1zd6qSxYnJoniE5Ssr5w2WPt61oUCJyXIFQIqO/29zw== +"@babel/plugin-syntax-export-default-from@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.10.4.tgz#e5494f95006355c10292a0ff1ce42a5746002ec8" + integrity sha512-79V6r6Pgudz0RnuMGp5xidu6Z+bPFugh8/Q9eDHonmLp4wKFAZDwygJwYgCzuDu8lFA/sYyT+mc5y2wkd7bTXA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-export-namespace-from@^7.8.3": version "7.8.3" @@ -687,26 +617,26 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-flow@^7.10.1", "@babel/plugin-syntax-flow@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.10.1.tgz#cd4bbca62fb402babacb174f64f8734310d742f0" - integrity sha512-b3pWVncLBYoPP60UOTc7NMlbtsHQ6ITim78KQejNHK6WJ2mzV5kCcg4mIWpasAfJEgwVTibwo2e+FU7UEIKQUg== +"@babel/plugin-syntax-flow@^7.10.4", "@babel/plugin-syntax-flow@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.10.4.tgz#53351dd7ae01995e567d04ce42af1a6e0ba846a6" + integrity sha512-yxQsX1dJixF4qEEdzVbst3SZQ58Nrooz8NV9Z9GL4byTE25BvJgl5lf0RECUf0fh28rZBb/RYTWn/eeKwCMrZQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-function-sent@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-function-sent/-/plugin-syntax-function-sent-7.10.1.tgz#42a03af38dd7f46121c97c67d032da4749792478" - integrity sha512-Ze/5A9mFucmT7UyEA8D60YijmclEZQp3kjzbbEImWnyMLmjE/3S5x7lkCr+W7g2wc00nqk1QLsloa4+1EiHULA== +"@babel/plugin-syntax-function-sent@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-function-sent/-/plugin-syntax-function-sent-7.10.4.tgz#b551f38b629e2e20908e53624f96f9ab300f5061" + integrity sha512-dwElaRoDQhlVevbgKOlEUTe08QNJo4ZjWw3rqnMbEvH8NRJM+iPN2tTQtzyfNloXD8f3Jdiyf5Pn400B1U3SVA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-import-meta@7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.1.tgz#3e59120ed8b3c2ccc5abb1cfc7aaa3ea01cd36b6" - integrity sha512-ypC4jwfIVF72og0dgvEcFRdOM2V9Qm1tu7RGmdZOlhsccyK0wisXmMObGuWEOd5jQ+K9wcIgSNftCpk2vkjUfQ== +"@babel/plugin-syntax-import-meta@7.10.4", "@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings@^7.8.0", "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" @@ -715,19 +645,19 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.10.1.tgz#0ae371134a42b91d5418feb3c8c8d43e1565d2da" - integrity sha512-+OxyOArpVFXQeXKLO9o+r2I4dIoVoy6+Uu0vKELrlweDM3QJADZj+Z+5ERansZqIZBcLj42vHnDI8Rz9BnRIuQ== +"@babel/plugin-syntax-jsx@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.10.4.tgz#39abaae3cbf710c4373d8429484e6ba21340166c" + integrity sha512-KCg9mio9jwiARCB7WAcQ7Y1q+qicILjoK8LP/VkPkEKaf5dkaZZK1EcTe91a3JJlZ3qy6L5s9X52boEYi8DM9g== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-logical-assignment-operators@^7.10.1", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.1.tgz#fffee77b4934ce77f3b427649ecdddbec1958550" - integrity sha512-XyHIFa9kdrgJS91CUH+ccPVTnJShr8nLGc5bG2IhGXv5p1Rd+8BleGE5yzIg2Nc1QZAdHDa0Qp4m6066OL96Iw== +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0", "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": version "7.8.3" @@ -736,12 +666,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.10.1", "@babel/plugin-syntax-numeric-separator@^7.8.0", "@babel/plugin-syntax-numeric-separator@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.1.tgz#25761ee7410bc8cf97327ba741ee94e4a61b7d99" - integrity sha512-uTd0OsHrpe3tH5gRPTxG8Voh99/WCU78vIm5NMRYPAqC8lR4vajt6KkCAknCHrx24vkPdd/05yfdGSB4EIY2mg== +"@babel/plugin-syntax-numeric-separator@^7.10.4", "@babel/plugin-syntax-numeric-separator@^7.8.0", "@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread@^7.8.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": version "7.8.3" @@ -764,115 +694,114 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-pipeline-operator@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-pipeline-operator/-/plugin-syntax-pipeline-operator-7.10.1.tgz#07cd46978b26f21eb8c4231534a64aaa686b3cd3" - integrity sha512-6jvu8KNBnEGuwlRpAQxTHsKcYuGqSf1gAv1c7j+CP7evNU8atjCRW6pK/W1AxeTz1WXWpzciOQTK4hLfPlXKDQ== +"@babel/plugin-syntax-pipeline-operator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-pipeline-operator/-/plugin-syntax-pipeline-operator-7.10.4.tgz#31bf327cf780dd60e0444fd98561119795247a6c" + integrity sha512-QOmXevisZebt9pBkMdDdXWg+fndB8dT/puwSKKu/1K3P4oBwmydN/4dX1hdrNvPHbw4xE+ocIoEus7c4eh7Igg== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-throw-expressions@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-throw-expressions/-/plugin-syntax-throw-expressions-7.10.1.tgz#09a88bacf2ad8af7a465af5e910a61d93136b147" - integrity sha512-1ieYCCX6HCEvBefYt1Njja2XFrbThi2pffdfpPeB7WzVwbX/UlVOrPw9WSPQyVoyo+kqO0l/KGRNZyrTKo0bew== +"@babel/plugin-syntax-throw-expressions@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-throw-expressions/-/plugin-syntax-throw-expressions-7.10.4.tgz#a588df9fa2203207a3ac7e35f0db3b67bf68eca3" + integrity sha512-Yac/4W71+JdAiOV3aLbnUUe2R0NZzNvdy5EqdauFnBQTxIXT58M89lOplIFVELTSus6PxFMjmbi2vXaJDiV/PQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-top-level-await@^7.10.1", "@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.1.tgz#8b8733f8c57397b3eaa47ddba8841586dcaef362" - integrity sha512-hgA5RYkmZm8FTFT3yu2N9Bx7yVVOKYT6yEdXXo6j2JTm0wNxgqaGeQVaSHRjhfnQbX91DtjFB6McRFSlcJH3xQ== +"@babel/plugin-syntax-top-level-await@^7.10.4", "@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz#4bbeb8917b54fcf768364e0a81f560e33a3ef57d" + integrity sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-typescript@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.10.1.tgz#5e82bc27bb4202b93b949b029e699db536733810" - integrity sha512-X/d8glkrAtra7CaQGMiGs/OGa6XgUzqPcBXCIGFCpCqnfGlT0Wfbzo/B89xHhnInTaItPK8LALblVXcUOEh95Q== +"@babel/plugin-syntax-typescript@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.10.4.tgz#2f55e770d3501e83af217d782cb7517d7bb34d25" + integrity sha512-oSAEz1YkBCAKr5Yiq8/BNtvSAPwkp/IyUnwZogd8p+F0RuYQQrLeRUzIQhueQTTBy/F+a40uS7OFKxnkRvmvFQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-arrow-functions@^7.10.1", "@babel/plugin-transform-arrow-functions@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.1.tgz#cb5ee3a36f0863c06ead0b409b4cc43a889b295b" - integrity sha512-6AZHgFJKP3DJX0eCNJj01RpytUa3SOGawIxweHkNX2L6PYikOZmoh5B0d7hIHaIgveMjX990IAa/xK7jRTN8OA== +"@babel/plugin-transform-arrow-functions@^7.10.4", "@babel/plugin-transform-arrow-functions@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz#e22960d77e697c74f41c501d44d73dbf8a6a64cd" + integrity sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-async-to-generator@^7.10.1", "@babel/plugin-transform-async-to-generator@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.1.tgz#e5153eb1a3e028f79194ed8a7a4bf55f862b2062" - integrity sha512-XCgYjJ8TY2slj6SReBUyamJn3k2JLUIiiR5b6t1mNCMSvv7yx+jJpaewakikp0uWFQSF7ChPPoe3dHmXLpISkg== +"@babel/plugin-transform-async-to-generator@^7.10.4", "@babel/plugin-transform-async-to-generator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz#41a5017e49eb6f3cda9392a51eef29405b245a37" + integrity sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ== dependencies: - "@babel/helper-module-imports" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/helper-remap-async-to-generator" "^7.10.1" + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.10.4" -"@babel/plugin-transform-block-scoped-functions@^7.10.1", "@babel/plugin-transform-block-scoped-functions@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.1.tgz#146856e756d54b20fff14b819456b3e01820b85d" - integrity sha512-B7K15Xp8lv0sOJrdVAoukKlxP9N59HS48V1J3U/JGj+Ad+MHq+am6xJVs85AgXrQn4LV8vaYFOB+pr/yIuzW8Q== +"@babel/plugin-transform-block-scoped-functions@^7.10.4", "@babel/plugin-transform-block-scoped-functions@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz#1afa595744f75e43a91af73b0d998ecfe4ebc2e8" + integrity sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-block-scoping@^7.10.1", "@babel/plugin-transform-block-scoping@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.1.tgz#47092d89ca345811451cd0dc5d91605982705d5e" - integrity sha512-8bpWG6TtF5akdhIm/uWTyjHqENpy13Fx8chg7pFH875aNLwX8JxIxqm08gmAT+Whe6AOmaTeLPe7dpLbXt+xUw== +"@babel/plugin-transform-block-scoping@^7.10.4", "@babel/plugin-transform-block-scoping@^7.8.3": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.5.tgz#b81b8aafefbfe68f0f65f7ef397b9ece68a6037d" + integrity sha512-6Ycw3hjpQti0qssQcA6AMSFDHeNJ++R6dIMnpRqUjFeBBTmTDPa8zgF90OVfTvAo11mXZTlVUViY1g8ffrURLg== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - lodash "^4.17.13" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-classes@^7.10.1", "@babel/plugin-transform-classes@^7.9.0": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.1.tgz#6e11dd6c4dfae70f540480a4702477ed766d733f" - integrity sha512-P9V0YIh+ln/B3RStPoXpEQ/CoAxQIhRSUn7aXqQ+FZJ2u8+oCtjIXR3+X0vsSD8zv+mb56K7wZW1XiDTDGiDRQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.1" - "@babel/helper-define-map" "^7.10.1" - "@babel/helper-function-name" "^7.10.1" - "@babel/helper-optimise-call-expression" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/helper-replace-supers" "^7.10.1" - "@babel/helper-split-export-declaration" "^7.10.1" +"@babel/plugin-transform-classes@^7.10.4", "@babel/plugin-transform-classes@^7.9.0": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz#405136af2b3e218bc4a1926228bc917ab1a0adc7" + integrity sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-define-map" "^7.10.4" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.10.1", "@babel/plugin-transform-computed-properties@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.1.tgz#59aa399064429d64dce5cf76ef9b90b7245ebd07" - integrity sha512-mqSrGjp3IefMsXIenBfGcPXxJxweQe2hEIwMQvjtiDQ9b1IBvDUjkAtV/HMXX47/vXf14qDNedXsIiNd1FmkaQ== +"@babel/plugin-transform-computed-properties@^7.10.4", "@babel/plugin-transform-computed-properties@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz#9ded83a816e82ded28d52d4b4ecbdd810cdfc0eb" + integrity sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-destructuring@^7.10.1", "@babel/plugin-transform-destructuring@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.1.tgz#abd58e51337815ca3a22a336b85f62b998e71907" - integrity sha512-V/nUc4yGWG71OhaTH705pU8ZSdM6c1KmmLP8ys59oOYbT7RpMYAR3MsVOt6OHL0WzG7BlTU076va9fjJyYzJMA== +"@babel/plugin-transform-destructuring@^7.10.4", "@babel/plugin-transform-destructuring@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz#70ddd2b3d1bea83d01509e9bb25ddb3a74fc85e5" + integrity sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-dotall-regex@^7.10.1", "@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.1.tgz#920b9fec2d78bb57ebb64a644d5c2ba67cc104ee" - integrity sha512-19VIMsD1dp02RvduFUmfzj8uknaO3uiHHF0s3E1OHnVsNj8oge8EQ5RzHRbJjGSetRnkEuBYO7TG1M5kKjGLOA== +"@babel/plugin-transform-dotall-regex@^7.10.4", "@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz#469c2062105c1eb6a040eaf4fac4b488078395ee" + integrity sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-duplicate-keys@^7.10.1", "@babel/plugin-transform-duplicate-keys@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.1.tgz#c900a793beb096bc9d4d0a9d0cde19518ffc83b9" - integrity sha512-wIEpkX4QvX8Mo9W6XF3EdGttrIPZWozHfEaDTU0WJD/TDnXMvdDh30mzUl/9qWhnf7naicYartcEfUghTCSNpA== +"@babel/plugin-transform-duplicate-keys@^7.10.4", "@babel/plugin-transform-duplicate-keys@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz#697e50c9fee14380fe843d1f306b295617431e47" + integrity sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-exponentiation-operator@^7.10.1", "@babel/plugin-transform-exponentiation-operator@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.1.tgz#279c3116756a60dd6e6f5e488ba7957db9c59eb3" - integrity sha512-lr/przdAbpEA2BUzRvjXdEDLrArGRRPwbaF9rvayuHRvdQ7lUTTkZnhZrJ4LE2jvgMRFF4f0YuPQ20vhiPYxtA== +"@babel/plugin-transform-exponentiation-operator@^7.10.4", "@babel/plugin-transform-exponentiation-operator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz#5ae338c57f8cf4001bdb35607ae66b92d665af2e" + integrity sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-flow-strip-types@7.9.0": version "7.9.0" @@ -882,131 +811,131 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-flow" "^7.8.3" -"@babel/plugin-transform-flow-strip-types@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.10.1.tgz#59eafbff9ae85ec8932d4c16c068654be814ec5e" - integrity sha512-i4o0YwiJBIsIx7/liVCZ3Q2WkWr1/Yu39PksBOnh/khW2SwIFsGa5Ze+MSon5KbDfrEHP9NeyefAgvUSXzaEkw== +"@babel/plugin-transform-flow-strip-types@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.10.4.tgz#c497957f09e86e3df7296271e9eb642876bf7788" + integrity sha512-XTadyuqNst88UWBTdLjM+wEY7BFnY2sYtPyAidfC7M/QaZnSuIZpMvLxqGT7phAcnGyWh/XQFLKcGf04CnvxSQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-flow" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-flow" "^7.10.4" -"@babel/plugin-transform-for-of@^7.10.1", "@babel/plugin-transform-for-of@^7.9.0": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.1.tgz#ff01119784eb0ee32258e8646157ba2501fcfda5" - integrity sha512-US8KCuxfQcn0LwSCMWMma8M2R5mAjJGsmoCBVwlMygvmDUMkTCykc84IqN1M7t+agSfOmLYTInLCHJM+RUoz+w== +"@babel/plugin-transform-for-of@^7.10.4", "@babel/plugin-transform-for-of@^7.9.0": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz#c08892e8819d3a5db29031b115af511dbbfebae9" + integrity sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-function-name@^7.10.1", "@babel/plugin-transform-function-name@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.1.tgz#4ed46fd6e1d8fde2a2ec7b03c66d853d2c92427d" - integrity sha512-//bsKsKFBJfGd65qSNNh1exBy5Y9gD9ZN+DvrJ8f7HXr4avE5POW6zB7Rj6VnqHV33+0vXWUwJT0wSHubiAQkw== +"@babel/plugin-transform-function-name@^7.10.4", "@babel/plugin-transform-function-name@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz#6a467880e0fc9638514ba369111811ddbe2644b7" + integrity sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg== dependencies: - "@babel/helper-function-name" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-literals@^7.10.1", "@babel/plugin-transform-literals@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.1.tgz#5794f8da82846b22e4e6631ea1658bce708eb46a" - integrity sha512-qi0+5qgevz1NHLZroObRm5A+8JJtibb7vdcPQF1KQE12+Y/xxl8coJ+TpPW9iRq+Mhw/NKLjm+5SHtAHCC7lAw== +"@babel/plugin-transform-literals@^7.10.4", "@babel/plugin-transform-literals@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz#9f42ba0841100a135f22712d0e391c462f571f3c" + integrity sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-member-expression-literals@^7.10.1", "@babel/plugin-transform-member-expression-literals@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.1.tgz#90347cba31bca6f394b3f7bd95d2bbfd9fce2f39" - integrity sha512-UmaWhDokOFT2GcgU6MkHC11i0NQcL63iqeufXWfRy6pUOGYeCGEKhvfFO6Vz70UfYJYHwveg62GS83Rvpxn+NA== +"@babel/plugin-transform-member-expression-literals@^7.10.4", "@babel/plugin-transform-member-expression-literals@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz#b1ec44fcf195afcb8db2c62cd8e551c881baf8b7" + integrity sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-modules-amd@^7.10.1", "@babel/plugin-transform-modules-amd@^7.9.0": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.1.tgz#65950e8e05797ebd2fe532b96e19fc5482a1d52a" - integrity sha512-31+hnWSFRI4/ACFr1qkboBbrTxoBIzj7qA69qlq8HY8p7+YCzkCT6/TvQ1a4B0z27VeWtAeJd6pr5G04dc1iHw== +"@babel/plugin-transform-modules-amd@^7.10.4", "@babel/plugin-transform-modules-amd@^7.9.0": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz#1b9cddaf05d9e88b3aad339cb3e445c4f020a9b1" + integrity sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw== dependencies: - "@babel/helper-module-transforms" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-module-transforms" "^7.10.5" + "@babel/helper-plugin-utils" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.10.1", "@babel/plugin-transform-modules-commonjs@^7.9.0": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.1.tgz#d5ff4b4413ed97ffded99961056e1fb980fb9301" - integrity sha512-AQG4fc3KOah0vdITwt7Gi6hD9BtQP/8bhem7OjbaMoRNCH5Djx42O2vYMfau7QnAzQCa+RJnhJBmFFMGpQEzrg== +"@babel/plugin-transform-modules-commonjs@^7.10.4", "@babel/plugin-transform-modules-commonjs@^7.9.0": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz#66667c3eeda1ebf7896d41f1f16b17105a2fbca0" + integrity sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w== dependencies: - "@babel/helper-module-transforms" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/helper-simple-access" "^7.10.1" + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-systemjs@^7.10.1", "@babel/plugin-transform-modules-systemjs@^7.9.0": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.1.tgz#9962e4b0ac6aaf2e20431ada3d8ec72082cbffb6" - integrity sha512-ewNKcj1TQZDL3YnO85qh9zo1YF1CHgmSTlRQgHqe63oTrMI85cthKtZjAiZSsSNjPQ5NCaYo5QkbYqEw1ZBgZA== +"@babel/plugin-transform-modules-systemjs@^7.10.4", "@babel/plugin-transform-modules-systemjs@^7.9.0": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz#6270099c854066681bae9e05f87e1b9cadbe8c85" + integrity sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw== dependencies: - "@babel/helper-hoist-variables" "^7.10.1" - "@babel/helper-module-transforms" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-hoist-variables" "^7.10.4" + "@babel/helper-module-transforms" "^7.10.5" + "@babel/helper-plugin-utils" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-umd@^7.10.1", "@babel/plugin-transform-modules-umd@^7.9.0": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.1.tgz#ea080911ffc6eb21840a5197a39ede4ee67b1595" - integrity sha512-EIuiRNMd6GB6ulcYlETnYYfgv4AxqrswghmBRQbWLHZxN4s7mupxzglnHqk9ZiUpDI4eRWewedJJNj67PWOXKA== +"@babel/plugin-transform-modules-umd@^7.10.4", "@babel/plugin-transform-modules-umd@^7.9.0": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz#9a8481fe81b824654b3a0b65da3df89f3d21839e" + integrity sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA== dependencies: - "@babel/helper-module-transforms" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@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" - integrity sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw== +"@babel/plugin-transform-named-capturing-groups-regex@^7.10.4", "@babel/plugin-transform-named-capturing-groups-regex@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz#78b4d978810b6f3bcf03f9e318f2fc0ed41aecb6" + integrity sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/helper-create-regexp-features-plugin" "^7.10.4" -"@babel/plugin-transform-new-target@^7.10.1", "@babel/plugin-transform-new-target@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.1.tgz#6ee41a5e648da7632e22b6fb54012e87f612f324" - integrity sha512-MBlzPc1nJvbmO9rPr1fQwXOM2iGut+JC92ku6PbiJMMK7SnQc1rytgpopveE3Evn47gzvGYeCdgfCDbZo0ecUw== +"@babel/plugin-transform-new-target@^7.10.4", "@babel/plugin-transform-new-target@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz#9097d753cb7b024cb7381a3b2e52e9513a9c6888" + integrity sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-object-super@^7.10.1", "@babel/plugin-transform-object-super@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.1.tgz#2e3016b0adbf262983bf0d5121d676a5ed9c4fde" - integrity sha512-WnnStUDN5GL+wGQrJylrnnVlFhFmeArINIR9gjhSeYyvroGhBrSAXYg/RHsnfzmsa+onJrTJrEClPzgNmmQ4Gw== +"@babel/plugin-transform-object-super@^7.10.4", "@babel/plugin-transform-object-super@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz#d7146c4d139433e7a6526f888c667e314a093894" + integrity sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/helper-replace-supers" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" -"@babel/plugin-transform-parameters@^7.10.1", "@babel/plugin-transform-parameters@^7.8.7": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.1.tgz#b25938a3c5fae0354144a720b07b32766f683ddd" - integrity sha512-tJ1T0n6g4dXMsL45YsSzzSDZCxiHXAQp/qHrucOq5gEHncTA3xDxnd5+sZcoQp+N1ZbieAaB8r/VUCG0gqseOg== +"@babel/plugin-transform-parameters@^7.10.4", "@babel/plugin-transform-parameters@^7.8.7": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz#59d339d58d0b1950435f4043e74e2510005e2c4a" + integrity sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw== dependencies: - "@babel/helper-get-function-arity" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-property-literals@^7.10.1", "@babel/plugin-transform-property-literals@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.1.tgz#cffc7315219230ed81dc53e4625bf86815b6050d" - integrity sha512-Kr6+mgag8auNrgEpbfIWzdXYOvqDHZOF0+Bx2xh4H2EDNwcbRb9lY6nkZg8oSjsX+DH9Ebxm9hOqtKW+gRDeNA== +"@babel/plugin-transform-property-literals@^7.10.4", "@babel/plugin-transform-property-literals@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz#f6fe54b6590352298785b83edd815d214c42e3c0" + integrity sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-proto-to-assign@7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-proto-to-assign/-/plugin-transform-proto-to-assign-7.10.1.tgz#9eaf5687a29bbd0f58cd198c52aa52e8196b7de3" - integrity sha512-pLncdKyDSYzAjHLTUgkFXBOMb2M3thcQNbHI1F7JTC8mxieckutj+4TRC7aDp98NjznzHPt8xSWkYxKeqZYVDQ== +"@babel/plugin-transform-proto-to-assign@7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-proto-to-assign/-/plugin-transform-proto-to-assign-7.10.5.tgz#43acd79f44d445394f5ff730dcb4960b7c3ceec8" + integrity sha512-41dBtZu5moqBv9Xis1DVwoQZksF8/zb5u46qP39fGcRoXd8z8FL1P0CzYmO/r5q5w9sk3X36ejudcuSbRQ3wqw== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - lodash "^4.17.13" + "@babel/helper-plugin-utils" "^7.10.4" + lodash "^4.17.19" "@babel/plugin-transform-react-constant-elements@^7.0.0", "@babel/plugin-transform-react-constant-elements@^7.2.0", "@babel/plugin-transform-react-constant-elements@^7.6.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.10.1.tgz#c7f117a54657cba3f9d32012e050fc89982df9e1" - integrity sha512-V4os6bkWt/jbrzfyVcZn2ZpuHZkvj3vyBU0U/dtS8SZuMS7Rfx5oknTrtfyXJ2/QZk8gX7Yls5Z921ItNpE30Q== + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.10.4.tgz#0f485260bf1c29012bb973e7e404749eaac12c9e" + integrity sha512-cYmQBW1pXrqBte1raMkAulXmi7rjg3VI6ZLg9QIic8Hq7BtYXaWuZSxsr2siOMI6SWwpxjWfnwhTUrd7JlAV7g== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-react-display-name@7.8.3": version "7.8.3" @@ -1015,69 +944,69 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-react-display-name@^7.10.1", "@babel/plugin-transform-react-display-name@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.10.1.tgz#e6a33f6d48dfb213dda5e007d0c7ff82b6a3d8ef" - integrity sha512-rBjKcVwjk26H3VX8pavMxGf33LNlbocMHdSeldIEswtQ/hrjyTG8fKKILW1cSkODyRovckN/uZlGb2+sAV9JUQ== +"@babel/plugin-transform-react-display-name@^7.10.4", "@babel/plugin-transform-react-display-name@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.10.4.tgz#b5795f4e3e3140419c3611b7a2a3832b9aef328d" + integrity sha512-Zd4X54Mu9SBfPGnEcaGcOrVAYOtjT2on8QZkLKEq1S/tHexG39d9XXGZv19VfRrDjPJzFmPfTAqOQS1pfFOujw== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-react-jsx-development@^7.10.1", "@babel/plugin-transform-react-jsx-development@^7.9.0": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.10.1.tgz#1ac6300d8b28ef381ee48e6fec430cc38047b7f3" - integrity sha512-XwDy/FFoCfw9wGFtdn5Z+dHh6HXKHkC6DwKNWpN74VWinUagZfDcEJc3Y8Dn5B3WMVnAllX8Kviaw7MtC5Epwg== +"@babel/plugin-transform-react-jsx-development@^7.10.4", "@babel/plugin-transform-react-jsx-development@^7.9.0": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.10.4.tgz#6ec90f244394604623880e15ebc3c34c356258ba" + integrity sha512-RM3ZAd1sU1iQ7rI2dhrZRZGv0aqzNQMbkIUCS1txYpi9wHQ2ZHNjo5TwX+UD6pvFW4AbWqLVYvKy5qJSAyRGjQ== dependencies: - "@babel/helper-builder-react-jsx-experimental" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-jsx" "^7.10.1" + "@babel/helper-builder-react-jsx-experimental" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" -"@babel/plugin-transform-react-jsx-self@^7.10.1", "@babel/plugin-transform-react-jsx-self@^7.9.0": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.10.1.tgz#22143e14388d72eb88649606bb9e46f421bc3821" - integrity sha512-4p+RBw9d1qV4S749J42ZooeQaBomFPrSxa9JONLHJ1TxCBo3TzJ79vtmG2S2erUT8PDDrPdw4ZbXGr2/1+dILA== +"@babel/plugin-transform-react-jsx-self@^7.10.4", "@babel/plugin-transform-react-jsx-self@^7.9.0": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.10.4.tgz#cd301a5fed8988c182ed0b9d55e9bd6db0bd9369" + integrity sha512-yOvxY2pDiVJi0axdTWHSMi5T0DILN+H+SaeJeACHKjQLezEzhLx9nEF9xgpBLPtkZsks9cnb5P9iBEi21En3gg== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-jsx" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" -"@babel/plugin-transform-react-jsx-source@^7.10.1", "@babel/plugin-transform-react-jsx-source@^7.9.0": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.10.1.tgz#30db3d4ee3cdebbb26a82a9703673714777a4273" - integrity sha512-neAbaKkoiL+LXYbGDvh6PjPG+YeA67OsZlE78u50xbWh2L1/C81uHiNP5d1fw+uqUIoiNdCC8ZB+G4Zh3hShJA== +"@babel/plugin-transform-react-jsx-source@^7.10.4", "@babel/plugin-transform-react-jsx-source@^7.9.0": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.10.5.tgz#34f1779117520a779c054f2cdd9680435b9222b4" + integrity sha512-wTeqHVkN1lfPLubRiZH3o73f4rfon42HpgxUSs86Nc+8QIcm/B9s8NNVXu/gwGcOyd7yDib9ikxoDLxJP0UiDA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-jsx" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" -"@babel/plugin-transform-react-jsx@^7.10.1", "@babel/plugin-transform-react-jsx@^7.9.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.10.1.tgz#91f544248ba131486decb5d9806da6a6e19a2896" - integrity sha512-MBVworWiSRBap3Vs39eHt+6pJuLUAaK4oxGc8g+wY+vuSJvLiEQjW1LSTqKb8OUPtDvHCkdPhk7d6sjC19xyFw== +"@babel/plugin-transform-react-jsx@^7.10.4", "@babel/plugin-transform-react-jsx@^7.9.1": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.10.4.tgz#673c9f913948764a4421683b2bef2936968fddf2" + integrity sha512-L+MfRhWjX0eI7Js093MM6MacKU4M6dnCRa/QPDwYMxjljzSCzzlzKzj9Pk4P3OtrPcxr2N3znR419nr3Xw+65A== dependencies: - "@babel/helper-builder-react-jsx" "^7.10.1" - "@babel/helper-builder-react-jsx-experimental" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-jsx" "^7.10.1" + "@babel/helper-builder-react-jsx" "^7.10.4" + "@babel/helper-builder-react-jsx-experimental" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" -"@babel/plugin-transform-react-pure-annotations@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.10.1.tgz#f5e7c755d3e7614d4c926e144f501648a5277b70" - integrity sha512-mfhoiai083AkeewsBHUpaS/FM1dmUENHBMpS/tugSJ7VXqXO5dCN1Gkint2YvM1Cdv1uhmAKt1ZOuAjceKmlLA== +"@babel/plugin-transform-react-pure-annotations@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.10.4.tgz#3eefbb73db94afbc075f097523e445354a1c6501" + integrity sha512-+njZkqcOuS8RaPakrnR9KvxjoG1ASJWpoIv/doyWngId88JoFlPlISenGXjrVacZUIALGUr6eodRs1vmPnF23A== dependencies: - "@babel/helper-annotate-as-pure" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-regenerator@^7.10.1", "@babel/plugin-transform-regenerator@^7.8.7": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.1.tgz#10e175cbe7bdb63cc9b39f9b3f823c5c7c5c5490" - integrity sha512-B3+Y2prScgJ2Bh/2l9LJxKbb8C8kRfsG4AdPT+n7ixBHIxJaIG8bi8tgjxUMege1+WqSJ+7gu1YeoMVO3gPWzw== +"@babel/plugin-transform-regenerator@^7.10.4", "@babel/plugin-transform-regenerator@^7.8.7": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz#2015e59d839074e76838de2159db421966fd8b63" + integrity sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw== dependencies: regenerator-transform "^0.14.2" -"@babel/plugin-transform-reserved-words@^7.10.1", "@babel/plugin-transform-reserved-words@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.1.tgz#0fc1027312b4d1c3276a57890c8ae3bcc0b64a86" - integrity sha512-qN1OMoE2nuqSPmpTqEM7OvJ1FkMEV+BjVeZZm9V9mq/x1JLKQ4pcv8riZJMNN3u2AUGl0ouOMjRr2siecvHqUQ== +"@babel/plugin-transform-reserved-words@^7.10.4", "@babel/plugin-transform-reserved-words@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz#8f2682bcdcef9ed327e1b0861585d7013f8a54dd" + integrity sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-runtime@7.9.0": version "7.9.0" @@ -1089,66 +1018,67 @@ resolve "^1.8.1" semver "^5.5.1" -"@babel/plugin-transform-shorthand-properties@^7.10.1", "@babel/plugin-transform-shorthand-properties@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.1.tgz#e8b54f238a1ccbae482c4dce946180ae7b3143f3" - integrity sha512-AR0E/lZMfLstScFwztApGeyTHJ5u3JUKMjneqRItWeEqDdHWZwAOKycvQNCasCK/3r5YXsuNG25funcJDu7Y2g== +"@babel/plugin-transform-shorthand-properties@^7.10.4", "@babel/plugin-transform-shorthand-properties@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz#9fd25ec5cdd555bb7f473e5e6ee1c971eede4dd6" + integrity sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-spread@^7.10.1", "@babel/plugin-transform-spread@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.10.1.tgz#0c6d618a0c4461a274418460a28c9ccf5239a7c8" - integrity sha512-8wTPym6edIrClW8FI2IoaePB91ETOtg36dOkj3bYcNe7aDMN2FXEoUa+WrmPc4xa1u2PQK46fUX2aCb+zo9rfw== +"@babel/plugin-transform-spread@^7.11.0", "@babel/plugin-transform-spread@^7.8.3": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz#fa84d300f5e4f57752fe41a6d1b3c554f13f17cc" + integrity sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" -"@babel/plugin-transform-sticky-regex@^7.10.1", "@babel/plugin-transform-sticky-regex@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.1.tgz#90fc89b7526228bed9842cff3588270a7a393b00" - integrity sha512-j17ojftKjrL7ufX8ajKvwRilwqTok4q+BjkknmQw9VNHnItTyMP5anPFzxFJdCQs7clLcWpCV3ma+6qZWLnGMA== +"@babel/plugin-transform-sticky-regex@^7.10.4", "@babel/plugin-transform-sticky-regex@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz#8f3889ee8657581130a29d9cc91d7c73b7c4a28d" + integrity sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/helper-regex" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-regex" "^7.10.4" -"@babel/plugin-transform-template-literals@^7.10.1", "@babel/plugin-transform-template-literals@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.1.tgz#914c7b7f4752c570ea00553b4284dad8070e8628" - integrity sha512-t7B/3MQf5M1T9hPCRG28DNGZUuxAuDqLYS03rJrIk2prj/UV7Z6FOneijhQhnv/Xa039vidXeVbvjK2SK5f7Gg== +"@babel/plugin-transform-template-literals@^7.10.4", "@babel/plugin-transform-template-literals@^7.8.3": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz#78bc5d626a6642db3312d9d0f001f5e7639fde8c" + integrity sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw== dependencies: - "@babel/helper-annotate-as-pure" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-typeof-symbol@^7.10.1", "@babel/plugin-transform-typeof-symbol@^7.8.4": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.1.tgz#60c0239b69965d166b80a84de7315c1bc7e0bb0e" - integrity sha512-qX8KZcmbvA23zDi+lk9s6hC1FM7jgLHYIjuLgULgc8QtYnmB3tAVIYkNoKRQ75qWBeyzcoMoK8ZQmogGtC/w0g== +"@babel/plugin-transform-typeof-symbol@^7.10.4", "@babel/plugin-transform-typeof-symbol@^7.8.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz#9509f1a7eec31c4edbffe137c16cc33ff0bc5bfc" + integrity sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-typescript@^7.9.0": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.10.1.tgz#2c54daea231f602468686d9faa76f182a94507a6" - integrity sha512-v+QWKlmCnsaimLeqq9vyCsVRMViZG1k2SZTlcZvB+TqyH570Zsij8nvVUZzOASCRiQFUxkLrn9Wg/kH0zgy5OQ== + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.11.0.tgz#2b4879676af37342ebb278216dd090ac67f13abb" + integrity sha512-edJsNzTtvb3MaXQwj8403B7mZoGu9ElDJQZOKjGUnvilquxBA3IQoEIOvkX/1O8xfAsnHS/oQhe2w/IXrr+w0w== dependencies: - "@babel/helper-create-class-features-plugin" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-typescript" "^7.10.1" + "@babel/helper-create-class-features-plugin" "^7.10.5" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-typescript" "^7.10.4" -"@babel/plugin-transform-unicode-escapes@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.1.tgz#add0f8483dab60570d9e03cecef6c023aa8c9940" - integrity sha512-zZ0Poh/yy1d4jeDWpx/mNwbKJVwUYJX73q+gyh4bwtG0/iUlzdEu0sLMda8yuDFS6LBQlT/ST1SJAR6zYwXWgw== +"@babel/plugin-transform-unicode-escapes@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz#feae523391c7651ddac115dae0a9d06857892007" + integrity sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-unicode-regex@^7.10.1", "@babel/plugin-transform-unicode-regex@^7.8.3": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.1.tgz#6b58f2aea7b68df37ac5025d9c88752443a6b43f" - integrity sha512-Y/2a2W299k0VIUdbqYm9X2qS6fE0CUBhhiPpimK6byy7OJ/kORLlIX+J6UrjgNu5awvs62k+6RSslxhcvVw2Tw== +"@babel/plugin-transform-unicode-regex@^7.10.4", "@babel/plugin-transform-unicode-regex@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz#e56d71f9282fac6db09c82742055576d5e6d80a8" + integrity sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/preset-env@7.9.0": version "7.9.0" @@ -1217,69 +1147,73 @@ semver "^5.5.0" "@babel/preset-env@^7.4.5": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.10.2.tgz#715930f2cf8573b0928005ee562bed52fb65fdfb" - integrity sha512-MjqhX0RZaEgK/KueRzh+3yPSk30oqDKJ5HP5tqTSB1e2gzGS3PLy7K0BIpnp78+0anFuSwOeuCf1zZO7RzRvEA== - dependencies: - "@babel/compat-data" "^7.10.1" - "@babel/helper-compilation-targets" "^7.10.2" - "@babel/helper-module-imports" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-proposal-async-generator-functions" "^7.10.1" - "@babel/plugin-proposal-class-properties" "^7.10.1" - "@babel/plugin-proposal-dynamic-import" "^7.10.1" - "@babel/plugin-proposal-json-strings" "^7.10.1" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.10.1" - "@babel/plugin-proposal-numeric-separator" "^7.10.1" - "@babel/plugin-proposal-object-rest-spread" "^7.10.1" - "@babel/plugin-proposal-optional-catch-binding" "^7.10.1" - "@babel/plugin-proposal-optional-chaining" "^7.10.1" - "@babel/plugin-proposal-private-methods" "^7.10.1" - "@babel/plugin-proposal-unicode-property-regex" "^7.10.1" + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.11.0.tgz#860ee38f2ce17ad60480c2021ba9689393efb796" + integrity sha512-2u1/k7rG/gTh02dylX2kL3S0IJNF+J6bfDSp4DI2Ma8QN6Y9x9pmAax59fsCk6QUQG0yqH47yJWA+u1I1LccAg== + dependencies: + "@babel/compat-data" "^7.11.0" + "@babel/helper-compilation-targets" "^7.10.4" + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-proposal-async-generator-functions" "^7.10.4" + "@babel/plugin-proposal-class-properties" "^7.10.4" + "@babel/plugin-proposal-dynamic-import" "^7.10.4" + "@babel/plugin-proposal-export-namespace-from" "^7.10.4" + "@babel/plugin-proposal-json-strings" "^7.10.4" + "@babel/plugin-proposal-logical-assignment-operators" "^7.11.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.10.4" + "@babel/plugin-proposal-numeric-separator" "^7.10.4" + "@babel/plugin-proposal-object-rest-spread" "^7.11.0" + "@babel/plugin-proposal-optional-catch-binding" "^7.10.4" + "@babel/plugin-proposal-optional-chaining" "^7.11.0" + "@babel/plugin-proposal-private-methods" "^7.10.4" + "@babel/plugin-proposal-unicode-property-regex" "^7.10.4" "@babel/plugin-syntax-async-generators" "^7.8.0" - "@babel/plugin-syntax-class-properties" "^7.10.1" + "@babel/plugin-syntax-class-properties" "^7.10.4" "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - "@babel/plugin-syntax-numeric-separator" "^7.10.1" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@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.10.1" - "@babel/plugin-transform-arrow-functions" "^7.10.1" - "@babel/plugin-transform-async-to-generator" "^7.10.1" - "@babel/plugin-transform-block-scoped-functions" "^7.10.1" - "@babel/plugin-transform-block-scoping" "^7.10.1" - "@babel/plugin-transform-classes" "^7.10.1" - "@babel/plugin-transform-computed-properties" "^7.10.1" - "@babel/plugin-transform-destructuring" "^7.10.1" - "@babel/plugin-transform-dotall-regex" "^7.10.1" - "@babel/plugin-transform-duplicate-keys" "^7.10.1" - "@babel/plugin-transform-exponentiation-operator" "^7.10.1" - "@babel/plugin-transform-for-of" "^7.10.1" - "@babel/plugin-transform-function-name" "^7.10.1" - "@babel/plugin-transform-literals" "^7.10.1" - "@babel/plugin-transform-member-expression-literals" "^7.10.1" - "@babel/plugin-transform-modules-amd" "^7.10.1" - "@babel/plugin-transform-modules-commonjs" "^7.10.1" - "@babel/plugin-transform-modules-systemjs" "^7.10.1" - "@babel/plugin-transform-modules-umd" "^7.10.1" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" - "@babel/plugin-transform-new-target" "^7.10.1" - "@babel/plugin-transform-object-super" "^7.10.1" - "@babel/plugin-transform-parameters" "^7.10.1" - "@babel/plugin-transform-property-literals" "^7.10.1" - "@babel/plugin-transform-regenerator" "^7.10.1" - "@babel/plugin-transform-reserved-words" "^7.10.1" - "@babel/plugin-transform-shorthand-properties" "^7.10.1" - "@babel/plugin-transform-spread" "^7.10.1" - "@babel/plugin-transform-sticky-regex" "^7.10.1" - "@babel/plugin-transform-template-literals" "^7.10.1" - "@babel/plugin-transform-typeof-symbol" "^7.10.1" - "@babel/plugin-transform-unicode-escapes" "^7.10.1" - "@babel/plugin-transform-unicode-regex" "^7.10.1" + "@babel/plugin-syntax-top-level-await" "^7.10.4" + "@babel/plugin-transform-arrow-functions" "^7.10.4" + "@babel/plugin-transform-async-to-generator" "^7.10.4" + "@babel/plugin-transform-block-scoped-functions" "^7.10.4" + "@babel/plugin-transform-block-scoping" "^7.10.4" + "@babel/plugin-transform-classes" "^7.10.4" + "@babel/plugin-transform-computed-properties" "^7.10.4" + "@babel/plugin-transform-destructuring" "^7.10.4" + "@babel/plugin-transform-dotall-regex" "^7.10.4" + "@babel/plugin-transform-duplicate-keys" "^7.10.4" + "@babel/plugin-transform-exponentiation-operator" "^7.10.4" + "@babel/plugin-transform-for-of" "^7.10.4" + "@babel/plugin-transform-function-name" "^7.10.4" + "@babel/plugin-transform-literals" "^7.10.4" + "@babel/plugin-transform-member-expression-literals" "^7.10.4" + "@babel/plugin-transform-modules-amd" "^7.10.4" + "@babel/plugin-transform-modules-commonjs" "^7.10.4" + "@babel/plugin-transform-modules-systemjs" "^7.10.4" + "@babel/plugin-transform-modules-umd" "^7.10.4" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.10.4" + "@babel/plugin-transform-new-target" "^7.10.4" + "@babel/plugin-transform-object-super" "^7.10.4" + "@babel/plugin-transform-parameters" "^7.10.4" + "@babel/plugin-transform-property-literals" "^7.10.4" + "@babel/plugin-transform-regenerator" "^7.10.4" + "@babel/plugin-transform-reserved-words" "^7.10.4" + "@babel/plugin-transform-shorthand-properties" "^7.10.4" + "@babel/plugin-transform-spread" "^7.11.0" + "@babel/plugin-transform-sticky-regex" "^7.10.4" + "@babel/plugin-transform-template-literals" "^7.10.4" + "@babel/plugin-transform-typeof-symbol" "^7.10.4" + "@babel/plugin-transform-unicode-escapes" "^7.10.4" + "@babel/plugin-transform-unicode-regex" "^7.10.4" "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.10.2" + "@babel/types" "^7.11.0" browserslist "^4.12.0" core-js-compat "^3.6.2" invariant "^2.2.2" @@ -1287,12 +1221,12 @@ semver "^5.5.0" "@babel/preset-flow@^7.0.0": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.10.1.tgz#29498ec23baf9aa6dae50c568ceba09d71692b82" - integrity sha512-FuQsibb5PaX07fF1XUO5gjjxdEZbcJv8+ugPDaeFEsBIvUTib8hCtEJow/c2F0jq9ZUjpHCQ8IQKNHRvKE1kJQ== + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.10.4.tgz#e0d9c72f8cb02d1633f6a5b7b16763aa2edf659f" + integrity sha512-XI6l1CptQCOBv+ZKYwynyswhtOKwpZZp5n0LG1QKCo8erRhqjoQV6nvx61Eg30JHpysWQSBwA2AWRU3pBbSY5g== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-transform-flow-strip-types" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-flow-strip-types" "^7.10.4" "@babel/preset-modules@^0.1.3": version "0.1.3" @@ -1305,18 +1239,18 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/preset-react@7.10.1", "@babel/preset-react@^7.0.0": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.10.1.tgz#e2ab8ae9a363ec307b936589f07ed753192de041" - integrity sha512-Rw0SxQ7VKhObmFjD/cUcKhPTtzpeviEFX1E6PgP+cYOhQ98icNqtINNFANlsdbQHrmeWnqdxA4Tmnl1jy5tp3Q== +"@babel/preset-react@7.10.4", "@babel/preset-react@^7.0.0": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.10.4.tgz#92e8a66d816f9911d11d4cc935be67adfc82dbcf" + integrity sha512-BrHp4TgOIy4M19JAfO1LhycVXOPWdDbTRep7eVyatf174Hff+6Uk53sDyajqZPu8W1qXRBiYOfIamek6jA7YVw== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-transform-react-display-name" "^7.10.1" - "@babel/plugin-transform-react-jsx" "^7.10.1" - "@babel/plugin-transform-react-jsx-development" "^7.10.1" - "@babel/plugin-transform-react-jsx-self" "^7.10.1" - "@babel/plugin-transform-react-jsx-source" "^7.10.1" - "@babel/plugin-transform-react-pure-annotations" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-react-display-name" "^7.10.4" + "@babel/plugin-transform-react-jsx" "^7.10.4" + "@babel/plugin-transform-react-jsx-development" "^7.10.4" + "@babel/plugin-transform-react-jsx-self" "^7.10.4" + "@babel/plugin-transform-react-jsx-source" "^7.10.4" + "@babel/plugin-transform-react-pure-annotations" "^7.10.4" "@babel/preset-react@7.9.1": version "7.9.1" @@ -1338,45 +1272,37 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-transform-typescript" "^7.9.0" -"@babel/register@7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.10.3.tgz#b49b6603fc8d214cd2f77a6ed2256bd198b5994b" - integrity sha512-s1il0vdd02HCGwV1iocGJEzcbTNouZqMolSXKXFAiTNJSudPas9jdLQwyPPyAJxdNL6KGJ8pwWIOpKmgO/JWqg== +"@babel/register@7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.10.5.tgz#354f3574895f1307f79efe37a51525e52fd38d89" + integrity sha512-eYHdLv43nyvmPn9bfNfrcC4+iYNwdQ8Pxk1MFJuU/U5LpSYl/PH4dFMazCYZDFVi8ueG3shvO+AQfLrxpYulQw== dependencies: find-cache-dir "^2.0.0" - lodash "^4.17.13" + lodash "^4.17.19" make-dir "^2.1.0" pirates "^4.0.0" source-map-support "^0.5.16" "@babel/runtime-corejs2@^7.0.0": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs2/-/runtime-corejs2-7.10.2.tgz#532f20b839684615f97e9f700f630e995efed426" - integrity sha512-ZLwsFnNm3WpIARU1aLFtufjMHsmEnc8TjtrfAjmbgMbeoyR+LuQoyESoNdTfeDhL6IdY12SpeycXMgSgl8XGXA== + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs2/-/runtime-corejs2-7.11.0.tgz#95a95beb65d2003b7bc495b5d14cf1c598153b86" + integrity sha512-vFaGjzMzlDF4FUWvYBHGM/+nLwIzyf9mFfsU+1KcCGmS6S5/bVENENZ3Kq6BEJnbeMZut9qq72wuNhTvIQoNiA== dependencies: core-js "^2.6.5" regenerator-runtime "^0.13.4" "@babel/runtime-corejs3@^7.10.2": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.10.3.tgz#931ed6941d3954924a7aa967ee440e60c507b91a" - integrity sha512-HA7RPj5xvJxQl429r5Cxr2trJwOfPjKiqhCXcdQPSqO2G0RHPZpXu4fkYmBaTKCp2c/jRaMK9GB/lN+7zvvFPw== - dependencies: - core-js-pure "^3.0.0" - regenerator-runtime "^0.13.4" - -"@babel/runtime-corejs3@^7.8.3": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.10.2.tgz#3511797ddf9a3d6f3ce46b99cc835184817eaa4e" - integrity sha512-+a2M/u7r15o3dV1NEizr9bRi+KUVnrs/qYxF0Z06DAPx/4VCWaz1WA7EcbE+uqGgt39lp5akWGmHsTseIkHkHg== + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.11.0.tgz#db54a2251206f0f8579b41918acb14488b8dd2c0" + integrity sha512-K0ioacsw8JgzDSPpUiGWokMvLzGvnZPXLrTsJfyHPrFsnp4yoKn+Ap/8NNZgWKZG9o5+qotH8tAa8AXn8gTN5A== dependencies: core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" -"@babel/runtime@7.10.3", "@babel/runtime@^7.10.2": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.3.tgz#670d002655a7c366540c67f6fd3342cd09500364" - integrity sha512-RzGO0RLSdokm9Ipe/YD+7ww8X2Ro79qiXZF3HU9ljrM+qnJmH1Vqth+hbiQZy761LnMJTMitHDuKVYTk3k4dLw== +"@babel/runtime@7.11.2": + version "7.11.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736" + integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw== dependencies: regenerator-runtime "^0.13.4" @@ -1387,77 +1313,44 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2", "@babel/runtime@^7.9.6": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.2.tgz#d103f21f2602497d38348a32e008637d506db839" - integrity sha512-6sF3uQw2ivImfVIl62RZ7MXhO2tap69WeWK57vAaimT6AZbE4FbqjdEJIN1UqoD6wI6B+1n9UiagafH1sxjOtg== +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.5", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.0.tgz#f10245877042a815e07f7e693faff0ae9d3a2aac" + integrity sha512-qArkXsjJq7H+T86WrIFV0Fnu/tNOkZ4cgXmjkzAu3b/58D5mFIO8JH/y77t7C9q0OdDRdh9s7Ue5GasYssxtXw== dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.10.1", "@babel/template@^7.3.3", "@babel/template@^7.8.6": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.1.tgz#e167154a94cb5f14b28dc58f5356d2162f539811" - integrity sha512-OQDg6SqvFSsc9A0ej6SKINWrpJiNonRIniYondK2ViKhB06i3c0s+76XUft71iqBEe9S1OKsHwPAjfHnuvnCig== - dependencies: - "@babel/code-frame" "^7.10.1" - "@babel/parser" "^7.10.1" - "@babel/types" "^7.10.1" - -"@babel/template@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.3.tgz#4d13bc8e30bf95b0ce9d175d30306f42a2c9a7b8" - integrity sha512-5BjI4gdtD+9fHZUsaxPHPNpwa+xRkDO7c7JbhYn2afvrkDu5SfAAbi9AIMXw2xEhO/BR35TqiW97IqNvCo/GqA== - dependencies: - "@babel/code-frame" "^7.10.3" - "@babel/parser" "^7.10.3" - "@babel/types" "^7.10.3" - -"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.1", "@babel/traverse@^7.7.0", "@babel/traverse@^7.9.0": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.1.tgz#bbcef3031e4152a6c0b50147f4958df54ca0dd27" - integrity sha512-C/cTuXeKt85K+p08jN6vMDz8vSV0vZcI0wmQ36o6mjbuo++kPMdpOYw23W2XH04dbRt9/nMEfA4W3eR21CD+TQ== - dependencies: - "@babel/code-frame" "^7.10.1" - "@babel/generator" "^7.10.1" - "@babel/helper-function-name" "^7.10.1" - "@babel/helper-split-export-declaration" "^7.10.1" - "@babel/parser" "^7.10.1" - "@babel/types" "^7.10.1" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.13" - -"@babel/traverse@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.3.tgz#0b01731794aa7b77b214bcd96661f18281155d7e" - integrity sha512-qO6623eBFhuPm0TmmrUFMT1FulCmsSeJuVGhiLodk2raUDFhhTECLd9E9jC4LBIWziqt4wgF6KuXE4d+Jz9yug== - dependencies: - "@babel/code-frame" "^7.10.3" - "@babel/generator" "^7.10.3" - "@babel/helper-function-name" "^7.10.3" - "@babel/helper-split-export-declaration" "^7.10.1" - "@babel/parser" "^7.10.3" - "@babel/types" "^7.10.3" +"@babel/template@^7.10.4", "@babel/template@^7.3.3", "@babel/template@^7.8.6": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" + integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/parser" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.11.0", "@babel/traverse@^7.9.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.0.tgz#9b996ce1b98f53f7c3e4175115605d56ed07dd24" + integrity sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.0" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/parser" "^7.11.0" + "@babel/types" "^7.11.0" debug "^4.1.0" globals "^11.1.0" - lodash "^4.17.13" - -"@babel/types@^7.0.0", "@babel/types@^7.10.1", "@babel/types@^7.10.2", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.9.0": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.2.tgz#30283be31cad0dbf6fb00bd40641ca0ea675172d" - integrity sha512-AD3AwWBSz0AWF0AkCN9VPiWrvldXq+/e3cHa4J89vo4ymjz1XwrBFFVZmkJTsQIPNk+ZVomPSXUJqq8yyjZsng== - dependencies: - "@babel/helper-validator-identifier" "^7.10.1" - lodash "^4.17.13" - to-fast-properties "^2.0.0" + lodash "^4.17.19" -"@babel/types@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.3.tgz#6535e3b79fea86a6b09e012ea8528f935099de8e" - integrity sha512-nZxaJhBXBQ8HVoIcGsf9qWep3Oh3jCENK54V4mRF7qaJabVsAYdbTtmSD8WmAp1R6ytPiu5apMwSXyxB1WlaBA== +"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.9.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.0.tgz#2ae6bf1ba9ae8c3c43824e5861269871b206e90d" + integrity sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA== dependencies: - "@babel/helper-validator-identifier" "^7.10.3" - lodash "^4.17.13" + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" to-fast-properties "^2.0.0" "@bcoe/v8-coverage@^0.2.3": @@ -1465,12 +1358,12 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@blueprintjs/core@3.29.0", "@blueprintjs/core@^3.29.0": - version "3.29.0" - resolved "https://registry.yarnpkg.com/@blueprintjs/core/-/core-3.29.0.tgz#3b8df57e512f9e42623ee21a3fe71fa13c2b7ba1" - integrity sha512-3BO6hAFHEN0dS4yeDFH+Luh5ZPbCgl9LHWgaI+Aj4/5doPRImF5lRY+r9L3nW/KK7LBPnCS8gVc1BcfvoZgQVw== +"@blueprintjs/core@3.30.1", "@blueprintjs/core@^3.30.1": + version "3.30.1" + resolved "https://registry.yarnpkg.com/@blueprintjs/core/-/core-3.30.1.tgz#e9edad79ee474dc5b2c1ac3a54055174482f94e3" + integrity sha512-vx4Sfpj3EatYGp7BbL9Y8bFHl9XeQhD86QDbK3E2QH+rPSVod1HvUmGnEvzt0fgbpYWGhfIx/AIEj9D4Ap3rKg== dependencies: - "@blueprintjs/icons" "^3.19.0" + "@blueprintjs/icons" "^3.20.0" "@types/dom4" "^2.0.1" classnames "^2.2" dom4 "^2.1.5" @@ -1482,21 +1375,21 @@ resize-observer-polyfill "^1.5.1" tslib "~1.10.0" -"@blueprintjs/datetime@3.18.3": - version "3.18.3" - resolved "https://registry.yarnpkg.com/@blueprintjs/datetime/-/datetime-3.18.3.tgz#3c0d6ac0429c2ebdb0f20ba68cdce798c9e2edd3" - integrity sha512-kFPyBup3V3UMU6cUeD5RCvbMj0bbvEd3XzWeVAPwhVhSEH/VeGXb0kdI6Su41PCzekpYL6uKXU/dbWtcUpwwpA== +"@blueprintjs/datetime@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@blueprintjs/datetime/-/datetime-3.18.5.tgz#e9606ee6dd37d6a58af362f21ae03c3c0d579c6b" + integrity sha512-ktrI7zRzsGiT8gLoHaRAJBLSikYrrQy0GenYAwFXFU3Wlbx6aRz25pBHS0l1mDPqTee0rhOkouF3mRvtcre5kg== dependencies: - "@blueprintjs/core" "^3.29.0" + "@blueprintjs/core" "^3.30.1" classnames "^2.2" react-day-picker "7.3.2" react-lifecycles-compat "^3.0.4" tslib "~1.10.0" -"@blueprintjs/icons@^3.19.0": - version "3.19.0" - resolved "https://registry.yarnpkg.com/@blueprintjs/icons/-/icons-3.19.0.tgz#83ad9fe213705f6656dbec6e9d6bec75d3564455" - integrity sha512-pFgEdSDj8q8ESofuXXSfonsiiqQNJ0u54vr8zxQyKggSwgMyASM/h9MdFVED7jXaj5nsda4or+hWM1ilUeES4Q== +"@blueprintjs/icons@^3.20.0": + version "3.20.0" + resolved "https://registry.yarnpkg.com/@blueprintjs/icons/-/icons-3.20.0.tgz#8eae6fa490735ed2e20a670851cb6ff9d0d3973f" + integrity sha512-bEn7S/aYF8K1p9QJb4KcQ8R9vJLDJ+VtB81w0JlMWIrWTJyM/U3953mp22mK/jr7zJ1pyVIzw6ZRSrG8ht4rgw== dependencies: classnames "^2.2" tslib "~1.10.0" @@ -1526,7 +1419,7 @@ "@emotion/utils" "0.11.3" "@emotion/weak-memoize" "0.2.5" -"@emotion/core@^10.0.0", "@emotion/core@^10.0.20", "@emotion/core@^10.0.28": +"@emotion/core@10.0.28", "@emotion/core@^10.0.0", "@emotion/core@^10.0.20", "@emotion/core@^10.0.28": version "10.0.28" resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.0.28.tgz#bb65af7262a234593a9e952c041d0f1c9b9bef3d" integrity sha512-pH8UueKYO5jgg0Iq+AmCLxBsvuGtvlmiDCOuv8fGNYn3cowFpLN98L8zO56U0H1PjDIyAlXymgL3Wu7u7v6hbA== @@ -1590,7 +1483,7 @@ "@emotion/serialize" "^0.11.15" "@emotion/utils" "0.11.3" -"@emotion/styled@^10.0.0", "@emotion/styled@^10.0.17": +"@emotion/styled@10.0.27", "@emotion/styled@^10.0.0", "@emotion/styled@^10.0.17": version "10.0.27" resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-10.0.27.tgz#12cb67e91f7ad7431e1875b1d83a94b814133eaf" integrity sha512-iK/8Sh7+NLJzyp9a5+vIQIXTYxfT4yB/OJbjzQanB2RZpvmzBQOHZWhpAMZWYEKRNNbsD6WfBw5sVWkb6WzS/Q== @@ -1669,89 +1562,93 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== -"@jest/console@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.1.0.tgz#f67c89e4f4d04dbcf7b052aed5ab9c74f915b954" - integrity sha512-+0lpTHMd/8pJp+Nd4lyip+/Iyf2dZJvcCqrlkeZQoQid+JlThA4M9vxHtheyrQ99jJTMQam+es4BcvZ5W5cC3A== +"@jest/console@^26.2.0": + version "26.2.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.2.0.tgz#d18f2659b90930e7ec3925fb7209f1ba2cf463f0" + integrity sha512-mXQfx3nSLwiHm1i7jbu+uvi+vvpVjNGzIQYLCfsat9rapC+MJkS4zBseNrgJE0vU921b3P67bQzhduphjY3Tig== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" + "@types/node" "*" chalk "^4.0.0" - jest-message-util "^26.1.0" - jest-util "^26.1.0" + jest-message-util "^26.2.0" + jest-util "^26.2.0" slash "^3.0.0" -"@jest/core@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-26.1.0.tgz#4580555b522de412a7998b3938c851e4f9da1c18" - integrity sha512-zyizYmDJOOVke4OO/De//aiv8b07OwZzL2cfsvWF3q9YssfpcKfcnZAwDY8f+A76xXSMMYe8i/f/LPocLlByfw== - dependencies: - "@jest/console" "^26.1.0" - "@jest/reporters" "^26.1.0" - "@jest/test-result" "^26.1.0" - "@jest/transform" "^26.1.0" - "@jest/types" "^26.1.0" +"@jest/core@^26.2.2": + version "26.2.2" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-26.2.2.tgz#63de01ffce967618003dd7a0164b05c8041b81a9" + integrity sha512-UwA8gNI8aeV4FHGfGAUfO/DHjrFVvlBravF1Tm9Kt6qFE+6YHR47kFhgdepOFpADEKstyO+MVdPvkV6/dyt9sA== + dependencies: + "@jest/console" "^26.2.0" + "@jest/reporters" "^26.2.2" + "@jest/test-result" "^26.2.0" + "@jest/transform" "^26.2.2" + "@jest/types" "^26.2.0" + "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.4" - jest-changed-files "^26.1.0" - jest-config "^26.1.0" - jest-haste-map "^26.1.0" - jest-message-util "^26.1.0" + jest-changed-files "^26.2.0" + jest-config "^26.2.2" + jest-haste-map "^26.2.2" + jest-message-util "^26.2.0" jest-regex-util "^26.0.0" - jest-resolve "^26.1.0" - jest-resolve-dependencies "^26.1.0" - jest-runner "^26.1.0" - jest-runtime "^26.1.0" - jest-snapshot "^26.1.0" - jest-util "^26.1.0" - jest-validate "^26.1.0" - jest-watcher "^26.1.0" + jest-resolve "^26.2.2" + jest-resolve-dependencies "^26.2.2" + jest-runner "^26.2.2" + jest-runtime "^26.2.2" + jest-snapshot "^26.2.2" + jest-util "^26.2.0" + jest-validate "^26.2.0" + jest-watcher "^26.2.0" micromatch "^4.0.2" p-each-series "^2.1.0" rimraf "^3.0.0" slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/environment@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.1.0.tgz#378853bcdd1c2443b4555ab908cfbabb851e96da" - integrity sha512-86+DNcGongbX7ai/KE/S3/NcUVZfrwvFzOOWX/W+OOTvTds7j07LtC+MgGydH5c8Ri3uIrvdmVgd1xFD5zt/xA== +"@jest/environment@^26.2.0": + version "26.2.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.2.0.tgz#f6faee1630fcc2fad208953164bccb31dbe0e45f" + integrity sha512-oCgp9NmEiJ5rbq9VI/v/yYLDpladAAVvFxZgNsnJxOETuzPZ0ZcKKHYjKYwCtPOP1WCrM5nmyuOhMStXFGHn+g== dependencies: - "@jest/fake-timers" "^26.1.0" - "@jest/types" "^26.1.0" - jest-mock "^26.1.0" + "@jest/fake-timers" "^26.2.0" + "@jest/types" "^26.2.0" + "@types/node" "*" + jest-mock "^26.2.0" -"@jest/fake-timers@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.1.0.tgz#9a76b7a94c351cdbc0ad53e5a748789f819a65fe" - integrity sha512-Y5F3kBVWxhau3TJ825iuWy++BAuQzK/xEa+wD9vDH3RytW9f2DbMVodfUQC54rZDX3POqdxCgcKdgcOL0rYUpA== +"@jest/fake-timers@^26.2.0": + version "26.2.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.2.0.tgz#b485c57dc4c74d61406a339807a9af4bac74b75a" + integrity sha512-45Gfe7YzYTKqTayBrEdAF0qYyAsNRBzfkV0IyVUm3cx7AsCWlnjilBM4T40w7IXT5VspOgMPikQlV0M6gHwy/g== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" "@sinonjs/fake-timers" "^6.0.1" - jest-message-util "^26.1.0" - jest-mock "^26.1.0" - jest-util "^26.1.0" + "@types/node" "*" + jest-message-util "^26.2.0" + jest-mock "^26.2.0" + jest-util "^26.2.0" -"@jest/globals@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-26.1.0.tgz#6cc5d7cbb79b76b120f2403d7d755693cf063ab1" - integrity sha512-MKiHPNaT+ZoG85oMaYUmGHEqu98y3WO2yeIDJrs2sJqHhYOy3Z6F7F/luzFomRQ8SQ1wEkmahFAz2291Iv8EAw== +"@jest/globals@^26.2.0": + version "26.2.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-26.2.0.tgz#ad78f1104f250c1a4bf5184a2ba51facc59b23f6" + integrity sha512-Hoc6ScEIPaym7RNytIL2ILSUWIGKlwEv+JNFof9dGYOdvPjb2evEURSslvCMkNuNg1ECEClTE8PH7ULlMJntYA== dependencies: - "@jest/environment" "^26.1.0" - "@jest/types" "^26.1.0" - expect "^26.1.0" + "@jest/environment" "^26.2.0" + "@jest/types" "^26.2.0" + expect "^26.2.0" -"@jest/reporters@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.1.0.tgz#08952e90c90282e14ff49e927bdf1873617dae78" - integrity sha512-SVAysur9FOIojJbF4wLP0TybmqwDkdnFxHSPzHMMIYyBtldCW9gG+Q5xWjpMFyErDiwlRuPyMSJSU64A67Pazg== +"@jest/reporters@^26.2.2": + version "26.2.2" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.2.2.tgz#5a8632ab410f4fc57782bc05dcf115e91818e869" + integrity sha512-7854GPbdFTAorWVh+RNHyPO9waRIN6TcvCezKVxI1khvFq9YjINTW7J3WU+tbR038Ynn6WjYred6vtT0YmIWVQ== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^26.1.0" - "@jest/test-result" "^26.1.0" - "@jest/transform" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/console" "^26.2.0" + "@jest/test-result" "^26.2.0" + "@jest/transform" "^26.2.2" + "@jest/types" "^26.2.0" chalk "^4.0.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" @@ -1762,10 +1659,10 @@ istanbul-lib-report "^3.0.0" istanbul-lib-source-maps "^4.0.0" istanbul-reports "^3.0.2" - jest-haste-map "^26.1.0" - jest-resolve "^26.1.0" - jest-util "^26.1.0" - jest-worker "^26.1.0" + jest-haste-map "^26.2.2" + jest-resolve "^26.2.2" + jest-util "^26.2.0" + jest-worker "^26.2.1" slash "^3.0.0" source-map "^0.6.0" string-length "^4.0.1" @@ -1783,72 +1680,63 @@ graceful-fs "^4.2.4" source-map "^0.6.0" -"@jest/test-result@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.1.0.tgz#a93fa15b21ad3c7ceb21c2b4c35be2e407d8e971" - integrity sha512-Xz44mhXph93EYMA8aYDz+75mFbarTV/d/x0yMdI3tfSRs/vh4CqSxgzVmCps1fPkHDCtn0tU8IH9iCKgGeGpfw== +"@jest/test-result@^26.2.0": + version "26.2.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.2.0.tgz#51c9b165c8851cfcf7a3466019114785e154f76b" + integrity sha512-kgPlmcVafpmfyQEu36HClK+CWI6wIaAWDHNxfQtGuKsgoa2uQAYdlxjMDBEa3CvI40+2U3v36gQF6oZBkoKatw== dependencies: - "@jest/console" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/console" "^26.2.0" + "@jest/types" "^26.2.0" "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-sequencer@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-26.1.0.tgz#41a6fc8b850c3f33f48288ea9ea517c047e7f14e" - integrity sha512-Z/hcK+rTq56E6sBwMoQhSRDVjqrGtj1y14e2bIgcowARaIE1SgOanwx6gvY4Q9gTKMoZQXbXvptji+q5GYxa6Q== +"@jest/test-sequencer@^26.2.2": + version "26.2.2" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-26.2.2.tgz#5e8091f2e6c61fdf242af566cb820a4eadc6c4af" + integrity sha512-SliZWon5LNqV/lVXkeowSU6L8++FGOu3f43T01L1Gv6wnFDP00ER0utV9jyK9dVNdXqfMNCN66sfcyar/o7BNw== dependencies: - "@jest/test-result" "^26.1.0" + "@jest/test-result" "^26.2.0" graceful-fs "^4.2.4" - jest-haste-map "^26.1.0" - jest-runner "^26.1.0" - jest-runtime "^26.1.0" + jest-haste-map "^26.2.2" + jest-runner "^26.2.2" + jest-runtime "^26.2.2" -"@jest/transform@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.1.0.tgz#697f48898c2a2787c9b4cb71d09d7e617464e509" - integrity sha512-ICPm6sUXmZJieq45ix28k0s+d/z2E8CHDsq+WwtWI6kW8m7I8kPqarSEcUN86entHQ570ZBRci5OWaKL0wlAWw== +"@jest/transform@^26.2.2": + version "26.2.2" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.2.2.tgz#86c005c8d5d749ac54d8df53ea58675fffe7a97e" + integrity sha512-c1snhvi5wRVre1XyoO3Eef5SEWpuBCH/cEbntBUd9tI5sNYiBDmO0My/lc5IuuGYKp/HFIHV1eZpSx5yjdkhKw== dependencies: "@babel/core" "^7.1.0" - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" babel-plugin-istanbul "^6.0.0" chalk "^4.0.0" convert-source-map "^1.4.0" fast-json-stable-stringify "^2.0.0" graceful-fs "^4.2.4" - jest-haste-map "^26.1.0" + jest-haste-map "^26.2.2" jest-regex-util "^26.0.0" - jest-util "^26.1.0" + jest-util "^26.2.0" micromatch "^4.0.2" pirates "^4.0.1" slash "^3.0.0" source-map "^0.6.1" write-file-atomic "^3.0.0" -"@jest/types@^25.5.0": - version "25.5.0" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-25.5.0.tgz#4d6a4793f7b9599fc3680877b856a97dbccf2a9d" - integrity sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw== - dependencies: - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^1.1.1" - "@types/yargs" "^15.0.0" - chalk "^3.0.0" - -"@jest/types@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.1.0.tgz#f8afaaaeeb23b5cad49dd1f7779689941dcb6057" - integrity sha512-GXigDDsp6ZlNMhXQDeuy/iYCDsRIHJabWtDzvnn36+aqFfG14JmFV0e/iXxY4SP9vbXSiPNOWdehU5MeqrYHBQ== +"@jest/types@^26.2.0": + version "26.2.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.2.0.tgz#b28ca1fb517a4eb48c0addea7fcd9edc4ab45721" + integrity sha512-lvm3rJvctxd7+wxKSxxbzpDbr4FXDLaC57WEKdUIZ2cjTYuxYSc0zlyD7Z4Uqr5VdKxRUrtwIkiqBuvgf8uKJA== dependencies: "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^1.1.1" + "@types/node" "*" "@types/yargs" "^15.0.0" chalk "^4.0.0" "@mdx-js/react@^1.0.0", "@mdx-js/react@^1.5.2": - version "1.6.5" - resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-1.6.5.tgz#70380f25209b62ef69349b7eef09fad7e1103824" - integrity sha512-y1Yu9baw3KokFrs7g5RxHpJNSU4e1zk/5bAJX94yVATglG5HyAL0lYMySU8YzebXNE+fJJMCx9CuiQHy2ezoew== + version "1.6.16" + resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-1.6.16.tgz#538eb14473194d0b3c54020cb230e426174315cd" + integrity sha512-+FhuSVOPo7+4fZaRwWuCSRUcZkJOkZu0rfAbBKvoCg1LWb1Td8Vzi0DTLORdSvgWNbU6+EL40HIgwTOs00x2Jw== "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" @@ -1891,10 +1779,46 @@ dependencies: mkdirp "^1.0.4" +"@projectstorm/geometry@^6.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@projectstorm/geometry/-/geometry-6.2.0.tgz#51c708fda2f95016984287a0e406f14fb084646d" + integrity sha512-Bu7PRdIQAbrqxTrIqGpAIgqvwGpnZSd+jqu3Dv6XvhuE8+WIZVgUBty/eTYo62Ohnc1/chjXH6EtEdgfnj9aRw== + +"@projectstorm/react-canvas-core@^6.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@projectstorm/react-canvas-core/-/react-canvas-core-6.2.0.tgz#46fe2316ff949d7da07e2d215bc0bc6fdd98ca05" + integrity sha512-GxypohDe86O+4DtHi2joGaDuoP7L8l4ppe/1987JhcPM+RmFZw4FJzNVg7kUVIPvQDMBhebXwywDGEz85uluMQ== + dependencies: + "@projectstorm/geometry" "^6.2.0" + +"@projectstorm/react-diagrams-core@6.2.0", "@projectstorm/react-diagrams-core@^6.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@projectstorm/react-diagrams-core/-/react-diagrams-core-6.2.0.tgz#cc70bf237bf565a21be65857cc7213798707f427" + integrity sha512-Vkjt2dUJK+aoS0ZXc7TqRPV0wXaPEe5CsEhXUK3CqBXyvVBE1/iN1qec36uKNWxpdG3OB/PBd1X1fQq64C4J3g== + dependencies: + "@projectstorm/geometry" "^6.2.0" + "@projectstorm/react-canvas-core" "^6.2.0" + +"@projectstorm/react-diagrams-defaults@6.2.0", "@projectstorm/react-diagrams-defaults@^6.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@projectstorm/react-diagrams-defaults/-/react-diagrams-defaults-6.2.0.tgz#571cabc12bb92d1bd1f7099d3dff7b82e74339eb" + integrity sha512-kD4+S8oh/7hzgGEyQqC6mYupr2YM/3y2CJJcHff9IBubt+V2DJndvll3UJOA+sy5VXZl82mvOpz5nLjMQB142w== + dependencies: + "@projectstorm/react-diagrams-core" "^6.2.0" + +"@projectstorm/react-diagrams-routing@6.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@projectstorm/react-diagrams-routing/-/react-diagrams-routing-6.2.0.tgz#12bf14c6184360734cd52c170d3136bd1464a36a" + integrity sha512-+VnhCarWA6TPt5THIlEX1lOgHI+6MNjvSxSE8K06/iPeYhcVa9XcyX9fCthUBBzOYU1hie36o/jXBPri/sambA== + dependencies: + "@projectstorm/geometry" "^6.2.0" + "@projectstorm/react-diagrams-core" "^6.2.0" + "@projectstorm/react-diagrams-defaults" "^6.2.0" + "@reach/router@^1.2.1": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@reach/router/-/router-1.3.3.tgz#58162860dce6c9449d49be86b0561b5ef46d80db" - integrity sha512-gOIAiFhWdiVGSVjukKeNKkCRBLmnORoTPyBihI/jLunICPgxdP30DroAvPQuf1eVfQbfGJQDJkwhJXsNPMnVWw== + version "1.3.4" + resolved "https://registry.yarnpkg.com/@reach/router/-/router-1.3.4.tgz#d2574b19370a70c80480ed91f3da840136d10f8c" + integrity sha512-+mtn9wjlB9NN2CNnnC/BRYtwdKBfSyyasPYraNAyvaV1occr/5NnB4CVzjEZipNHwYebQwcndGUmpFzxAUoqSA== dependencies: create-react-context "0.3.0" invariant "^2.2.3" @@ -1906,15 +1830,15 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== -"@sindresorhus/is@^2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-2.1.1.tgz#ceff6a28a5b4867c2dd4a1ba513de278ccbe8bb1" - integrity sha512-/aPsuoj/1Dw/kzhkgz+ES6TxG0zfTMGLwuK2ZG00k/iJzYHTLCE8mVU8EPqEOp/lmxPoq1C1C9RYToRKb2KEfg== +"@sindresorhus/is@^3.0.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-3.1.0.tgz#d8735532635bea69ad39119df5f0f10099bd09dc" + integrity sha512-n4J+zu52VdY43kdi/XdI9DzuMr1Mur8zFL5ZRG2opCans9aiFwkPxHYFEb5Xgy7n1Z4K6WfI4FpqUqsh3E8BPQ== "@sinonjs/commons@^1.7.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.0.tgz#c8d68821a854c555bba172f3b06959a0039b236d" - integrity sha512-wEj54PfsZ5jGSwMX68G8ZXFawcSglQSXqCftWX3ec8MDUzQdHgcKvw97awHbY0efQEL5iKUOAmmVtoYgmrSG4Q== + version "1.8.1" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.1.tgz#e7df00f98a203324f6dc7cc606cad9d4a8ab2217" + integrity sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw== dependencies: type-detect "4.0.8" @@ -2545,7 +2469,7 @@ resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a" integrity sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA== -"@types/babel__core@^7.0.0": +"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7": version "7.1.9" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.9.tgz#77e59d438522a6fb898fa43dc3455c6e72f3963d" integrity sha512-sY2RsIJ5rpER1u3/aQ8OFSI7qGIy8o1NEEbgb2UaJcvOtXOMpd39ko723NBpjQFg9SIX7TXtjejZVGeIMLhoOw== @@ -2556,17 +2480,6 @@ "@types/babel__template" "*" "@types/babel__traverse" "*" -"@types/babel__core@^7.1.7": - version "7.1.8" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.8.tgz#057f725aca3641f49fc11c7a87a9de5ec588a5d7" - integrity sha512-KXBiQG2OXvaPWFPDS1rD8yV9vO0OuWIqAEqLsbfX0oU2REN5KuoMnZ1gClWcBhO5I3n6oTVAmrMufOvRqdmFTQ== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - "@types/babel__generator" "*" - "@types/babel__template" "*" - "@types/babel__traverse" "*" - "@types/babel__generator@*": version "7.6.1" resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.1.tgz#4901767b397e8711aeb99df8d396d7ba7b7f0e04" @@ -2583,9 +2496,9 @@ "@babel/types" "^7.0.0" "@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.0.12" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.12.tgz#22f49a028e69465390f87bb103ebd61bd086b8f5" - integrity sha512-t4CoEokHTfcyfb4hUaF9oOHu9RmmNWnm1CP0YmMqOOfClKascOmvlEM736vlqeScuGvBDsHkf8R2INd4DWreQA== + version "7.0.13" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.13.tgz#1874914be974a492e1b4cb00585cabb274e8ba18" + integrity sha512-i+zS7t6/s9cdQvbqKDARrcbrPvtJGlbYsMkazo03nTAK3RX9FNrLllXys22uiTGJapPOTZTQ35nHh4ISph4SLQ== dependencies: "@babel/types" "^7.3.0" @@ -2622,9 +2535,9 @@ "@types/domhandler" "*" "@types/glob@^7.1.1": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.2.tgz#06ca26521353a545d94a0adc74f38a59d232c987" - integrity sha512-VgNIkxK+j7Nz5P7jvUZlRvhuPSmsEfS03b0alKcq5V/STUKAa3Plemsn5mrQUO7am6OErJ4rhGEGJbACclrtRA== + version "7.1.3" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183" + integrity sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w== dependencies: "@types/minimatch" "*" "@types/node" "*" @@ -2637,9 +2550,9 @@ "@types/node" "*" "@types/history@*": - version "4.7.6" - resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.6.tgz#ed8fc802c45b8e8f54419c2d054e55c9ea344356" - integrity sha512-GRTZLeLJ8ia00ZH8mxMO8t0aC9M1N9bN461Z2eaRurJo6Fpa+utgCwLzI4jQHcrdzuzp5WPN9jRwpsCQ1VhJ5w== + version "4.7.7" + resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.7.tgz#613957d900fab9ff84c8dfb24fa3eef0c2a40896" + integrity sha512-2xtoL22/3Mv6a70i4+4RB7VgbDDORoWwjcqeNysojZA0R7NK17RbY5Gof/2QiFfJgX+KkWghbwJ+d/2SB8Ndzg== "@types/hoist-non-react-statics@^3.3.1": version "3.3.1" @@ -2674,9 +2587,9 @@ integrity sha512-iTs9HReBu7evG77Q4EC8hZnqRt57irBDkK9nvmHroiOIVwYMQc4IvYvdRgwKfYepunIY7Oh/dBuuld+Gj9uo6w== "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.2.tgz#79d7a78bad4219f4c03d6557a1c72d9ca6ba62d5" - integrity sha512-rsZg7eL+Xcxsxk2XlBt9KcG8nOp9iYdKCOikY9x2RFJCyOdNj4MKPQty0e8oZr29vVAzKXr1BmR+kZauti3o1w== + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" + integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw== "@types/istanbul-lib-report@*": version "3.0.0" @@ -2694,9 +2607,9 @@ "@types/istanbul-lib-report" "*" "@types/json-schema@^7.0.4": - version "7.0.4" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" - integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA== + version "7.0.5" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd" + integrity sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ== "@types/json5@^0.0.29": version "0.0.29" @@ -2715,10 +2628,10 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== -"@types/node@*", "@types/node@>=6": - version "14.0.12" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.12.tgz#9c1d8ffb8084e8936603a6122a7649e40e68e04b" - integrity sha512-/sjzehvjkkpvLpYtN6/2dv5kg41otMGuHQUt9T2aiAuIfleCQRQHXXzF1eAw/qkZTj5Kcf4JSTf7EIizHocy6Q== +"@types/node@*": + version "14.0.27" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.27.tgz#a151873af5a5e851b51b3b065c9e63390a9e0eb1" + integrity sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -2736,15 +2649,22 @@ integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== "@types/prettier@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.0.1.tgz#b6e98083f13faa1e5231bfa3bdb1b0feff536b6d" - integrity sha512-boy4xPNEtiw6N3abRhBi/e7hNvy3Tt8E9ZRAQrwAGzoCGZS/1wjo9KY7JHhnfnEsG5wSjDbymCozUM9a3ea7OQ== + version "2.0.2" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.0.2.tgz#5bb52ee68d0f8efa9cc0099920e56be6cc4e37f3" + integrity sha512-IkVfat549ggtkZUthUzEX49562eGikhSYeVGX97SkMFn+sTZrgRewXjQ4tPKFPCykZHkX1Zfd9OoELGqKU2jJA== "@types/prop-types@*": version "15.7.3" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== +"@types/puppeteer@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/puppeteer/-/puppeteer-3.0.1.tgz#053ec20facc162b25a64785affccaa3e5817c607" + integrity sha512-t03eNKCvWJXhQ8wkc5C6GYuSqMEdKLOX0GLMGtks25YZr38wKZlKTwGM/BoAPVtdysX7Bb9tdwrDS1+NrW3RRA== + dependencies: + "@types/node" "*" + "@types/q@^1.5.1": version "1.5.4" resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" @@ -2773,12 +2693,12 @@ "@types/react" "*" "@types/react@*", "@types/react@^16.9.11": - version "16.9.35" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.35.tgz#a0830d172e8aadd9bd41709ba2281a3124bbd368" - integrity sha512-q0n0SsWcGc8nDqH2GJfWQWUOmZSJhXV64CjVN5SvcNti3TdEaA3AH0D8DwNmMdzjMAC/78tB8nAZIlV8yTz+zQ== + version "16.9.44" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.44.tgz#da84b179c031aef67dc92c33bd3401f1da2fa3bc" + integrity sha512-BtLoJrXdW8DVZauKP+bY4Kmiq7ubcJq+H/aCpRfvPF7RAT3RwR73Sg8szdc2YasbAlWBDrQ6Q+AFM0KwtQY+WQ== dependencies: "@types/prop-types" "*" - csstype "^2.2.0" + csstype "^3.0.2" "@types/responselike@*", "@types/responselike@^1.0.0": version "1.0.0" @@ -2798,14 +2718,14 @@ integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== "@types/tapable@*", "@types/tapable@^1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.5.tgz#9adbc12950582aa65ead76bffdf39fe0c27a3c02" - integrity sha512-/gG2M/Imw7cQFp8PGvz/SwocNrmKFjFsm5Pb8HdbHkZ1K8pmuPzOX4VeVoiEecFCVf4CsN1r3/BRvx+6sNqwtQ== + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.6.tgz#a9ca4b70a18b270ccb2bc0aaafefd1d486b7ea74" + integrity sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA== "@types/uglify-js@*": - version "3.9.2" - resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.9.2.tgz#01992579debba674e1e359cd6bcb1a1d0ab2e02b" - integrity sha512-d6dIfpPbF+8B7WiCi2ELY7m0w1joD8cRW4ms88Emdb2w062NeEpbNCeWwVCgzLRpVG+5e74VFSg4rgJ2xXjEiQ== + version "3.9.3" + resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.9.3.tgz#d94ed608e295bc5424c9600e6b8565407b6b4b6b" + integrity sha512-KswB5C7Kwduwjj04Ykz+AjvPcfgv/37Za24O2EDzYNbwyzOo8+ydtvzUfZ5UMguiVu29Gx44l1A6VsPPcmYu9w== dependencies: source-map "^0.6.1" @@ -2815,18 +2735,18 @@ integrity sha512-67ZgZpAlhIICIdfQrB5fnDvaKFcDxpKibxznfYRVAT4mQE41Dido/3Ty+E3xGBmTogc5+0Qb8tWhna+5B8z1iQ== "@types/webpack-sources@*": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-1.4.0.tgz#e58f1f05f87d39a5c64cf85705bdbdbb94d4d57e" - integrity sha512-c88dKrpSle9BtTqR6ifdaxu1Lvjsl3C5OsfvuUbUwdXymshv1TkufUAXBajCCUM/f/TmnkZC/Esb03MinzSiXQ== + version "1.4.2" + resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-1.4.2.tgz#5d3d4dea04008a779a90135ff96fb5c0c9e6292c" + integrity sha512-77T++JyKow4BQB/m9O96n9d/UUHWLQHlcqXb9Vsf4F1+wKNrrlWNFPDLKNT92RJnCSL6CieTc+NDXtCVZswdTw== dependencies: "@types/node" "*" "@types/source-list-map" "*" source-map "^0.7.3" "@types/webpack@^4.4.31", "@types/webpack@^4.41.8": - version "4.41.17" - resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.17.tgz#0a69005e644d657c85b7d6ec1c826a71bebd1c93" - integrity sha512-6FfeCidTSHozwKI67gIVQQ5Mp0g4X96c2IXxX75hYEQJwST/i6NyZexP//zzMOBb+wG9jJ7oO8fk9yObP2HWAw== + version "4.41.21" + resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.21.tgz#cc685b332c33f153bb2f5fc1fa3ac8adeb592dee" + integrity sha512-2j9WVnNrr/8PLAB5csW44xzQSJwS26aOnICsP3pSGCEdsu6KYtfQ6QJsVUKHWRnm1bL7HziJsfh5fHqth87yKA== dependencies: "@types/anymatch" "*" "@types/node" "*" @@ -2868,14 +2788,14 @@ browserstack-local "^1.4.5" got "^11.0.2" -"@wdio/cli@6.1.22": - version "6.1.22" - resolved "https://registry.yarnpkg.com/@wdio/cli/-/cli-6.1.22.tgz#3e4633718761b2c00ac87957f2af44fc5ded36cb" - integrity sha512-/Z8Vef7m2qb2+Wsv0e9PKSUzsKynf0IgB4TT1bo5xhPjusm4DqWH+ptBuCkXXXoJBHSSyzZFqP2cSnByjICAWQ== +"@wdio/cli@6.3.6": + version "6.3.6" + resolved "https://registry.yarnpkg.com/@wdio/cli/-/cli-6.3.6.tgz#98aabe3f75f113160719dfdc2b1871b431456c4e" + integrity sha512-KYM/PdtUk1Hqt9RuynNDUgQi5SEZmCVdUQt0z7tJTKhF4pEoRx0qBTqSS9l6jPtCRIRMP0ue8F+2iklILjpLkw== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" - "@wdio/utils" "6.1.17" + "@wdio/utils" "6.3.6" async-exit-hook "^2.0.1" chalk "^4.0.0" chokidar "^3.0.0" @@ -2886,8 +2806,9 @@ lodash.flattendeep "^4.4.0" lodash.pickby "^4.6.0" lodash.union "^4.6.0" - log-update "^4.0.0" - webdriverio "6.1.22" + mkdirp "^1.0.4" + recursive-readdir "^2.2.2" + webdriverio "6.3.6" yargs "^15.0.1" yarn-install "^1.0.0" @@ -2900,14 +2821,14 @@ deepmerge "^4.0.0" glob "^7.1.2" -"@wdio/local-runner@6.1.22": - version "6.1.22" - resolved "https://registry.yarnpkg.com/@wdio/local-runner/-/local-runner-6.1.22.tgz#e11350896c53c8c6349f949be3d033670350b30d" - integrity sha512-i7wIUDG4giJQehNg8N78vMi+GS5NGaOmz9OsyhW6jy0ZC7Pmx8pLG9S9Su99WPYth4TE9VXwnhZu64oUTxHYAQ== +"@wdio/local-runner@6.3.6": + version "6.3.6" + resolved "https://registry.yarnpkg.com/@wdio/local-runner/-/local-runner-6.3.6.tgz#ef01af6000bb046a459f653e6b9360d97e1331de" + integrity sha512-40qyjnfdgM3lYo29FTwD21Jl+bQZJr0BC4YauxRF8C/g/SMuc+NyU3v5vCKXFsz3leMvgqCucurDYT81W4IwuA== dependencies: "@wdio/logger" "6.0.16" - "@wdio/repl" "6.1.17" - "@wdio/runner" "6.1.22" + "@wdio/repl" "6.3.6" + "@wdio/runner" "6.3.6" async-exit-hook "^2.0.1" stream-buffers "^3.0.2" @@ -2921,70 +2842,71 @@ loglevel-plugin-prefix "^0.8.4" strip-ansi "^6.0.0" -"@wdio/mocha-framework@6.1.19": - version "6.1.19" - resolved "https://registry.yarnpkg.com/@wdio/mocha-framework/-/mocha-framework-6.1.19.tgz#92f528d0398f9f3fc366036ec617ec5385903ad8" - integrity sha512-yxU+hsyxfwtf7gGuLUlSjAlaN74M/4YB6xAtxFw+PASUyDSOmmZfNbV37g1gTYOm5+tgdyEihXmiYKy/er290A== +"@wdio/mocha-framework@6.3.6": + version "6.3.6" + resolved "https://registry.yarnpkg.com/@wdio/mocha-framework/-/mocha-framework-6.3.6.tgz#d6a7b9ca34c3d5c1b57812954e674688810ae9ae" + integrity sha512-lNcm5fZYnJTiduPFLmRQ4NWV7o/EJd+y1rXVFNNK24oI4lhTdnX87tvnCnco1dkcZRSSv1fS90PBPD7HXkAwWQ== dependencies: "@wdio/logger" "6.0.16" - "@wdio/utils" "6.1.17" + "@wdio/utils" "6.3.6" expect-webdriverio "^1.1.5" mocha "^8.0.1" -"@wdio/protocols@6.1.14": - version "6.1.14" - resolved "https://registry.yarnpkg.com/@wdio/protocols/-/protocols-6.1.14.tgz#ac499b4b8777524c9de7ff054c96896927d2bac1" - integrity sha512-UtRLQ55i23cLQRGtFiEJty1F6AbAfiSpfIxDAiXKHbw6Rp1StwxlqHFrhNe5F48Zu4hnie46t9N/tr/cZOe0kA== +"@wdio/protocols@6.3.6": + version "6.3.6" + resolved "https://registry.yarnpkg.com/@wdio/protocols/-/protocols-6.3.6.tgz#fc408b4441d9701bdd370b0981cf243862ce7e19" + integrity sha512-cocBRkv5sYUBxXResuxskQhIkKgDgE/yAtgMGR5wXLrtG/sMpZ2HVy6LOcOeARidAaRwbav80M2ZHjTCjPn53w== -"@wdio/repl@6.1.17": - version "6.1.17" - resolved "https://registry.yarnpkg.com/@wdio/repl/-/repl-6.1.17.tgz#a611a93443fd7d5a08bf7968ce86f42f38e1a8e8" - integrity sha512-bGzzb+4IgFZ21QifMXPz7VHPidgEjSgWOTF3R2KMKc+FYRjqmje0VD00a0JRc/sh6Fc/BsLdCH8ud+RJBFHFFw== +"@wdio/repl@6.3.6": + version "6.3.6" + resolved "https://registry.yarnpkg.com/@wdio/repl/-/repl-6.3.6.tgz#a4c07ef6bcc4360cd68f07ae6ccdb1e97a97c2ae" + integrity sha512-FDvYacQxSmrrBYsscpcJuz8HGEq2TDosJkrMOyJ6q+Voi5wisvVF8fIiLEvwvL+Uraj1gHwXABFD2YlZZJqFKw== dependencies: - "@wdio/utils" "6.1.17" + "@wdio/utils" "6.3.6" -"@wdio/reporter@6.1.14": - version "6.1.14" - resolved "https://registry.yarnpkg.com/@wdio/reporter/-/reporter-6.1.14.tgz#1885d280654b7b8e14b7be33a5cbf1471d32fb1e" - integrity sha512-Pt6P0JU0COHTpggsOoJKUJyAyQsi7xlHebBNU/DWdHHpmzYd4e9vDutjyTqXu/1zn+t+Zq+uL1IC0E4Xjv6f7w== +"@wdio/reporter@6.3.6": + version "6.3.6" + resolved "https://registry.yarnpkg.com/@wdio/reporter/-/reporter-6.3.6.tgz#c9f94b295339989eb7fabbf7d46f61ac9f4d3320" + integrity sha512-u+iaIZS1oAyHUyXxzyr+pySi2gaFe7u1v6HD1vW6C0sNvICK+wFco4fOSpatizPnVSjuEamgI7ErngBdzUiUag== dependencies: fs-extra "^9.0.0" -"@wdio/runner@6.1.22": - version "6.1.22" - resolved "https://registry.yarnpkg.com/@wdio/runner/-/runner-6.1.22.tgz#827a93e45b29ddaccdb45f3dac30b6d3194d59c3" - integrity sha512-EWon74uKMEO/kPzoIQ71n/qI3c+OoILrpqzu0qvnF39n4XrLrHcqxuy7VMtGGG7uP7fnCQdCKP9f80wc8JWLTA== +"@wdio/runner@6.3.6": + version "6.3.6" + resolved "https://registry.yarnpkg.com/@wdio/runner/-/runner-6.3.6.tgz#2d109448cedddd6110ae35c443f4f42236dc5aec" + integrity sha512-k2EcQ4QIWWSpOA0OaBKpLxt4bSwsVk+BjsgT9TIRp4Ao+DR+AL4nLn6C11NjCnbdoGdFZ5WAsaqZPdy4zmm7ZA== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" - "@wdio/utils" "6.1.17" + "@wdio/utils" "6.3.6" deepmerge "^4.0.0" gaze "^1.1.2" - webdriver "6.1.17" - webdriverio "6.1.22" + webdriver "6.3.6" + webdriverio "6.3.6" -"@wdio/spec-reporter@6.1.14": - version "6.1.14" - resolved "https://registry.yarnpkg.com/@wdio/spec-reporter/-/spec-reporter-6.1.14.tgz#b396e6ece3a651ee1f2743050d899d523d6ea5fa" - integrity sha512-QaSBgnzllzLp9LR7/5DTkmrI8BqcznUma8ZxwUNmhvskv/oKzrmNyeCsGoiExFmCk81A9FgZiZPXey7CuaTkdw== +"@wdio/spec-reporter@6.3.6": + version "6.3.6" + resolved "https://registry.yarnpkg.com/@wdio/spec-reporter/-/spec-reporter-6.3.6.tgz#b5e69d665905e761296bd58139a2ec5054dbf7cc" + integrity sha512-RO/Bc8NIGE8VScrmJz8VNFtIAFoW02xOgFGD8J4LgObQ/cKyn/v6vxCCRgGv27DHYW4j0/rtrem/+z/hgU/C9w== dependencies: - "@wdio/reporter" "6.1.14" + "@wdio/reporter" "6.3.6" chalk "^4.0.0" easy-table "^1.1.1" pretty-ms "^7.0.0" -"@wdio/sync@6.1.14": - version "6.1.14" - resolved "https://registry.yarnpkg.com/@wdio/sync/-/sync-6.1.14.tgz#8c60564cc05aff455a11f360e817e309d4d154b6" - integrity sha512-94K0kQdrOU0aMlJ2Xsd4tWr4tPpmCFp612Ml5+ecQh4C4XD07ocfsvGs+mwI7cfF1sO6g/Hoc+XTY2D+/8En3w== +"@wdio/sync@6.3.6": + version "6.3.6" + resolved "https://registry.yarnpkg.com/@wdio/sync/-/sync-6.3.6.tgz#7e23e0aeaa9b4f35537b3fe0bfc89dd36b8e11f2" + integrity sha512-G8JWHEBvvFaMiEJwN/wViMw+rpsCq1vt1AC3sNAVNw+bQPcR3d0Ml3WprppmhSC9NbKYRxEQPDBdQTo6pNSJqQ== dependencies: + "@types/puppeteer" "^3.0.1" "@wdio/logger" "6.0.16" fibers "^4.0.1" -"@wdio/utils@6.1.17": - version "6.1.17" - resolved "https://registry.yarnpkg.com/@wdio/utils/-/utils-6.1.17.tgz#99890c83dc856879c85894430e62eff56ee4d98d" - integrity sha512-CvXzRq7JeTiMKDyK52LlWghoCOXX1x5bx6tWOIPQh3S4eTQOCAogxVjhzrfgDNV/A+dfIkfByA6n8AifNbupPQ== +"@wdio/utils@6.3.6": + version "6.3.6" + resolved "https://registry.yarnpkg.com/@wdio/utils/-/utils-6.3.6.tgz#80bb0f843d571884c275faf14652ecdac34f2ce5" + integrity sha512-qY/RR/t2YCu+4V5wDlPnuouRiO38BRq0ubMipjRGDixytK6VPa5CfosVqDOlrsXrIBrGHCQct1aGLk7KiugmiQ== dependencies: "@wdio/logger" "6.0.16" @@ -3133,18 +3055,17 @@ "@webassemblyjs/wast-parser" "1.9.0" "@xtuc/long" "4.2.2" -"@wry/context@^0.4.0": - version "0.4.4" - resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.4.4.tgz#e50f5fa1d6cfaabf2977d1fda5ae91717f8815f8" - integrity sha512-LrKVLove/zw6h2Md/KZyWxIkFM6AoyKp71OqpH9Hiip1csjPVoD3tPxlbQUNxEnHENks3UGgNpSBCAfq9KWuag== +"@wry/context@^0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.5.2.tgz#f2a5d5ab9227343aa74c81e06533c1ef84598ec7" + integrity sha512-B/JLuRZ/vbEKHRUiGj6xiMojST1kHhu4WcreLfNN7q9DqQFrb97cWgf/kiYsPSUCAMVN0HzfFc8XjJdzgZzfjw== dependencies: - "@types/node" ">=6" tslib "^1.9.3" -"@wry/equality@^0.1.2", "@wry/equality@^0.1.9": - version "0.1.11" - resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.1.11.tgz#35cb156e4a96695aa81a9ecc4d03787bc17f1790" - integrity sha512-mwEVBDUVODlsQQ5dfuLUS5/Tf7jqUKyhKYHmVi4fPB6bDMOfWvUPJmKgS1Z7Za/sOI3vzWt4+O7yCiL/70MogA== +"@wry/equality@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.2.0.tgz#a312d1b6a682d0909904c2bcd355b02303104fb7" + integrity sha512-Y4d+WH6hs+KZJUC8YKLYGarjGekBrhslDbf/R20oV+AakHPINSitHfDRQz3EGcEWc1luXYNUvMhawWtZVWNGvQ== dependencies: tslib "^1.9.3" @@ -3159,9 +3080,9 @@ integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== abab@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" - integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg== + version "2.0.4" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.4.tgz#6dfa57b417ca06d21b2478f0e638302f99c2405c" + integrity sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ== accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: version "1.3.7" @@ -3184,25 +3105,20 @@ acorn-jsx@^5.2.0: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe" integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ== -acorn-walk@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.1.1.tgz#345f0dffad5c735e7373d2fec9a1023e6a44b83e" - integrity sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ== +acorn-walk@^7.1.1, acorn-walk@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" + integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== acorn@^6.4.1: version "6.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== -acorn@^7.1.1, acorn@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.2.0.tgz#17ea7e40d7c8640ff54a694c889c26f31704effe" - integrity sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ== - -acorn@^7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd" - integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA== +acorn@^7.1.1, acorn@^7.3.1: + version "7.4.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c" + integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w== address@1.1.2, address@^1.0.1: version "1.1.2" @@ -3214,6 +3130,13 @@ agent-base@5: resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-5.1.1.tgz#e8fb3f242959db44d63be665db7a8e739537a32c" integrity sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g== +agent-base@6: + version "6.0.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.1.tgz#808007e4e5867decb0ab6ab2f928fbdb5a596db4" + integrity sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg== + dependencies: + debug "4" + aggregate-error@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" @@ -3263,14 +3186,14 @@ ajv-errors@^1.0.0: integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" - integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.5.5: - version "6.12.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd" - integrity sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ== +ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.3: + version "6.12.3" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706" + integrity sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA== dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" @@ -3284,12 +3207,12 @@ ansi-align@^3.0.0: dependencies: string-width "^3.0.0" -ansi-colors@4.1.1: +ansi-colors@4.1.1, ansi-colors@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== -ansi-colors@^3.0.0, ansi-colors@^3.2.1: +ansi-colors@^3.0.0: version "3.2.4" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== @@ -3299,7 +3222,7 @@ ansi-escapes@^3.2.0: resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== -ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: +ansi-escapes@^4.2.1: version "4.3.1" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61" integrity sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA== @@ -3374,101 +3297,6 @@ anymatch@^3.0.3, anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" -apollo-boost@0.4.9: - version "0.4.9" - resolved "https://registry.yarnpkg.com/apollo-boost/-/apollo-boost-0.4.9.tgz#ab3ba539c2ca944e6fd156583a1b1954b17a6791" - integrity sha512-05y5BKcDaa8w47f8d81UVwKqrAjn8uKLv6QM9fNdldoNzQ+rnOHgFlnrySUZRz9QIT3vPftQkEz2UEASp1Mi5g== - dependencies: - apollo-cache "^1.3.5" - apollo-cache-inmemory "^1.6.6" - apollo-client "^2.6.10" - apollo-link "^1.0.6" - apollo-link-error "^1.0.3" - apollo-link-http "^1.3.1" - graphql-tag "^2.4.2" - ts-invariant "^0.4.0" - tslib "^1.10.0" - -apollo-cache-inmemory@^1.6.6: - version "1.6.6" - resolved "https://registry.yarnpkg.com/apollo-cache-inmemory/-/apollo-cache-inmemory-1.6.6.tgz#56d1f2a463a6b9db32e9fa990af16d2a008206fd" - integrity sha512-L8pToTW/+Xru2FFAhkZ1OA9q4V4nuvfoPecBM34DecAugUZEBhI2Hmpgnzq2hTKZ60LAMrlqiASm0aqAY6F8/A== - dependencies: - apollo-cache "^1.3.5" - apollo-utilities "^1.3.4" - optimism "^0.10.0" - ts-invariant "^0.4.0" - tslib "^1.10.0" - -apollo-cache@1.3.5, apollo-cache@^1.3.5: - version "1.3.5" - resolved "https://registry.yarnpkg.com/apollo-cache/-/apollo-cache-1.3.5.tgz#9dbebfc8dbe8fe7f97ba568a224bca2c5d81f461" - integrity sha512-1XoDy8kJnyWY/i/+gLTEbYLnoiVtS8y7ikBr/IfmML4Qb+CM7dEEbIUOjnY716WqmZ/UpXIxTfJsY7rMcqiCXA== - dependencies: - apollo-utilities "^1.3.4" - tslib "^1.10.0" - -apollo-client@^2.6.10: - version "2.6.10" - resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-2.6.10.tgz#86637047b51d940c8eaa771a4ce1b02df16bea6a" - integrity sha512-jiPlMTN6/5CjZpJOkGeUV0mb4zxx33uXWdj/xQCfAMkuNAC3HN7CvYDyMHHEzmcQ5GV12LszWoQ/VlxET24CtA== - dependencies: - "@types/zen-observable" "^0.8.0" - apollo-cache "1.3.5" - apollo-link "^1.0.0" - apollo-utilities "1.3.4" - symbol-observable "^1.0.2" - ts-invariant "^0.4.0" - tslib "^1.10.0" - zen-observable "^0.8.0" - -apollo-link-error@^1.0.3: - version "1.1.13" - resolved "https://registry.yarnpkg.com/apollo-link-error/-/apollo-link-error-1.1.13.tgz#c1a1bb876ffe380802c8df0506a32c33aad284cd" - integrity sha512-jAZOOahJU6bwSqb2ZyskEK1XdgUY9nkmeclCrW7Gddh1uasHVqmoYc4CKdb0/H0Y1J9lvaXKle2Wsw/Zx1AyUg== - dependencies: - apollo-link "^1.2.14" - apollo-link-http-common "^0.2.16" - tslib "^1.9.3" - -apollo-link-http-common@^0.2.16: - version "0.2.16" - resolved "https://registry.yarnpkg.com/apollo-link-http-common/-/apollo-link-http-common-0.2.16.tgz#756749dafc732792c8ca0923f9a40564b7c59ecc" - integrity sha512-2tIhOIrnaF4UbQHf7kjeQA/EmSorB7+HyJIIrUjJOKBgnXwuexi8aMecRlqTIDWcyVXCeqLhUnztMa6bOH/jTg== - dependencies: - apollo-link "^1.2.14" - ts-invariant "^0.4.0" - tslib "^1.9.3" - -apollo-link-http@^1.3.1: - version "1.5.17" - resolved "https://registry.yarnpkg.com/apollo-link-http/-/apollo-link-http-1.5.17.tgz#499e9f1711bf694497f02c51af12d82de5d8d8ba" - integrity sha512-uWcqAotbwDEU/9+Dm9e1/clO7hTB2kQ/94JYcGouBVLjoKmTeJTUPQKcJGpPwUjZcSqgYicbFqQSoJIW0yrFvg== - dependencies: - apollo-link "^1.2.14" - apollo-link-http-common "^0.2.16" - tslib "^1.9.3" - -apollo-link@^1.0.0, apollo-link@^1.0.6, apollo-link@^1.2.14: - version "1.2.14" - resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.14.tgz#3feda4b47f9ebba7f4160bef8b977ba725b684d9" - integrity sha512-p67CMEFP7kOG1JZ0ZkYZwRDa369w5PIjtMjvrQd/HnIV8FRsHRqLqK+oAZQnFa1DDdZtOtHTi+aMIW6EatC2jg== - dependencies: - apollo-utilities "^1.3.0" - ts-invariant "^0.4.0" - tslib "^1.9.3" - zen-observable-ts "^0.8.21" - -apollo-utilities@1.3.4, apollo-utilities@^1.3.0, apollo-utilities@^1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.3.4.tgz#6129e438e8be201b6c55b0f13ce49d2c7175c9cf" - integrity sha512-pk2hiWrCXMAy2fRPwEyhvka+mqwzeP60Jr1tRYi5xru+3ko94HI9o6lK0CT33/w4RDlxWchmdhDCrvdr+pHCig== - dependencies: - "@wry/equality" "^0.1.2" - fast-json-stable-stringify "^2.0.0" - ts-invariant "^0.4.0" - tslib "^1.10.0" - app-root-dir@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/app-root-dir/-/app-root-dir-1.0.2.tgz#38187ec2dea7577fff033ffcb12172692ff6e118" @@ -3495,18 +3323,18 @@ archiver-utils@^2.1.0: normalize-path "^3.0.0" readable-stream "^2.0.0" -archiver@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/archiver/-/archiver-4.0.1.tgz#3f722b121777e361ca9fad374ecda38e77e63c7f" - integrity sha512-/YV1pU4Nhpf/rJArM23W6GTUjT0l++VbjykrCRua1TSXrn+yM8Qs7XvtwSiRse0iCe49EPNf7ktXnPsWuSb91Q== +archiver@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/archiver/-/archiver-5.0.0.tgz#b1e7dc075a4e18e0aa59afdd7c3e5f3d3321cbeb" + integrity sha512-AEWhJz6Yi6hWtN1Sqy/H4sZo/lLMJ/NftXxGaDy/TnOMmmjsRaZc/Ts+U4BsPoBQkuunTN6t8hk7iU9A+HBxLw== dependencies: archiver-utils "^2.1.0" - async "^2.6.3" + async "^3.2.0" buffer-crc32 "^0.2.1" - glob "^7.1.6" readable-stream "^3.6.0" + readdir-glob "^1.0.0" tar-stream "^2.1.2" - zip-stream "^3.0.1" + zip-stream "^4.0.0" are-we-there-yet@~1.1.2: version "1.1.5" @@ -3600,7 +3428,7 @@ array.prototype.flat@^1.2.1, array.prototype.flat@^1.2.3: define-properties "^1.1.3" es-abstract "^1.17.0-next.1" -array.prototype.flatmap@^1.2.1: +array.prototype.flatmap@^1.2.1, array.prototype.flatmap@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.3.tgz#1c13f84a178566042dd63de4414440db9222e443" integrity sha512-OOEk+lkePcg+ODXIpvuU9PAryCikCJyo7GlDG1upleEpQRx6mzL9puEBkozQ5iAx20KV0l3DbyQwqciJtqe5Pg== @@ -3723,13 +3551,18 @@ async@0.9.x: resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" integrity sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0= -async@^2.6.2, async@^2.6.3: +async@^2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== dependencies: lodash "^4.17.14" +async@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720" + integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw== + async@~0.2.10: version "0.2.10" resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" @@ -3750,60 +3583,47 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -autoprefixer@9.8.4: - version "9.8.4" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.4.tgz#736f1012673a70fa3464671d78d41abd54512863" - integrity sha512-84aYfXlpUe45lvmS+HoAWKCkirI/sw4JK0/bTeeqgHYco3dcsOn0NqdejISjptsYwNji/21dnkDri9PsYKk89A== +autoprefixer@9.8.6, autoprefixer@^9.7.2: + version "9.8.6" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f" + integrity sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg== dependencies: browserslist "^4.12.0" - caniuse-lite "^1.0.30001087" - colorette "^1.2.0" + caniuse-lite "^1.0.30001109" + colorette "^1.2.1" normalize-range "^0.1.2" num2fraction "^1.2.2" postcss "^7.0.32" postcss-value-parser "^4.1.0" -autoprefixer@^9.7.2: - version "9.8.0" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.0.tgz#68e2d2bef7ba4c3a65436f662d0a56a741e56511" - integrity sha512-D96ZiIHXbDmU02dBaemyAg53ez+6F5yZmapmgKcjm35yEe1uVDYI8hGW3VYoGRaG290ZFf91YxHrR518vC0u/A== - dependencies: - browserslist "^4.12.0" - caniuse-lite "^1.0.30001061" - chalk "^2.4.2" - normalize-range "^0.1.2" - num2fraction "^1.2.2" - postcss "^7.0.30" - postcss-value-parser "^4.1.0" - -ava@3.9.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/ava/-/ava-3.9.0.tgz#ac91eac980555fcc6c1b91872ac6923ff4c0ffae" - integrity sha512-EnK5I/AX1U5nF4X1YG3QQYg2+jWnpvMW3z2y096DBvbwITkq9rB7Gu1j5clWcuizAJUlYbvcX6YfP+zkRFgC8Q== +ava@3.11.1: + version "3.11.1" + resolved "https://registry.yarnpkg.com/ava/-/ava-3.11.1.tgz#580bfc974b858fb13f7ce948b9651da4e5b17bc8" + integrity sha512-yGPD0msa5Qronw7GHDNlLaB7oU5zryYtXeuvny40YV6TMskSghqK7Ky3NisM/sr+aqI3DY7sfmORx8dIWQgMoQ== dependencies: "@concordance/react" "^2.0.0" acorn "^7.3.1" - acorn-walk "^7.1.1" + acorn-walk "^7.2.0" ansi-styles "^4.2.1" arrgv "^1.0.2" arrify "^2.0.1" callsites "^3.1.0" chalk "^4.1.0" - chokidar "^3.4.0" + chokidar "^3.4.1" chunkd "^2.0.1" ci-info "^2.0.0" - ci-parallel-vars "^1.0.0" + ci-parallel-vars "^1.0.1" clean-yaml-object "^0.1.0" cli-cursor "^3.1.0" cli-truncate "^2.1.0" - code-excerpt "^2.1.1" + code-excerpt "^3.0.0" common-path-prefix "^3.0.0" concordance "^5.0.0" convert-source-map "^1.7.0" currently-unhandled "^0.4.1" debug "^4.1.1" del "^5.1.0" - emittery "^0.7.0" + emittery "^0.7.1" equal-length "^1.0.0" figures "^3.2.0" globby "^11.0.1" @@ -3811,14 +3631,14 @@ ava@3.9.0: import-local "^3.0.2" indent-string "^4.0.0" is-error "^2.2.2" - is-plain-object "^3.0.0" + is-plain-object "^4.1.1" is-promise "^4.0.0" - lodash "^4.17.15" + lodash "^4.17.19" matcher "^3.0.0" md5-hex "^3.0.1" mem "^6.1.0" ms "^2.1.2" - ora "^4.0.4" + ora "^4.0.5" p-map "^4.0.0" picomatch "^2.2.2" pkg-conf "^3.1.0" @@ -3835,7 +3655,7 @@ ava@3.9.0: trim-off-newlines "^1.0.1" update-notifier "^4.1.0" write-file-atomic "^3.0.3" - yargs "^15.3.1" + yargs "^15.4.1" aws-sign2@~0.7.0: version "0.7.0" @@ -3860,9 +3680,9 @@ axios@^0.19.2: follow-redirects "1.5.10" axobject-query@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.1.2.tgz#2bdffc0371e643e5f03ba99065d5179b9ca79799" - integrity sha512-ICt34ZmrVt8UQnvPl6TVyDTkmhXmAyAT4Jh5ugfGUX4MOrZ+U/ZY6/sdylRw3qGNr9Ub5AJsaHeDMzNLehRdOQ== + version "2.2.0" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" + integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== babel-code-frame@^6.22.0: version "6.26.0" @@ -3873,18 +3693,6 @@ babel-code-frame@^6.22.0: esutils "^2.0.2" js-tokens "^3.0.2" -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.7.0" - "@babel/traverse" "^7.7.0" - "@babel/types" "^7.7.0" - eslint-visitor-keys "^1.0.0" - resolve "^1.12.0" - babel-helper-evaluate-path@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.5.0.tgz#a62fa9c4e64ff7ea5cea9353174ef023a900a67c" @@ -3920,16 +3728,16 @@ babel-helper-to-multiple-sequence-expressions@^0.5.0: resolved "https://registry.yarnpkg.com/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.5.0.tgz#a3f924e3561882d42fcf48907aa98f7979a4588d" integrity sha512-m2CvfDW4+1qfDdsrtf4dwOslQC3yhbgyBFptncp4wvtdrDHqueW7slsYv4gArie056phvQFhT2nRcGS4bnm6mA== -babel-jest@26.1.0, babel-jest@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.1.0.tgz#b20751185fc7569a0f135730584044d1cb934328" - integrity sha512-Nkqgtfe7j6PxLO6TnCQQlkMm8wdTdnIF8xrdpooHCuD5hXRzVEPbPneTJKknH5Dsv3L8ip9unHDAp48YQ54Dkg== +babel-jest@26.2.2, babel-jest@^26.2.2: + version "26.2.2" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.2.2.tgz#70f618f2d7016ed71b232241199308985462f812" + integrity sha512-JmLuePHgA+DSOdOL8lPxCgD2LhPPm+rdw1vnxR73PpIrnmKCS2/aBhtkAcxQWuUcW2hBrH8MJ3LKXE7aWpNZyA== dependencies: - "@jest/transform" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/transform" "^26.2.2" + "@jest/types" "^26.2.0" "@types/babel__core" "^7.1.7" babel-plugin-istanbul "^6.0.0" - babel-preset-jest "^26.1.0" + babel-preset-jest "^26.2.0" chalk "^4.0.0" graceful-fs "^4.2.4" slash "^3.0.0" @@ -3984,10 +3792,10 @@ babel-plugin-istanbul@^6.0.0: istanbul-lib-instrument "^4.0.0" test-exclude "^6.0.0" -babel-plugin-jest-hoist@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.1.0.tgz#c6a774da08247a28285620a64dfadbd05dd5233a" - integrity sha512-qhqLVkkSlqmC83bdMhM8WW4Z9tB+JkjqAqlbbohS9sJLT5Ha2vfzuKqg5yenXrAjOPG2YC0WiXdH3a9PvB+YYw== +babel-plugin-jest-hoist@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.2.0.tgz#bdd0011df0d3d513e5e95f76bd53b51147aca2dd" + integrity sha512-B/hVMRv8Nh1sQ1a3EY8I0n4Y1Wty3NrR5ebOyVT302op+DOAau+xNEImGMsUWOC3++ZlMooCytKz+NgN8aKGbA== dependencies: "@babel/template" "^7.3.3" "@babel/types" "^7.3.3" @@ -4163,13 +3971,14 @@ babel-plugin-transform-undefined-to-void@^6.9.4: integrity sha1-viQcqBQEAwZ4t0hxcyK4nQyP4oA= babel-preset-current-node-syntax@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.2.tgz#fb4a4c51fe38ca60fede1dc74ab35eb843cb41d6" - integrity sha512-u/8cS+dEiK1SFILbOC8/rUI3ml9lboKuuMvZ/4aQnQmhecQAgPw5ew066C1ObnEAUmlx7dv/s2z52psWEtLNiw== + version "0.1.3" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.3.tgz#b4b547acddbf963cba555ba9f9cbbb70bfd044da" + integrity sha512-uyexu1sVwcdFnyq9o8UQYsXwXflIh8LvrF5+cKrYam93ned1CStffB3+BEcsxGSgagoA3GEyjDqO4a/58hyPYQ== dependencies: "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-bigint" "^7.8.3" "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" "@babel/plugin-syntax-json-strings" "^7.8.3" "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" @@ -4178,12 +3987,12 @@ babel-preset-current-node-syntax@^0.1.2: "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -babel-preset-jest@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.1.0.tgz#612f714e5b457394acfd863793c564cbcdb7d1c1" - integrity sha512-na9qCqFksknlEj5iSdw1ehMVR06LCCTkZLGKeEtxDDdhg8xpUF09m29Kvh1pRbZ07h7AQ5ttLYUwpXL4tO6w7w== +babel-preset-jest@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.2.0.tgz#f198201a4e543a43eb40bc481e19736e095fd3e0" + integrity sha512-R1k8kdP3R9phYQugXeNnK/nvCGlBzG4m3EoIIukC80GXb6wCv2XiwPhK6K9MAkQcMszWBYvl2Wm+yigyXFQqXg== dependencies: - babel-plugin-jest-hoist "^26.1.0" + babel-plugin-jest-hoist "^26.2.0" babel-preset-current-node-syntax "^0.1.2" "babel-preset-minify@^0.5.0 || 0.6.0-alpha.5": @@ -4297,9 +4106,9 @@ binary-extensions@^1.0.0: integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== binary-extensions@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" - integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== + version "2.1.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9" + integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== bindings@^1.5.0: version "1.5.0" @@ -4323,9 +4132,9 @@ bluebird@^3.3.5, bluebird@^3.5.5: integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== blueimp-md5@^2.10.0: - version "2.16.0" - resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.16.0.tgz#9018bb805e4ee05512e0e8cbdb9305eeecbdc87c" - integrity sha512-j4nzWIqEFpLSbdhUApHRGDwfXbV8ALhqOn+FY5L6XBdKPAXU9BpGgFSbDsgqogfqPPR9R2WooseWCsfhfEC6uQ== + version "2.17.0" + resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.17.0.tgz#f4fcac088b115f7b4045f19f5da59e9d01b1bb96" + integrity sha512-x5PKJHY5rHQYaADj6NwPUR2QRCUVSggPzrUKkeENpj871o9l9IefJbO2jkT5UvYykeOK9dx0VmkIo6dZ+vThYw== bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.4.0: version "4.11.9" @@ -4506,14 +4315,14 @@ browserslist@4.7.0: node-releases "^1.1.29" browserslist@^4.12.0, browserslist@^4.8.5, browserslist@^4.9.1: - version "4.12.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.12.0.tgz#06c6d5715a1ede6c51fc39ff67fd647f740b656d" - integrity sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg== + version "4.13.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.13.0.tgz#42556cba011e1b0a2775b611cba6a8eca18e940d" + integrity sha512-MINatJ5ZNrLnQ6blGvePd/QOz9Xtu+Ne+x29iQSCHfkU5BugKVJwZKn/iiL8UbpIpa3JhviKjz+XxMo0m2caFQ== dependencies: - caniuse-lite "^1.0.30001043" - electron-to-chromium "^1.3.413" - node-releases "^1.1.53" - pkg-up "^2.0.0" + caniuse-lite "^1.0.30001093" + electron-to-chromium "^1.3.488" + escalade "^3.0.1" + node-releases "^1.1.58" browserstack-local@^1.4.5: version "1.4.5" @@ -4648,16 +4457,16 @@ cacache@^13.0.1: unique-filename "^1.1.1" cacache@^15.0.4: - version "15.0.4" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.0.4.tgz#b2c23cf4ac4f5ead004fb15a0efb0a20340741f1" - integrity sha512-YlnKQqTbD/6iyoJvEY3KJftjrdBYroCbxxYXzhOzsFLWlp6KX4BOlEf4mTx0cMUfVaTS3ENL2QtDWeRYoGLkkw== + version "15.0.5" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.0.5.tgz#69162833da29170d6732334643c60e005f5f17d0" + integrity sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A== dependencies: "@npmcli/move-file" "^1.0.1" chownr "^2.0.0" fs-minipass "^2.0.0" glob "^7.1.4" infer-owner "^1.0.4" - lru-cache "^5.1.1" + lru-cache "^6.0.0" minipass "^3.1.1" minipass-collect "^1.0.2" minipass-flush "^1.0.5" @@ -4793,15 +4602,10 @@ can-use-dom@^0.1.0: resolved "https://registry.yarnpkg.com/can-use-dom/-/can-use-dom-0.1.0.tgz#22cc4a34a0abc43950f42c6411024a3f6366b45a" integrity sha1-IsxKNKCrxDlQ9CxkEQJKP2NmtFo= -caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001043, caniuse-lite@^1.0.30001061: - version "1.0.30001079" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001079.tgz#ed3e5225cd9a6850984fdd88bf24ce45d69b9c22" - integrity sha512-2KaYheg0iOY+CMmDuAB3DHehrXhhb4OZU4KBVGDr/YKyYAcpudaiUQ9PJ9rxrPlKEoJ3ATasQ5AN48MqpwS43Q== - -caniuse-lite@^1.0.30001087: - version "1.0.30001087" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001087.tgz#4a0bdc5998a114fcf8b7954e7ba6c2c29831c54a" - integrity sha512-KAQRGtt+eGCQBSp2iZTQibdCf9oe6cNTi5lmpsW38NnxP4WMYzfU6HCRmh4kJyh6LrTM9/uyElK4xcO93kafpg== +caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001093, caniuse-lite@^1.0.30001109: + version "1.0.30001110" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001110.tgz#9003e3c7f5a43ea6f1193d4d5acba0bfb152c71a" + integrity sha512-KqJWeat4rhSHF0ito4yz9q/JuZHkvn71SsBnxge4azjPDbowIjOUnS8i1xpKGxZxU6BFiPqO2hSV2eiCpFQVRw== capital-case@^1.0.3: version "1.0.3" @@ -4959,10 +4763,10 @@ chokidar@^2.0.4, chokidar@^2.1.8: optionalDependencies: fsevents "^1.2.7" -chokidar@^3.0.0, chokidar@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.0.tgz#b30611423ce376357c765b9b8f904b9fba3c0be8" - integrity sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ== +chokidar@^3.0.0, chokidar@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.1.tgz#e905bdecf10eaa0a0b1db0c664481cc4cbc22ba1" + integrity sha512-TQTJyr2stihpC4Sya9hs2Xh+O2wf+igjL36Y75xx2WdHuiICcn/XJza46Jwt0eT5hVpQOzo3FpY3cj3RVYLX0g== dependencies: anymatch "~3.1.1" braces "~3.0.2" @@ -4985,9 +4789,9 @@ chownr@^2.0.0: integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== chrome-launcher@^0.13.1: - version "0.13.3" - resolved "https://registry.yarnpkg.com/chrome-launcher/-/chrome-launcher-0.13.3.tgz#5dd72ae4e9b3de19ce3fe1941f89551c0ceb1d30" - integrity sha512-ovrDuFXgXS96lzeDqFPQRsczkxla+6QMvzsF+1u0mKlD1KE8EuhjdLwiDfIFedb0FSLz18RK3y6IbKu8oqA0qw== + version "0.13.4" + resolved "https://registry.yarnpkg.com/chrome-launcher/-/chrome-launcher-0.13.4.tgz#4c7d81333c98282899c4e38256da23e00ed32f73" + integrity sha512-nnzXiDbGKjDSK6t2I+35OAPBy5Pw/39bgkb/ZAFwMhwJbdYBp6aH+vW28ZgtjdU890Q7D+3wN/tB8N66q5Gi2A== dependencies: "@types/node" "*" escape-string-regexp "^1.0.5" @@ -5003,15 +4807,16 @@ chrome-trace-event@^1.0.2: dependencies: tslib "^1.9.0" -chromedriver@83.0.0: - version "83.0.0" - resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-83.0.0.tgz#75d7d838e58014658c3990089464166fef951926" - integrity sha512-AePp9ykma+z4aKPRqlbzvVlc22VsQ6+rgF+0aL3B5onHOncK18dWSkLrSSJMczP/mXILN9ohGsvpuTwoRSj6OQ== +chromedriver@84.0.1: + version "84.0.1" + resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-84.0.1.tgz#eaca7723f1a58c262a5c521b8596769af40b0d4f" + integrity sha512-iJ6Y680yp58+KlAPS5YgYe3oePVFf8jY5k4YoczhXkT0p/mQZKfGNkGG/Xc0LjGWDQRTgZwXg66hOXoApIQecg== dependencies: "@testim/chrome-version" "^1.0.7" axios "^0.19.2" del "^5.1.0" - extract-zip "^2.0.0" + extract-zip "^2.0.1" + https-proxy-agent "^5.0.0" mkdirp "^1.0.4" tcp-port-used "^1.0.1" @@ -5025,10 +4830,10 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== -ci-parallel-vars@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/ci-parallel-vars/-/ci-parallel-vars-1.0.0.tgz#af97729ed1c7381911ca37bcea263d62638701b3" - integrity sha512-u6dx20FBXm+apMi+5x7UVm6EH7BL1gc4XrcnQewjcB7HWRcor/V5qWc3RG2HwpgDJ26gIi2DSEu3B7sXynAw/g== +ci-parallel-vars@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ci-parallel-vars/-/ci-parallel-vars-1.0.1.tgz#e87ff0625ccf9d286985b29b4ada8485ca9ffbc2" + integrity sha512-uvzpYrpmidaoxvIQHM+rKSrigjOe9feHYbw4uOI2gdfe1C3xIlxO+kVXq83WQWNniTf8bAxVpy+cQeFQsMERKg== cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" @@ -5098,9 +4903,9 @@ cli-cursor@^3.1.0: restore-cursor "^3.1.0" cli-spinners@^2.1.0, cli-spinners@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.3.0.tgz#0632239a4b5aa4c958610142c34bb7a651fc8df5" - integrity sha512-Xs2Hf2nzrvJMFKimOR7YR0QwZ8fc0u98kdtwN1eNAZzNQgH3vK2pXzff6GJtKh7S5hoJ87ECiAiZFS2fb5Ii2w== + version "2.4.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.4.0.tgz#c6256db216b878cfba4720e719cec7cf72685d7f" + integrity sha512-sJAofoarcm76ZGpuooaO0eDy8saEy+YoZBLjC4h8srt4jeBnkYeOgqxgsJQTpyt2LjI5PTfLJHSL+41Yu4fEJA== cli-table3@0.5.1: version "0.5.1" @@ -5125,6 +4930,11 @@ cli-width@^2.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== +cli-width@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" + integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== + clipboard@^2.0.0: version "2.0.6" resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.6.tgz#52921296eec0fdf77ead1749421b21c968647376" @@ -5163,6 +4973,15 @@ clone-deep@^0.2.4: lazy-cache "^1.0.3" shallow-clone "^0.1.2" +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + clone-response@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" @@ -5175,6 +4994,13 @@ clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= +closest@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/closest/-/closest-0.0.1.tgz#26da6f80b3e0e17e71f80f12782819e9f653495c" + integrity sha1-JtpvgLPg4X5x+A8SeCgZ6fZTSVw= + dependencies: + matches-selector "0.0.1" + clsx@^1.0.4: version "1.1.1" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" @@ -5194,10 +5020,10 @@ coa@^2.0.2: chalk "^2.4.1" q "^1.1.2" -code-excerpt@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/code-excerpt/-/code-excerpt-2.1.1.tgz#5fe3057bfbb71a5f300f659ef2cc0a47651ba77c" - integrity sha512-tJLhH3EpFm/1x7heIW0hemXJTUU5EWl2V0EIX558jp05Mt1U6DVryCgkp3l37cxqs+DNbNgxG43SkwJXpQ14Jw== +code-excerpt@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/code-excerpt/-/code-excerpt-3.0.0.tgz#fcfb6748c03dba8431c19f5474747fad3f250f10" + integrity sha512-VHNTVhd7KsLGOqfX3SyeO8RyYPMp1GJOg194VITk04WMYCv4plV68YWe6TJZxd9MhobjtpMRnVky01gqZsalaw== dependencies: convert-to-spaces "^1.0.1" @@ -5215,9 +5041,9 @@ codemirror-graphql@^0.12.0: graphql-language-service-parser "^1.6.0" codemirror@^5.52.2: - version "5.54.0" - resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.54.0.tgz#82b6adf662b29eeb7b867fe7839d49e25e4a0b38" - integrity sha512-Pgf3surv4zvw+KaW3doUU7pGjF0BPU8/sj7eglWJjzni46U/DDW8pu3nZY0QgQKUcICDXRkq8jZmq0y6KhxM3Q== + version "5.56.0" + resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.56.0.tgz#675640fcc780105cd22d3faa738b5d7ea6426f61" + integrity sha512-MfKVmYgifXjQpLSgpETuih7A7WTTIsxvKfSLGseTY5+qt0E1UD1wblZGM6WLenORo8sgmf+3X+WTe2WF7mufyw== collect-v8-coverage@^1.0.0: version "1.0.1" @@ -5256,10 +5082,10 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -colorette@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.0.tgz#45306add826d196e8c87236ac05d797f25982e63" - integrity sha512-soRSroY+OF/8OdA3PTQXwaDJeMc7TfknKKrxeSCencL2a4+Tx5zhxmmv7hdpCjhKBjehzp8+bwe/T68K0hpIjw== +colorette@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b" + integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw== colors@1.4.0, colors@^1.1.2: version "1.4.0" @@ -5278,7 +5104,7 @@ comma-separated-tokens@^1.0.0: resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== -commander@2, commander@^2.19.0, commander@^2.20.0, commander@~2.20.3: +commander@2, commander@^2.19.0, commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -5298,20 +5124,25 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= +complex.js@^2.0.11: + version "2.0.11" + resolved "https://registry.yarnpkg.com/complex.js/-/complex.js-2.0.11.tgz#09a873fbf15ffd8c18c9c2201ccef425c32b8bf1" + integrity sha512-6IArJLApNtdg1P1dFtn3dnyzoZBEF0MwMnrfF1exSBRpZYoy4yieMkpZhQDC0uwctw48vii0CFVyHfpgZ/DfGw== + component-emitter@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== -compress-commons@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-3.0.0.tgz#833944d84596e537224dd91cf92f5246823d4f1d" - integrity sha512-FyDqr8TKX5/X0qo+aVfaZ+PVmNJHJeckFBlq8jZGSJOgnynhfifoyl24qaqdUdDIBe0EVTHByN6NAkqYvE/2Xg== +compress-commons@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-4.0.1.tgz#c5fa908a791a0c71329fba211d73cd2a32005ea8" + integrity sha512-xZm9o6iikekkI0GnXCmAl3LQGZj5TBDj0zLowsqi7tJtEa3FMGSEcHcqrSJIrOAk1UG/NBbDn/F1q+MG/p/EsA== dependencies: buffer-crc32 "^0.2.13" - crc32-stream "^3.0.1" + crc32-stream "^4.0.0" normalize-path "^3.0.0" - readable-stream "^2.3.7" + readable-stream "^3.6.0" compressible@~2.0.16: version "2.0.18" @@ -5478,21 +5309,21 @@ copy-to-clipboard@^3.0.8, copy-to-clipboard@^3.2.0: dependencies: toggle-selection "^1.0.6" -copy-webpack-plugin@6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-6.0.2.tgz#10efc6ad219a61acbf2f5fb50af83da38431bc34" - integrity sha512-9Gm8X0c6eXlKnmltMPFCBeGOKjtcRIyTt4VaO3k1TkNgVTe5Ov2lYsYVuyLp0kp8DItO3apewflM+1GYgh6V2Q== +copy-webpack-plugin@6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-6.0.3.tgz#2b3d2bfc6861b96432a65f0149720adbd902040b" + integrity sha512-q5m6Vz4elsuyVEIUXr7wJdIdePWTubsqVbEMvf1WQnHGv0Q+9yPRu7MtYFPt+GBOXRav9lvIINifTQ1vSCs+eA== dependencies: cacache "^15.0.4" - fast-glob "^3.2.2" + fast-glob "^3.2.4" find-cache-dir "^3.3.1" glob-parent "^5.1.1" globby "^11.0.1" loader-utils "^2.0.0" normalize-path "^3.0.0" - p-limit "^2.3.0" + p-limit "^3.0.1" schema-utils "^2.7.0" - serialize-javascript "^3.1.0" + serialize-javascript "^4.0.0" webpack-sources "^1.4.3" core-js-compat@^3.6.2: @@ -5557,15 +5388,15 @@ cosmiconfig@^6.0.0: path-type "^4.0.0" yaml "^1.7.2" -countries-list@2.5.4: - version "2.5.4" - resolved "https://registry.yarnpkg.com/countries-list/-/countries-list-2.5.4.tgz#c1a0ab8f63c0972b266254d63e595ea86a6cfe1e" - integrity sha512-6+AIKth3MCOEWTLOVTgR7zTe6oH3JlL0MworsJwIyG0jQi+cKeChOEPvcKszNtGAuCp7p+OrqdxPWxjhu8LqoA== +countries-list@2.5.6: + version "2.5.6" + resolved "https://registry.yarnpkg.com/countries-list/-/countries-list-2.5.6.tgz#af237e7d00b2d1283fe766614a945fe5348eefbb" + integrity sha512-IEt6KCIzexbR1pTvSJakKCKbqlmHKkEO4oYHN6UCiNToUdN/zXy/1NxiUfZ3ktS0QO/UryCJGPoLkLdYsrAzNw== -crc32-stream@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-3.0.1.tgz#cae6eeed003b0e44d739d279de5ae63b171b4e85" - integrity sha512-mctvpXlbzsvK+6z8kJwSJ5crm7yBwrQMTybJzMw1O4lLGJqjlDCXY2Zw7KheiA6XBEcBmfLx1D88mjRGVJtY9w== +crc32-stream@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-4.0.0.tgz#05b7ca047d831e98c215538666f372b756d91893" + integrity sha512-tyMw2IeUX6t9jhgXI6um0eKfWq4EIDpfv5m7GX4Jzp7eVelQ360xd8EPXJhp2mHwLQIkqlnMLjzqSZI3a+0wRw== dependencies: crc "^3.4.4" readable-stream "^3.4.0" @@ -5673,42 +5504,42 @@ crypto-random-string@^2.0.0: resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== -css-loader@3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.6.0.tgz#2e4b2c7e6e2d27f8c8f28f61bffcd2e6c91ef645" - integrity sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ== +css-loader@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-4.2.0.tgz#b57efb92ac8f0cd85bf92d89df9634ef1f51b8bf" + integrity sha512-ko7a9b0iFpWtk9eSI/C8IICvZeGtYnjxYjw45rJprokXj/+kBd/siX4vAIBq9Uij8Jubc4jL1EvSnTjCEwaHSw== dependencies: - camelcase "^5.3.1" + camelcase "^6.0.0" cssesc "^3.0.0" icss-utils "^4.1.1" - loader-utils "^1.2.3" + loader-utils "^2.0.0" normalize-path "^3.0.0" postcss "^7.0.32" postcss-modules-extract-imports "^2.0.0" - postcss-modules-local-by-default "^3.0.2" + postcss-modules-local-by-default "^3.0.3" postcss-modules-scope "^2.2.0" postcss-modules-values "^3.0.0" postcss-value-parser "^4.1.0" schema-utils "^2.7.0" - semver "^6.3.0" + semver "^7.3.2" css-loader@^3.0.0: - version "3.5.3" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.5.3.tgz#95ac16468e1adcd95c844729e0bb167639eb0bcf" - integrity sha512-UEr9NH5Lmi7+dguAm+/JSPovNjYbm2k3TK58EiwQHzOHH5Jfq1Y+XoP2bQO6TMn7PptMd0opxxedAWcaSTRKHw== + version "3.6.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.6.0.tgz#2e4b2c7e6e2d27f8c8f28f61bffcd2e6c91ef645" + integrity sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ== dependencies: camelcase "^5.3.1" cssesc "^3.0.0" icss-utils "^4.1.1" loader-utils "^1.2.3" normalize-path "^3.0.0" - postcss "^7.0.27" + postcss "^7.0.32" postcss-modules-extract-imports "^2.0.0" postcss-modules-local-by-default "^3.0.2" postcss-modules-scope "^2.2.0" postcss-modules-values "^3.0.0" - postcss-value-parser "^4.0.3" - schema-utils "^2.6.6" + postcss-value-parser "^4.1.0" + schema-utils "^2.7.0" semver "^6.3.0" css-select-base-adapter@^0.1.1: @@ -5796,10 +5627,15 @@ cssstyle@^2.2.0: dependencies: cssom "~0.3.6" -csstype@^2.2.0, csstype@^2.5.7, csstype@^2.6.7: - version "2.6.10" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.10.tgz#e63af50e66d7c266edb6b32909cfd0aabe03928b" - integrity sha512-D34BqZU4cIlMCY93rZHbrq9pjTAQJ3U8S8rfBqjwHxkGPThWFjzZDQpgMJY0QViLxth6ZKYiwFBo14RdN44U/w== +csstype@^2.5.7: + version "2.6.13" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.13.tgz#a6893015b90e84dd6e85d0e3b442a1e84f2dbe0f" + integrity sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A== + +csstype@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.2.tgz#ee5ff8f208c8cd613b389f7b222c9801ca62b3f7" + integrity sha512-ofovWglpqoqbfLNOTBNZLSbMuGrblAf1efvvArGKOZMBrIoJeu5UsAipQolkijtyQx5MtAzT/J9IHj/CEY1mJw== currently-unhandled@^0.4.1: version "0.4.1" @@ -5968,9 +5804,9 @@ d3-scale@2: d3-time-format "2" d3-selection@1, d3-selection@^1.1.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-1.4.1.tgz#98eedbbe085fbda5bafa2f9e3f3a2f4d7d622a98" - integrity sha512-BTIbRjv/m5rcVTfBs4AMBLKs4x8XaaLkwm28KWu9S2vKNqXkXt2AH2Qf0sdPZHjFxcWg/YL53zcqAz+3g4/7PA== + version "1.4.2" + resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-1.4.2.tgz#dcaa49522c0dbf32d6c1858afc26b6094555bc5c" + integrity sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg== d3-shape@1: version "1.3.7" @@ -6061,6 +5897,14 @@ d3@5.16.0: d3-voronoi "1" d3-zoom "1" +dagre@0.8.5: + version "0.8.5" + resolved "https://registry.yarnpkg.com/dagre/-/dagre-0.8.5.tgz#ba30b0055dac12b6c1fcc247817442777d06afee" + integrity sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw== + dependencies: + graphlib "^2.1.8" + lodash "^4.17.15" + damerau-levenshtein@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz#143c1641cb3d85c60c32329e26899adea8701791" @@ -6331,6 +6175,11 @@ detect-newline@^3.0.0: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== +detect-node-es@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.0.0.tgz#c0318b9e539a5256ca780dd9575c9345af05b8ed" + integrity sha512-S4AHriUkTX9FoFvL4G8hXDcx6t3gp2HpfCza3Q0v6S78gul2hKWifLQbeW+ZF89+hSm2ZIc/uF3J97ZgytgTRg== + detect-node@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" @@ -6352,17 +6201,22 @@ detect-port@^1.3.0: address "^1.0.1" debug "^2.6.0" -devtools@6.1.22: - version "6.1.22" - resolved "https://registry.yarnpkg.com/devtools/-/devtools-6.1.22.tgz#7b55a41b497e131b47a33147e5297c7809d7fa51" - integrity sha512-6m8UCXjDvJgcxm2MuL7TSss2c14KlOZ972jyGdUZi8omjeIa1s2ZrXYFGPK2Gl3XKvl8k8Co3d97W8AHODZgEg== +devtools-protocol@0.0.781568: + version "0.0.781568" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.781568.tgz#4cdca90a952d2c77831096ff6cd32695d8715a04" + integrity sha512-9Uqnzy6m6zEStluH9iyJ3iHyaQziFnMnLeC8vK0eN6smiJmIx7+yB64d67C2lH/LZra+5cGscJAJsNXO+MdPMg== + +devtools@6.3.6: + version "6.3.6" + resolved "https://registry.yarnpkg.com/devtools/-/devtools-6.3.6.tgz#416d7e2fac54175299e4bf6c537240d52f8fc121" + integrity sha512-Pkir5lsMvvONrcH9nUakGNOr/3y2FiOCuGg4O+0XX0CbSmLSZV+AmuXTZ+yBbRzpH3llUCkGMzsVVzFVhF5/aQ== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" - "@wdio/protocols" "6.1.14" - "@wdio/utils" "6.1.17" + "@wdio/protocols" "6.3.6" + "@wdio/utils" "6.3.6" chrome-launcher "^0.13.1" - puppeteer-core "^4.0.0" + puppeteer-core "^5.1.0" ua-parser-js "^0.7.21" uuid "^8.0.0" @@ -6371,11 +6225,6 @@ diacritics@1.3.0: resolved "https://registry.yarnpkg.com/diacritics/-/diacritics-1.3.0.tgz#3efa87323ebb863e6696cebb0082d48ff3d6f7a1" integrity sha1-PvqHMj67hj5mls67AILUj/PW96E= -diff-sequences@^25.2.6: - version "25.2.6" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd" - integrity sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg== - diff-sequences@^26.0.0: version "26.0.0" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.0.0.tgz#0760059a5c287637b842bd7085311db7060e88a6" @@ -6481,12 +6330,12 @@ dom-helpers@^3.2.0, dom-helpers@^3.2.1, dom-helpers@^3.4.0: "@babel/runtime" "^7.1.2" dom-helpers@^5.0.1: - version "5.1.4" - resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.1.4.tgz#4609680ab5c79a45f2531441f1949b79d6587f4b" - integrity sha512-TjMyeVUvNEnOnhzs6uAn9Ya47GmMo3qq7m+Lr/3ON0Rs5kHvb8I+SQYjLUSYn7qhEm0QjW0yrBkvz9yOrwwz1A== + version "5.2.0" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.0.tgz#57fd054c5f8f34c52a3eeffdb7e7e93cd357d95b" + integrity sha512-Ru5o9+V8CpunKnz5LGgWXkmrH/20cGKwcHwS4m73zIvs54CN9epEmT/HLqFJW3kXpakAFkEdzgy1hzlJe3E4OQ== dependencies: "@babel/runtime" "^7.8.7" - csstype "^2.6.7" + csstype "^3.0.2" dom-serializer@0, dom-serializer@^0.2.1: version "0.2.2" @@ -6729,10 +6578,10 @@ ejs@^3.0.1: dependencies: jake "^10.6.1" -electron-to-chromium@^1.3.247, electron-to-chromium@^1.3.413: - version "1.3.465" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.465.tgz#d692e5c383317570c2bd82092a24a0308c6ccf29" - integrity sha512-K/lUeT3NLAsJ5SHRDhK3/zd0tw7OUllYD8w+fTOXm6ljCPsp2qq+vMzxpLo8u1M27ZjZAjRbsA6rirvne2nAMQ== +electron-to-chromium@^1.3.247, electron-to-chromium@^1.3.488: + version "1.3.518" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.518.tgz#c54ee9cf1a7bafd6e482a1a6cceac86448d941e8" + integrity sha512-IspiwXYDKZMxo+qc3Vof4WtwbG9BMDbJfati8PYj7uS4DJmJ67pwjCKZxlTBSAuCZSMcbRnj2Xz2H14uiKT7bQ== element-resize-detector@^1.1.10, element-resize-detector@^1.2.1: version "1.2.1" @@ -6742,9 +6591,9 @@ element-resize-detector@^1.1.10, element-resize-detector@^1.2.1: batch-processor "1.0.0" elliptic@^6.0.0, elliptic@^6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.2.tgz#05c5678d7173c049d8ca433552224a495d0e3762" - integrity sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw== + version "6.5.3" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6" + integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw== dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -6759,10 +6608,10 @@ email-addresses@3.1.0: resolved "https://registry.yarnpkg.com/email-addresses/-/email-addresses-3.1.0.tgz#cabf7e085cbdb63008a70319a74e6136188812fb" integrity sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg== -emittery@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.7.0.tgz#0f0789ea90e03f3de7865feb806e4f0916d16c93" - integrity sha512-/kshvS+tZaggOPQDLGzXopumRRIzxciGILDlYTGIU+PmqbSfhn4wDVphFPry4H+2TNl2QxLduexPhxcWLULA5A== +emittery@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.7.1.tgz#c02375a927a40948c0345cc903072597f5270451" + integrity sha512-d34LN4L6h18Bzz9xpoku2nPwKxCPlPMr3EEKTkoEBi+1/+b0lcRkRJ1UVyyZaKNeqGR3swcGl6s390DNO4YVgQ== emoji-regex@^7.0.1: version "7.0.3" @@ -6804,11 +6653,11 @@ encodeurl@~1.0.2: integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= encoding@^0.1.11: - version "0.1.12" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" - integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s= + version "0.1.13" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== dependencies: - iconv-lite "~0.4.13" + iconv-lite "^0.6.2" end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.4" @@ -6817,30 +6666,21 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" -enhanced-resolve@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz#2937e2b8066cd0fe7ce0990a98f0d71a35189f66" - integrity sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA== - dependencies: - graceful-fs "^4.1.2" - memory-fs "^0.5.0" - tapable "^1.0.0" - -enhanced-resolve@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.2.0.tgz#5d43bda4a0fd447cb0ebbe71bef8deff8805ad0d" - integrity sha512-S7eiFb/erugyd1rLb6mQ3Vuq+EXHv5cpCkNqqIkYkBgN2QdFnyCZzFBleqwGEx4lgNGYij81BWnCrFNK7vxvjQ== +enhanced-resolve@^4.1.1, enhanced-resolve@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz#3b806f3bfafc1ec7de69551ef93cca46c1704126" + integrity sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ== dependencies: graceful-fs "^4.1.2" memory-fs "^0.5.0" tapable "^1.0.0" enquirer@^2.3.5: - version "2.3.5" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.5.tgz#3ab2b838df0a9d8ab9e7dff235b0e8712ef92381" - integrity sha512-BNT1C08P9XD0vNg3J475yIUG+mVdp9T6towYFHUv897X0KoHBjB1shyrNmhmtHWKP17iSWgo7Gqh7BBuzLZMSA== + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== dependencies: - ansi-colors "^3.2.1" + ansi-colors "^4.1.1" entities@^1.1.1, entities@^1.1.2: version "1.1.2" @@ -6872,21 +6712,21 @@ error-ex@^1.2.0, error-ex@^1.3.1: is-arrayish "^0.2.1" es-abstract@^1.17.0, es-abstract@^1.17.0-next.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.4, es-abstract@^1.17.5: - version "1.17.5" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9" - integrity sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg== + version "1.17.6" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a" + integrity sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw== dependencies: es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" has-symbols "^1.0.1" - is-callable "^1.1.5" - is-regex "^1.0.5" + is-callable "^1.2.0" + is-regex "^1.1.0" object-inspect "^1.7.0" object-keys "^1.1.1" object.assign "^4.1.0" - string.prototype.trimleft "^2.1.1" - string.prototype.trimright "^2.1.1" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" es-array-method-boxes-properly@^1.0.0: version "1.0.0" @@ -6925,6 +6765,11 @@ es6-shim@^0.35.5: resolved "https://registry.yarnpkg.com/es6-shim/-/es6-shim-0.35.5.tgz#46f59dc0a84a1c5029e8ff1166ca0a902077a9ab" integrity sha512-E9kK/bjtCQRpN1K28Xh4BlmP8egvZBGJJ+9GtnzOwt7mdqtrjHFuVGr7QJfdjBIKqrlU5duPf3pCBoDrkjVYFg== +escalade@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.0.2.tgz#6a580d70edb87880f22b4c91d0d56078df6962c4" + integrity sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ== + escape-goat@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" @@ -6935,6 +6780,11 @@ escape-html@~1.0.3: resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= +escape-latex@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/escape-latex/-/escape-latex-1.2.0.tgz#07c03818cf7dac250cce517f4fda1b001ef2bca1" + integrity sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw== + escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -6951,9 +6801,9 @@ escape-string-regexp@^4.0.0: integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== escodegen@^1.14.1: - version "1.14.2" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.2.tgz#14ab71bf5026c2aa08173afba22c6f3173284a84" - integrity sha512-InuOIiKk8wwuOFg6x9BQXbzjrQhtyXh46K9bqVTPzSo2FnyMBaYGBMC6PhQy7yxxil9vIedFBweQBMK74/7o8A== + version "1.14.3" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" + integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== dependencies: esprima "^4.0.1" estraverse "^4.2.0" @@ -6987,9 +6837,9 @@ eslint-config-standard@14.1.1: integrity sha512-Z9B+VR+JIXRxz21udPTL9HpFMyoMUEeX1G251EQ6e05WD9aPVtVBn09XUmZ259wCMlCDmYDSZG62Hhm+ZTJcUg== eslint-import-resolver-node@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz#dbaa52b6b2816b50bc6711af75422de808e98404" - integrity sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg== + version "0.3.4" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717" + integrity sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA== dependencies: debug "^2.6.9" resolve "^1.13.1" @@ -7021,10 +6871,10 @@ eslint-plugin-es@^3.0.0: eslint-utils "^2.0.0" regexpp "^3.0.0" -eslint-plugin-flowtype@5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-5.1.3.tgz#0c63694463b0e8b296975649d637dd39fdf9e877" - integrity sha512-UU+BbIxBflqJ171yxbd/HcOktCmOdhXbchIVIq/yBvKpLZXvfzNDOyJGcnuQYLaH840hdoIdU/bqxhoW6I0rIQ== +eslint-plugin-flowtype@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-5.2.0.tgz#a4bef5dc18f9b2bdb41569a4ab05d73805a3d261" + integrity sha512-z7ULdTxuhlRJcEe1MVljePXricuPOrsWfScRXFhNzVD5dmTHWjIF57AxD0e7AbEoLSbjSsaA5S+hCg43WvpXJQ== dependencies: lodash "^4.17.15" string-natural-compare "^3.0.1" @@ -7082,65 +6932,65 @@ eslint-plugin-promise@4.2.1: resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a" integrity sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw== -eslint-plugin-react-hooks@4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.0.4.tgz#aed33b4254a41b045818cacb047b81e6df27fa58" - integrity sha512-equAdEIsUETLFNCmmCkiCGq6rkSK5MoJhXFPFYeUebcjKgBmWWcgVOqZyQC8Bv1BwVCnTq9tBxgJFgAJTWoJtA== +eslint-plugin-react-hooks@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.0.8.tgz#a9b1e3d57475ccd18276882eff3d6cba00da7a56" + integrity sha512-6SSb5AiMCPd8FDJrzah+Z4F44P2CdOaK026cXFV+o/xSRzfOiV1FNFeLl2z6xm3yqWOQEZ5OfVgiec90qV2xrQ== -eslint-plugin-react@7.20.0: - version "7.20.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.0.tgz#f98712f0a5e57dfd3e5542ef0604b8739cd47be3" - integrity sha512-rqe1abd0vxMjmbPngo4NaYxTcR3Y4Hrmc/jg4T+sYz63yqlmJRknpEQfmWY+eDWPuMmix6iUIK+mv0zExjeLgA== +eslint-plugin-react@7.20.5: + version "7.20.5" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.5.tgz#29480f3071f64a04b2c3d99d9b460ce0f76fb857" + integrity sha512-ajbJfHuFnpVNJjhyrfq+pH1C0gLc2y94OiCbAXT5O0J0YCKaFEHDV8+3+mDOr+w8WguRX+vSs1bM2BDG0VLvCw== dependencies: array-includes "^3.1.1" + array.prototype.flatmap "^1.2.3" doctrine "^2.1.0" has "^1.0.3" - jsx-ast-utils "^2.2.3" - object.entries "^1.1.1" + jsx-ast-utils "^2.4.1" + object.entries "^1.1.2" object.fromentries "^2.0.2" object.values "^1.1.1" prop-types "^15.7.2" - resolve "^1.15.1" + resolve "^1.17.0" string.prototype.matchall "^4.0.2" - xregexp "^4.3.0" eslint-plugin-standard@4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.1.tgz#ff0519f7ffaff114f76d1bd7c3996eef0f6e20b4" integrity sha512-v/KBnfyaOMPmZc/dmc6ozOdWqekGp7bBGq4jLAecEfPGmfKiWS4sA8sC0LqiV9w5qmXAtXVn4M3p1jSyhY85SQ== -eslint-scope@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" - integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== +eslint-scope@5.1.0, eslint-scope@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.0.tgz#d0f971dfe59c69e0cada684b23d49dbf82600ce5" + integrity sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w== dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-scope@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.0.tgz#d0f971dfe59c69e0cada684b23d49dbf82600ce5" - integrity sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w== +eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-utils@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.0.0.tgz#7be1cc70f27a72a76cd14aa698bcabed6890e1cd" - integrity sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA== +eslint-utils@^2.0.0, eslint-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== dependencies: eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.2.0.tgz#74415ac884874495f78ec2a97349525344c981fa" - integrity sha512-WFb4ihckKil6hu3Dp798xdzSfddwKKU3+nGniKF6HfeW6OLd2OUDEPP7TcHtB5+QXOKg2s6B2DaMPE1Nn/kxKQ== +eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== -eslint@7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.3.1.tgz#76392bd7e44468d046149ba128d1566c59acbe19" - integrity sha512-cQC/xj9bhWUcyi/RuMbRtC3I0eW8MH0jhRELSvpKYkWep3C6YZ2OkvcvJVUeO6gcunABmzptbXBuDoXsjHmfTA== +eslint@7.6.0: + version "7.6.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.6.0.tgz#522d67cfaea09724d96949c70e7a0550614d64d6" + integrity sha512-QlAManNtqr7sozWm5TF4wIH9gmUm2hE3vNRUvyoYAa4y1l5/jxD/PQStEjBMQtCqZmSep8UxrcecI60hOpe61w== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.10.0" @@ -7150,9 +7000,9 @@ eslint@7.3.1: doctrine "^3.0.0" enquirer "^2.3.5" eslint-scope "^5.1.0" - eslint-utils "^2.0.0" - eslint-visitor-keys "^1.2.0" - espree "^7.1.0" + eslint-utils "^2.1.0" + eslint-visitor-keys "^1.3.0" + espree "^7.2.0" esquery "^1.2.0" esutils "^2.0.2" file-entry-cache "^5.0.1" @@ -7166,7 +7016,7 @@ eslint@7.3.1: js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" - lodash "^4.17.14" + lodash "^4.17.19" minimatch "^3.0.4" natural-compare "^1.4.0" optionator "^0.9.1" @@ -7179,14 +7029,14 @@ eslint@7.3.1: text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-7.1.0.tgz#a9c7f18a752056735bf1ba14cb1b70adc3a5ce1c" - integrity sha512-dcorZSyfmm4WTuTnE5Y7MEN1DyoPYy1ZR783QW1FJoenn7RailyWFsq/UL6ZAAA7uXurN9FIpYyUs3OfiIW+Qw== +espree@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.2.0.tgz#1c263d5b513dbad0ac30c4991b93ac354e948d69" + integrity sha512-H+cQ3+3JYRMEIOl87e7QdHX70ocly5iW4+dttuR8iYSPr/hXKFb+7dBsZ7+u1adC4VrnPlTkv0+OwuPnDop19g== dependencies: - acorn "^7.2.0" + acorn "^7.3.1" acorn-jsx "^5.2.0" - eslint-visitor-keys "^1.2.0" + eslint-visitor-keys "^1.3.0" esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: version "4.0.1" @@ -7246,9 +7096,9 @@ eventemitter3@^4.0.0: integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== events@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.1.0.tgz#84279af1b34cb75aa88bf5ff291f6d0bd9b31a59" - integrity sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg== + version "3.2.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379" + integrity sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg== eventsource@^1.0.7: version "1.0.7" @@ -7284,9 +7134,9 @@ execa@^1.0.0: strip-eof "^1.0.0" execa@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.2.tgz#ad87fb7b2d9d564f70d2b62d511bee41d5cbb240" - integrity sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q== + version "4.0.3" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.3.tgz#0a34dabbad6d66100bd6f2c576c8669403f317f2" + integrity sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A== dependencies: cross-spawn "^7.0.0" get-stream "^5.0.0" @@ -7324,35 +7174,23 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: homedir-polyfill "^1.0.1" expect-webdriverio@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/expect-webdriverio/-/expect-webdriverio-1.1.5.tgz#acf834eeb2cf03d575d4f9f07fbd4b988ed37261" - integrity sha512-+RL4Lkne+/z+o1G5Y0S5QuEXeICxt4jExhBSM2Jn/mrDwb+PZVKPM2Yd1OzLsKeCdQLtw4Oft6514Gp5GLgdZA== - dependencies: - expect "^25.2.1" - jest-matcher-utils "^25.1.0" - -expect@^25.2.1: - version "25.5.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-25.5.0.tgz#f07f848712a2813bb59167da3fb828ca21f58bba" - integrity sha512-w7KAXo0+6qqZZhovCaBVPSIqQp7/UTcx4M9uKt2m6pd2VB1voyC8JizLRqeEqud3AAVP02g+hbErDu5gu64tlA== + version "1.2.0" + resolved "https://registry.yarnpkg.com/expect-webdriverio/-/expect-webdriverio-1.2.0.tgz#8e04abc34433008e74a78755c3a1f424aaea0955" + integrity sha512-nis1EL4LJSKvhqES6ojx1QqAZYtWAUHaVtwilXBXJELN2YZhwOcrfBT0AvxDvJXYKzgDDTED9STc9MwcK8KbYg== dependencies: - "@jest/types" "^25.5.0" - ansi-styles "^4.0.0" - jest-get-type "^25.2.6" - jest-matcher-utils "^25.5.0" - jest-message-util "^25.5.0" - jest-regex-util "^25.2.6" + expect "^26.0.1" + jest-matcher-utils "^26.0.1" -expect@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-26.1.0.tgz#8c62e31d0f8d5a8ebb186ee81473d15dd2fbf7c8" - integrity sha512-QbH4LZXDsno9AACrN9eM0zfnby9G+OsdNgZUohjg/P0mLy1O+/bzTAJGT6VSIjVCe8yKM6SzEl/ckEOFBT7Vnw== +expect@^26.0.1, expect@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-26.2.0.tgz#0140dd9cc7376d7833852e9cda88c05414f1efba" + integrity sha512-8AMBQ9UVcoUXt0B7v+5/U5H6yiUR87L6eKCfjE3spx7Ya5lF+ebUo37MCFBML2OiLfkX1sxmQOZhIDonyVTkcw== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" ansi-styles "^4.0.0" jest-get-type "^26.0.0" - jest-matcher-utils "^26.1.0" - jest-message-util "^26.1.0" + jest-matcher-utils "^26.2.0" + jest-message-util "^26.2.0" jest-regex-util "^26.0.0" express@^4.17.0, express@^4.17.1: @@ -7434,10 +7272,10 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" -extract-zip@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.0.tgz#f53b71d44f4ff5a4527a2259ade000fb8b303492" - integrity sha512-i42GQ498yibjdvIhivUsRslx608whtGoFIhF26Z7O4MYncBxp8CwalOs1lnHy21A9sIohWO2+uiE4SRtC9JXDg== +extract-zip@^2.0.0, extract-zip@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" + integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== dependencies: debug "^4.1.1" get-stream "^5.1.0" @@ -7457,7 +7295,7 @@ extsprintf@^1.2.0: "faker@https://github.com/Marak/faker.js.git": version "4.1.0" - resolved "https://github.com/Marak/faker.js.git#3b2fa4aebccee52ae1bafc15d575061fb30c3cf1" + resolved "https://github.com/Marak/faker.js.git#a0eefbb0a02c22a18c9bb56726b8347ebd0c21b8" fast-deep-equal@^2.0.1: version "2.0.1" @@ -7486,10 +7324,10 @@ fast-glob@^2.0.2: merge2 "^1.2.3" micromatch "^3.1.10" -fast-glob@^3.0.3, fast-glob@^3.1.1, fast-glob@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.2.tgz#ade1a9d91148965d4bf7c51f72e1ca662d32e63d" - integrity sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A== +fast-glob@^3.0.3, fast-glob@^3.1.1, fast-glob@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3" + integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -7780,10 +7618,10 @@ fn-name@~3.0.0: resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-3.0.0.tgz#0596707f635929634d791f452309ab41558e3c5c" integrity sha512-eNMNr5exLoavuAMhIUVsOKF79SWd/zG104ef6sxBTSw+cZc6BXdQXDvYcGvp0VbxVVSp1XDUNoz7mg1xMtSznA== -focus-lock@^0.6.7: - version "0.6.8" - resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.6.8.tgz#61985fadfa92f02f2ee1d90bc738efaf7f3c9f46" - integrity sha512-vkHTluRCoq9FcsrldC0ulQHiyBYgVJB2CX53I8r0nTC6KnEij7Of0jpBspjt3/CuNb6fyoj3aOh9J2HgQUM0og== +focus-lock@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.7.0.tgz#b2bfb0ca7beacc8710a1ff74275fe0dc60a1d88a" + integrity sha512-LI7v2mH02R55SekHYdv9pRHR9RajVNyIJ2N5IEkWbg7FT5ZmJ9Hw4mWxHeEUcd+dJo0QmzztHvDvWcc7prVFsw== follow-redirects@1.5.10: version "1.5.10" @@ -7793,11 +7631,9 @@ follow-redirects@1.5.10: debug "=3.1.0" follow-redirects@^1.0.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.11.0.tgz#afa14f08ba12a52963140fe43212658897bc0ecb" - integrity sha512-KZm0V+ll8PfBrKwMzdo5D13b1bur9Iq9Zd/RMmAoQQcl2PxxFml8cxXPaaPYVbV0RjNjq1CU7zIzAOqtUPudmA== - dependencies: - debug "^3.0.0" + version "1.12.1" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.12.1.tgz#de54a6205311b93d60398ebc01cf7015682312b6" + integrity sha512-tmRv0AVuR7ZyouUHLeNSiO6pqulF7dYa3s19c6t+wz9LD69/uSzdMxJ2S91nTI9U3rt/IldxpzMOFejp6f0hjg== for-in@^0.1.3: version "0.1.8" @@ -7849,10 +7685,10 @@ format@^0.2.0: resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" integrity sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs= -formik@2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/formik/-/formik-2.1.4.tgz#8deef07ec845ea98f75e03da4aad7aab4ac46570" - integrity sha512-oKz8S+yQBzuQVSEoxkqqJrKQS5XJASWGVn6mrs+oTWrBoHgByVwwI1qHiVc9GKDpZBU9vAxXYAKz2BvujlwunA== +formik@2.1.5: + version "2.1.5" + resolved "https://registry.yarnpkg.com/formik/-/formik-2.1.5.tgz#de5bbbe35543fa6d049fe96b8ee329d6cd6892b8" + integrity sha512-bWpo3PiqVDYslvrRjTq0Isrm0mFXHiO33D8MS6t6dWcqSFGeYF52nlpCM2xwOJ6tRVRznDkL+zz/iHPL4LDuvQ== dependencies: deepmerge "^2.1.1" hoist-non-react-statics "^3.3.0" @@ -7868,6 +7704,11 @@ forwarded@~0.1.2: resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= +fraction.js@^4.0.12: + version "4.0.12" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.0.12.tgz#0526d47c65a5fb4854df78bc77f7bec708d7b8c3" + integrity sha512-8Z1K0VTG4hzYY7kA/1sj4/r1/RWLBD3xwReT/RCrUCbzPszjNQCCsy3ktkU/eaEqX3MYa4pY37a52eiBlPMlhA== + fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" @@ -8033,6 +7874,11 @@ get-package-type@^0.1.0: resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== +get-port@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193" + integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ== + get-stream@^4.0.0, get-stream@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -8103,7 +7949,7 @@ glob-to-regexp@^0.3.0: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= -glob@7.1.6, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.1.1: +glob@7.1.6, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.1: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -8252,19 +8098,18 @@ good-listener@^1.2.2: delegate "^3.1.2" got@^11.0.2: - version "11.3.0" - resolved "https://registry.yarnpkg.com/got/-/got-11.3.0.tgz#25e8da8b0125b3b984613a6b719e678dd2e20406" - integrity sha512-yi/kiZY2tNMtt5IfbfX8UL3hAZWb2gZruxYZ72AY28pU5p0TZjZdl0uRsuaFbnC0JopdUi3I+Mh1F3dPQ9Dh0Q== + version "11.5.1" + resolved "https://registry.yarnpkg.com/got/-/got-11.5.1.tgz#bf098a270fe80b3fb88ffd5a043a59ebb0a391db" + integrity sha512-reQEZcEBMTGnujmQ+Wm97mJs/OK6INtO6HmLI+xt3+9CvnRwWjXutUvb2mqr+Ao4Lu05Rx6+udx9sOQAmExMxA== dependencies: - "@sindresorhus/is" "^2.1.1" + "@sindresorhus/is" "^3.0.0" "@szmarczak/http-timer" "^4.0.5" "@types/cacheable-request" "^6.0.1" "@types/responselike" "^1.0.0" cacheable-lookup "^5.0.3" cacheable-request "^7.0.1" decompress-response "^6.0.0" - get-stream "^5.1.0" - http2-wrapper "^1.0.0-beta.4.5" + http2-wrapper "^1.0.0-beta.5.0" lowercase-keys "^2.0.0" p-cancelable "^2.0.0" responselike "^2.0.0" @@ -8312,6 +8157,13 @@ graphiql@1.0.3: regenerator-runtime "^0.13.5" theme-ui "^0.3.1" +graphlib@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.8.tgz#5761d414737870084c92ec7b5dbcb0592c9d35da" + integrity sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A== + dependencies: + lodash "^4.17.15" + graphql-language-service-interface@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/graphql-language-service-interface/-/graphql-language-service-interface-2.4.0.tgz#4e2e63242c76197c4f56c61122db68187ea566b3" @@ -8347,15 +8199,15 @@ graphql-language-service@^3.0.0: graphql-language-service-interface "^2.4.0" graphql-language-service-types "^1.6.0" -graphql-tag@^2.4.2: - version "2.10.3" - resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.10.3.tgz#ea1baba5eb8fc6339e4c4cf049dabe522b0edf03" - integrity sha512-4FOv3ZKfA4WdOKJeHdz6B3F/vxBLSgmBcGeAFPf4n1F64ltJUvOOerNj0rsJxONQGdhUMynQIvd6LzB+1J5oKA== +graphql-tag@^2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.11.0.tgz#1deb53a01c46a7eb401d6cb59dec86fa1cccbffd" + integrity sha512-VmsD5pJqWJnQZMUeRwrDhfgoyqcfwEkvtpANqcoUG8/tOLkwNgU9mzub/Mc78OJMhHjx7gfAMTxzdG43VGg3bA== -graphql@15.1.0: - version "15.1.0" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.1.0.tgz#b93e28de805294ec08e1630d901db550cb8960a1" - integrity sha512-0TVyfOlCGhv/DBczQkJmwXOK6fjWkjzY3Pt7wY8i0gcYXq8aogG3weCsg48m72lywKSeOqedEHvVPOvZvSD51Q== +graphql@15.3.0: + version "15.3.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.3.0.tgz#3ad2b0caab0d110e3be4a5a9b2aa281e362b5278" + integrity sha512-GTCJtzJmkFLWRfFJuoo9RWWa/FfamUHgiFosxi/X1Ani4AVWbeyBenZTNX6dM+7WSbbFfTo/25eh0LLkwHMw2w== growl@1.10.5: version "1.10.5" @@ -8413,11 +8265,11 @@ har-schema@^2.0.0: integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= har-validator@~5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" - integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== dependencies: - ajv "^6.5.5" + ajv "^6.12.3" har-schema "^2.0.0" has-ansi@^2.0.0: @@ -8535,6 +8387,11 @@ header-case@^2.0.3: capital-case "^1.0.3" tslib "^1.10.0" +heap@0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.5.tgz#713b65590ebcc40fcbeeaf55e851694092b39af1" + integrity sha1-cTtlWQ68xA/L7q9V6FFpQJKzmvE= + highlight.js@~9.13.0: version "9.13.1" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e" @@ -8561,7 +8418,7 @@ hmac-drbg@^1.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0: +hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -8767,12 +8624,12 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" -http2-wrapper@^1.0.0-beta.4.5: - version "1.0.0-beta.4.6" - resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.0-beta.4.6.tgz#9438f0fceb946c8cbd365076c228a4d3bd4d0143" - integrity sha512-9oB4BiGDTI1FmIBlOF9OJ5hwJvcBEmPCqk/hy314Uhy2uq5TjekUZM8w8SPLLlUEM+mxNhXdPAXfrJN2Zbb/GQ== +http2-wrapper@^1.0.0-beta.5.0: + version "1.0.0-beta.5.2" + resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.0-beta.5.2.tgz#8b923deb90144aea65cf834b016a340fc98556f3" + integrity sha512-xYz9goEyBnC8XwXDTuC/MZ6t+MrKVQZOk4s7+PaDkwIsQd8IwqvM+0M6bA/2lvG8GHXcPdf+MejTUeO2LCPCeQ== dependencies: - quick-lru "^5.0.0" + quick-lru "^5.1.1" resolve-alpn "^1.0.0" https-browserify@^1.0.0: @@ -8788,6 +8645,14 @@ https-proxy-agent@^4.0.0: agent-base "5" debug "4" +https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + human-signals@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" @@ -8800,13 +8665,20 @@ i18n-iso-countries@6.0.0: dependencies: diacritics "1.3.0" -iconv-lite@0.4, iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.13: +iconv-lite@0.4, iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" +iconv-lite@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.2.tgz#ce13d1875b0c3a674bd6a04b7f76b01b1b6ded01" + integrity sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + icss-utils@^4.0.0, icss-utils@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" @@ -8998,20 +8870,20 @@ inquirer@6.5.0: through "^2.3.6" inquirer@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.1.0.tgz#1298a01859883e17c7264b82870ae1034f92dd29" - integrity sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg== + version "7.3.3" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" + integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA== dependencies: ansi-escapes "^4.2.1" - chalk "^3.0.0" + chalk "^4.1.0" cli-cursor "^3.1.0" - cli-width "^2.0.0" + cli-width "^3.0.0" external-editor "^3.0.3" figures "^3.0.0" - lodash "^4.17.15" + lodash "^4.17.19" mute-stream "0.0.8" run-async "^2.4.0" - rxjs "^6.5.3" + rxjs "^6.6.0" string-width "^4.1.0" strip-ansi "^6.0.0" through "^2.3.6" @@ -9102,6 +8974,11 @@ is-alphanumerical@^1.0.0: is-alphabetical "^1.0.0" is-decimal "^1.0.0" +is-any-array@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/is-any-array/-/is-any-array-0.0.3.tgz#cbdd8c7189d47b53b050969245f4ef7e55550b9b" + integrity sha512-Lr5SRykZv6uuYMZURz7+YpigT1ziTBHOTgFJ1zK7gL+9Wbet5Ha1ws6S84Jo/lH4zep02b95sk6o4+MTk97mPQ== + is-arguments@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3" @@ -9136,7 +9013,7 @@ is-buffer@~2.0.3: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== -is-callable@^1.1.4, is-callable@^1.1.5: +is-callable@^1.1.4, is-callable@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb" integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw== @@ -9196,9 +9073,9 @@ is-directory@^0.3.1: integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= is-docker@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.0.0.tgz#2cb0df0e75e2d064fe1864c37cdeacb7b2dcf25b" - integrity sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ== + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.0.tgz#25dc043e4fdc3cf969d622735e05a86ba9952e2b" + integrity sha512-mB2WygGsSeoXtLKpSYzP6sa0Z9DyU9ZyKlnvuZWxCociaI0qsF8u12sR72DFTX236g1u6oWSWYFuUk09nGQEjg== is-dom@^1.0.9: version "1.1.0" @@ -9357,7 +9234,7 @@ is-path-inside@^3.0.1: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017" integrity sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg== -is-plain-obj@^1.0.0: +is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= @@ -9369,12 +9246,15 @@ is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-plain-object@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.0.tgz#47bfc5da1b5d50d64110806c199359482e75a928" - integrity sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg== - dependencies: - isobject "^4.0.0" +is-plain-object@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.1.tgz#662d92d24c0aa4302407b0d45d21f2251c85f85b" + integrity sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g== + +is-plain-object@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-4.1.1.tgz#1a14d6452cbd50790edc7fdaa0aed5a40a35ebb5" + integrity sha512-5Aw8LLVsDlZsETVMhoMXzqsXwQqr/0vlnBYzIXJbYo2F4yYlhLHs+Ez7Bod7IIQKWkJbJfxrWD7pA1Dw1TKrwA== is-potential-custom-element-name@^1.0.0: version "1.0.0" @@ -9386,10 +9266,10 @@ is-promise@^4.0.0: resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-4.0.0.tgz#42ff9f84206c1991d26debf520dd5c01042dd2f3" integrity sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ== -is-regex@^1.0.4, is-regex@^1.0.5: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.0.tgz#ece38e389e490df0dc21caea2bd596f987f767ff" - integrity sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw== +is-regex@^1.0.4, is-regex@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" + integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== dependencies: has-symbols "^1.0.1" @@ -9595,77 +9475,72 @@ jake@^10.6.1: filelist "^1.0.1" minimatch "^3.0.4" -jest-changed-files@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.1.0.tgz#de66b0f30453bca2aff98e9400f75905da495305" - integrity sha512-HS5MIJp3B8t0NRKGMCZkcDUZo36mVRvrDETl81aqljT1S9tqiHRSpyoOvWg9ZilzZG9TDisDNaN1IXm54fLRZw== +javascript-natural-sort@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59" + integrity sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k= + +jest-changed-files@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.2.0.tgz#b4946201defe0c919a2f3d601e9f98cb21dacc15" + integrity sha512-+RyJb+F1K/XBLIYiL449vo5D+CvlHv29QveJUWNPXuUicyZcq+tf1wNxmmFeRvAU1+TzhwqczSjxnCCFt7+8iA== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" execa "^4.0.0" throat "^5.0.0" -jest-cli@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.1.0.tgz#eb9ec8a18cf3b6aa556d9deaa9e24be12b43ad87" - integrity sha512-Imumvjgi3rU7stq6SJ1JUEMaV5aAgJYXIs0jPqdUnF47N/Tk83EXfmtvNKQ+SnFVI6t6mDOvfM3aA9Sg6kQPSw== +jest-cli@^26.2.2: + version "26.2.2" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.2.2.tgz#4c273e5474baafac1eb15fd25aaafb4703f5ffbc" + integrity sha512-vVcly0n/ijZvdy6gPQiQt0YANwX2hLTPQZHtW7Vi3gcFdKTtif7YpI85F8R8JYy5DFSWz4x1OW0arnxlziu5Lw== dependencies: - "@jest/core" "^26.1.0" - "@jest/test-result" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/core" "^26.2.2" + "@jest/test-result" "^26.2.0" + "@jest/types" "^26.2.0" chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.4" import-local "^3.0.2" is-ci "^2.0.0" - jest-config "^26.1.0" - jest-util "^26.1.0" - jest-validate "^26.1.0" + jest-config "^26.2.2" + jest-util "^26.2.0" + jest-validate "^26.2.0" prompts "^2.0.1" yargs "^15.3.1" -jest-config@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-26.1.0.tgz#9074f7539acc185e0113ad6d22ed589c16a37a73" - integrity sha512-ONTGeoMbAwGCdq4WuKkMcdMoyfs5CLzHEkzFOlVvcDXufZSaIWh/OXMLa2fwKXiOaFcqEw8qFr4VOKJQfn4CVw== +jest-config@^26.2.2: + version "26.2.2" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-26.2.2.tgz#f3ebc7e2bc3f49de8ed3f8007152f345bb111917" + integrity sha512-2lhxH0y4YFOijMJ65usuf78m7+9/8+hAb1PZQtdRdgnQpAb4zP6KcVDDktpHEkspBKnc2lmFu+RQdHukUUbiTg== dependencies: "@babel/core" "^7.1.0" - "@jest/test-sequencer" "^26.1.0" - "@jest/types" "^26.1.0" - babel-jest "^26.1.0" + "@jest/test-sequencer" "^26.2.2" + "@jest/types" "^26.2.0" + babel-jest "^26.2.2" chalk "^4.0.0" deepmerge "^4.2.2" glob "^7.1.1" graceful-fs "^4.2.4" - jest-environment-jsdom "^26.1.0" - jest-environment-node "^26.1.0" + jest-environment-jsdom "^26.2.0" + jest-environment-node "^26.2.0" jest-get-type "^26.0.0" - jest-jasmine2 "^26.1.0" + jest-jasmine2 "^26.2.2" jest-regex-util "^26.0.0" - jest-resolve "^26.1.0" - jest-util "^26.1.0" - jest-validate "^26.1.0" + jest-resolve "^26.2.2" + jest-util "^26.2.0" + jest-validate "^26.2.0" micromatch "^4.0.2" - pretty-format "^26.1.0" - -jest-diff@^25.5.0: - version "25.5.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-25.5.0.tgz#1dd26ed64f96667c068cef026b677dfa01afcfa9" - integrity sha512-z1kygetuPiREYdNIumRpAHY6RXiGmp70YHptjdaxTWGmA085W3iCnXNx0DhflK3vwrKmrRWyY1wUpkPMVxMK7A== - dependencies: - chalk "^3.0.0" - diff-sequences "^25.2.6" - jest-get-type "^25.2.6" - pretty-format "^25.5.0" + pretty-format "^26.2.0" -jest-diff@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.1.0.tgz#00a549bdc936c9691eb4dc25d1fbd78bf456abb2" - integrity sha512-GZpIcom339y0OXznsEKjtkfKxNdg7bVbEofK8Q6MnevTIiR1jNhDWKhRX6X0SDXJlwn3dy59nZ1z55fLkAqPWg== +jest-diff@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.2.0.tgz#dee62c771adbb23ae585f3f1bd289a6e8ef4f298" + integrity sha512-Wu4Aopi2nzCsHWLBlD48TgRy3Z7OsxlwvHNd1YSnHc7q1NJfrmyCPoUXrTIrydQOG5ApaYpsAsdfnMbJqV1/wQ== dependencies: chalk "^4.0.0" diff-sequences "^26.0.0" jest-get-type "^26.0.0" - pretty-format "^26.1.0" + pretty-format "^26.2.0" jest-docblock@^26.0.0: version "26.0.0" @@ -9674,142 +9549,117 @@ jest-docblock@^26.0.0: dependencies: detect-newline "^3.0.0" -jest-each@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-26.1.0.tgz#e35449875009a22d74d1bda183b306db20f286f7" - integrity sha512-lYiSo4Igr81q6QRsVQq9LIkJW0hZcKxkIkHzNeTMPENYYDw/W/Raq28iJ0sLlNFYz2qxxeLnc5K2gQoFYlu2bA== +jest-each@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-26.2.0.tgz#aec8efa01d072d7982c900e74940863385fa884e" + integrity sha512-gHPCaho1twWHB5bpcfnozlc6mrMi+VAewVPNgmwf81x2Gzr6XO4dl+eOrwPWxbkYlgjgrYjWK2xgKnixbzH3Ew== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" chalk "^4.0.0" jest-get-type "^26.0.0" - jest-util "^26.1.0" - pretty-format "^26.1.0" + jest-util "^26.2.0" + pretty-format "^26.2.0" -jest-environment-jsdom@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.1.0.tgz#9dc7313ffe1b59761dad1fedb76e2503e5d37c5b" - integrity sha512-dWfiJ+spunVAwzXbdVqPH1LbuJW/kDL+FyqgA5YzquisHqTi0g9hquKif9xKm7c1bKBj6wbmJuDkeMCnxZEpUw== - dependencies: - "@jest/environment" "^26.1.0" - "@jest/fake-timers" "^26.1.0" - "@jest/types" "^26.1.0" - jest-mock "^26.1.0" - jest-util "^26.1.0" +jest-environment-jsdom@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.2.0.tgz#6443a6f3569297dcaa4371dddf93acaf167302dc" + integrity sha512-sDG24+5M4NuIGzkI3rJW8XUlrpkvIdE9Zz4jhD8OBnVxAw+Y1jUk9X+lAOD48nlfUTlnt3lbAI3k2Ox+WF3S0g== + dependencies: + "@jest/environment" "^26.2.0" + "@jest/fake-timers" "^26.2.0" + "@jest/types" "^26.2.0" + "@types/node" "*" + jest-mock "^26.2.0" + jest-util "^26.2.0" jsdom "^16.2.2" -jest-environment-node@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-26.1.0.tgz#8bb387b3eefb132eab7826f9a808e4e05618960b" - integrity sha512-DNm5x1aQH0iRAe9UYAkZenuzuJ69VKzDCAYISFHQ5i9e+2Tbeu2ONGY7YStubCLH8a1wdKBgqScYw85+ySxqxg== +jest-environment-node@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-26.2.0.tgz#fee89e06bdd4bed3f75ee2978d73ede9bb57a681" + integrity sha512-4M5ExTYkJ19efBzkiXtBi74JqKLDciEk4CEsp5tTjWGYMrlKFQFtwIVG3tW1OGE0AlXhZjuHPwubuRYY4j4uOw== dependencies: - "@jest/environment" "^26.1.0" - "@jest/fake-timers" "^26.1.0" - "@jest/types" "^26.1.0" - jest-mock "^26.1.0" - jest-util "^26.1.0" - -jest-get-type@^25.2.6: - version "25.2.6" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-25.2.6.tgz#0b0a32fab8908b44d508be81681487dbabb8d877" - integrity sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig== + "@jest/environment" "^26.2.0" + "@jest/fake-timers" "^26.2.0" + "@jest/types" "^26.2.0" + "@types/node" "*" + jest-mock "^26.2.0" + jest-util "^26.2.0" jest-get-type@^26.0.0: version "26.0.0" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.0.0.tgz#381e986a718998dbfafcd5ec05934be538db4039" integrity sha512-zRc1OAPnnws1EVfykXOj19zo2EMw5Hi6HLbFCSjpuJiXtOWAYIjNsHVSbpQ8bDX7L5BGYGI8m+HmKdjHYFF0kg== -jest-haste-map@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.1.0.tgz#ef31209be73f09b0d9445e7d213e1b53d0d1476a" - integrity sha512-WeBS54xCIz9twzkEdm6+vJBXgRBQfdbbXD0dk8lJh7gLihopABlJmIQFdWSDDtuDe4PRiObsjZSUjbJ1uhWEpA== +jest-haste-map@^26.2.2: + version "26.2.2" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.2.2.tgz#6d4267b1903854bfdf6a871419f35a82f03ae71e" + integrity sha512-3sJlMSt+NHnzCB+0KhJ1Ut4zKJBiJOlbrqEYNdRQGlXTv8kqzZWjUKQRY3pkjmlf+7rYjAV++MQ4D6g4DhAyOg== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" "@types/graceful-fs" "^4.1.2" + "@types/node" "*" anymatch "^3.0.3" fb-watchman "^2.0.0" graceful-fs "^4.2.4" - jest-serializer "^26.1.0" - jest-util "^26.1.0" - jest-worker "^26.1.0" + jest-regex-util "^26.0.0" + jest-serializer "^26.2.0" + jest-util "^26.2.0" + jest-worker "^26.2.1" micromatch "^4.0.2" sane "^4.0.3" walker "^1.0.7" - which "^2.0.2" optionalDependencies: fsevents "^2.1.2" -jest-jasmine2@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.1.0.tgz#4dfe349b2b2d3c6b3a27c024fd4cb57ac0ed4b6f" - integrity sha512-1IPtoDKOAG+MeBrKvvuxxGPJb35MTTRSDglNdWWCndCB3TIVzbLThRBkwH9P081vXLgiJHZY8Bz3yzFS803xqQ== +jest-jasmine2@^26.2.2: + version "26.2.2" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.2.2.tgz#d82b1721fac2b153a4f8b3f0c95e81e702812de2" + integrity sha512-Q8AAHpbiZMVMy4Hz9j1j1bg2yUmPa1W9StBvcHqRaKa9PHaDUMwds8LwaDyzP/2fkybcTQE4+pTMDOG9826tEw== dependencies: "@babel/traverse" "^7.1.0" - "@jest/environment" "^26.1.0" + "@jest/environment" "^26.2.0" "@jest/source-map" "^26.1.0" - "@jest/test-result" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/test-result" "^26.2.0" + "@jest/types" "^26.2.0" + "@types/node" "*" chalk "^4.0.0" co "^4.6.0" - expect "^26.1.0" + expect "^26.2.0" is-generator-fn "^2.0.0" - jest-each "^26.1.0" - jest-matcher-utils "^26.1.0" - jest-message-util "^26.1.0" - jest-runtime "^26.1.0" - jest-snapshot "^26.1.0" - jest-util "^26.1.0" - pretty-format "^26.1.0" + jest-each "^26.2.0" + jest-matcher-utils "^26.2.0" + jest-message-util "^26.2.0" + jest-runtime "^26.2.2" + jest-snapshot "^26.2.2" + jest-util "^26.2.0" + pretty-format "^26.2.0" throat "^5.0.0" -jest-leak-detector@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-26.1.0.tgz#039c3a07ebcd8adfa984b6ac015752c35792e0a6" - integrity sha512-dsMnKF+4BVOZwvQDlgn3MG+Ns4JuLv8jNvXH56bgqrrboyCbI1rQg6EI5rs+8IYagVcfVP2yZFKfWNZy0rK0Hw== +jest-leak-detector@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-26.2.0.tgz#073ee6d8db7a9af043e7ce99d8eea17a4fb0cc50" + integrity sha512-aQdzTX1YiufkXA1teXZu5xXOJgy7wZQw6OJ0iH5CtQlOETe6gTSocaYKUNui1SzQ91xmqEUZ/WRavg9FD82rtQ== dependencies: jest-get-type "^26.0.0" - pretty-format "^26.1.0" - -jest-matcher-utils@^25.1.0, jest-matcher-utils@^25.5.0: - version "25.5.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-25.5.0.tgz#fbc98a12d730e5d2453d7f1ed4a4d948e34b7867" - integrity sha512-VWI269+9JS5cpndnpCwm7dy7JtGQT30UHfrnM3mXl22gHGt/b7NkjBqXfbhZ8V4B7ANUsjK18PlSBmG0YH7gjw== - dependencies: - chalk "^3.0.0" - jest-diff "^25.5.0" - jest-get-type "^25.2.6" - pretty-format "^25.5.0" + pretty-format "^26.2.0" -jest-matcher-utils@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.1.0.tgz#cf75a41bd413dda784f022de5a65a2a5c73a5c92" - integrity sha512-PW9JtItbYvES/xLn5mYxjMd+Rk+/kIt88EfH3N7w9KeOrHWaHrdYPnVHndGbsFGRJ2d5gKtwggCvkqbFDoouQA== +jest-matcher-utils@^26.0.1, jest-matcher-utils@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.2.0.tgz#b107af98c2b8c557ffd46c1adf06f794aa52d622" + integrity sha512-2cf/LW2VFb3ayPHrH36ZDjp9+CAeAe/pWBAwsV8t3dKcrINzXPVxq8qMWOxwt5BaeBCx4ZupVGH7VIgB8v66vQ== dependencies: chalk "^4.0.0" - jest-diff "^26.1.0" + jest-diff "^26.2.0" jest-get-type "^26.0.0" - pretty-format "^26.1.0" - -jest-message-util@^25.5.0: - version "25.5.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-25.5.0.tgz#ea11d93204cc7ae97456e1d8716251185b8880ea" - integrity sha512-ezddz3YCT/LT0SKAmylVyWWIGYoKHOFOFXx3/nA4m794lfVUskMcwhip6vTgdVrOtYdjeQeis2ypzes9mZb4EA== - dependencies: - "@babel/code-frame" "^7.0.0" - "@jest/types" "^25.5.0" - "@types/stack-utils" "^1.0.1" - chalk "^3.0.0" - graceful-fs "^4.2.4" - micromatch "^4.0.2" - slash "^3.0.0" - stack-utils "^1.0.1" + pretty-format "^26.2.0" -jest-message-util@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.1.0.tgz#52573fbb8f5cea443c4d1747804d7a238a3e233c" - integrity sha512-dY0+UlldiAJwNDJ08SF0HdF32g9PkbF2NRK/+2iMPU40O6q+iSn1lgog/u0UH8ksWoPv0+gNq8cjhYO2MFtT0g== +jest-message-util@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.2.0.tgz#757fbc1323992297092bb9016a71a2eb12fd22ea" + integrity sha512-g362RhZaJuqeqG108n1sthz5vNpzTNy926eNDszo4ncRbmmcMRIUAZibnd6s5v2XSBCChAxQtCoN25gnzp7JbQ== dependencies: "@babel/code-frame" "^7.0.0" - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" "@types/stack-utils" "^1.0.1" chalk "^4.0.0" graceful-fs "^4.2.4" @@ -9817,169 +9667,169 @@ jest-message-util@^26.1.0: slash "^3.0.0" stack-utils "^2.0.2" -jest-mock@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.1.0.tgz#80d8286da1f05a345fbad1bfd6fa49a899465d3d" - integrity sha512-1Rm8EIJ3ZFA8yCIie92UbxZWj9SuVmUGcyhLHyAhY6WI3NIct38nVcfOPWhJteqSn8V8e3xOMha9Ojfazfpovw== +jest-mock@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.2.0.tgz#a1b3303ab38c34aa1dbbc16ab57cdc1a59ed50d1" + integrity sha512-XeC7yWtWmWByoyVOHSsE7NYsbXJLtJNgmhD7z4MKumKm6ET0si81bsSLbQ64L5saK3TgsHo2B/UqG5KNZ1Sp/Q== dependencies: - "@jest/types" "^26.1.0" - -jest-pnp-resolver@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a" - integrity sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ== + "@jest/types" "^26.2.0" + "@types/node" "*" -jest-regex-util@^25.2.6: - version "25.2.6" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-25.2.6.tgz#d847d38ba15d2118d3b06390056028d0f2fd3964" - integrity sha512-KQqf7a0NrtCkYmZZzodPftn7fL1cq3GQAFVMn5Hg8uKx/fIenLEobNanUxb7abQ1sjADHBseG/2FGpsv/wr+Qw== +jest-pnp-resolver@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" + integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== jest-regex-util@^26.0.0: version "26.0.0" resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" integrity sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A== -jest-resolve-dependencies@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-26.1.0.tgz#1ce36472f864a5dadf7dc82fa158e1c77955691b" - integrity sha512-fQVEPHHQ1JjHRDxzlLU/buuQ9om+hqW6Vo928aa4b4yvq4ZHBtRSDsLdKQLuCqn5CkTVpYZ7ARh2fbA8WkRE6g== +jest-resolve-dependencies@^26.2.2: + version "26.2.2" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-26.2.2.tgz#2ad3cd9281730e9a5c487cd846984c5324e47929" + integrity sha512-S5vufDmVbQXnpP7435gr710xeBGUFcKNpNswke7RmFvDQtmqPjPVU/rCeMlEU0p6vfpnjhwMYeaVjKZAy5QYJA== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" jest-regex-util "^26.0.0" - jest-snapshot "^26.1.0" + jest-snapshot "^26.2.2" -jest-resolve@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.1.0.tgz#a530eaa302b1f6fa0479079d1561dd69abc00e68" - integrity sha512-KsY1JV9FeVgEmwIISbZZN83RNGJ1CC+XUCikf/ZWJBX/tO4a4NvA21YixokhdR9UnmPKKAC4LafVixJBrwlmfg== +jest-resolve@^26.2.2: + version "26.2.2" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.2.2.tgz#324a20a516148d61bffa0058ed0c77c510ecfd3e" + integrity sha512-ye9Tj/ILn/0OgFPE/3dGpQPUqt4dHwIocxt5qSBkyzxQD8PbL0bVxBogX2FHxsd3zJA7V2H/cHXnBnNyyT9YoQ== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" chalk "^4.0.0" graceful-fs "^4.2.4" - jest-pnp-resolver "^1.2.1" - jest-util "^26.1.0" + jest-pnp-resolver "^1.2.2" + jest-util "^26.2.0" read-pkg-up "^7.0.1" resolve "^1.17.0" slash "^3.0.0" -jest-runner@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.1.0.tgz#457f7fc522afe46ca6db1dccf19f87f500b3288d" - integrity sha512-elvP7y0fVDREnfqit0zAxiXkDRSw6dgCkzPCf1XvIMnSDZ8yogmSKJf192dpOgnUVykmQXwYYJnCx641uLTgcw== +jest-runner@^26.2.2: + version "26.2.2" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.2.2.tgz#6d03d057886e9c782e10b2cf37443f902fe0e39e" + integrity sha512-/qb6ptgX+KQ+aNMohJf1We695kaAfuu3u3ouh66TWfhTpLd9WbqcF6163d/tMoEY8GqPztXPLuyG0rHRVDLxCA== dependencies: - "@jest/console" "^26.1.0" - "@jest/environment" "^26.1.0" - "@jest/test-result" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/console" "^26.2.0" + "@jest/environment" "^26.2.0" + "@jest/test-result" "^26.2.0" + "@jest/types" "^26.2.0" + "@types/node" "*" chalk "^4.0.0" + emittery "^0.7.1" exit "^0.1.2" graceful-fs "^4.2.4" - jest-config "^26.1.0" + jest-config "^26.2.2" jest-docblock "^26.0.0" - jest-haste-map "^26.1.0" - jest-jasmine2 "^26.1.0" - jest-leak-detector "^26.1.0" - jest-message-util "^26.1.0" - jest-resolve "^26.1.0" - jest-runtime "^26.1.0" - jest-util "^26.1.0" - jest-worker "^26.1.0" + jest-haste-map "^26.2.2" + jest-leak-detector "^26.2.0" + jest-message-util "^26.2.0" + jest-resolve "^26.2.2" + jest-runtime "^26.2.2" + jest-util "^26.2.0" + jest-worker "^26.2.1" source-map-support "^0.5.6" throat "^5.0.0" -jest-runtime@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-26.1.0.tgz#45a37af42115f123ed5c51f126c05502da2469cb" - integrity sha512-1qiYN+EZLmG1QV2wdEBRf+Ci8i3VSfIYLF02U18PiUDrMbhfpN/EAMMkJtT02jgJUoaEOpHAIXG6zS3QRMzRmA== +jest-runtime@^26.2.2: + version "26.2.2" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-26.2.2.tgz#2480ff79320680a643031dd21998d7c63d83ab68" + integrity sha512-a8VXM3DxCDnCIdl9+QucWFfQ28KdqmyVFqeKLigHdErtsx56O2ZIdQkhFSuP1XtVrG9nTNHbKxjh5XL1UaFDVQ== dependencies: - "@jest/console" "^26.1.0" - "@jest/environment" "^26.1.0" - "@jest/fake-timers" "^26.1.0" - "@jest/globals" "^26.1.0" + "@jest/console" "^26.2.0" + "@jest/environment" "^26.2.0" + "@jest/fake-timers" "^26.2.0" + "@jest/globals" "^26.2.0" "@jest/source-map" "^26.1.0" - "@jest/test-result" "^26.1.0" - "@jest/transform" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/test-result" "^26.2.0" + "@jest/transform" "^26.2.2" + "@jest/types" "^26.2.0" "@types/yargs" "^15.0.0" chalk "^4.0.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" glob "^7.1.3" graceful-fs "^4.2.4" - jest-config "^26.1.0" - jest-haste-map "^26.1.0" - jest-message-util "^26.1.0" - jest-mock "^26.1.0" + jest-config "^26.2.2" + jest-haste-map "^26.2.2" + jest-message-util "^26.2.0" + jest-mock "^26.2.0" jest-regex-util "^26.0.0" - jest-resolve "^26.1.0" - jest-snapshot "^26.1.0" - jest-util "^26.1.0" - jest-validate "^26.1.0" + jest-resolve "^26.2.2" + jest-snapshot "^26.2.2" + jest-util "^26.2.0" + jest-validate "^26.2.0" slash "^3.0.0" strip-bom "^4.0.0" yargs "^15.3.1" -jest-serializer@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.1.0.tgz#72a394531fc9b08e173dc7d297440ac610d95022" - integrity sha512-eqZOQG/0+MHmr25b2Z86g7+Kzd5dG9dhCiUoyUNJPgiqi38DqbDEOlHcNijyfZoj74soGBohKBZuJFS18YTJ5w== +jest-serializer@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.2.0.tgz#92dcae5666322410f4bf50211dd749274959ddac" + integrity sha512-V7snZI9IVmyJEu0Qy0inmuXgnMWDtrsbV2p9CRAcmlmPVwpC2ZM8wXyYpiugDQnwLHx0V4+Pnog9Exb3UO8M6Q== dependencies: + "@types/node" "*" graceful-fs "^4.2.4" -jest-snapshot@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.1.0.tgz#c36ed1e0334bd7bd2fe5ad07e93a364ead7e1349" - integrity sha512-YhSbU7eMTVQO/iRbNs8j0mKRxGp4plo7sJ3GzOQ0IYjvsBiwg0T1o0zGQAYepza7lYHuPTrG5J2yDd0CE2YxSw== +jest-snapshot@^26.2.2: + version "26.2.2" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.2.2.tgz#9d2eda083a4a1017b157e351868749bd63211799" + integrity sha512-NdjD8aJS7ePu268Wy/n/aR1TUisG0BOY+QOW4f6h46UHEKOgYmmkvJhh2BqdVZQ0BHSxTMt04WpCf9njzx8KtA== dependencies: "@babel/types" "^7.0.0" - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" "@types/prettier" "^2.0.0" chalk "^4.0.0" - expect "^26.1.0" + expect "^26.2.0" graceful-fs "^4.2.4" - jest-diff "^26.1.0" + jest-diff "^26.2.0" jest-get-type "^26.0.0" - jest-haste-map "^26.1.0" - jest-matcher-utils "^26.1.0" - jest-message-util "^26.1.0" - jest-resolve "^26.1.0" + jest-haste-map "^26.2.2" + jest-matcher-utils "^26.2.0" + jest-message-util "^26.2.0" + jest-resolve "^26.2.2" natural-compare "^1.4.0" - pretty-format "^26.1.0" + pretty-format "^26.2.0" semver "^7.3.2" -jest-util@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.1.0.tgz#80e85d4ba820decacf41a691c2042d5276e5d8d8" - integrity sha512-rNMOwFQevljfNGvbzNQAxdmXQ+NawW/J72dmddsK0E8vgxXCMtwQ/EH0BiWEIxh0hhMcTsxwAxINt7Lh46Uzbg== +jest-util@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.2.0.tgz#0597d2a27c559340957609f106c408c17c1d88ac" + integrity sha512-YmDwJxLZ1kFxpxPfhSJ0rIkiZOM0PQbRcfH0TzJOhqCisCAsI1WcmoQqO83My9xeVA2k4n+rzg2UuexVKzPpig== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" + "@types/node" "*" chalk "^4.0.0" graceful-fs "^4.2.4" is-ci "^2.0.0" micromatch "^4.0.2" -jest-validate@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-26.1.0.tgz#942c85ad3d60f78250c488a7f85d8f11a29788e7" - integrity sha512-WPApOOnXsiwhZtmkDsxnpye+XLb/tUISP+H6cHjfUIXvlG+eKwP+isnivsxlHCPaO9Q5wvbhloIBkdF3qUn+Nw== +jest-validate@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-26.2.0.tgz#97fedf3e7984b7608854cbf925b9ca6ebcbdb78a" + integrity sha512-8XKn3hM6VIVmLNuyzYLCPsRCT83o8jMZYhbieh4dAyKLc4Ypr36rVKC+c8WMpWkfHHpGnEkvWUjjIAyobEIY/Q== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" camelcase "^6.0.0" chalk "^4.0.0" jest-get-type "^26.0.0" leven "^3.1.0" - pretty-format "^26.1.0" + pretty-format "^26.2.0" -jest-watcher@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-26.1.0.tgz#99812a0cd931f0cb3d153180426135ab83e4d8f2" - integrity sha512-ffEOhJl2EvAIki613oPsSG11usqnGUzIiK7MMX6hE4422aXOcVEG3ySCTDFLn1+LZNXGPE8tuJxhp8OBJ1pgzQ== +jest-watcher@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-26.2.0.tgz#45bdf2fecadd19c0a501f3b071a474dca636825b" + integrity sha512-674Boco4Joe0CzgKPL6K4Z9LgyLx+ZvW2GilbpYb8rFEUkmDGgsZdv1Hv5rxsRpb1HLgKUOL/JfbttRCuFdZXQ== dependencies: - "@jest/test-result" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/test-result" "^26.2.0" + "@jest/types" "^26.2.0" + "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" - jest-util "^26.1.0" + jest-util "^26.2.0" string-length "^4.0.1" jest-worker@^25.4.0: @@ -9990,22 +9840,23 @@ jest-worker@^25.4.0: merge-stream "^2.0.0" supports-color "^7.0.0" -jest-worker@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.1.0.tgz#65d5641af74e08ccd561c240e7db61284f82f33d" - integrity sha512-Z9P5pZ6UC+kakMbNJn+tA2RdVdNX5WH1x+5UCBZ9MxIK24pjYtFt96fK+UwBTrjLYm232g1xz0L3eTh51OW+yQ== +jest-worker@^26.2.1: + version "26.2.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.2.1.tgz#5d630ab93f666b53f911615bc13e662b382bd513" + integrity sha512-+XcGMMJDTeEGncRb5M5Zq9P7K4sQ1sirhjdOxsN1462h6lFo9w59bl2LVQmdGEEeU3m+maZCkS2Tcc9SfCHO4A== dependencies: + "@types/node" "*" merge-stream "^2.0.0" supports-color "^7.0.0" -jest@26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-26.1.0.tgz#2f3aa7bcffb9bfd025473f83bbbf46a3af026263" - integrity sha512-LIti8jppw5BcQvmNJe4w2g1N/3V68HUfAv9zDVm7v+VAtQulGhH0LnmmiVkbNE4M4I43Bj2fXPiBGKt26k9tHw== +jest@26.2.2: + version "26.2.2" + resolved "https://registry.yarnpkg.com/jest/-/jest-26.2.2.tgz#a022303887b145147204c5f66e6a5c832333c7e7" + integrity sha512-EkJNyHiAG1+A8pqSz7cXttoVa34hOEzN/MrnJhYnfp5VHxflVcf2pu3oJSrhiy6LfIutLdWo+n6q63tjcoIeig== dependencies: - "@jest/core" "^26.1.0" + "@jest/core" "^26.2.2" import-local "^3.0.2" - jest-cli "^26.1.0" + jest-cli "^26.2.2" js-string-escape@^1.0.1: version "1.0.1" @@ -10044,9 +9895,9 @@ jsbn@~0.1.0: integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= jsdom@^16.2.2: - version "16.2.2" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.2.2.tgz#76f2f7541646beb46a938f5dc476b88705bedf2b" - integrity sha512-pDFQbcYtKBHxRaP55zGXCJWgFHkDAYbKcsXEK/3Icu9nKYZkutUXfLBwbD+09XDutkYSHcgfQLZ0qvpAAm9mvg== + version "16.3.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.3.0.tgz#75690b7dac36c67be49c336dcd7219bbbed0810c" + integrity sha512-zggeX5UuEknpdZzv15+MS1dPYG0J/TftiiNunOeNxSl3qr8Z6cIlQpN0IdJa44z9aFxZRIVqRncvEhQ7X5DtZg== dependencies: abab "^2.0.3" acorn "^7.1.1" @@ -10068,7 +9919,7 @@ jsdom@^16.2.2: tough-cookie "^3.0.1" w3c-hr-time "^1.0.2" w3c-xmlserializer "^2.0.0" - webidl-conversions "^6.0.0" + webidl-conversions "^6.1.0" whatwg-encoding "^1.0.5" whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" @@ -10187,14 +10038,6 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" -jsx-ast-utils@^2.2.3: - version "2.3.0" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.3.0.tgz#edd727794ea284d7fda575015ed1b0cde0289ab6" - integrity sha512-3HNoc7nZ1hpZIKB3hJ7BlFRkzCx2BynRtfSwbkqZdpRdvAPsGMnzclPwrvDBS7/lalHTj21NwIeaEpysHBOudg== - dependencies: - array-includes "^3.1.1" - object.assign "^4.1.0" - jsx-ast-utils@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz#1114a4c1209481db06c690c2b4f488cc665f657e" @@ -10204,9 +10047,9 @@ jsx-ast-utils@^2.4.1: object.assign "^4.1.0" jszip@^3.2.2: - version "3.4.0" - resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.4.0.tgz#1a69421fa5f0bb9bc222a46bca88182fba075350" - integrity sha512-gZAOYuPl4EhPTXT0GjhI3o+ZAz3su6EhLrKUoAivcKqyqC7laS5JEv4XWZND9BgcDcF83vI85yGbDmDR6UhrIg== + version "3.5.0" + resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.5.0.tgz#b4fd1f368245346658e781fec9675802489e15f6" + integrity sha512-WRtu7TPCmYePR1nazfrtuF216cIVon/3GWOvHS9QR5bIwSbnxtdpma6un3jyGGNhHsKCSzn5Ypk+EkDRvTGiFA== dependencies: lie "~3.3.0" pako "~1.0.2" @@ -10595,10 +10438,10 @@ lodash.zip@^4.2.0: resolved "https://registry.yarnpkg.com/lodash.zip/-/lodash.zip-4.2.0.tgz#ec6662e4896408ed4ab6c542a3990b72cc080020" integrity sha1-7GZi5IlkCO1KtsVCo5kLcswIACA= -lodash@4.17.15, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@~4.17.10, lodash@~4.17.12: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== +lodash@4.17.19, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@~4.17.10, lodash@~4.17.12: + version "4.17.19" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" + integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== log-symbols@3.0.0, log-symbols@^3.0.0: version "3.0.0" @@ -10607,16 +10450,6 @@ log-symbols@3.0.0, log-symbols@^3.0.0: dependencies: chalk "^2.4.2" -log-update@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" - integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== - dependencies: - ansi-escapes "^4.3.0" - cli-cursor "^3.1.0" - slice-ansi "^4.0.0" - wrap-ansi "^6.2.0" - loglevel-plugin-prefix@^0.8.4: version "0.8.4" resolved "https://registry.yarnpkg.com/loglevel-plugin-prefix/-/loglevel-plugin-prefix-0.8.4.tgz#2fe0e05f1a820317d98d8c123e634c1bd84ff644" @@ -10674,6 +10507,13 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + make-dir@^2.0.0, make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -10761,11 +10601,30 @@ matcher@^3.0.0: dependencies: escape-string-regexp "^4.0.0" +matches-selector@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/matches-selector/-/matches-selector-0.0.1.tgz#1df5262243ae341c1a0804dd302048267ac713bb" + integrity sha1-HfUmIkOuNBwaCATdMCBIJnrHE7s= + math-expression-evaluator@^1.2.14: version "1.2.22" resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.22.tgz#c14dcb3d8b4d150e5dcea9c68c8dad80309b0d5e" integrity sha512-L0j0tFVZBQQLeEjmWOvDLoRciIY8gQGWahvkztXUal8jH8R5Rlqo9GCvgqvXcy9LQhEWdQCVvzqAbxgYNt4blQ== +mathjs@7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-7.1.0.tgz#83226e336b8b258b046a139865373e667db94afb" + integrity sha512-Km6PO2UR+COs5mru5auKQKi84GKBryuL5JDdKeAxAi0QV8mH/qwpZKLnzrycxBacQ/X/4Z4Kn+gtYc5gEeWsDQ== + dependencies: + complex.js "^2.0.11" + decimal.js "^10.2.0" + escape-latex "^1.2.0" + fraction.js "^4.0.12" + javascript-natural-sort "^0.7.1" + seed-random "^2.2.0" + tiny-emitter "^2.1.0" + typed-function "^2.0.0" + md5-hex@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-3.0.1.tgz#be3741b510591434b2784d79e556eefc2c9a8e5c" @@ -10940,9 +10799,9 @@ mimic-fn@^2.1.0: integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== mimic-fn@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.0.0.tgz#76044cfa8818bbf6999c5c9acadf2d3649b14b4b" - integrity sha512-PiVO95TKvhiwgSwg1IdLYlCTdul38yZxZMIcnDSFIBUm4BNZha2qpQ4GpJ++15bHoKDtrW2D69lMfFwdFYtNZQ== + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74" + integrity sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ== mimic-response@^1.0.0, mimic-response@^1.0.1: version "1.0.1" @@ -11021,9 +10880,9 @@ minipass-flush@^1.0.5: minipass "^3.0.0" minipass-pipeline@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.3.tgz#55f7839307d74859d6e8ada9c3ebe72cec216a34" - integrity sha512-cFOknTvng5vqnwOpDsZTWhNll6Jf8o2x+/diplafmxpuIymAjzoOolZG0VvQf3V2HgqzJNhnuKHYp2BqDgz8IQ== + version "1.2.4" + resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" + integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== dependencies: minipass "^3.0.0" @@ -11058,11 +10917,6 @@ mississippi@^3.0.0: stream-each "^1.1.0" through2 "^2.0.0" -mitt@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/mitt/-/mitt-2.0.1.tgz#9e8a075b4daae82dd91aac155a0ece40ca7cb393" - integrity sha512-FhuJY+tYHLnPcBHQhbUFzscD5512HumCPE4URXZUgPi3IvOJi4Xva5IIgy3xX56GqCmw++MAm5UURG6kDBYTdg== - mixin-deep@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" @@ -11084,7 +10938,7 @@ mkdirp-classic@^0.5.2: resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== -mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1: +mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -11096,10 +10950,40 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +ml-array-max@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/ml-array-max/-/ml-array-max-1.1.2.tgz#ac14a4954ebdb9f401774cc1572fce439e12f94d" + integrity sha512-it2hYUSuYEwIRO6hjTWfe6gbGutF4Tuct7jxt3LiLE4wKFs6ku5FLNIRKtOL2jyH+Jdwt1ddbqKMX8inBM8RxA== + dependencies: + is-any-array "^0.0.3" + +ml-array-min@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/ml-array-min/-/ml-array-min-1.1.2.tgz#a084370fe78998a4131d566d066ee01bccce253a" + integrity sha512-92QzvsyK7TxGz618pno6bu0LXYcRKssbimP85qRllk2xX5Z4gnVxlOmrMjSerUut9zzbt1eQB4byXNCwT0vgwA== + dependencies: + is-any-array "^0.0.3" + +ml-array-rescale@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/ml-array-rescale/-/ml-array-rescale-1.3.1.tgz#7e55871af8741d212e2b47b8acd55571936c822b" + integrity sha512-PMj/f3MXBf5j2is8E4ugfNx6txi5y6qO4iVizfGjUVcpBl9RpXhznsoOz5iLtVtW1uDiWl+ToHaW4IGwoG+rmg== + dependencies: + is-any-array "^0.0.3" + ml-array-max "^1.1.2" + ml-array-min "^1.1.2" + +ml-matrix@6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/ml-matrix/-/ml-matrix-6.5.1.tgz#b61305024f548ce198faa001974fd961cd162a98" + integrity sha512-KJ5DVN5cH7+HmFhjVhYh4FI1m1v4Xmw1Xi+huTlP0tDAKKuC5ZY4IlElCaT0LalsERE9nDQQ3YwT/o9Gss/B5w== + dependencies: + ml-array-rescale "^1.3.1" + mocha@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.0.1.tgz#fe01f0530362df271aa8f99510447bc38b88d8ed" - integrity sha512-vefaXfdYI8+Yo8nPZQQi0QO2o+5q9UIMX1jZ1XMmK3+4+CQjc7+B0hPdUeglXiTlr8IHMVRo63IhO9Mzt6fxOg== + version "8.1.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.1.0.tgz#e651d05dcc5e42389f3412c2173ca13352a8bacd" + integrity sha512-sI0gaI1I/jPVu3KFpnveWGadfe3JNBAENqgTUPgLZAUppu725zS2mrVztzAgIR8DUscuS4doEBTx9LATC+HSeA== dependencies: ansi-colors "4.1.1" browser-stdout "1.3.1" @@ -11117,7 +11001,7 @@ mocha@^8.0.1: ms "2.1.2" object.assign "4.1.0" promise.allsettled "1.0.2" - serialize-javascript "3.0.0" + serialize-javascript "4.0.0" strip-json-comments "3.0.1" supports-color "7.1.0" which "2.0.2" @@ -11125,7 +11009,7 @@ mocha@^8.0.1: workerpool "6.0.0" yargs "13.3.2" yargs-parser "13.1.2" - yargs-unparser "1.6.0" + yargs-unparser "1.6.1" moment-timezone@0.5.31: version "0.5.31" @@ -11134,16 +11018,11 @@ moment-timezone@0.5.31: dependencies: moment ">= 2.9.0" -moment@2.27.0: +moment@2.27.0, "moment@>= 2.9.0", moment@>=1.6.0: version "2.27.0" resolved "https://registry.yarnpkg.com/moment/-/moment-2.27.0.tgz#8bff4e3e26a236220dfe3e36de756b6ebaa0105d" integrity sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ== -"moment@>= 2.9.0": - version "2.26.0" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.26.0.tgz#5e1f82c6bafca6e83e808b30c8705eed0dcbd39a" - integrity sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw== - monaco-editor@^0.20.0: version "0.20.0" resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.20.0.tgz#5d5009343a550124426cb4d965a4d27a348b4dea" @@ -11241,9 +11120,9 @@ negotiator@0.6.2: integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" - integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== nice-try@^1.0.4: version "1.0.5" @@ -11323,21 +11202,21 @@ node-modules-regexp@^1.0.0: integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= node-notifier@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-7.0.1.tgz#a355e33e6bebacef9bf8562689aed0f4230ca6f9" - integrity sha512-VkzhierE7DBmQEElhTGJIoiZa1oqRijOtgOlsXg32KrJRXsPy0NXFBqWGW/wTswnJlDCs5viRYaqWguqzsKcmg== + version "7.0.2" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-7.0.2.tgz#3a70b1b70aca5e919d0b1b022530697466d9c675" + integrity sha512-ux+n4hPVETuTL8+daJXTOC6uKLgMsl1RYfFv7DKRzyvzBapqco0rZZ9g72ZN8VS6V+gvNYHYa/ofcCY8fkJWsA== dependencies: growly "^1.3.0" - is-wsl "^2.1.1" - semver "^7.2.1" + is-wsl "^2.2.0" + semver "^7.3.2" shellwords "^0.1.1" - uuid "^7.0.3" + uuid "^8.2.0" which "^2.0.2" -node-releases@^1.1.29, node-releases@^1.1.53: - version "1.1.58" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.58.tgz#8ee20eef30fa60e52755fcc0942def5a734fe935" - integrity sha512-NxBudgVKiRh/2aPWMgPR7bPTX0VPmGx5QBwCtdHitnqFE5/O8DeBXuIMH1nwNnw/aMo6AjOrpsHzfY3UbUJ7yg== +node-releases@^1.1.29, node-releases@^1.1.58: + version "1.1.60" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.60.tgz#6948bdfce8286f0b5d0e5a88e8384e954dfe7084" + integrity sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA== normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" @@ -11457,9 +11336,9 @@ object-hash@^2.0.3: integrity sha512-JPKn0GMu+Fa3zt3Bmr66JhokJU5BaNBIh4ZeTlaCBzrBsOeXzwcKKAK1tbLiPKgvwmPXsDvvLHoWh5Bm7ofIYg== object-inspect@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" - integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== + version "1.8.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" + integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== object-is@^1.0.1: version "1.1.2" @@ -11491,7 +11370,7 @@ object.assign@4.1.0, object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" -object.entries@^1.1.0, object.entries@^1.1.1: +object.entries@^1.1.0, object.entries@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.2.tgz#bc73f00acb6b6bb16c203434b10f9a7e797d3add" integrity sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA== @@ -11567,9 +11446,9 @@ onetime@^2.0.0: mimic-fn "^1.0.0" onetime@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" - integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + version "5.1.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.1.tgz#5c8016847b0d67fcedb7eef254751cfcdc7e9418" + integrity sha512-ZpZpjcJeugQfWsfyQlshVoowIIQ1qBGSVll4rfDq6JJVO//fesjoX808hXWfBjY+ROZgpKDI5TRSRBSoJiZ8eg== dependencies: mimic-fn "^2.1.0" @@ -11581,9 +11460,9 @@ open@^6.3.0: is-wsl "^1.1.0" open@^7.0.0: - version "7.0.4" - resolved "https://registry.yarnpkg.com/open/-/open-7.0.4.tgz#c28a9d315e5c98340bf979fdcb2e58664aa10d83" - integrity sha512-brSA+/yq+b08Hsr4c8fsEW2CRzk1BmfN3SAK/5VCHQ9bdoZJ4qa/+AfR0xHjlbbZUyPkUHs1b8x1RqdyZdkVqQ== + version "7.1.0" + resolved "https://registry.yarnpkg.com/open/-/open-7.1.0.tgz#68865f7d3cb238520fa1225a63cf28bcf8368a1c" + integrity sha512-lLPI5KgOwEYCDKXf4np7y1PBEkj7HYIyP2DY8mVDRnx0VIIu6bNrRB0R66TuO7Mack6EnTNLm4uvcl1UoklTpA== dependencies: is-docker "^2.0.0" is-wsl "^2.1.1" @@ -11595,12 +11474,12 @@ opn@^5.5.0: dependencies: is-wsl "^1.1.0" -optimism@^0.10.0: - version "0.10.3" - resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.10.3.tgz#163268fdc741dea2fb50f300bedda80356445fd7" - integrity sha512-9A5pqGoQk49H6Vhjb9kPgAeeECfUDF6aIICbMDL23kDLStBn1MWk3YvcZ4xWF9CsSf6XEgvRLkXy4xof/56vVw== +optimism@^0.12.1: + version "0.12.1" + resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.12.1.tgz#933f9467b9aef0e601655adb9638f893e486ad02" + integrity sha512-t8I7HM1dw0SECitBYAqFOVHoBAHEQBTeKjIL9y9ImHzAVkdyPK4ifTgM4VJRDtTUY4r/u5Eqxs4XcGPHaoPkeQ== dependencies: - "@wry/context" "^0.4.0" + "@wry/context" "^0.5.2" optionator@^0.8.1: version "0.8.3" @@ -11626,10 +11505,10 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" -ora@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/ora/-/ora-4.0.4.tgz#e8da697cc5b6a47266655bf68e0fb588d29a545d" - integrity sha512-77iGeVU1cIdRhgFzCK8aw1fbtT1B/iZAvWjS+l/o1x0RShMgxHUZaD2yDpWsNCPwXg9z1ZA78Kbdvr8kBmG/Ww== +ora@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/ora/-/ora-4.0.5.tgz#7410b5cc2d99fa637fd5099bbb9f02bfbb5a361e" + integrity sha512-jCDgm9DqvRcNIAEv2wZPrh7E5PcQiDUnbnWbAfu4NGAE2ZNqPFbDixmWldy1YG2QfLeQhuiu6/h5VRrk6cG50w== dependencies: chalk "^3.0.0" cli-cursor "^3.1.0" @@ -11696,6 +11575,13 @@ p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.3.0: dependencies: p-try "^2.0.0" +p-limit@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.0.2.tgz#1664e010af3cadc681baafd3e2a437be7b0fb5fe" + integrity sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg== + dependencies: + p-try "^2.0.0" + p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -11832,9 +11718,9 @@ parse-json@^4.0.0: json-parse-better-errors "^1.0.1" parse-json@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" - integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw== + version "5.0.1" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.1.tgz#7cfe35c1ccd641bce3981467e6c2ece61b3b3878" + integrity sha512-ztoZ4/DYeXQq4E21v169sC8qWINGpcosGv9XhTDvg9/hWvx/zrFkc9BiWxR58OJLHGk28j5BL0SDLeV2WmFZlQ== dependencies: "@babel/code-frame" "^7.0.0" error-ex "^1.3.1" @@ -11979,6 +11865,18 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pathfinding@0.4.18: + version "0.4.18" + resolved "https://registry.yarnpkg.com/pathfinding/-/pathfinding-0.4.18.tgz#a9990f6fa22b7ef196e5651b049165403a045fe8" + integrity sha1-qZkPb6IrfvGW5WUbBJFlQDoEX+g= + dependencies: + heap "0.2.5" + +paths-js@0.4.11: + version "0.4.11" + resolved "https://registry.yarnpkg.com/paths-js/-/paths-js-0.4.11.tgz#b2a9d5f94ee9949aa8fee945f78a12abff44599e" + integrity sha512-3mqcLomDBXOo7Fo+UlaenG6f71bk1ZezPQy2JCmYHy2W2k5VKpP+Jbin9H0bjXynelTbglCqdFhSEkeIkKTYUA== + pathval@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" @@ -12080,7 +11978,7 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -pkg-up@2.0.0, pkg-up@^2.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= @@ -12107,9 +12005,9 @@ pnp-webpack-plugin@1.5.0: ts-pnp "^1.1.2" polished@^3.3.1: - version "3.6.4" - resolved "https://registry.yarnpkg.com/polished/-/polished-3.6.4.tgz#cec6bc0fbffc5d6ce5799c85bcc1bca5e63f1dee" - integrity sha512-21moJXCm/7EvjeKQz5w89QDDKNPCoimc83CqwZZGJluFdMXsFlMQl9lPA/OMRkoceZ19kU0anKlMgZmY7LJSJw== + version "3.6.5" + resolved "https://registry.yarnpkg.com/polished/-/polished-3.6.5.tgz#dbefdde64c675935ec55119fe2a2ab627ca82e9c" + integrity sha512-VwhC9MlhW7O5dg/z7k32dabcAFW1VI2+7fSe8cE/kXcfL7mVdoa5UxciYGW2sJU78ldDLT6+ROEKIZKFNTnUXQ== dependencies: "@babel/runtime" "^7.9.2" @@ -12119,13 +12017,13 @@ popper.js@^1.14.4, popper.js@^1.14.7, popper.js@^1.16.1: integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== portfinder@^1.0.26: - version "1.0.26" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.26.tgz#475658d56ca30bed72ac7f1378ed350bd1b64e70" - integrity sha512-Xi7mKxJHHMI3rIUrnm/jjUgwhbYMkp/XKEcZX3aG4BrumLpq3nmoQMX+ClYnDZnZ/New7IatC1no5RX0zo1vXQ== + version "1.0.28" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" + integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== dependencies: async "^2.6.2" debug "^3.1.1" - mkdirp "^0.5.1" + mkdirp "^0.5.5" posix-character-classes@^0.1.0: version "0.1.1" @@ -12164,15 +12062,15 @@ postcss-modules-extract-imports@^2.0.0: dependencies: postcss "^7.0.5" -postcss-modules-local-by-default@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz#e8a6561be914aaf3c052876377524ca90dbb7915" - integrity sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ== +postcss-modules-local-by-default@^3.0.2, postcss-modules-local-by-default@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0" + integrity sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw== dependencies: icss-utils "^4.1.1" - postcss "^7.0.16" + postcss "^7.0.32" postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.0.0" + postcss-value-parser "^4.1.0" postcss-modules-scope@^2.2.0: version "2.2.0" @@ -12199,12 +12097,12 @@ postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: indexes-of "^1.0.1" uniq "^1.0.1" -postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.3, postcss-value-parser@^4.1.0: +postcss-value-parser@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== -postcss@^7.0.0, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.26, postcss@^7.0.27, postcss@^7.0.30, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: +postcss@^7.0.0, postcss@^7.0.14, postcss@^7.0.26, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: version "7.0.32" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d" integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw== @@ -12246,22 +12144,12 @@ pretty-error@^2.1.1: renderkid "^2.0.1" utila "~0.4" -pretty-format@^25.5.0: - version "25.5.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-25.5.0.tgz#7873c1d774f682c34b8d48b6743a2bf2ac55791a" - integrity sha512-kbo/kq2LQ/A/is0PQwsEHM7Ca6//bGPPvU6UnsdDRSKTWxT/ru/xb88v4BJf6a69H+uTytOEsTusT9ksd/1iWQ== - dependencies: - "@jest/types" "^25.5.0" - ansi-regex "^5.0.0" - ansi-styles "^4.0.0" - react-is "^16.12.0" - -pretty-format@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.1.0.tgz#272b9cd1f1a924ab5d443dc224899d7a65cb96ec" - integrity sha512-GmeO1PEYdM+non4BKCj+XsPJjFOJIPnsLewqhDVoqY1xo0yNmDas7tC2XwpMrRAHR3MaE2hPo37deX5OisJ2Wg== +pretty-format@^26.2.0: + version "26.2.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.2.0.tgz#83ecc8d7de676ff224225055e72bd64821cec4f1" + integrity sha512-qi/8IuBu2clY9G7qCXgCdD1Bf9w+sXakdHTRToknzMtVy0g7c4MBWaZy7MfB7ndKZovRO6XRwJiAYqq+MC7SDA== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" ansi-regex "^5.0.0" ansi-styles "^4.0.0" react-is "^16.12.0" @@ -12292,7 +12180,7 @@ prismjs@~1.17.0: optionalDependencies: clipboard "^2.0.0" -private@^0.1.8, private@~0.1.5: +private@~0.1.5: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== @@ -12475,16 +12363,17 @@ pupa@^2.0.1: dependencies: escape-goat "^2.0.0" -puppeteer-core@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-4.0.0.tgz#32cb3c97efd280301a8084caf5566b5c2d83896f" - integrity sha512-Tb5FVp9h9wkd2gXpc/qfBFFI7zjLxxe3pw34U5ntpSnIoUV2m9IKIjAf7ou+5N3fU9VPV3MNJ3HQiDVasN/MPQ== +puppeteer-core@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-5.2.1.tgz#0d21b5bbb30c82db9b439d255a459f3538cc7235" + integrity sha512-gLjEOrzwgcnwRH+sm4hS1TBqe2/DN248nRb2hYB7+lZ9kCuLuACNvuzlXILlPAznU3Ob+mEvVEBDcLuFa0zq3g== dependencies: debug "^4.1.0" + devtools-protocol "0.0.781568" extract-zip "^2.0.0" https-proxy-agent "^4.0.0" mime "^2.0.3" - mitt "^2.0.1" + pkg-dir "^4.2.0" progress "^2.0.1" proxy-from-env "^1.0.0" rimraf "^3.0.2" @@ -12535,7 +12424,7 @@ querystringify@^2.1.1: resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== -quick-lru@^5.0.0: +quick-lru@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== @@ -12770,12 +12659,12 @@ react-fast-compare@^3.0.1: integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== react-focus-lock@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.3.1.tgz#9d5d85899773609c7eefa4fc54fff6a0f5f2fc47" - integrity sha512-j15cWLPzH0gOmRrUg01C09Peu8qbcdVqr6Bjyfxj80cNZmH+idk/bNBYEDSmkAtwkXI+xEYWSmHYqtaQhZ8iUQ== + version "2.4.1" + resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.4.1.tgz#e842cc93da736b5c5d331799012544295cbcee4f" + integrity sha512-c5ZP56KSpj9EAxzScTqQO7bQQNPltf/W1ZEBDqNDOV1XOIwvAyHX0O7db9ekiAtxyKgnqZjQlLppVg94fUeL9w== dependencies: "@babel/runtime" "^7.0.0" - focus-lock "^0.6.7" + focus-lock "^0.7.0" prop-types "^15.6.2" react-clientside-effect "^1.2.2" use-callback-ref "^1.2.1" @@ -12813,11 +12702,18 @@ react-is@^16.12.0, react-is@^16.3.2, react-is@^16.6.0, react-is@^16.7.0, react-i resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -react-lifecycles-compat@^3.0.2, react-lifecycles-compat@^3.0.4: +react-lifecycles-compat@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== +react-moment-proptypes@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/react-moment-proptypes/-/react-moment-proptypes-1.7.0.tgz#89881479840a76c13574a86e3bb214c4ba564e7a" + integrity sha512-ZbOn/P4u469WEGAw5hgkS/E+g1YZqdves2BjYsLluJobzUZCtManhjHiZKjniBVT7MSHM6D/iKtRVzlXVv3ikA== + dependencies: + moment ">=1.6.0" + react-mosaic-component@3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/react-mosaic-component/-/react-mosaic-component-3.2.0.tgz#b06d10d28e5d4e24a5aa8218aca73e964d8edbea" @@ -12885,18 +12781,18 @@ react-property@1.0.1: resolved "https://registry.yarnpkg.com/react-property/-/react-property-1.0.1.tgz#4ae4211557d0a0ae050a71aa8ad288c074bea4e6" integrity sha512-1tKOwxFn3dXVomH6pM9IkLkq2Y8oh+fh/lYW3MJ/B03URswUTqttgckOlbxY2XHF3vPG6uanSc4dVsLW/wk3wQ== -react-redux-loading-bar@4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/react-redux-loading-bar/-/react-redux-loading-bar-4.6.0.tgz#034a1771a97b43e7d835e67d2ba717ca378279f4" - integrity sha512-ehokhN6eq/UXMr0udqoKuvpEUel1q3T5cWGkwKy2Xrt528QeEtjreixCfrSndN+DNr/5yxxnz0ZEhZt4irZEZg== +react-redux-loading-bar@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/react-redux-loading-bar/-/react-redux-loading-bar-5.0.0.tgz#fffbc2b893c556b7b4c577743427507ee6dbc1f3" + integrity sha512-orxhhnuTDHUJ8sWBf7NHc9iIvPx8+8LVmMmC9ka3UcXKbMRaPdaYfH2wCikOwVV6gxhRceFA/zaSLSdnGrF41Q== dependencies: - prop-types "^15.6.2" - react-lifecycles-compat "^3.0.2" + prop-types "^15.7.2" + react-lifecycles-compat "^3.0.4" -react-redux@7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.0.tgz#f970f62192b3981642fec46fd0db18a074fe879d" - integrity sha512-EvCAZYGfOLqwV7gh849xy9/pt55rJXPwmYvI4lilPM5rUT/1NxuuN59ipdBksRVSvz0KInbPnp4IfoXJXCqiDA== +react-redux@7.2.1: + version "7.2.1" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.1.tgz#8dedf784901014db2feca1ab633864dee68ad985" + integrity sha512-T+VfD/bvgGTUA74iW9d2i5THrDQWbweXP0AVNI8tNd1Rk5ch1rnMiJkDD67ejw7YBKM4+REvcvqRuWJb7BLuEg== dependencies: "@babel/runtime" "^7.5.5" hoist-non-react-statics "^3.3.0" @@ -12940,13 +12836,13 @@ react-router@5.2.0: tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-scroll@1.7.16: - version "1.7.16" - resolved "https://registry.yarnpkg.com/react-scroll/-/react-scroll-1.7.16.tgz#814f0b97ed171aad1f27e45dad16a8444817fec8" - integrity sha512-f4M5AdL+3cw3MJ7c/T0hPMY2iHCeQLDXV13lRanAFQ6JIt9xyAdHCpTH9mLUQt9SQh4pRarD+Qc7KhU6qMx3Yg== +react-scroll@1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/react-scroll/-/react-scroll-1.8.0.tgz#0280cbe575e4e1a2f103c7cc6143dd38133573bd" + integrity sha512-oZfBXPhcxYPR8elI9tC3ORT6+iqiPPJWslsdR9intbNI5PVSa4XoAfC0I/cB3zk5lxQ/NSexCnT+8RqJL8mSZQ== dependencies: lodash.throttle "^4.1.1" - prop-types "^15.5.8" + prop-types "^15.7.2" react-sizeme@^2.6.7: version "2.6.12" @@ -13006,19 +12902,19 @@ react-textarea-autosize@^7.1.0: "@babel/runtime" "^7.1.2" prop-types "^15.6.0" -react-toastify@6.0.6: - version "6.0.6" - resolved "https://registry.yarnpkg.com/react-toastify/-/react-toastify-6.0.6.tgz#7409ef8e89d12492308a8e561317031b5d90615e" - integrity sha512-NdHiMhj76Z877kZlXuelVfJONslvpmDTL95FVAoBy2kkU75hiqR5+pu1GdJZfRWPhen9ecdb58d3HmefaJ06Yw== +react-toastify@6.0.8: + version "6.0.8" + resolved "https://registry.yarnpkg.com/react-toastify/-/react-toastify-6.0.8.tgz#84625d81d0fd01902a7f4c6f317eb074cb3bba67" + integrity sha512-NSqCNwv+C4IfR+c92PFZiNyeBwOJvigrP2bcRi2f6Hg3WqcHhEHOknbSQOs9QDFuqUjmK3SOrdvScQ3z63ifXg== dependencies: classnames "^2.2.6" prop-types "^15.7.2" react-transition-group "^4.4.1" -react-tooltip@4.2.7: - version "4.2.7" - resolved "https://registry.yarnpkg.com/react-tooltip/-/react-tooltip-4.2.7.tgz#245b26aa23bc8ca877f9086ad169207d77281894" - integrity sha512-z5T3gNplT76rkT7ZImfx/uXfBtS+x7+WK2H8MVZ5skSwETDDx0hs0+P0jwL5gYDaBvsZ7LYiCBzAOd3tN85CMA== +react-tooltip@4.2.8: + version "4.2.8" + resolved "https://registry.yarnpkg.com/react-tooltip/-/react-tooltip-4.2.8.tgz#270858fee46fab73b66de316271aa94145f7446b" + integrity sha512-pDWa0/khTAgIfldp95tHgyuYyBhWNlfaU2LF9ubAKxpoqNe15uyf+uLlnhK/Lstb6FU8E8/SL28Wp6oEO9xw3g== dependencies: prop-types "^15.7.2" uuid "^7.0.3" @@ -13118,7 +13014,7 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@^2.3.7, readable-stream@~2.3.6: +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -13140,6 +13036,13 @@ readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable string_decoder "^1.1.1" util-deprecate "^1.0.1" +readdir-glob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/readdir-glob/-/readdir-glob-1.0.0.tgz#a495436934bbe57be6a68039d16e8946621eb8c5" + integrity sha512-km0DIcwQVZ1ZUhXhMWpF74/Wm5aFEd5/jDiVWF1Hkw2myPQovG8vCQ8+FQO2KXE9npQQvCnAMZhhWuUee4WcCQ== + dependencies: + minimatch "^3.0.4" + readdirp@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" @@ -13180,7 +13083,7 @@ rechoir@^0.6.2: dependencies: resolve "^1.1.6" -recursive-readdir@2.2.2: +recursive-readdir@2.2.2, recursive-readdir@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" integrity sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg== @@ -13238,17 +13141,16 @@ regenerate@^1.4.0: integrity sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A== regenerator-runtime@^0.13.2, regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.5: - version "0.13.5" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" - integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== + version "0.13.7" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" + integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== 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== + version "0.14.5" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" + integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== dependencies: "@babel/runtime" "^7.8.4" - private "^0.1.8" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" @@ -13284,9 +13186,9 @@ regexpu-core@^4.7.0: unicode-match-property-value-ecmascript "^1.2.0" registry-auth-token@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.1.1.tgz#40a33be1e82539460f94328b0f7f0f84c16d9479" - integrity sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA== + version "4.2.0" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.0.tgz#1d37dffda72bbecd0f581e4715540213a65eb7da" + integrity sha512-P+lWzPrsgfN+UEpDS3U8AQKg/UjZX6mQSJueZj3EK+vNESoqBSpBUD3gmu4sF9lOsjXWjF11dQKUqemf3veq1w== dependencies: rc "^1.2.8" @@ -13340,19 +13242,19 @@ repeat-string@^1.6.1: resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= -request-promise-core@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.3.tgz#e9a3c081b51380dfea677336061fea879a829ee9" - integrity sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ== +request-promise-core@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" + integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw== dependencies: - lodash "^4.17.15" + lodash "^4.17.19" request-promise-native@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.8.tgz#a455b960b826e44e2bf8999af64dff2bfe58cb36" - integrity sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ== + version "1.0.9" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28" + integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== dependencies: - request-promise-core "1.1.3" + request-promise-core "1.1.4" stealthy-require "^1.1.1" tough-cookie "^2.3.3" @@ -13397,7 +13299,7 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= -resize-observer-polyfill@^1.5.1: +resize-observer-polyfill@1.5.1, resize-observer-polyfill@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== @@ -13454,7 +13356,7 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.11.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.15.1, resolve@^1.17.0, resolve@^1.3.2, resolve@^1.8.1: +resolve@^1.1.6, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.11.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.3.2, resolve@^1.8.1: version "1.17.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== @@ -13581,10 +13483,10 @@ rw@1: resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" integrity sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q= -rxjs@^6.4.0, rxjs@^6.5.3: - version "6.5.5" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec" - integrity sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ== +rxjs@^6.4.0, rxjs@^6.6.0: + version "6.6.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.2.tgz#8096a7ac03f2cc4fe5860ef6e572810d9e01c0d2" + integrity sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg== dependencies: tslib "^1.9.0" @@ -13610,7 +13512,7 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -13676,6 +13578,11 @@ schema-utils@^2.0.0, schema-utils@^2.0.1, schema-utils@^2.5.0, schema-utils@^2.6 ajv "^6.12.2" ajv-keywords "^3.4.1" +seed-random@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/seed-random/-/seed-random-2.2.0.tgz#2a9b19e250a817099231a5b99a4daf80b7fbed54" + integrity sha1-KpsZ4lCoFwmSMaW5mk2vgLf77VQ= + select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" @@ -13769,10 +13676,12 @@ serialize-error@^7.0.0: dependencies: type-fest "^0.13.1" -serialize-javascript@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-3.0.0.tgz#492e489a2d77b7b804ad391a5f5d97870952548e" - integrity sha512-skZcHYw2vEX4bw90nAr2iTTsz6x2SrHEnfxgKYmZlvJYBEZrvbKtobJWlQ20zczKb3bsHHXXTYt48zBA7ni9cw== +serialize-javascript@4.0.0, serialize-javascript@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" + integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== + dependencies: + randombytes "^2.1.0" serialize-javascript@^3.1.0: version "3.1.0" @@ -13868,6 +13777,13 @@ shallow-clone@^0.1.2: lazy-cache "^0.2.3" mixin-object "^2.0.1" +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + shallow-equal@^1.1.0: version "1.2.1" resolved "https://registry.yarnpkg.com/shallow-equal/-/shallow-equal-1.2.1.tgz#4c16abfa56043aa20d050324efa68940b0da79da" @@ -13987,15 +13903,6 @@ slice-ansi@^3.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" -slice-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" - integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - snake-case@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.3.tgz#c598b822ab443fcbb145ae8a82c5e43526d5bbee" @@ -14221,11 +14128,6 @@ stable@^0.1.8: resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== -stack-utils@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" - integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA== - stack-utils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.2.tgz#5cf48b4557becb4638d0bc4f21d23f5d19586593" @@ -14381,7 +14283,7 @@ string.prototype.padstart@^3.0.0: define-properties "^1.1.3" es-abstract "^1.17.0-next.1" -string.prototype.trimend@^1.0.0: +string.prototype.trimend@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== @@ -14389,25 +14291,7 @@ string.prototype.trimend@^1.0.0: define-properties "^1.1.3" es-abstract "^1.17.5" -string.prototype.trimleft@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz#4408aa2e5d6ddd0c9a80739b087fbc067c03b3cc" - integrity sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - string.prototype.trimstart "^1.0.0" - -string.prototype.trimright@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz#c76f1cef30f21bbad8afeb8db1511496cfb0f2a3" - integrity sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - string.prototype.trimend "^1.0.0" - -string.prototype.trimstart@^1.0.0: +string.prototype.trimstart@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== @@ -14497,9 +14381,9 @@ strip-json-comments@3.0.1: integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== strip-json-comments@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.0.tgz#7638d31422129ecf4457440009fba03f9f9ac180" - integrity sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w== + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== strip-json-comments@~2.0.1: version "2.0.1" @@ -14614,7 +14498,7 @@ svgo@^1.2.2: unquote "~1.1.1" util.promisify "~1.0.0" -symbol-observable@^1.0.2, symbol-observable@^1.2.0: +symbol-observable@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== @@ -14632,7 +14516,7 @@ symbol.prototype.description@^1.0.0: es-abstract "^1.17.0-next.1" has-symbols "^1.0.1" -synchronous-promise@^2.0.10: +synchronous-promise@^2.0.13: version "2.0.13" resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.13.tgz#9d8c165ddee69c5a6542862b405bc50095926702" integrity sha512-R9N6uDkVsghHePKh1TEqbnLddO2IY25OcsksyFp/qBe7XYd0PVbKEWxhcdMhpLzE1I6skj5l4aEZ3CRxcbArlA== @@ -14663,9 +14547,9 @@ tar-fs@^2.0.0: tar-stream "^2.0.0" tar-stream@^2.0.0, tar-stream@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.2.tgz#6d5ef1a7e5783a95ff70b69b97455a5968dc1325" - integrity sha512-UaF6FoJ32WqALZGOIAApXx+OdxhekNMChu6axLJR85zMMjXKWFGjbIRe+J6P4UnRGg9rAwWvbTT0oI7hD/Un7Q== + version "2.1.3" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.3.tgz#1e2022559221b7866161660f118255e20fa79e41" + integrity sha512-Z9yri56Dih8IaK8gncVPx4Wqt86NDmQTSh49XLZgjWpGZL9GK9HKParS2scqHCC4w6X9Gh2jwaU45V47XTKwVA== dependencies: bl "^4.0.1" end-of-stream "^1.4.1" @@ -14763,9 +14647,9 @@ terser-webpack-plugin@^2.1.2: webpack-sources "^1.4.3" terser@^4.1.2, terser@^4.6.12, terser@^4.6.3: - version "4.7.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.7.0.tgz#15852cf1a08e3256a80428e865a2fa893ffba006" - integrity sha512-Lfb0RiZcjRDXCC3OSHJpEkxJ9Qeqs6mp2v4jf2MHfy8vGERmVDuvjXdd/EnP5Deme5F2yBRBymKmKHCBg2echw== + version "4.8.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" + integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== dependencies: commander "^2.20.0" source-map "~0.6.1" @@ -14846,7 +14730,7 @@ timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" -tiny-emitter@^2.0.0: +tiny-emitter@^2.0.0, tiny-emitter@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== @@ -14976,7 +14860,7 @@ ts-dedent@^1.1.0: resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-1.1.1.tgz#68fad040d7dbd53a90f545b450702340e17d18f3" integrity sha512-UGTRZu1evMw4uTPyYF66/KFd22XiU+jMaIuHrkIHQ2GivAXVlLV0v/vHrpOuTRf9BmpNHi/SO7Vd0rLu0y57jg== -ts-invariant@^0.4.0, ts-invariant@^0.4.4: +ts-invariant@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.4.4.tgz#97a523518688f93aafad01b0e80eb803eb2abd86" integrity sha512-uEtWkFM/sdZvRNNDL3Ehu4WVpwaulhwQszV8mrtcdeE8nN00BV9mAmQ88RkrBhFgl9gMgvjJLAQcZbnPXI9mlA== @@ -15077,6 +14961,11 @@ type-is@~1.6.17, type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" +typed-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/typed-function/-/typed-function-2.0.0.tgz#15ab3825845138a8b1113bd89e60cd6a435739e8" + integrity sha512-Hhy1Iwo/e4AtLZNK10ewVVcP2UEs408DS35ubP825w/YgSBK1KVLwALvvIG4yX75QJrxjCpcWkzkVRB0BwwYlA== + typed-styles@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/typed-styles/-/typed-styles-0.0.7.tgz#93392a008794c4595119ff62dde6809dbc40a3d9" @@ -15105,11 +14994,9 @@ uc.micro@^1.0.1, uc.micro@^1.0.5: integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== uglify-js@^3.1.4: - version "3.9.4" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.9.4.tgz#867402377e043c1fc7b102253a22b64e5862401b" - integrity sha512-8RZBJq5smLOa7KslsNsVcSH+KOXf1uDU8yqLeNuVKwmT0T3FA0ZoXlinQfRad7SDcbZZRZE4ov+2v71EnxNyCA== - dependencies: - commander "~2.20.3" + version "3.10.1" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.10.1.tgz#dd14767eb7150de97f2573a5ff210db14fffe4ad" + integrity sha512-RjxApKkrPJB6kjJxQS3iZlf///REXWYxYJxO/MpmlQzVkDWVI3PSnCBWezMecmTU/TRkNxrl8bmsfFQCp+LO+Q== ultimate-pagination@1.0.0: version "1.0.0" @@ -15318,17 +15205,17 @@ use-callback-ref@^1.2.1: resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.2.4.tgz#d86d1577bfd0b955b6e04aaf5971025f406bea3c" integrity sha512-rXpsyvOnqdScyied4Uglsp14qzag1JIemLeTWGKbwpotWht57hbP78aNT+Q4wdFKQfQibbUX4fb6Qb4y11aVOQ== -use-debounce@3.4.2: - version "3.4.2" - resolved "https://registry.yarnpkg.com/use-debounce/-/use-debounce-3.4.2.tgz#f4333cca59504244b916159600427bf977ec4c46" - integrity sha512-rW44wZaFPh3XiwUzGBA0JRuklpbfKO/szU/5CYD2Q/erLmCem63lJ650p3a+NJE6S+g0rulKtBOfa/3rw/GN+Q== +use-debounce@3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/use-debounce/-/use-debounce-3.4.3.tgz#5df9322322b3f1b1c263d46413f9facf6d8b56ab" + integrity sha512-nxy+opOxDccWfhMl36J5BSCTpvcj89iaQk2OZWLAtBJQj7ISCtx1gh+rFbdjGfMl6vtCZf6gke/kYvrkVfHMoA== use-sidecar@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.0.2.tgz#e72f582a75842f7de4ef8becd6235a4720ad8af6" - integrity sha512-287RZny6m5KNMTb/Kq9gmjafi7lQL0YHO1lYolU6+tY1h9+Z3uCtkJJ3OSOq3INwYf2hBryCcDh4520AhJibMA== + version "1.0.3" + resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.0.3.tgz#17a4e567d4830c0c0ee100040e85a7fe68611e0f" + integrity sha512-ygJwGUBeQfWgDls7uTrlEDzJUUR67L8Rm14v/KfFtYCdHhtjHZx1Krb3DIQl3/Q5dJGfXLEQ02RY8BdNBv87SQ== dependencies: - detect-node "^2.0.4" + detect-node-es "^1.0.0" tslib "^1.9.3" use@^3.1.0: @@ -15393,10 +15280,10 @@ uuid@^7.0.3: resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== -uuid@^8.0.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.1.0.tgz#6f1536eb43249f473abc6bd58ff983da1ca30d8d" - integrity sha512-CI18flHDznR0lq54xBycOVmphdCYnQLKn8abKn7PXUiKUGdEd+/l9LWNJmugXel4hXq7S+RMNl34ecyC9TntWg== +uuid@^8.0.0, uuid@^8.2.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.0.tgz#ab738085ca22dc9a8c92725e459b1d507df5d6ea" + integrity sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ== v8-compile-cache@^2.0.3, v8-compile-cache@^2.1.1: version "2.1.1" @@ -15491,15 +15378,15 @@ watchpack-chokidar2@^2.0.0: dependencies: chokidar "^2.1.8" -watchpack@^1.6.1: - version "1.7.2" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.2.tgz#c02e4d4d49913c3e7e122c3325365af9d331e9aa" - integrity sha512-ymVbbQP40MFTp+cNMvpyBpBtygHnPzPkHqoIwRRj/0B8KhqQwV8LaKjtbaxF2lK4vl8zN9wCxS46IFCU5K4W0g== +watchpack@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.4.tgz#6e9da53b3c80bb2d6508188f5b200410866cd30b" + integrity sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg== dependencies: graceful-fs "^4.1.2" neo-async "^2.5.0" optionalDependencies: - chokidar "^3.4.0" + chokidar "^3.4.1" watchpack-chokidar2 "^2.0.0" wbuf@^1.1.0, wbuf@^1.7.3: @@ -15523,46 +15410,51 @@ wdio-chromedriver-service@6.0.3: dependencies: fs-extra "^9.0.0" -webdriver@6.1.17: - version "6.1.17" - resolved "https://registry.yarnpkg.com/webdriver/-/webdriver-6.1.17.tgz#669249677625d5e29caf90a2e3dab6ed2240eb9c" - integrity sha512-wtxKpq5FdQxu3wpakAMbsO5mdRAgjl0x4okrE7jm5RqE9voSh6TmyGdbb61YHmigQQVMhl6Mhq4+gCzaJfJfRQ== +webdriver@6.3.6: + version "6.3.6" + resolved "https://registry.yarnpkg.com/webdriver/-/webdriver-6.3.6.tgz#614c4d7e00ba3fdf3683882bc0f9cb1b45c46c64" + integrity sha512-cp8RSA50rBGDRBUG7oG5tZYvnvwLIfJsGbVtC6/C2DIRSGDaJvPRIsO0pJh/QL9T+dxk/KkA8xhZTPheV98h2g== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" - "@wdio/protocols" "6.1.14" - "@wdio/utils" "6.1.17" + "@wdio/protocols" "6.3.6" + "@wdio/utils" "6.3.6" got "^11.0.2" lodash.merge "^4.6.1" -webdriverio@6.1.22: - version "6.1.22" - resolved "https://registry.yarnpkg.com/webdriverio/-/webdriverio-6.1.22.tgz#c230d639e141e64c16240dbcce49e13183cb46c8" - integrity sha512-OBiur+Lybs3V+//OtU+9/qwTsLwRIicsVyYCBSqVFGBu3shk0zM6BppfB6uHeRSBmMGSRtA4od1K/rFysX1j6w== +webdriverio@6.3.6: + version "6.3.6" + resolved "https://registry.yarnpkg.com/webdriverio/-/webdriverio-6.3.6.tgz#33121669dd585125f85375e5fb243af8a3fd11e4" + integrity sha512-srgbSrJrcuADCwu37iijat1Z8JckTbcqbSCCdyLHOWEe0CgFdLcYKK5dYfuTQPhqSv6XYgPXq1Fce6jzo7nShA== dependencies: + "@types/puppeteer" "^3.0.1" "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" - "@wdio/repl" "6.1.17" - "@wdio/utils" "6.1.17" - archiver "^4.0.1" + "@wdio/repl" "6.3.6" + "@wdio/utils" "6.3.6" + archiver "^5.0.0" + atob "^2.1.2" css-value "^0.0.1" - devtools "6.1.22" + devtools "6.3.6" + get-port "^5.1.1" grapheme-splitter "^1.0.2" lodash.clonedeep "^4.5.0" lodash.isobject "^3.0.2" lodash.isplainobject "^4.0.6" lodash.zip "^4.2.0" + minimatch "^3.0.4" + puppeteer-core "^5.1.0" resq "^1.6.0" rgb2hex "^0.2.0" serialize-error "^7.0.0" - webdriver "6.1.17" + webdriver "6.3.6" webidl-conversions@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== -webidl-conversions@^6.0.0: +webidl-conversions@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== @@ -15652,12 +15544,13 @@ webpack-log@^2.0.0: ansi-colors "^3.0.0" uuid "^3.3.2" -webpack-merge@4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d" - integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g== +webpack-merge@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.1.1.tgz#c79f36b4ad39a597c3bb780f809b514d65d85d01" + integrity sha512-UhIkHAVqeG9EqFfYo7dRELrVfH6HYaOTYM7ssKCwfIIHYnWepGVOFp1E166GwgPGFqV6M68UgRiKOERjVOKIXA== dependencies: - lodash "^4.17.15" + clone-deep "^4.0.1" + wildcard "^2.0.0" webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3: version "1.4.3" @@ -15674,10 +15567,10 @@ webpack-virtual-modules@^0.2.0: dependencies: debug "^3.0.0" -webpack@4.43.0, webpack@^4.33.0, webpack@^4.38.0: - version "4.43.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.43.0.tgz#c48547b11d563224c561dad1172c8aa0b8a678e6" - integrity sha512-GW1LjnPipFW2Y78OOab8NJlCflB7EFskMih2AHdvjbpKMeDJqEgSx24cXXXiPS65+WSwVyxtDsJH6jGX2czy+g== +webpack@4.44.1, webpack@^4.33.0, webpack@^4.38.0: + version "4.44.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.1.tgz#17e69fff9f321b8f117d1fda714edfc0b939cc21" + integrity sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ== dependencies: "@webassemblyjs/ast" "1.9.0" "@webassemblyjs/helper-module-context" "1.9.0" @@ -15687,7 +15580,7 @@ webpack@4.43.0, webpack@^4.33.0, webpack@^4.38.0: ajv "^6.10.2" ajv-keywords "^3.4.1" chrome-trace-event "^1.0.2" - enhanced-resolve "^4.1.0" + enhanced-resolve "^4.3.0" eslint-scope "^4.0.3" json-parse-better-errors "^1.0.2" loader-runner "^2.4.0" @@ -15700,7 +15593,7 @@ webpack@4.43.0, webpack@^4.33.0, webpack@^4.38.0: schema-utils "^1.0.0" tapable "^1.1.3" terser-webpack-plugin "^1.4.3" - watchpack "^1.6.1" + watchpack "^1.7.4" webpack-sources "^1.4.1" websocket-driver@0.6.5: @@ -15737,9 +15630,9 @@ whatwg-encoding@^1.0.5: iconv-lite "0.4.24" whatwg-fetch@>=0.10.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" - integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q== + version "3.2.0" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.2.0.tgz#8e134f701f0a4ab5fda82626f113e2b647fd16dc" + integrity sha512-SdGPoQMMnzVYThUbSrEvqTlkvC1Ux27NehaJ/GUHBfNrh5Mjg+1/uRyFMwVnxO2MrikMWvWAqUGgQOfVU4hT7w== whatwg-mimetype@^2.3.0: version "2.3.0" @@ -15788,6 +15681,11 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" +wildcard@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" + integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== + word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" @@ -15865,9 +15763,9 @@ ws@^6.2.1: async-limiter "~1.0.0" ws@^7.2.3: - version "7.3.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.0.tgz#4b2f7f219b3d3737bc1a2fbf145d825b94d38ffd" - integrity sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w== + version "7.3.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.1.tgz#d0547bf67f7ce4f12a72dfe31262c68d7dc551c8" + integrity sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA== xdg-basedir@^4.0.0: version "4.0.0" @@ -15889,13 +15787,6 @@ xmlchars@^2.2.0: resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== -xregexp@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.3.0.tgz#7e92e73d9174a99a59743f67a4ce879a04b5ae50" - integrity sha512-7jXDIFXh5yJ/orPn4SXjuVrWWoi4Cr8jfV1eHv9CixKSbU+jY4mxfrBwAuDvupPNKpMUY+FeIqsVw/JLT9+B8g== - dependencies: - "@babel/runtime-corejs3" "^7.8.3" - xtend@^4.0.0, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" @@ -15934,7 +15825,15 @@ yargs-parser@13.1.2, yargs-parser@^13.1.2: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^18.1.1: +yargs-parser@^15.0.1: + version "15.0.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.1.tgz#54786af40b820dcb2fb8025b11b4d659d76323b3" + integrity sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^18.1.2: version "18.1.3" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== @@ -15942,16 +15841,18 @@ yargs-parser@^18.1.1: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-unparser@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" - integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== +yargs-unparser@1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.1.tgz#bd4b0ee05b4c94d058929c32cb09e3fce71d3c5f" + integrity sha512-qZV14lK9MWsGCmcr7u5oXGH0dbGqZAIxTDrWXZDo5zUr6b6iUmelNKO6x6R1dQT24AH3LgRxJpr8meWy2unolA== dependencies: + camelcase "^5.3.1" + decamelize "^1.2.0" flat "^4.1.0" - lodash "^4.17.15" - yargs "^13.3.0" + is-plain-obj "^1.1.0" + yargs "^14.2.3" -yargs@13.3.2, yargs@^13.3.0, yargs@^13.3.2: +yargs@13.3.2, yargs@^13.3.2: version "13.3.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== @@ -15967,10 +15868,27 @@ yargs@13.3.2, yargs@^13.3.0, yargs@^13.3.2: y18n "^4.0.0" yargs-parser "^13.1.2" -yargs@^15.0.1, yargs@^15.3.1: - version "15.3.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b" - integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA== +yargs@^14.2.3: + version "14.2.3" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.3.tgz#1a1c3edced1afb2a2fea33604bc6d1d8d688a414" + integrity sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg== + dependencies: + cliui "^5.0.0" + decamelize "^1.2.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^15.0.1" + +yargs@^15.0.1, yargs@^15.3.1, yargs@^15.4.1: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== dependencies: cliui "^6.0.0" decamelize "^1.2.0" @@ -15982,7 +15900,7 @@ yargs@^15.0.1, yargs@^15.3.1: string-width "^4.2.0" which-module "^2.0.0" y18n "^4.0.0" - yargs-parser "^18.1.1" + yargs-parser "^18.1.2" yarn-install@^1.0.0: version "1.0.0" @@ -16001,37 +15919,29 @@ yauzl@^2.10.0: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" -yup@0.29.1: - version "0.29.1" - resolved "https://registry.yarnpkg.com/yup/-/yup-0.29.1.tgz#35d25aab470a0c3950f66040ba0ff4b1b6efe0d9" - integrity sha512-U7mPIbgfQWI6M3hZCJdGFrr+U0laG28FxMAKIgNvgl7OtyYuUoc4uy9qCWYHZjh49b8T7Ug8NNDdiMIEytcXrQ== +yup@0.29.3: + version "0.29.3" + resolved "https://registry.yarnpkg.com/yup/-/yup-0.29.3.tgz#69a30fd3f1c19f5d9e31b1cf1c2b851ce8045fea" + integrity sha512-RNUGiZ/sQ37CkhzKFoedkeMfJM0vNQyaz+wRZJzxdKE7VfDeVKH8bb4rr7XhRLbHJz5hSjoDNwMEIaKhuMZ8gQ== dependencies: - "@babel/runtime" "^7.9.6" + "@babel/runtime" "^7.10.5" fn-name "~3.0.0" lodash "^4.17.15" lodash-es "^4.17.11" property-expr "^2.0.2" - synchronous-promise "^2.0.10" + synchronous-promise "^2.0.13" toposort "^2.0.2" -zen-observable-ts@^0.8.21: - version "0.8.21" - resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.21.tgz#85d0031fbbde1eba3cd07d3ba90da241215f421d" - integrity sha512-Yj3yXweRc8LdRMrCC8nIc4kkjWecPAUVh0TI0OUrWXx6aX790vLcDlWca6I4vsyCGH3LpWxq0dJRcMOFoVqmeg== - dependencies: - tslib "^1.9.3" - zen-observable "^0.8.0" - -zen-observable@^0.8.0: +zen-observable@^0.8.14: version "0.8.15" resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15" integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ== -zip-stream@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-3.0.1.tgz#cb8db9d324a76c09f9b76b31a12a48638b0b9708" - integrity sha512-r+JdDipt93ttDjsOVPU5zaq5bAyY+3H19bDrThkvuVxC0xMQzU1PJcS6D+KrP3u96gH9XLomcHPb+2skoDjulQ== +zip-stream@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-4.0.2.tgz#3a20f1bd7729c2b59fd4efa04df5eb7a5a217d2e" + integrity sha512-TGxB2g+1ur6MHkvM644DuZr8Uzyz0k0OYWtS3YlpfWBEmK4woaC2t3+pozEL3dBfIPmpgmClR5B2QRcMgGt22g== dependencies: archiver-utils "^2.1.0" - compress-commons "^3.0.0" + compress-commons "^4.0.0" readable-stream "^3.6.0" diff --git a/data/dashboards/process.json b/data/dashboards/process.json new file mode 100644 index 0000000000..366e453980 --- /dev/null +++ b/data/dashboards/process.json @@ -0,0 +1,274 @@ +{ + "id": "5e8f4298-b397-4f02-b710-382c7953d721", + "locked": false, + "offsetX": 1, + "offsetY": 0, + "zoom": 100, + "gridSize": 0, + "layers": [ + { + "id": "d5357380-94c7-492e-962e-fd73336fe104", + "type": "diagram-links", + "isSvg": true, + "transformed": true, + "models": { + "f54b1341-e2ac-43b6-8375-23c225f91978": { + "id": "f54b1341-e2ac-43b6-8375-23c225f91978", + "type": "anet", + "selected": false, + "source": "a28ebd7d-e511-4fb5-9a47-c8893385db37", + "sourcePort": "85ebab8a-7f54-4e9e-af34-f9ac6f4100dc", + "target": "df3f9b31-862a-491d-8476-bbabffd3e753", + "targetPort": "65276a57-e53e-400f-a8fe-3a9b299e49a7", + "points": [ + { + "id": "87ab6133-beb5-4c80-9449-9abc3cacf7e1", + "type": "point", + "x": 610, + "y": 271.71665954589844 + }, + { + "id": "dfc6564e-3939-47a5-b3af-aeb4223e57e5", + "type": "point", + "x": 782, + "y": 449.71665954589844 + } + ], + "labels": [], + "width": 3, + "color": "gray", + "curvyness": 50, + "selectedColor": "rgb(0,192,255)" + }, + "7ce21d4a-673e-4df1-a13b-3c7295b35b54": { + "id": "7ce21d4a-673e-4df1-a13b-3c7295b35b54", + "type": "anet", + "selected": false, + "source": "df3f9b31-862a-491d-8476-bbabffd3e753", + "sourcePort": "46fe31b2-f567-4285-8cea-d3dc2c1b8c5c", + "target": "0a256a8c-18ad-4f4b-bb16-bef8a7a30155", + "targetPort": "ef59038e-8ed2-4bc6-bcde-f0fce449601c", + "points": [ + { + "id": "5ebb0abd-365e-4194-ba21-7fe11e30c940", + "type": "point", + "x": 832, + "y": 449.71665954589844 + }, + { + "id": "f2f13d89-2778-4f41-ae40-538218a6618c", + "type": "point", + "x": 919, + "y": 269.71665954589844 + } + ], + "labels": [], + "width": 3, + "color": "gray", + "curvyness": 50, + "selectedColor": "rgb(0,192,255)" + }, + "014a3d2d-eb2c-48c5-b09b-9ed8fd315e55": { + "id": "014a3d2d-eb2c-48c5-b09b-9ed8fd315e55", + "type": "anet", + "selected": false, + "source": "0a256a8c-18ad-4f4b-bb16-bef8a7a30155", + "sourcePort": "29f90858-5443-41c5-93f9-b35c5a1c6cb5", + "target": "a28ebd7d-e511-4fb5-9a47-c8893385db37", + "targetPort": "1d368742-fe36-42f5-8668-7f2dfd692581", + "points": [ + { + "id": "463df0a6-53a1-4e7a-8f9c-3ffae4fb099b", + "type": "point", + "x": 944, + "y": 244.71665954589844 + }, + { + "id": "7e3b28e8-582f-4b3a-a045-b67dedcd1512", + "type": "point", + "x": 585, + "y": 246.71665954589844 + } + ], + "labels": [], + "width": 3, + "color": "gray", + "curvyness": 50, + "selectedColor": "rgb(0,192,255)" + } + } + }, + { + "id": "10c5a688-a891-429a-9c50-605fadc1c29e", + "type": "diagram-nodes", + "isSvg": false, + "transformed": true, + "models": { + "a28ebd7d-e511-4fb5-9a47-c8893385db37": { + "id": "a28ebd7d-e511-4fb5-9a47-c8893385db37", + "type": "anet", + "x": 560, + "y": 246.71665954589844, + "ports": [ + { + "id": "1d368742-fe36-42f5-8668-7f2dfd692581", + "type": "anet", + "x": 577, + "y": 238.71665954589844, + "name": "top", + "alignment": "top", + "parentNode": "a28ebd7d-e511-4fb5-9a47-c8893385db37", + "links": [ + "014a3d2d-eb2c-48c5-b09b-9ed8fd315e55" + ] + }, + { + "id": "935f4364-226e-4fff-80cf-ac9874bdfdc4", + "type": "anet", + "x": 552, + "y": 263.71665954589844, + "name": "left", + "alignment": "left", + "parentNode": "a28ebd7d-e511-4fb5-9a47-c8893385db37", + "links": [] + }, + { + "id": "03275d0c-3414-400f-a711-3504df2de6ad", + "type": "anet", + "x": 577, + "y": 288.71665954589844, + "name": "bottom", + "alignment": "bottom", + "parentNode": "a28ebd7d-e511-4fb5-9a47-c8893385db37", + "links": [] + }, + { + "id": "85ebab8a-7f54-4e9e-af34-f9ac6f4100dc", + "type": "anet", + "x": 602, + "y": 263.71665954589844, + "name": "right", + "alignment": "right", + "parentNode": "a28ebd7d-e511-4fb5-9a47-c8893385db37", + "links": [ + "f54b1341-e2ac-43b6-8375-23c225f91978" + ] + } + ], + "anetObjectUuid": "17ae023f-0869-4860-8592-3a9116afc780", + "anetObjectType": "Person" + }, + "df3f9b31-862a-491d-8476-bbabffd3e753": { + "id": "df3f9b31-862a-491d-8476-bbabffd3e753", + "type": "anet", + "selected": false, + "x": 782, + "y": 424.71665954589844, + "ports": [ + { + "id": "e3f62d9d-281a-4bb5-9d20-ca4141e3fa87", + "type": "anet", + "x": 799, + "y": 416.71665954589844, + "name": "top", + "alignment": "top", + "parentNode": "df3f9b31-862a-491d-8476-bbabffd3e753", + "links": [] + }, + { + "id": "65276a57-e53e-400f-a8fe-3a9b299e49a7", + "type": "anet", + "x": 774, + "y": 441.71665954589844, + "name": "left", + "alignment": "left", + "parentNode": "df3f9b31-862a-491d-8476-bbabffd3e753", + "links": [ + "f54b1341-e2ac-43b6-8375-23c225f91978" + ] + }, + { + "id": "a2211547-714f-48f7-b18f-e50baf058776", + "type": "anet", + "x": 799, + "y": 466.71665954589844, + "name": "bottom", + "alignment": "bottom", + "parentNode": "df3f9b31-862a-491d-8476-bbabffd3e753", + "links": [] + }, + { + "id": "46fe31b2-f567-4285-8cea-d3dc2c1b8c5c", + "type": "anet", + "x": 824, + "y": 441.71665954589844, + "name": "right", + "alignment": "right", + "parentNode": "df3f9b31-862a-491d-8476-bbabffd3e753", + "links": [ + "7ce21d4a-673e-4df1-a13b-3c7295b35b54" + ] + } + ], + "anetObjectUuid": "17ae023f-0869-4860-8592-3a9116afc780", + "anetObjectType": "Person" + }, + "0a256a8c-18ad-4f4b-bb16-bef8a7a30155": { + "id": "0a256a8c-18ad-4f4b-bb16-bef8a7a30155", + "type": "anet", + "selected": false, + "x": 919, + "y": 244.71665954589844, + "ports": [ + { + "id": "29f90858-5443-41c5-93f9-b35c5a1c6cb5", + "type": "anet", + "x": 936, + "y": 236.71665954589844, + "name": "top", + "alignment": "top", + "parentNode": "0a256a8c-18ad-4f4b-bb16-bef8a7a30155", + "links": [ + "014a3d2d-eb2c-48c5-b09b-9ed8fd315e55" + ] + }, + { + "id": "ef59038e-8ed2-4bc6-bcde-f0fce449601c", + "type": "anet", + "x": 911, + "y": 261.71665954589844, + "name": "left", + "alignment": "left", + "parentNode": "0a256a8c-18ad-4f4b-bb16-bef8a7a30155", + "links": [ + "7ce21d4a-673e-4df1-a13b-3c7295b35b54" + ] + }, + { + "id": "1361c974-fca0-45aa-afb5-77d90acf46be", + "type": "anet", + "x": 936, + "y": 286.71665954589844, + "name": "bottom", + "alignment": "bottom", + "parentNode": "0a256a8c-18ad-4f4b-bb16-bef8a7a30155", + "links": [] + }, + { + "id": "ad383950-ee03-4765-99fb-9dc52c021ebb", + "type": "anet", + "x": 961, + "y": 261.71665954589844, + "name": "right", + "alignment": "right", + "parentNode": "0a256a8c-18ad-4f4b-bb16-bef8a7a30155", + "links": [] + } + ], + "anetObjectUuid": "e8658d12-c28d-4e4e-9732-fc1f19a7c2ef", + "anetObjectType": "Organization" + } + } + } + ] +} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 622ab64a3c..bb8b2fc26b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/insertBaseData-mssql.sql b/insertBaseData-mssql.sql index 3c8ec27422..84d32d5502 100644 --- a/insertBaseData-mssql.sql +++ b/insertBaseData-mssql.sql @@ -319,12 +319,12 @@ INSERT INTO tasks (uuid, shortName, longName, category, createdAt, updatedAt, cu INSERT INTO tasks (uuid, shortName, longName, category, createdAt, updatedAt, customFieldRef1Uuid, customFields) VALUES - (N'953e0b0b-25e6-44b6-bc77-ef98251d046a', '1.2.A', 'Milestone the First in EF 1.2', 'Milestone', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'fe6b6b2f-d2a1-4ce1-9aa7-05361812a4d0', '{ "assessmentDefinition": "{ \"question1\": { \"type\": \"special_field\", \"widget\": \"likertScale\", \"label\": \"Test Question 1\", \"helpText\": \"Please provide assessment for something important\", \"levels\": [ { \"color\": \"red\", \"endValue\": 2, \"label\": \"test\" }, { \"color\": \"#FFBF00\", \"endValue\": 8, \"label\": \"mid\" }, { \"color\": \"green\", \"endValue\": 10, \"label\": \"high\" } ], \"aggregation\": { \"widget\": \"likertScale\" } }, \"question2\": { \"type\": \"number\", \"label\": \"Test Question 2\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Test Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }" }'), - (N'9d3da7f4-8266-47af-b518-995f587250c9', '1.2.B', 'Milestone the Second in EF 1.2', 'Milestone', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'fe6b6b2f-d2a1-4ce1-9aa7-05361812a4d0', '{ "assessmentDefinition": "{ \"frenchFlag\": { \"type\": \"special_field\", \"widget\": \"likertScale\", \"label\": \"French Flag assessment\", \"helpText\": \"Please tell us which is the best color in the French flag\", \"levels\": [ { \"color\": \"blue\", \"endValue\": 3.3, \"label\": \"blue\" }, { \"color\": \"white\", \"endValue\": 6.6, \"label\": \"white\" }, { \"color\": \"red\", \"endValue\": 10, \"label\": \"red\" } ] }, \"levels\": { \"type\": \"enumset\", \"label\": \"Achieved levels\", \"choices\": { \"lvl1\": { \"label\": \"Level 1\" }, \"lvl2\": { \"label\": \"Level 2\" }, \"lvl3\": { \"label\": \"Level 3\" } } }, \"description\": { \"type\": \"special_field\", \"label\": \"Detail levels\", \"widget\": \"richTextEditor\" } }" }'); + (N'953e0b0b-25e6-44b6-bc77-ef98251d046a', '1.2.A', 'Milestone the First in EF 1.2', 'Milestone', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'fe6b6b2f-d2a1-4ce1-9aa7-05361812a4d0', '{ "assessments":[{"questions":"{ \"question1\": { \"type\": \"special_field\", \"widget\": \"likertScale\", \"label\": \"Test Question 1\", \"helpText\": \"Please provide assessment for something important\", \"levels\": [ { \"color\": \"red\", \"endValue\": 2, \"label\": \"test\" }, { \"color\": \"#FFBF00\", \"endValue\": 8, \"label\": \"mid\" }, { \"color\": \"green\", \"endValue\": 10, \"label\": \"high\" } ], \"aggregation\": { \"widget\": \"likertScale\" } }, \"question2\": { \"type\": \"number\", \"label\": \"Test Question 2\", \"aggregation\": { \"widget\": \"numberAggregation\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Test Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\" } } }","relatedObjectType":"report"}] }'), + (N'9d3da7f4-8266-47af-b518-995f587250c9', '1.2.B', 'Milestone the Second in EF 1.2', 'Milestone', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'fe6b6b2f-d2a1-4ce1-9aa7-05361812a4d0', '{ "assessments":[{"questions":"{ \"frenchFlag\": { \"type\": \"special_field\", \"widget\": \"likertScale\", \"label\": \"French Flag assessment\", \"helpText\": \"Please tell us which is the best color in the French flag\", \"levels\": [ { \"color\": \"blue\", \"endValue\": 3.3, \"label\": \"blue\" }, { \"color\": \"white\", \"endValue\": 6.6, \"label\": \"white\" }, { \"color\": \"red\", \"endValue\": 10, \"label\": \"red\" } ] }, \"levels\": { \"type\": \"enumset\", \"label\": \"Achieved levels\", \"choices\": { \"lvl1\": { \"label\": \"Level 1\" }, \"lvl2\": { \"label\": \"Level 2\" }, \"lvl3\": { \"label\": \"Level 3\" } } }, \"description\": { \"type\": \"special_field\", \"label\": \"Detail levels\", \"widget\": \"richTextEditor\" } }","relatedObjectType":"report"}] }'), + (N'6bbb1be9-4655-48d7-83f2-bc474781544a', '1.2.C', 'Milestone the Third in EF 1.2', 'Milestone', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'fe6b6b2f-d2a1-4ce1-9aa7-05361812a4d0', '{ "assessments":[{"questions":"{ \"question1\": { \"type\": \"special_field\", \"widget\": \"likertScale\", \"label\": \"Monthly assessment Question 1\", \"helpText\": \"Please provide assessment for something important\", \"levels\": [ { \"color\": \"red\", \"endValue\": 2, \"label\": \"test\" }, { \"color\": \"#FFBF00\", \"endValue\": 8, \"label\": \"mid\" }, { \"color\": \"green\", \"endValue\": 10, \"label\": \"high\" } ], \"aggregation\": { \"widget\": \"likertScale\" } }, \"question2\": { \"type\": \"number\", \"label\": \"Monthly assessment Question 2\", \"aggregation\": { \"widget\": \"numberAggregation\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Monthly assessment Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\" } } }","recurrence":"monthly"},{"questions":"{ \"question1\": { \"type\": \"special_field\", \"widget\": \"likertScale\", \"label\": \"Weekly assessment Question 1\", \"helpText\": \"Please provide assessment for something important\", \"levels\": [ { \"color\": \"red\", \"endValue\": 2, \"label\": \"test\" }, { \"color\": \"#FFBF00\", \"endValue\": 8, \"label\": \"mid\" }, { \"color\": \"green\", \"endValue\": 10, \"label\": \"high\" } ], \"aggregation\": { \"widget\": \"likertScale\" } }, \"question2\": { \"type\": \"number\", \"label\": \"Weekly assessment Question 2\", \"aggregation\": { \"widget\": \"numberAggregation\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Weekly assessment Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\" } } }","recurrence":"weekly"},{"questions":"{ \"question1\": { \"type\": \"special_field\", \"widget\": \"likertScale\", \"label\": \"Instant assessment Question 1\", \"helpText\": \"Please provide assessment for something important\", \"levels\": [ { \"color\": \"red\", \"endValue\": 2, \"label\": \"test\" }, { \"color\": \"#FFBF00\", \"endValue\": 8, \"label\": \"mid\" }, { \"color\": \"green\", \"endValue\": 10, \"label\": \"high\" } ], \"aggregation\": { \"widget\": \"likertScale\" } }, \"question2\": { \"type\": \"number\", \"label\": \"Instant assessment Question 2\", \"aggregation\": { \"widget\": \"numberAggregation\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Instant assessment Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\" } } }","relatedObjectType":"report"}] }'); INSERT INTO tasks (uuid, shortName, longName, category, createdAt, updatedAt, customFieldRef1Uuid) VALUES - (N'6bbb1be9-4655-48d7-83f2-bc474781544a', '1.2.C', 'Milestone the Third in EF 1.2', 'Milestone', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'fe6b6b2f-d2a1-4ce1-9aa7-05361812a4d0'), (N'076793eb-9950-4ea6-bbd5-2d8b8827828c', '1.3.A', 'Getting a budget in place', 'Milestone', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'ac466253-1456-4fc8-9b14-a3643746e5a6'), (N'30bc5708-c12d-4a21-916c-5acd7f6f11da', '1.3.B', 'Tracking your expenses', 'Milestone', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'ac466253-1456-4fc8-9b14-a3643746e5a6'), (N'df920c99-10ea-44e8-940f-cb1d1cbd22da', '1.3.C', 'Knowing when you run out of money', 'Milestone', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, N'ac466253-1456-4fc8-9b14-a3643746e5a6'), @@ -927,7 +927,7 @@ INSERT INTO noteRelatedObjects (noteUuid, relatedObjectType, relatedObjectUuid) -- Add measurement assessments to tasks related to reports SET @noteUuid = lower(newid()); INSERT INTO notes (uuid, authorUuid, type, text, createdAt, updatedAt) - VALUES (@noteUuid, @authorUuid, 3, '{"question1":4.462819020045945,"question2":"1","question3":"22"}', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); + VALUES (@noteUuid, @authorUuid, 3, '{"__recurrence":"once","__relatedObjectType":"report","question1":4.462819020045945,"question2":"1","question3":"22"}', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); INSERT INTO noteRelatedObjects (noteUuid, relatedObjectType, relatedObjectUuid) SELECT @noteUuid, 'reports', r.uuid FROM reports r @@ -939,7 +939,7 @@ INSERT INTO noteRelatedObjects (noteUuid, relatedObjectType, relatedObjectUuid) SET @noteUuid = lower(newid()); INSERT INTO notes (uuid, authorUuid, type, text, createdAt, updatedAt) - VALUES (@noteUuid, @authorUuid, 3, '{"description":"

level 1

easily achieved

level 3

easily achieved

","frenchFlag":7.670554793177809,"levels":["lvl1","lvl3"]}', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); + VALUES (@noteUuid, @authorUuid, 3, '{"__recurrence":"once","__relatedObjectType":"report","description":"

level 1

easily achieved

level 3

easily achieved

","frenchFlag":7.670554793177809,"levels":["lvl1","lvl3"]}', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); INSERT INTO noteRelatedObjects (noteUuid, relatedObjectType, relatedObjectUuid) SELECT @noteUuid, 'reports', r.uuid FROM reports r @@ -949,15 +949,6 @@ INSERT INTO noteRelatedObjects (noteUuid, relatedObjectType, relatedObjectUuid) FROM tasks t WHERE t.shortName = '1.2.B'; --- Add a monthly assessment for task 1.2.B -SET @noteUuid = lower(newid()); -INSERT INTO notes (uuid, authorUuid, type, text, createdAt, updatedAt) - VALUES (@noteUuid, @authorUuid, 3, '{"issues":"

no issues this month

"}', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO noteRelatedObjects (noteUuid, relatedObjectType, relatedObjectUuid) - SELECT @noteUuid, 'tasks', t.uuid - FROM tasks t - WHERE t.shortName = '1.2.B'; - -- LEAVE THIS AS LAST STATEMENT -- Truncate all the dates (on reports etc.) to dates that could have been generated by -- Java (millisecond precision) rather than by the database itself (microsecond precision) diff --git a/src/main/java/mil/dds/anet/beans/AuthorizationGroup.java b/src/main/java/mil/dds/anet/beans/AuthorizationGroup.java index 9ca12c43ba..9939eb3df9 100644 --- a/src/main/java/mil/dds/anet/beans/AuthorizationGroup.java +++ b/src/main/java/mil/dds/anet/beans/AuthorizationGroup.java @@ -11,7 +11,7 @@ import mil.dds.anet.utils.Utils; import mil.dds.anet.views.AbstractAnetBean; -public class AuthorizationGroup extends AbstractAnetBean { +public class AuthorizationGroup extends AbstractAnetBean implements RelatableObject { public static enum AuthorizationGroupStatus { ACTIVE, INACTIVE diff --git a/src/main/java/mil/dds/anet/beans/Location.java b/src/main/java/mil/dds/anet/beans/Location.java index 151850721b..9b73248941 100644 --- a/src/main/java/mil/dds/anet/beans/Location.java +++ b/src/main/java/mil/dds/anet/beans/Location.java @@ -11,7 +11,7 @@ import mil.dds.anet.utils.Utils; import mil.dds.anet.views.AbstractAnetBean; -public class Location extends AbstractAnetBean { +public class Location extends AbstractAnetBean implements RelatableObject { /** Pseudo uuid to represent 'no location'. */ public static final String DUMMY_LOCATION_UUID = "-1"; diff --git a/src/main/java/mil/dds/anet/beans/NoteRelatedObject.java b/src/main/java/mil/dds/anet/beans/NoteRelatedObject.java index c67abe1e18..5c135d68fa 100644 --- a/src/main/java/mil/dds/anet/beans/NoteRelatedObject.java +++ b/src/main/java/mil/dds/anet/beans/NoteRelatedObject.java @@ -10,7 +10,9 @@ import java.util.Map; import java.util.concurrent.CompletableFuture; import javax.ws.rs.WebApplicationException; +import mil.dds.anet.utils.IdDataLoaderKey; import mil.dds.anet.views.AbstractAnetBean; +import mil.dds.anet.views.UuidFetcher; public class NoteRelatedObject extends AbstractAnetBean { @@ -23,6 +25,8 @@ public class NoteRelatedObject extends AbstractAnetBean { @GraphQLQuery @GraphQLInputField private String relatedObjectUuid; + // annotated below + private RelatableObject relatedObject; @Override @JsonIgnore @@ -103,4 +107,17 @@ public void setRelatedObjectUuid(String relatedObjectUuid) { this.relatedObjectUuid = relatedObjectUuid; } + @GraphQLQuery(name = "relatedObject") + public CompletableFuture loadRelatedObject( + @GraphQLRootContext Map context) { + if (relatedObject != null) { + return CompletableFuture.completedFuture(relatedObject); + } + return new UuidFetcher() + .load(context, IdDataLoaderKey.valueOfTableName(relatedObjectType), relatedObjectUuid) + .thenApply(o -> { + relatedObject = (RelatableObject) o; + return relatedObject; + }); + } } diff --git a/src/main/java/mil/dds/anet/beans/Organization.java b/src/main/java/mil/dds/anet/beans/Organization.java index d2a3c8bf5a..8b645c69c6 100644 --- a/src/main/java/mil/dds/anet/beans/Organization.java +++ b/src/main/java/mil/dds/anet/beans/Organization.java @@ -22,7 +22,7 @@ import mil.dds.anet.views.AbstractAnetBean; import mil.dds.anet.views.UuidFetcher; -public class Organization extends AbstractAnetBean { +public class Organization extends AbstractAnetBean implements RelatableObject { /** Pseudo uuid to represent all/top-level organization(s). */ public static final String DUMMY_ORG_UUID = "-1"; diff --git a/src/main/java/mil/dds/anet/beans/Person.java b/src/main/java/mil/dds/anet/beans/Person.java index 733086b66d..52eb7b8f81 100644 --- a/src/main/java/mil/dds/anet/beans/Person.java +++ b/src/main/java/mil/dds/anet/beans/Person.java @@ -21,7 +21,7 @@ import mil.dds.anet.views.AbstractCustomizableAnetBean; import mil.dds.anet.views.UuidFetcher; -public class Person extends AbstractCustomizableAnetBean implements Principal { +public class Person extends AbstractCustomizableAnetBean implements Principal, RelatableObject { public static enum PersonStatus { ACTIVE, INACTIVE, NEW_USER diff --git a/src/main/java/mil/dds/anet/beans/Position.java b/src/main/java/mil/dds/anet/beans/Position.java index 7a31867063..847eaf027a 100644 --- a/src/main/java/mil/dds/anet/beans/Position.java +++ b/src/main/java/mil/dds/anet/beans/Position.java @@ -14,7 +14,7 @@ import mil.dds.anet.views.AbstractAnetBean; import mil.dds.anet.views.UuidFetcher; -public class Position extends AbstractAnetBean { +public class Position extends AbstractAnetBean implements RelatableObject { public static enum PositionType { ADVISOR, PRINCIPAL, SUPER_USER, ADMINISTRATOR diff --git a/src/main/java/mil/dds/anet/beans/RelatableObject.java b/src/main/java/mil/dds/anet/beans/RelatableObject.java new file mode 100644 index 0000000000..22dcc4c688 --- /dev/null +++ b/src/main/java/mil/dds/anet/beans/RelatableObject.java @@ -0,0 +1,7 @@ +package mil.dds.anet.beans; + +import io.leangen.graphql.annotations.types.GraphQLUnion; + +@GraphQLUnion(name = "RelatableObject", possibleTypeAutoDiscovery = true) +public interface RelatableObject { +} diff --git a/src/main/java/mil/dds/anet/beans/Report.java b/src/main/java/mil/dds/anet/beans/Report.java index 50a5d10f4b..38115d0838 100644 --- a/src/main/java/mil/dds/anet/beans/Report.java +++ b/src/main/java/mil/dds/anet/beans/Report.java @@ -8,6 +8,7 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; @@ -23,7 +24,7 @@ import mil.dds.anet.views.AbstractCustomizableAnetBean; import mil.dds.anet.views.UuidFetcher; -public class Report extends AbstractCustomizableAnetBean { +public class Report extends AbstractCustomizableAnetBean implements RelatableObject { public enum ReportState { DRAFT, PENDING_APPROVAL, PUBLISHED, REJECTED, CANCELLED, // - @@ -32,6 +33,10 @@ public enum ReportState { APPROVED } + public enum EngagementStatus { + HAPPENED, FUTURE, CANCELLED + } + public enum Atmosphere { POSITIVE, NEUTRAL, NEGATIVE } @@ -786,6 +791,16 @@ public boolean isFutureEngagement() { return engagementDate != null && engagementDate.isAfter(Utils.endOfToday()); } + @GraphQLQuery(name = "engagementStatus") + public List loadEngagementStatus() { + LinkedList statuses = new LinkedList(); + if (state == ReportState.CANCELLED) { + statuses.add(EngagementStatus.CANCELLED); + } + statuses.add(isFutureEngagement() ? EngagementStatus.FUTURE : EngagementStatus.HAPPENED); + return statuses; + } + @Override public boolean equals(Object o) { if (!(o instanceof Report)) { diff --git a/src/main/java/mil/dds/anet/beans/Task.java b/src/main/java/mil/dds/anet/beans/Task.java index a9f8dfdf3a..f1952438dd 100644 --- a/src/main/java/mil/dds/anet/beans/Task.java +++ b/src/main/java/mil/dds/anet/beans/Task.java @@ -19,7 +19,7 @@ import mil.dds.anet.views.AbstractCustomizableAnetBean; import mil.dds.anet.views.UuidFetcher; -public class Task extends AbstractCustomizableAnetBean { +public class Task extends AbstractCustomizableAnetBean implements RelatableObject { /** Pseudo uuid to represent 'no task'. */ public static final String DUMMY_TASK_UUID = "-1"; diff --git a/src/main/java/mil/dds/anet/beans/search/ReportSearchQuery.java b/src/main/java/mil/dds/anet/beans/search/ReportSearchQuery.java index 71d4499e16..07b6cc0b73 100644 --- a/src/main/java/mil/dds/anet/beans/search/ReportSearchQuery.java +++ b/src/main/java/mil/dds/anet/beans/search/ReportSearchQuery.java @@ -8,15 +8,12 @@ import java.util.List; import java.util.Objects; import mil.dds.anet.beans.Report.Atmosphere; +import mil.dds.anet.beans.Report.EngagementStatus; import mil.dds.anet.beans.Report.ReportCancelledReason; import mil.dds.anet.beans.Report.ReportState; public class ReportSearchQuery extends AbstractSearchQuery { - public static enum EngagementStatus { - HAPPENED, FUTURE, CANCELLED - } - @GraphQLQuery @GraphQLInputField String authorUuid; diff --git a/src/main/java/mil/dds/anet/database/ReportDao.java b/src/main/java/mil/dds/anet/database/ReportDao.java index 6628d24a48..d9310cda07 100644 --- a/src/main/java/mil/dds/anet/database/ReportDao.java +++ b/src/main/java/mil/dds/anet/database/ReportDao.java @@ -66,9 +66,9 @@ public class ReportDao extends AnetBaseDao { // Must always retrieve these e.g. for ORDER BY or search post-processing public static final String[] minimalFields = {"uuid", "approvalStepUuid", - "advisorOrganizationUuid", "createdAt", "updatedAt", "engagementDate", "releasedAt"}; - public static final String[] additionalFields = {"state", "duration", "intent", "exsum", - "locationUuid", "principalOrganizationUuid", "authorUuid", "atmosphere", "cancelledReason", + "advisorOrganizationUuid", "createdAt", "updatedAt", "engagementDate", "releasedAt", "state"}; + public static final String[] additionalFields = {"duration", "intent", "exsum", "locationUuid", + "principalOrganizationUuid", "authorUuid", "atmosphere", "cancelledReason", "atmosphereDetails", "text", "keyOutcomes", "nextSteps", "customFields"}; public static final String[] allFields = ObjectArrays.concat(minimalFields, additionalFields, String.class); diff --git a/src/main/java/mil/dds/anet/database/TagDao.java b/src/main/java/mil/dds/anet/database/TagDao.java index 8459888ec3..be927feb96 100644 --- a/src/main/java/mil/dds/anet/database/TagDao.java +++ b/src/main/java/mil/dds/anet/database/TagDao.java @@ -7,7 +7,6 @@ import mil.dds.anet.beans.lists.AnetBeanList; import mil.dds.anet.beans.search.TagSearchQuery; import mil.dds.anet.database.mappers.TagMapper; -import mil.dds.anet.utils.DaoUtils; public class TagDao extends AnetBaseDao { @@ -36,19 +35,12 @@ public List getByIds(List uuids) { @Override public Tag insertInternal(Tag t) { - getDbHandle().createUpdate( - "/* tagInsert */ INSERT INTO tags (uuid, name, description, \"createdAt\", \"updatedAt\") " - + "VALUES (:uuid, :name, :description, :createdAt, :updatedAt)") - .bindBean(t).bind("createdAt", DaoUtils.asLocalDateTime(t.getCreatedAt())) - .bind("updatedAt", DaoUtils.asLocalDateTime(t.getUpdatedAt())).execute(); - return t; + throw new UnsupportedOperationException(); } @Override public int updateInternal(Tag t) { - return getDbHandle().createUpdate("/* updateTag */ UPDATE tags " - + "SET name = :name, description = :description, \"updatedAt\" = :updatedAt WHERE uuid = :uuid") - .bindBean(t).bind("updatedAt", DaoUtils.asLocalDateTime(t.getUpdatedAt())).execute(); + throw new UnsupportedOperationException(); } @Override diff --git a/src/main/java/mil/dds/anet/resources/GraphQlResource.java b/src/main/java/mil/dds/anet/resources/GraphQlResource.java index 665edef6ee..b18f063043 100644 --- a/src/main/java/mil/dds/anet/resources/GraphQlResource.java +++ b/src/main/java/mil/dds/anet/resources/GraphQlResource.java @@ -8,6 +8,7 @@ import graphql.GraphQL; import graphql.GraphQLError; import graphql.schema.GraphQLSchema; +import graphql.schema.visibility.NoIntrospectionGraphqlFieldVisibility; import io.dropwizard.auth.Auth; import io.leangen.graphql.GraphQLSchemaGenerator; import io.leangen.graphql.annotations.GraphQLInputField; @@ -41,6 +42,7 @@ import mil.dds.anet.graphql.outputtransformers.JsonToXlsxTransformer; import mil.dds.anet.graphql.outputtransformers.JsonToXmlTransformer; import mil.dds.anet.graphql.outputtransformers.XsltXmlTransformer; +import mil.dds.anet.utils.AuthUtils; import mil.dds.anet.utils.BatchingUtils; import org.apache.commons.lang3.StringUtils; import org.dataloader.DataLoaderRegistry; @@ -60,6 +62,7 @@ public class GraphQlResource { private final MetricRegistry metricRegistry; private GraphQLSchema graphqlSchema; + private GraphQLSchema graphqlSchemaWithoutIntrospection; private final List resourceTransformers = new LinkedList(); @@ -142,7 +145,7 @@ public ResponseBuilder apply(final Map json) { */ private void buildGraph() { final String topPackage = "mil.dds.anet"; - final GraphQLSchemaGenerator schemaBuilder = new GraphQLSchemaGenerator() + final GraphQLSchemaGenerator schemaGenerator = new GraphQLSchemaGenerator() // Load only our own packages: .withBasePackages(topPackage) // Resolve queries by @GraphQLQuery annotations only: @@ -163,10 +166,16 @@ protected boolean isAnnotated(AnnotatedElement element) { .withTypeMappers( (config, defaults) -> defaults.insertBefore(ScalarMapper.class, new DateTimeMapper())); for (final Object resource : resources) { - schemaBuilder.withOperationsFromSingleton(resource); + schemaGenerator.withOperationsFromSingleton(resource); } - - graphqlSchema = schemaBuilder.generate(); + graphqlSchema = schemaGenerator.generate(); + + graphqlSchemaWithoutIntrospection = + GraphQLSchema.newSchema(graphqlSchema) + .codeRegistry(graphqlSchema.getCodeRegistry() + .transform(builder -> builder.fieldVisibility( + NoIntrospectionGraphqlFieldVisibility.NO_INTROSPECTION_FIELD_VISIBILITY))) + .build(); } @POST @@ -233,7 +242,8 @@ private ExecutionResult dispatchRequest(Person user, String operationName, Strin ExecutionInput.newExecutionInput().operationName(operationName).query(query) .variables(variables).dataLoaderRegistry(dataLoaderRegistry).context(context).build(); - final GraphQL graphql = GraphQL.newGraphQL(graphqlSchema) + final GraphQL graphql = GraphQL + .newGraphQL(AuthUtils.isAdmin(user) ? graphqlSchema : graphqlSchemaWithoutIntrospection) // Prevent adding .instrumentation(new DataLoaderDispatcherInstrumentation()) // — use our own dispatcher instead .doNotAddDefaultInstrumentations().build(); diff --git a/src/main/java/mil/dds/anet/resources/NoteResource.java b/src/main/java/mil/dds/anet/resources/NoteResource.java index a56b75bd5c..f1e7d24881 100644 --- a/src/main/java/mil/dds/anet/resources/NoteResource.java +++ b/src/main/java/mil/dds/anet/resources/NoteResource.java @@ -1,23 +1,31 @@ package mil.dds.anet.resources; +import com.fasterxml.jackson.core.JsonProcessingException; import io.leangen.graphql.annotations.GraphQLArgument; import io.leangen.graphql.annotations.GraphQLMutation; import io.leangen.graphql.annotations.GraphQLRootContext; +import java.lang.invoke.MethodHandles; import java.util.List; import java.util.Map; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response.Status; import mil.dds.anet.AnetObjectEngine; import mil.dds.anet.beans.Note; +import mil.dds.anet.beans.Note.NoteType; import mil.dds.anet.beans.Person; import mil.dds.anet.database.NoteDao; import mil.dds.anet.utils.AnetAuditLogger; import mil.dds.anet.utils.AuthUtils; import mil.dds.anet.utils.DaoUtils; import mil.dds.anet.utils.Utils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class NoteResource { + private static final Logger logger = + LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + private final NoteDao dao; public NoteResource(AnetObjectEngine engine) { @@ -27,7 +35,7 @@ public NoteResource(AnetObjectEngine engine) { @GraphQLMutation(name = "createNote") public Note createNote(@GraphQLRootContext Map context, @GraphQLArgument(name = "note") Note n) { - checkText(n); + checkAndFixText(n); checkNoteRelatedObjects(n); final Person user = DaoUtils.getUserFromContext(context); n.setAuthorUuid(DaoUtils.getUuid(user)); @@ -52,7 +60,7 @@ public Note updateNote(@GraphQLRootContext Map context, @GraphQLArgument(name = "note") Note n) { final Person user = DaoUtils.getUserFromContext(context); checkPermission(n, user); - checkText(n); + checkAndFixText(n); checkNoteRelatedObjects(n); final int numRows = dao.update(n); if (numRows == 0) { @@ -77,7 +85,8 @@ public Integer deleteNote(@GraphQLRootContext Map context, throw new WebApplicationException("Couldn't process note delete", Status.NOT_FOUND); } AnetAuditLogger.log("Note {} deleted by {}", n, user); - // GraphQL mutations *have* to return something, so we return the number of deleted rows + // GraphQL mutations *have* to return something, so we return the number of + // deleted rows return numRows; } @@ -88,10 +97,24 @@ private void checkPermission(Note n, final Person user) { } } - private void checkText(Note n) { + private void checkAndFixText(Note n) { if (n.getText() == null || n.getText().trim().length() == 0) { throw new WebApplicationException("Note text must not be empty", Status.BAD_REQUEST); } + sanitizeText(n); + } + + private void sanitizeText(Note n) { + if (NoteType.FREE_TEXT.equals(n.getType())) { + n.setText(Utils.isEmptyHtml(n.getText()) ? null : Utils.sanitizeHtml(n.getText())); + } else { + try { + n.setText(Utils.sanitizeJson(n.getText())); + } catch (JsonProcessingException e) { + n.setText(null); + logger.error("Unable to process Json, payload discarded", e); + } + } } private void checkNoteRelatedObjects(Note n) { diff --git a/src/main/java/mil/dds/anet/resources/PersonResource.java b/src/main/java/mil/dds/anet/resources/PersonResource.java index 85ce244e56..5c014000b8 100644 --- a/src/main/java/mil/dds/anet/resources/PersonResource.java +++ b/src/main/java/mil/dds/anet/resources/PersonResource.java @@ -51,6 +51,7 @@ public Person getByUuid(@GraphQLArgument(name = "uuid") String uuid) { @GraphQLMutation(name = "createPerson") public Person createPerson(@GraphQLRootContext Map context, @GraphQLArgument(name = "person") Person p) { + p.checkAndFixCustomFields(); final Person user = DaoUtils.getUserFromContext(context); if (!canCreateOrUpdatePerson(user, p, true)) { throw new WebApplicationException("You do not have permissions to create this person", @@ -115,6 +116,7 @@ private boolean canCreateOrUpdatePerson(Person editor, Person subject, boolean c @GraphQLMutation(name = "updatePerson") public Integer updatePerson(@GraphQLRootContext Map context, @GraphQLArgument(name = "person") Person p) { + p.checkAndFixCustomFields(); final Person user = DaoUtils.getUserFromContext(context); final Person existing = dao.getByUuid(p.getUuid()); if (!canCreateOrUpdatePerson(user, existing, false)) { diff --git a/src/main/java/mil/dds/anet/resources/ReportResource.java b/src/main/java/mil/dds/anet/resources/ReportResource.java index b35bcc5c2f..6d82179b71 100644 --- a/src/main/java/mil/dds/anet/resources/ReportResource.java +++ b/src/main/java/mil/dds/anet/resources/ReportResource.java @@ -115,6 +115,7 @@ public Report getByUuid(@GraphQLArgument(name = "uuid") String uuid) { @GraphQLMutation(name = "createReport") public Report createReport(@GraphQLRootContext Map context, @GraphQLArgument(name = "report") Report r) { + r.checkAndFixCustomFields(); Person author = DaoUtils.getUserFromContext(context); if (r.getState() == null) { r.setState(ReportState.DRAFT); @@ -123,6 +124,11 @@ public Report createReport(@GraphQLRootContext Map context, r.setAuthorUuid(author.getUuid()); } + // FIXME: Eventually, also admins should no longer be allowed to create non-draft reports + if (r.getState() != ReportState.DRAFT && !AuthUtils.isAdmin(author)) { + throw new WebApplicationException("Can only create Draft reports", Status.BAD_REQUEST); + } + Person primaryAdvisor = findPrimaryAttendee(r, Role.ADVISOR); if (r.getAdvisorOrgUuid() == null && primaryAdvisor != null) { logger.debug("Setting advisor org for new report based on {}", primaryAdvisor); @@ -148,6 +154,7 @@ public Report createReport(@GraphQLRootContext Map context, public Report updateReport(@GraphQLRootContext Map context, @GraphQLArgument(name = "report") Report r, @GraphQLArgument(name = "sendEditEmail", defaultValue = "true") boolean sendEmail) { + r.checkAndFixCustomFields(); Person editor = DaoUtils.getUserFromContext(context); // perform all modifications to the report and its tasks and steps in a single transaction, // returning the original state of the report @@ -367,7 +374,6 @@ private void assertCanUpdateReport(Report report, Person editor) { @GraphQLMutation(name = "submitReport") public Report submitReport(@GraphQLRootContext Map context, @GraphQLArgument(name = "uuid") String uuid) { - // TODO: this needs to be done by either the Author, a Superuser for the AO, or an Administrator Person user = DaoUtils.getUserFromContext(context); final Report r = dao.getByUuid(uuid); if (r == null) { @@ -376,6 +382,19 @@ public Report submitReport(@GraphQLRootContext Map context, logger.debug("Attempting to submit report {}, which has advisor org {} and primary advisor {}", r, r.getAdvisorOrg(), r.getPrimaryAdvisor()); + if (!Objects.equals(r.getAuthorUuid(), user.getUuid()) + && !AuthUtils.isSuperUserForOrg(user, r.getAdvisorOrgUuid(), true) + && !AuthUtils.isAdmin(user)) { + throw new WebApplicationException( + "Cannot submit report unless you are the report's author, his/her super user or an admin", + Status.FORBIDDEN); + } + + if (r.getState() != ReportState.DRAFT && r.getState() != ReportState.REJECTED) { + throw new WebApplicationException( + "Cannot submit report unless it is either Draft or Rejected", Status.BAD_REQUEST); + } + if (r.getAdvisorOrgUuid() == null) { final ReportPerson advisor = r.loadPrimaryAdvisor(engine.getContext()).join(); if (advisor == null) { diff --git a/src/main/java/mil/dds/anet/resources/TagResource.java b/src/main/java/mil/dds/anet/resources/TagResource.java index 1cf9658a65..d7b4dced3a 100644 --- a/src/main/java/mil/dds/anet/resources/TagResource.java +++ b/src/main/java/mil/dds/anet/resources/TagResource.java @@ -1,21 +1,14 @@ package mil.dds.anet.resources; import io.leangen.graphql.annotations.GraphQLArgument; -import io.leangen.graphql.annotations.GraphQLMutation; import io.leangen.graphql.annotations.GraphQLQuery; -import io.leangen.graphql.annotations.GraphQLRootContext; -import java.util.Map; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response.Status; import mil.dds.anet.AnetObjectEngine; -import mil.dds.anet.beans.Person; import mil.dds.anet.beans.Tag; import mil.dds.anet.beans.lists.AnetBeanList; import mil.dds.anet.beans.search.TagSearchQuery; import mil.dds.anet.database.TagDao; -import mil.dds.anet.utils.AnetAuditLogger; -import mil.dds.anet.utils.AuthUtils; -import mil.dds.anet.utils.DaoUtils; public class TagResource { @@ -39,31 +32,4 @@ public AnetBeanList search(@GraphQLArgument(name = "query") TagSearchQuery return dao.search(query); } - @GraphQLMutation(name = "createTag") - public Tag createTag(@GraphQLRootContext Map context, - @GraphQLArgument(name = "tag") Tag t) { - final Person user = DaoUtils.getUserFromContext(context); - AuthUtils.assertSuperUser(user); - if (t.getName() == null || t.getName().trim().length() == 0) { - throw new WebApplicationException("Tag name must not be empty", Status.BAD_REQUEST); - } - t = dao.insert(t); - AnetAuditLogger.log("Tag {} created by {}", t, DaoUtils.getUserFromContext(context)); - return t; - } - - @GraphQLMutation(name = "updateTag") - public Integer updateTag(@GraphQLRootContext Map context, - @GraphQLArgument(name = "tag") Tag t) { - final Person user = DaoUtils.getUserFromContext(context); - AuthUtils.assertSuperUser(user); - final int numRows = dao.update(t); - if (numRows == 0) { - throw new WebApplicationException("Couldn't process tag update", Status.NOT_FOUND); - } - AnetAuditLogger.log("Tag {} updated by {}", t, DaoUtils.getUserFromContext(context)); - // GraphQL mutations *have* to return something, so we return the number of updated rows - return numRows; - } - } diff --git a/src/main/java/mil/dds/anet/resources/TaskResource.java b/src/main/java/mil/dds/anet/resources/TaskResource.java index ab2864c45e..e3c38f9343 100644 --- a/src/main/java/mil/dds/anet/resources/TaskResource.java +++ b/src/main/java/mil/dds/anet/resources/TaskResource.java @@ -52,6 +52,7 @@ public Task getByUuid(@GraphQLArgument(name = "uuid") String uuid) { @GraphQLMutation(name = "createTask") public Task createTask(@GraphQLRootContext Map context, @GraphQLArgument(name = "task") Task t) { + t.checkAndFixCustomFields(); final Person user = DaoUtils.getUserFromContext(context); AuthUtils.assertAdministrator(user); final Task created; @@ -83,6 +84,7 @@ public Task createTask(@GraphQLRootContext Map context, @GraphQLMutation(name = "updateTask") public Integer updateTask(@GraphQLRootContext Map context, @GraphQLArgument(name = "task") Task t) { + t.checkAndFixCustomFields(); final Person user = DaoUtils.getUserFromContext(context); final List existingResponsiblePositions = dao.getResponsiblePositionsForTask(engine.getContext(), DaoUtils.getUuid(t)).join(); diff --git a/src/main/java/mil/dds/anet/search/AbstractAuthorizationGroupSearcher.java b/src/main/java/mil/dds/anet/search/AbstractAuthorizationGroupSearcher.java index f70a9028b1..907a515a9e 100644 --- a/src/main/java/mil/dds/anet/search/AbstractAuthorizationGroupSearcher.java +++ b/src/main/java/mil/dds/anet/search/AbstractAuthorizationGroupSearcher.java @@ -30,7 +30,7 @@ protected void buildQuery(AuthorizationGroupSearchQuery query) { qb.addTotalCount(); qb.addFromClause("\"authorizationGroups\""); - if (query.isTextPresent()) { + if (hasTextQuery(query)) { addTextQuery(query); } @@ -58,8 +58,6 @@ protected void buildQuery(AuthorizationGroupSearchQuery query) { addOrderByClauses(qb, query); } - protected abstract void addTextQuery(AuthorizationGroupSearchQuery query); - protected void addOrderByClauses(AbstractSearchQueryBuilder qb, AuthorizationGroupSearchQuery query) { switch (query.getSortBy()) { diff --git a/src/main/java/mil/dds/anet/search/AbstractLocationSearcher.java b/src/main/java/mil/dds/anet/search/AbstractLocationSearcher.java index 67c25c95ba..ce7b193c86 100644 --- a/src/main/java/mil/dds/anet/search/AbstractLocationSearcher.java +++ b/src/main/java/mil/dds/anet/search/AbstractLocationSearcher.java @@ -28,7 +28,7 @@ protected void buildQuery(LocationSearchQuery query) { qb.addTotalCount(); qb.addFromClause("locations"); - if (query.isTextPresent()) { + if (hasTextQuery(query)) { addTextQuery(query); } @@ -43,8 +43,6 @@ protected void buildQuery(LocationSearchQuery query) { addOrderByClauses(qb, query); } - protected abstract void addTextQuery(LocationSearchQuery query); - protected void addOrderByClauses(AbstractSearchQueryBuilder qb, LocationSearchQuery query) { switch (query.getSortBy()) { case CREATED_AT: diff --git a/src/main/java/mil/dds/anet/search/AbstractOrganizationSearcher.java b/src/main/java/mil/dds/anet/search/AbstractOrganizationSearcher.java index 15e196ac24..6eac4cc5cc 100644 --- a/src/main/java/mil/dds/anet/search/AbstractOrganizationSearcher.java +++ b/src/main/java/mil/dds/anet/search/AbstractOrganizationSearcher.java @@ -31,7 +31,7 @@ protected void buildQuery(OrganizationSearchQuery query) { qb.addTotalCount(); qb.addFromClause("organizations"); - if (query.isTextPresent()) { + if (hasTextQuery(query)) { addTextQuery(query); } @@ -57,8 +57,6 @@ protected void buildQuery(OrganizationSearchQuery query) { addOrderByClauses(qb, query); } - protected abstract void addTextQuery(OrganizationSearchQuery query); - @SuppressWarnings("unchecked") protected void addBatchClause(OrganizationSearchQuery query) { qb.addBatchClause( diff --git a/src/main/java/mil/dds/anet/search/AbstractPersonSearcher.java b/src/main/java/mil/dds/anet/search/AbstractPersonSearcher.java index d38e09078e..35431a9dc2 100644 --- a/src/main/java/mil/dds/anet/search/AbstractPersonSearcher.java +++ b/src/main/java/mil/dds/anet/search/AbstractPersonSearcher.java @@ -53,7 +53,7 @@ protected void buildQuery(Set subFields, PersonSearchQuery query) { qb.addFromClause("LEFT JOIN positions ON people.uuid = positions.\"currentPersonUuid\""); } - if (query.isTextPresent()) { + if (hasTextQuery(query)) { addTextQuery(query); } @@ -102,8 +102,6 @@ protected void buildQuery(Set subFields, PersonSearchQuery query) { addOrderByClauses(qb, query); } - protected abstract void addTextQuery(PersonSearchQuery query); - protected void addOrderByClauses(AbstractSearchQueryBuilder qb, PersonSearchQuery query) { switch (query.getSortBy()) { case CREATED_AT: diff --git a/src/main/java/mil/dds/anet/search/AbstractPositionSearcher.java b/src/main/java/mil/dds/anet/search/AbstractPositionSearcher.java index 3a4fe8d375..297eaf2cd9 100644 --- a/src/main/java/mil/dds/anet/search/AbstractPositionSearcher.java +++ b/src/main/java/mil/dds/anet/search/AbstractPositionSearcher.java @@ -34,7 +34,7 @@ protected void buildQuery(PositionSearchQuery query) { qb.addFromClause("LEFT JOIN people ON positions.\"currentPersonUuid\" = people.uuid"); } - if (query.isTextPresent()) { + if (hasTextQuery(query)) { addTextQuery(query); } @@ -78,8 +78,6 @@ protected void buildQuery(PositionSearchQuery query) { addOrderByClauses(qb, query); } - protected abstract void addTextQuery(PositionSearchQuery query); - @SuppressWarnings("unchecked") protected void addBatchClause(PositionSearchQuery query) { qb.addBatchClause((AbstractBatchParams) query.getBatchParams()); diff --git a/src/main/java/mil/dds/anet/search/AbstractReportSearcher.java b/src/main/java/mil/dds/anet/search/AbstractReportSearcher.java index 94cc087b03..0a0d81a02e 100644 --- a/src/main/java/mil/dds/anet/search/AbstractReportSearcher.java +++ b/src/main/java/mil/dds/anet/search/AbstractReportSearcher.java @@ -16,6 +16,7 @@ import mil.dds.anet.beans.Location; import mil.dds.anet.beans.Organization; import mil.dds.anet.beans.Report; +import mil.dds.anet.beans.Report.EngagementStatus; import mil.dds.anet.beans.Report.ReportCancelledReason; import mil.dds.anet.beans.Report.ReportState; import mil.dds.anet.beans.Task; @@ -24,7 +25,6 @@ import mil.dds.anet.beans.search.ISearchQuery.RecurseStrategy; import mil.dds.anet.beans.search.ISearchQuery.SortOrder; import mil.dds.anet.beans.search.ReportSearchQuery; -import mil.dds.anet.beans.search.ReportSearchQuery.EngagementStatus; import mil.dds.anet.database.PositionDao; import mil.dds.anet.database.ReportDao; import mil.dds.anet.search.AbstractSearchQueryBuilder.Comparison; @@ -87,7 +87,7 @@ protected String getTableFields(Set subFields) { protected void buildQuery(Set subFields, ReportSearchQuery query) { // Base select and from clauses are added by child classes - if (query.isTextPresent()) { + if (hasTextQuery(query)) { addTextQuery(query); } @@ -162,7 +162,6 @@ protected void buildQuery(Set subFields, ReportSearchQuery query) { } if (query.getPendingApprovalOf() != null) { - qb.addWhereClause("reports.\"authorUuid\" != :approverUuid"); qb.addWhereClause("reports.\"approvalStepUuid\" IN" + " (SELECT \"approvalStepUuid\" FROM approvers WHERE \"positionUuid\" IN" + " (SELECT uuid FROM positions WHERE \"currentPersonUuid\" = :approverUuid))"); @@ -275,8 +274,6 @@ protected void buildQuery(Set subFields, ReportSearchQuery query) { addOrderByClauses(qb, query); } - protected abstract void addTextQuery(ReportSearchQuery query); - protected abstract void addBatchClause(ReportSearchQuery query); @SuppressWarnings("unchecked") diff --git a/src/main/java/mil/dds/anet/search/AbstractSearcher.java b/src/main/java/mil/dds/anet/search/AbstractSearcher.java index 0488d7dc29..bd6beb31c5 100644 --- a/src/main/java/mil/dds/anet/search/AbstractSearcher.java +++ b/src/main/java/mil/dds/anet/search/AbstractSearcher.java @@ -50,6 +50,16 @@ protected String getTableFields(String tableName, Set allFields, return DaoUtils.buildFieldAliases(tableName, fieldsArray, true); } + protected boolean hasTextQuery(T query) { + if (!query.isTextPresent()) { + return false; + } + final String text = query.getText(); + return qb.getContainsQuery(text) != null && qb.getFullTextQuery(text) != null; + } + + protected abstract void addTextQuery(T query); + protected void addFullTextSearch(String tableName, String text, boolean isSortByPresent) { final List whereClauses = new ArrayList<>(); final List selectClauses = new ArrayList<>(); @@ -64,7 +74,7 @@ protected void addFullTextSearch(String tableName, String text, boolean isSortBy final String materializedView = String.format("\"mv_fts_%1$s\"", tableName); final String fullTextColumn = String.format("%1$s.full_text", materializedView); - final String tsQuery = "websearch_to_tsquery('anet', :fullTextQuery)"; + final String tsQuery = getTsQuery(); whereClauses.add(String.format("SELECT uuid FROM %1$s WHERE %2$s @@ %3$s", materializedView, fullTextColumn, tsQuery)); qb.addWhereClause(String.format("\"%1$s\".uuid IN (%2$s)", tableName, @@ -80,6 +90,13 @@ protected void addFullTextSearch(String tableName, String text, boolean isSortBy } } + private String getTsQuery() { + final String tsQueryTpl = "to_tsquery('%1$s', :fullTextQuery)"; + final String tsQueryAnet = String.format(tsQueryTpl, "anet"); + final String tsQuerySimple = String.format(tsQueryTpl, "simple"); + return String.format("(%1$s || %2$s)", tsQueryAnet, tsQuerySimple); + } + protected List getOrderBy(SortOrder sortOrder, String table, String... columns) { final List clauses = new ArrayList<>(); for (final String column : columns) { diff --git a/src/main/java/mil/dds/anet/search/AbstractTagSearcher.java b/src/main/java/mil/dds/anet/search/AbstractTagSearcher.java index 84d98739ef..c9b69569ce 100644 --- a/src/main/java/mil/dds/anet/search/AbstractTagSearcher.java +++ b/src/main/java/mil/dds/anet/search/AbstractTagSearcher.java @@ -27,15 +27,13 @@ protected void buildQuery(TagSearchQuery query) { qb.addTotalCount(); qb.addFromClause("tags"); - if (query.isTextPresent()) { + if (hasTextQuery(query)) { addTextQuery(query); } addOrderByClauses(qb, query); } - protected abstract void addTextQuery(TagSearchQuery query); - protected void addOrderByClauses(AbstractSearchQueryBuilder qb, TagSearchQuery query) { switch (query.getSortBy()) { case CREATED_AT: diff --git a/src/main/java/mil/dds/anet/search/AbstractTaskSearcher.java b/src/main/java/mil/dds/anet/search/AbstractTaskSearcher.java index 28e71c8eac..91191ba8c0 100644 --- a/src/main/java/mil/dds/anet/search/AbstractTaskSearcher.java +++ b/src/main/java/mil/dds/anet/search/AbstractTaskSearcher.java @@ -31,7 +31,7 @@ protected void buildQuery(TaskSearchQuery query) { qb.addTotalCount(); qb.addFromClause("tasks"); - if (query.isTextPresent()) { + if (hasTextQuery(query)) { addTextQuery(query); } @@ -79,8 +79,6 @@ protected void buildQuery(TaskSearchQuery query) { addOrderByClauses(qb, query); } - protected abstract void addTextQuery(TaskSearchQuery query); - @SuppressWarnings("unchecked") protected void addBatchClause(TaskSearchQuery query) { qb.addBatchClause((AbstractBatchParams) query.getBatchParams()); diff --git a/src/main/java/mil/dds/anet/search/mssql/MssqlAuthorizationGroupSearcher.java b/src/main/java/mil/dds/anet/search/mssql/MssqlAuthorizationGroupSearcher.java index bfce6e5a97..b07cc9be91 100644 --- a/src/main/java/mil/dds/anet/search/mssql/MssqlAuthorizationGroupSearcher.java +++ b/src/main/java/mil/dds/anet/search/mssql/MssqlAuthorizationGroupSearcher.java @@ -38,7 +38,7 @@ protected void addTextQuery(AuthorizationGroupSearchQuery query) { @Override protected void addOrderByClauses(AbstractSearchQueryBuilder qb, AuthorizationGroupSearchQuery query) { - if (query.isTextPresent() && !query.isSortByPresent()) { + if (hasTextQuery(query) && !query.isSortByPresent()) { // We're doing a full-text search without an explicit sort order, // so sort first on the search pseudo-rank. qb.addAllOrderByClauses(getOrderBy(SortOrder.DESC, null, "search_rank")); diff --git a/src/main/java/mil/dds/anet/search/mssql/MssqlLocationSearcher.java b/src/main/java/mil/dds/anet/search/mssql/MssqlLocationSearcher.java index bbd0f2a702..4fade5756a 100644 --- a/src/main/java/mil/dds/anet/search/mssql/MssqlLocationSearcher.java +++ b/src/main/java/mil/dds/anet/search/mssql/MssqlLocationSearcher.java @@ -28,7 +28,7 @@ protected void addTextQuery(LocationSearchQuery query) { @Override protected void addOrderByClauses(AbstractSearchQueryBuilder qb, LocationSearchQuery query) { - if (query.isTextPresent() && !query.isSortByPresent()) { + if (hasTextQuery(query) && !query.isSortByPresent()) { // We're doing a full-text search without an explicit sort order, // so sort first on the search pseudo-rank. qb.addAllOrderByClauses(getOrderBy(SortOrder.DESC, null, "search_rank")); diff --git a/src/main/java/mil/dds/anet/search/mssql/MssqlOrganizationSearcher.java b/src/main/java/mil/dds/anet/search/mssql/MssqlOrganizationSearcher.java index 5e01554bda..f3d6124d24 100644 --- a/src/main/java/mil/dds/anet/search/mssql/MssqlOrganizationSearcher.java +++ b/src/main/java/mil/dds/anet/search/mssql/MssqlOrganizationSearcher.java @@ -38,7 +38,7 @@ protected void addTextQuery(OrganizationSearchQuery query) { @Override protected void addOrderByClauses(AbstractSearchQueryBuilder qb, OrganizationSearchQuery query) { - if (query.isTextPresent() && !query.isSortByPresent()) { + if (hasTextQuery(query) && !query.isSortByPresent()) { // We're doing a full-text search without an explicit sort order, // so sort first on the search pseudo-rank. qb.addAllOrderByClauses(getOrderBy(SortOrder.DESC, null, "search_rank")); diff --git a/src/main/java/mil/dds/anet/search/mssql/MssqlPersonSearcher.java b/src/main/java/mil/dds/anet/search/mssql/MssqlPersonSearcher.java index 333ece27c9..8476681c1b 100644 --- a/src/main/java/mil/dds/anet/search/mssql/MssqlPersonSearcher.java +++ b/src/main/java/mil/dds/anet/search/mssql/MssqlPersonSearcher.java @@ -50,7 +50,7 @@ protected void addTextQuery(PersonSearchQuery query) { @Override protected void addOrderByClauses(AbstractSearchQueryBuilder qb, PersonSearchQuery query) { - if (query.isTextPresent() && !query.isSortByPresent()) { + if (hasTextQuery(query) && !query.isSortByPresent()) { // We're doing a full-text search without an explicit sort order, // so sort first on the search pseudo-rank. qb.addAllOrderByClauses(getOrderBy(SortOrder.DESC, null, "search_rank")); diff --git a/src/main/java/mil/dds/anet/search/mssql/MssqlPositionSearcher.java b/src/main/java/mil/dds/anet/search/mssql/MssqlPositionSearcher.java index e23a2e895f..3af2a449eb 100644 --- a/src/main/java/mil/dds/anet/search/mssql/MssqlPositionSearcher.java +++ b/src/main/java/mil/dds/anet/search/mssql/MssqlPositionSearcher.java @@ -41,7 +41,7 @@ protected void addTextQuery(PositionSearchQuery query) { @Override protected void addOrderByClauses(AbstractSearchQueryBuilder qb, PositionSearchQuery query) { - if (query.isTextPresent() && !query.isSortByPresent()) { + if (hasTextQuery(query) && !query.isSortByPresent()) { // We're doing a full-text search without an explicit sort order, // so sort first on the search pseudo-rank. qb.addAllOrderByClauses(getOrderBy(SortOrder.DESC, null, "search_rank")); diff --git a/src/main/java/mil/dds/anet/search/mssql/MssqlReportSearcher.java b/src/main/java/mil/dds/anet/search/mssql/MssqlReportSearcher.java index 45fb339054..ef1332c019 100644 --- a/src/main/java/mil/dds/anet/search/mssql/MssqlReportSearcher.java +++ b/src/main/java/mil/dds/anet/search/mssql/MssqlReportSearcher.java @@ -106,7 +106,7 @@ protected void addPrincipalOrgUuidQuery(ReportSearchQuery query) { protected void addOrderByClauses(AbstractSearchQueryBuilder qb, ReportSearchQuery query) { if (qb == outerQb) { // ordering must be on the outer query - if (query.isTextPresent() && !query.isSortByPresent()) { + if (hasTextQuery(query) && !query.isSortByPresent()) { // We're doing a full-text search without an explicit sort order, // so sort first on the search pseudo-rank. qb.addAllOrderByClauses(getOrderBy(SortOrder.DESC, null, "search_rank")); diff --git a/src/main/java/mil/dds/anet/search/mssql/MssqlSearchQueryBuilder.java b/src/main/java/mil/dds/anet/search/mssql/MssqlSearchQueryBuilder.java index a566b96fec..1ad690570f 100644 --- a/src/main/java/mil/dds/anet/search/mssql/MssqlSearchQueryBuilder.java +++ b/src/main/java/mil/dds/anet/search/mssql/MssqlSearchQueryBuilder.java @@ -5,6 +5,7 @@ import mil.dds.anet.beans.lists.AnetBeanList; import mil.dds.anet.beans.search.AbstractSearchQuery; import mil.dds.anet.search.AbstractSearchQueryBuilder; +import mil.dds.anet.utils.Utils; import mil.dds.anet.views.AbstractAnetBean; import org.jdbi.v3.core.Handle; import org.jdbi.v3.core.mapper.RowMapper; @@ -23,7 +24,13 @@ public MssqlSearchQueryBuilder(String queryName) { */ @Override public String getContainsQuery(String text) { + if (Utils.isEmptyOrNull(text)) { + return null; + } String cleanText = stripWildcards(text); + if (Utils.isEmptyOrNull(cleanText)) { + return null; + } if (text.endsWith("*")) { cleanText = "\"" + cleanText + "*\""; } else { @@ -34,6 +41,9 @@ public String getContainsQuery(String text) { @Override public String getFullTextQuery(String text) { + if (Utils.isEmptyOrNull(text)) { + return null; + } return text; } diff --git a/src/main/java/mil/dds/anet/search/mssql/MssqlTagSearcher.java b/src/main/java/mil/dds/anet/search/mssql/MssqlTagSearcher.java index 2904a7b54f..6fb4e9df6c 100644 --- a/src/main/java/mil/dds/anet/search/mssql/MssqlTagSearcher.java +++ b/src/main/java/mil/dds/anet/search/mssql/MssqlTagSearcher.java @@ -33,7 +33,7 @@ protected void addTextQuery(TagSearchQuery query) { @Override protected void addOrderByClauses(AbstractSearchQueryBuilder qb, TagSearchQuery query) { - if (query.isTextPresent() && !query.isSortByPresent()) { + if (hasTextQuery(query) && !query.isSortByPresent()) { // We're doing a full-text search without an explicit sort order, // so sort first on the search pseudo-rank. qb.addAllOrderByClauses(getOrderBy(SortOrder.DESC, null, "search_rank")); diff --git a/src/main/java/mil/dds/anet/search/mssql/MssqlTaskSearcher.java b/src/main/java/mil/dds/anet/search/mssql/MssqlTaskSearcher.java index 376e6567df..35eae8c2c9 100644 --- a/src/main/java/mil/dds/anet/search/mssql/MssqlTaskSearcher.java +++ b/src/main/java/mil/dds/anet/search/mssql/MssqlTaskSearcher.java @@ -31,7 +31,7 @@ protected void addTextQuery(TaskSearchQuery query) { @Override protected void addOrderByClauses(AbstractSearchQueryBuilder qb, TaskSearchQuery query) { - if (query.isTextPresent() && !query.isSortByPresent()) { + if (hasTextQuery(query) && !query.isSortByPresent()) { // We're doing a full-text search without an explicit sort order, // so sort first on the search pseudo-rank. qb.addAllOrderByClauses(getOrderBy(SortOrder.DESC, null, "search_rank")); diff --git a/src/main/java/mil/dds/anet/search/pg/PostgresqlAuthorizationGroupSearcher.java b/src/main/java/mil/dds/anet/search/pg/PostgresqlAuthorizationGroupSearcher.java index 165369c51a..8abb7ba789 100644 --- a/src/main/java/mil/dds/anet/search/pg/PostgresqlAuthorizationGroupSearcher.java +++ b/src/main/java/mil/dds/anet/search/pg/PostgresqlAuthorizationGroupSearcher.java @@ -21,7 +21,7 @@ protected void addTextQuery(AuthorizationGroupSearchQuery query) { @Override protected void addOrderByClauses(AbstractSearchQueryBuilder qb, AuthorizationGroupSearchQuery query) { - if (query.isTextPresent() && !query.isSortByPresent()) { + if (hasTextQuery(query) && !query.isSortByPresent()) { // We're doing a full-text search without an explicit sort order, // so sort first on the search pseudo-rank. qb.addAllOrderByClauses(getOrderBy(SortOrder.DESC, null, "search_rank")); diff --git a/src/main/java/mil/dds/anet/search/pg/PostgresqlLocationSearcher.java b/src/main/java/mil/dds/anet/search/pg/PostgresqlLocationSearcher.java index 99b33f14c2..e2e317bb4d 100644 --- a/src/main/java/mil/dds/anet/search/pg/PostgresqlLocationSearcher.java +++ b/src/main/java/mil/dds/anet/search/pg/PostgresqlLocationSearcher.java @@ -20,7 +20,7 @@ protected void addTextQuery(LocationSearchQuery query) { @Override protected void addOrderByClauses(AbstractSearchQueryBuilder qb, LocationSearchQuery query) { - if (query.isTextPresent() && !query.isSortByPresent()) { + if (hasTextQuery(query) && !query.isSortByPresent()) { // We're doing a full-text search without an explicit sort order, // so sort first on the search pseudo-rank. qb.addAllOrderByClauses(getOrderBy(SortOrder.DESC, null, "search_rank")); diff --git a/src/main/java/mil/dds/anet/search/pg/PostgresqlOrganizationSearcher.java b/src/main/java/mil/dds/anet/search/pg/PostgresqlOrganizationSearcher.java index a4238ac80a..2f760bc641 100644 --- a/src/main/java/mil/dds/anet/search/pg/PostgresqlOrganizationSearcher.java +++ b/src/main/java/mil/dds/anet/search/pg/PostgresqlOrganizationSearcher.java @@ -21,7 +21,7 @@ protected void addTextQuery(OrganizationSearchQuery query) { @Override protected void addOrderByClauses(AbstractSearchQueryBuilder qb, OrganizationSearchQuery query) { - if (query.isTextPresent() && !query.isSortByPresent()) { + if (hasTextQuery(query) && !query.isSortByPresent()) { // We're doing a full-text search without an explicit sort order, // so sort first on the search pseudo-rank. qb.addAllOrderByClauses(getOrderBy(SortOrder.DESC, null, "search_rank")); diff --git a/src/main/java/mil/dds/anet/search/pg/PostgresqlPersonSearcher.java b/src/main/java/mil/dds/anet/search/pg/PostgresqlPersonSearcher.java index 8a7636355b..1e13bb731e 100644 --- a/src/main/java/mil/dds/anet/search/pg/PostgresqlPersonSearcher.java +++ b/src/main/java/mil/dds/anet/search/pg/PostgresqlPersonSearcher.java @@ -19,7 +19,7 @@ protected void addTextQuery(PersonSearchQuery query) { @Override protected void addOrderByClauses(AbstractSearchQueryBuilder qb, PersonSearchQuery query) { - if (query.isTextPresent() && !query.isSortByPresent()) { + if (hasTextQuery(query) && !query.isSortByPresent()) { // We're doing a full-text search without an explicit sort order, // so sort first on the search pseudo-rank. qb.addAllOrderByClauses(getOrderBy(SortOrder.DESC, null, "search_rank")); diff --git a/src/main/java/mil/dds/anet/search/pg/PostgresqlPositionSearcher.java b/src/main/java/mil/dds/anet/search/pg/PostgresqlPositionSearcher.java index c90cc635f0..ac74ee9dfb 100644 --- a/src/main/java/mil/dds/anet/search/pg/PostgresqlPositionSearcher.java +++ b/src/main/java/mil/dds/anet/search/pg/PostgresqlPositionSearcher.java @@ -20,7 +20,7 @@ protected void addTextQuery(PositionSearchQuery query) { @Override protected void addOrderByClauses(AbstractSearchQueryBuilder qb, PositionSearchQuery query) { - if (query.isTextPresent() && !query.isSortByPresent()) { + if (hasTextQuery(query) && !query.isSortByPresent()) { // We're doing a full-text search without an explicit sort order, // so sort first on the search pseudo-rank. qb.addAllOrderByClauses(getOrderBy(SortOrder.DESC, null, "search_rank")); diff --git a/src/main/java/mil/dds/anet/search/pg/PostgresqlReportSearcher.java b/src/main/java/mil/dds/anet/search/pg/PostgresqlReportSearcher.java index 375b760ec4..c051e4657c 100644 --- a/src/main/java/mil/dds/anet/search/pg/PostgresqlReportSearcher.java +++ b/src/main/java/mil/dds/anet/search/pg/PostgresqlReportSearcher.java @@ -78,7 +78,7 @@ protected void addPrincipalOrgUuidQuery(ReportSearchQuery query) { @Override protected void addOrderByClauses(AbstractSearchQueryBuilder qb, ReportSearchQuery query) { - if (query.isTextPresent() && !query.isSortByPresent()) { + if (hasTextQuery(query) && !query.isSortByPresent()) { // We're doing a full-text search without an explicit sort order, // so sort first on the search pseudo-rank. qb.addAllOrderByClauses(getOrderBy(SortOrder.DESC, null, "search_rank")); diff --git a/src/main/java/mil/dds/anet/search/pg/PostgresqlSearchQueryBuilder.java b/src/main/java/mil/dds/anet/search/pg/PostgresqlSearchQueryBuilder.java index 990064bef2..6912e42149 100644 --- a/src/main/java/mil/dds/anet/search/pg/PostgresqlSearchQueryBuilder.java +++ b/src/main/java/mil/dds/anet/search/pg/PostgresqlSearchQueryBuilder.java @@ -6,6 +6,7 @@ import mil.dds.anet.beans.lists.AnetBeanList; import mil.dds.anet.beans.search.AbstractSearchQuery; import mil.dds.anet.search.AbstractSearchQueryBuilder; +import mil.dds.anet.utils.Utils; import mil.dds.anet.views.AbstractAnetBean; import org.jdbi.v3.core.Handle; import org.jdbi.v3.core.mapper.RowMapper; @@ -20,16 +21,33 @@ public PostgresqlSearchQueryBuilder(String queryName) { @Override public String getContainsQuery(String text) { - return "%" + stripWildcards(text) + "%"; + if (Utils.isEmptyOrNull(text)) { + return null; + } + final String cleanText = stripWildcards(text); + if (Utils.isEmptyOrNull(cleanText)) { + return null; + } + return "%" + cleanText + "%"; } @Override public String getFullTextQuery(String text) { - String cleanText = stripWildcards(text); - if (text.endsWith("*")) { - cleanText = cleanText + ":*"; + if (Utils.isEmptyOrNull(text)) { + return null; + } + // Replace all special characters for tsquery with spaces + final String cleanText = text.trim().replaceAll("[<>:*|&!()\"']", " ").trim(); + if (Utils.isEmptyOrNull(cleanText)) { + return null; + } + // Split into words + final String[] lexemes = cleanText.split("\\s+"); + if (lexemes.length == 0) { + return null; } - return cleanText; + // Turn each word into a prefix match, and AND them + return Joiner.on(":* & ").join(lexemes).concat(":*"); } @Override diff --git a/src/main/java/mil/dds/anet/search/pg/PostgresqlTagSearcher.java b/src/main/java/mil/dds/anet/search/pg/PostgresqlTagSearcher.java index a48b179efe..9efbc23ffb 100644 --- a/src/main/java/mil/dds/anet/search/pg/PostgresqlTagSearcher.java +++ b/src/main/java/mil/dds/anet/search/pg/PostgresqlTagSearcher.java @@ -19,7 +19,7 @@ protected void addTextQuery(TagSearchQuery query) { @Override protected void addOrderByClauses(AbstractSearchQueryBuilder qb, TagSearchQuery query) { - if (query.isTextPresent() && !query.isSortByPresent()) { + if (hasTextQuery(query) && !query.isSortByPresent()) { // We're doing a full-text search without an explicit sort order, // so sort first on the search pseudo-rank. qb.addAllOrderByClauses(getOrderBy(SortOrder.DESC, null, "search_rank")); diff --git a/src/main/java/mil/dds/anet/search/pg/PostgresqlTaskSearcher.java b/src/main/java/mil/dds/anet/search/pg/PostgresqlTaskSearcher.java index 121f20dcf8..0546212936 100644 --- a/src/main/java/mil/dds/anet/search/pg/PostgresqlTaskSearcher.java +++ b/src/main/java/mil/dds/anet/search/pg/PostgresqlTaskSearcher.java @@ -19,7 +19,7 @@ protected void addTextQuery(TaskSearchQuery query) { @Override protected void addOrderByClauses(AbstractSearchQueryBuilder qb, TaskSearchQuery query) { - if (query.isTextPresent() && !query.isSortByPresent()) { + if (hasTextQuery(query) && !query.isSortByPresent()) { // We're doing a full-text search without an explicit sort order, // so sort first on the search pseudo-rank. qb.addAllOrderByClauses(getOrderBy(SortOrder.DESC, null, "search_rank")); diff --git a/src/main/java/mil/dds/anet/utils/Utils.java b/src/main/java/mil/dds/anet/utils/Utils.java index 6570983c84..a4187d379d 100644 --- a/src/main/java/mil/dds/anet/utils/Utils.java +++ b/src/main/java/mil/dds/anet/utils/Utils.java @@ -1,5 +1,11 @@ package mil.dds.anet.utils; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.json.JsonSanitizer; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -10,6 +16,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; @@ -27,6 +34,7 @@ import mil.dds.anet.beans.Organization; import mil.dds.anet.beans.Task; import mil.dds.anet.database.ApprovalStepDao; +import mil.dds.anet.database.mappers.MapperUtils; import mil.dds.anet.views.AbstractAnetBean; import net.coobird.thumbnailator.Thumbnails; import org.jsoup.Jsoup; @@ -39,6 +47,7 @@ public class Utils { private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + private static final ObjectMapper mapper = MapperUtils.getDefaultMapper(); /** * Crude method to check whether a uuid is purely integer, in which case it is probably a legacy @@ -180,39 +189,77 @@ public static Map buildParentTaskMapping(List tasks, return result; } - public static final PolicyFactory POLICY_DEFINITION = - new HtmlPolicyBuilder().allowStandardUrlProtocols() - // Allow in-line image data - .allowUrlProtocols("data").allowAttributes("src") - .matching(Pattern.compile("^data:image/.*$")).onElements("img") - // Allow some image attributes - .allowAttributes("align", "alt", "border", "name", "height", "width", "hspace", "vspace") - .onElements("img") - // Allow title="..." on any element. - .allowAttributes("title").globally() - // Allow href="..." on elements (but not the 'data:' protocol!). - .allowAttributes("href").matching(Pattern.compile("^(?!data:).*$")).onElements("a") - // Defeat link spammers. - .requireRelNofollowOnLinks() - // The align attribute on

elements can have any value below. - .allowAttributes("align").matching(true, "center", "left", "right", "justify", "char") - .onElements("p").allowAttributes("class", "placeholder") - .onElements("h1", "h2", "h3", "h4", "h5", "h6", "p") - .allowAttributes("border", "cellpadding", "cellspacing").onElements("table") - .allowAttributes("colspan", "rowspan").onElements("td", "th").allowStyling() - // These elements are allowed. - .allowElements("a", "p", "div", "i", "b", "u", "em", "blockquote", "tt", "strong", "br", - "ul", "ol", "li", "table", "tr", "td", "thead", "tbody", "th", "span", "h1", "h2", - "h3", "h4", "h5", "h6", "hr", "img", "strike", "mark") - .toFactory(); + public static final PolicyFactory HTML_POLICY_DEFINITION = new HtmlPolicyBuilder() + .allowStandardUrlProtocols() + // Allow in-line image data + .allowUrlProtocols("data").allowAttributes("src").matching(Pattern.compile("^data:image/.*$")) + .onElements("img") + // Allow some image attributes + .allowAttributes("align", "alt", "border", "name", "height", "width", "hspace", "vspace") + .onElements("img") + // Allow title="..." on any element. + .allowAttributes("title").globally() + // Allow href="..." on elements (but not the 'data:' protocol!). + .allowAttributes("href").matching(Pattern.compile("^(?!data:).*$")).onElements("a") + // Defeat link spammers. + .requireRelNofollowOnLinks() + // The align attribute on

elements can have any value below. + .allowAttributes("align").matching(true, "center", "left", "right", "justify", "char") + .onElements("p").allowAttributes("class", "placeholder") + .onElements("h1", "h2", "h3", "h4", "h5", "h6", "p").allowAttributes("border", "cellpadding", "cellspacing").onElements("table") + .allowAttributes("colspan", "rowspan").onElements("td", "th").allowStyling() + // These elements are allowed. + .allowElements("a", "p", "div", "i", "b", "u", "em", "blockquote", "tt", "strong", "br", "ul", + "ol", "li", "table", "tr", "td", "thead", "tbody", "th", "span", "h1", "h2", "h3", "h4", + "h5", "h6", "hr", "img", "strike", "mark") + .toFactory(); public static String sanitizeHtml(String input) { if (input == null) { return null; } - return POLICY_DEFINITION.sanitize(input); + return HTML_POLICY_DEFINITION.sanitize(input); } + public static String sanitizeJson(String inputJson) throws JsonProcessingException { + if (inputJson == null) { + // `JsonSanitizer.sanitize(null)` would return `"null"` in this case, + // but we prefer plain `null` + return null; + } + final String sanitizedJson = JsonSanitizer.sanitize(inputJson); + final JsonNode jsonTree = mapper.readTree(sanitizedJson); + internalSanitizeJsonForHtml(jsonTree); + return mapper.writeValueAsString(jsonTree); + } + + private static void internalSanitizeJsonForHtml(JsonNode jsonNode) { + if (jsonNode.isObject()) { + final ObjectNode objectNode = (ObjectNode) jsonNode; + for (final Iterator> entryIter = objectNode.fields(); entryIter + .hasNext();) { + final Map.Entry entry = entryIter.next(); + final JsonNode newValue = entry.getValue().isTextual() + ? objectNode.textNode(sanitizeHtml(entry.getValue().asText())) + : entry.getValue(); + final String sanitizedKey = sanitizeHtml(entry.getKey()); + if (!entry.getKey().equals(sanitizedKey)) { + objectNode.remove(entry.getKey()); + } + objectNode.set(sanitizedKey, newValue); + internalSanitizeJsonForHtml(entry.getValue()); + } + } else if (jsonNode.isArray()) { + final ArrayNode arrayNode = (ArrayNode) jsonNode; + for (int i = 0; i < arrayNode.size(); i++) { + if (arrayNode.get(i).isTextual()) { + arrayNode.set(i, arrayNode.textNode(sanitizeHtml(arrayNode.get(i).asText()))); + } else { + internalSanitizeJsonForHtml(arrayNode.get(i)); + } + } + } + } public static String trimStringReturnNull(String input) { if (input == null) { diff --git a/src/main/java/mil/dds/anet/views/AbstractCustomizableAnetBean.java b/src/main/java/mil/dds/anet/views/AbstractCustomizableAnetBean.java index 619b1fe280..6977f96fce 100644 --- a/src/main/java/mil/dds/anet/views/AbstractCustomizableAnetBean.java +++ b/src/main/java/mil/dds/anet/views/AbstractCustomizableAnetBean.java @@ -1,11 +1,18 @@ package mil.dds.anet.views; +import com.fasterxml.jackson.core.JsonProcessingException; import io.leangen.graphql.annotations.GraphQLInputField; import io.leangen.graphql.annotations.GraphQLQuery; +import java.lang.invoke.MethodHandles; import mil.dds.anet.utils.Utils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public abstract class AbstractCustomizableAnetBean extends AbstractAnetBean { + private static final Logger logger = + LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + @GraphQLQuery @GraphQLInputField protected String customFields; @@ -17,4 +24,15 @@ public String getCustomFields() { public void setCustomFields(String customFields) { this.customFields = Utils.trimStringReturnNull(customFields); } + + public void checkAndFixCustomFields() { + try { + setCustomFields(Utils.sanitizeJson(getCustomFields())); + } catch (JsonProcessingException e) { + setCustomFields(null); + logger.error("Unable to process Json, customFields payload discarded", e); + } + + } + } diff --git a/src/main/resources/anet-schema.yml b/src/main/resources/anet-schema.yml index e9ef081726..c3c02be2bc 100644 --- a/src/main/resources/anet-schema.yml +++ b/src/main/resources/anet-schema.yml @@ -97,21 +97,24 @@ definitions: aggregation: type: object properties: + aggregationType: + type: string + enum: [countPerValue, numbersList, valuesList] widget: type: string - enum: [likertScale, numberAggregation, default] + enum: [pie, iqrBoxPlot, likertScale, default] dependencies: widget: oneOf: - properties: widget: - enum: [likertScale, default] + enum: [likertScale, countPerValue, default] - properties: type: - enum: [numberAggregation] - aggregationType: - type: string - enum: [sum, avg, min, max] + enum: [iqrBoxPlot] + aggregationType: + type: string + enum: [sum, avg, min, max] required: [aggregationType] # TODO: The following properties should not be here as these are only dependency fields. # I can't figure out yet why the schema validation will not pass without them @@ -201,6 +204,28 @@ definitions: type: string required: [levels] +# definition for assessment configuration + assessmentDef: + type: object + additionalProperties: false + required: [questions] + properties: + recurrence: + title: recurrence of an assessment + type: string + enum: [once, daily, weekly, biweekly, semimonthly, monthly, quarterly, semiannualy, annually] + default: once + relatedObjectType: + title: object type context in which the assessment will be made + type: string + enum: [report, null] + default: null + questions: + title: questions to respond when assessing + type: object + additionalProperties: + "$ref": "#/definitions/customField" + ######################################################### ### schema root ######################################################### @@ -350,14 +375,10 @@ properties: "$ref": "#/properties/fields/properties/task/properties/longLabel" longName: "$ref": "#/properties/fields/properties/task/properties/longName" - assessment: - type: object - required: [customFields] - properties: - customFields: - type: object - additionalProperties: - "$ref": "#/definitions/customField" + assessments: + type: array + items: + "$ref": "#/definitions/assessmentDef" subLevel: "$ref": "#/properties/fields/properties/task/properties/topLevel" projectedCompletion: @@ -618,6 +639,10 @@ properties: type: string color: type: string + assessments: + type: array + items: + "$ref": "#/definitions/assessmentDef" position: type: object @@ -795,6 +820,7 @@ properties: type: type: string enum: + - board - kanban - decisives diff --git a/src/main/resources/migrations.xml b/src/main/resources/migrations.xml index eb73bca54d..ed5edc6dbb 100644 --- a/src/main/resources/migrations.xml +++ b/src/main/resources/migrations.xml @@ -3148,4 +3148,231 @@ + + + + DROP MATERIALIZED VIEW "mv_fts_authorizationGroups"; + DROP MATERIALIZED VIEW mv_fts_locations; + DROP MATERIALIZED VIEW mv_fts_organizations; + DROP MATERIALIZED VIEW mv_fts_people; + DROP MATERIALIZED VIEW mv_fts_positions; + DROP MATERIALIZED VIEW mv_fts_reports; + DROP MATERIALIZED VIEW mv_fts_tags; + DROP MATERIALIZED VIEW mv_fts_tasks; + + + ALTER TABLE "authorizationGroups" DROP COLUMN full_text; + ALTER TABLE locations DROP COLUMN full_text; + ALTER TABLE organizations DROP COLUMN full_text; + ALTER TABLE notes DROP COLUMN full_text; + ALTER TABLE people DROP COLUMN full_text; + ALTER TABLE positions DROP COLUMN full_text; + ALTER TABLE reports DROP COLUMN full_text; + ALTER TABLE tags DROP COLUMN full_text; + ALTER TABLE tasks DROP COLUMN full_text; + + + ALTER TABLE "authorizationGroups" + ADD COLUMN full_text tsvector GENERATED ALWAYS AS ( + setweight(to_tsvector(${fts_config}, coalesce("authorizationGroups".name, '')) + || to_tsvector('simple', coalesce("authorizationGroups".name, '')), ${fts_high}) || + setweight(to_tsvector(${fts_config}, coalesce("authorizationGroups".description, '')) + || to_tsvector('simple', coalesce("authorizationGroups".description, '')), ${fts_low}) + ) STORED; + + ALTER TABLE locations + ADD COLUMN full_text tsvector GENERATED ALWAYS AS ( + setweight(to_tsvector(${fts_config}, coalesce(locations.name, '')) + || to_tsvector('simple', coalesce(locations.name, '')), ${fts_high}) + ) STORED; + + ALTER TABLE organizations + ADD COLUMN full_text tsvector GENERATED ALWAYS AS ( + setweight(to_tsvector('simple', coalesce(organizations."identificationCode", '')), ${fts_high}) || + setweight(to_tsvector('simple', coalesce(organizations."shortName", '')), ${fts_high}) || + setweight(to_tsvector(${fts_config}, coalesce(organizations."longName", '')) + || to_tsvector('simple', coalesce(organizations."longName", '')), ${fts_low}) + ) STORED; + + ALTER TABLE notes + ADD COLUMN full_text tsvector GENERATED ALWAYS AS ( + setweight(to_tsvector(${fts_config}, coalesce(notes.text, '')) + || to_tsvector('simple', coalesce(notes.text, '')), ${fts_low}) + ) STORED; + + ALTER TABLE people + ADD COLUMN full_text tsvector GENERATED ALWAYS AS ( + setweight(to_tsvector('simple', coalesce(people.name, '')), ${fts_high}) || + setweight(to_tsvector('simple', coalesce(people.code, '')), ${fts_high}) || + setweight(to_tsvector('simple', coalesce(people."domainUsername", '')), ${fts_high}) || + setweight(to_tsvector('simple', coalesce(people."emailAddress", '')), ${fts_high}) || + setweight(to_tsvector('simple', coalesce(people."phoneNumber", '')), ${fts_high}) || + setweight(to_tsvector(${fts_config}, coalesce(people.biography, '')) + || to_tsvector('simple', coalesce(people.biography, '')), ${fts_low}) + ) STORED; + + ALTER TABLE positions + ADD COLUMN full_text tsvector GENERATED ALWAYS AS ( + setweight(to_tsvector('simple', coalesce(positions.code, '')), ${fts_high}) || + setweight(to_tsvector(${fts_config}, coalesce(positions.name, '')) + || to_tsvector('simple', coalesce(positions.name, '')), ${fts_high}) + ) STORED; + + ALTER TABLE reports + ADD COLUMN full_text tsvector GENERATED ALWAYS AS ( + setweight(to_tsvector(${fts_config}, coalesce(reports.intent, '')) + || to_tsvector('simple', coalesce(reports.intent, '')), ${fts_high}) || + setweight(to_tsvector(${fts_config}, coalesce(reports."keyOutcomes", '')) + || to_tsvector('simple', coalesce(reports."keyOutcomes", '')), ${fts_high}) || + setweight(to_tsvector(${fts_config}, coalesce(reports."nextSteps", '')) + || to_tsvector('simple', coalesce(reports."nextSteps", '')), ${fts_high}) || + setweight(to_tsvector(${fts_config}, coalesce(reports.text, '')) + || to_tsvector('simple', coalesce(reports.text, '')), ${fts_low}) + ) STORED; + + ALTER TABLE tags + ADD COLUMN full_text tsvector GENERATED ALWAYS AS ( + setweight(to_tsvector(${fts_config}, coalesce(tags.name, '')) + || to_tsvector('simple', coalesce(tags.name, '')), ${fts_high}) || + setweight(to_tsvector(${fts_config}, coalesce(tags.description, '')) + || to_tsvector('simple', coalesce(tags.description, '')), ${fts_low}) + ) STORED; + + ALTER TABLE tasks + ADD COLUMN full_text tsvector GENERATED ALWAYS AS ( + setweight(to_tsvector('simple', coalesce(tasks."shortName", '')), ${fts_high}) || + setweight(to_tsvector(${fts_config}, coalesce(tasks."longName", '')) + || to_tsvector('simple', coalesce(tasks."longName", '')), ${fts_high}) + ) STORED; + + + CREATE MATERIALIZED VIEW IF NOT EXISTS "mv_fts_authorizationGroups"(uuid, full_text) AS + SELECT + "authorizationGroups".uuid, + "authorizationGroups".full_text + || coalesce(tsvector_agg(notes.full_text), ''::tsvector) + FROM "authorizationGroups" + LEFT JOIN "noteRelatedObjects" ON "noteRelatedObjects"."relatedObjectType" = 'authorizationGroups' + AND "noteRelatedObjects"."relatedObjectUuid" = "authorizationGroups".uuid + LEFT JOIN notes ON notes.uuid = "noteRelatedObjects"."noteUuid" + GROUP BY "authorizationGroups".uuid + WITH DATA; + CREATE UNIQUE INDEX "UQ_mv_fts_authorizationGroups_uuid" ON "mv_fts_authorizationGroups"(uuid); + CREATE INDEX "FT_mv_fts_authorizationGroups" ON "mv_fts_authorizationGroups" USING gin(full_text); + CREATE INDEX "TR_authorizationGroups_uuid" ON "mv_fts_authorizationGroups" USING gin(uuid gin_trgm_ops); + + CREATE MATERIALIZED VIEW IF NOT EXISTS mv_fts_locations(uuid, full_text) AS + SELECT + locations.uuid, + locations.full_text + || coalesce(tsvector_agg(notes.full_text), ''::tsvector) + FROM locations + LEFT JOIN "noteRelatedObjects" ON "noteRelatedObjects"."relatedObjectType" = 'locations' + AND "noteRelatedObjects"."relatedObjectUuid" = locations.uuid + LEFT JOIN notes ON notes.uuid = "noteRelatedObjects"."noteUuid" + GROUP BY locations.uuid + WITH DATA; + CREATE UNIQUE INDEX "UQ_mv_fts_locations_uuid" ON mv_fts_locations(uuid); + CREATE INDEX "FT_mv_fts_locations" ON mv_fts_locations USING gin(full_text); + CREATE INDEX "TR_locations_uuid" ON mv_fts_locations USING gin(uuid gin_trgm_ops); + + CREATE MATERIALIZED VIEW IF NOT EXISTS mv_fts_organizations(uuid, full_text) AS + SELECT + organizations.uuid, + organizations.full_text + || coalesce(tsvector_agg(notes.full_text), ''::tsvector) + FROM organizations + LEFT JOIN "noteRelatedObjects" ON "noteRelatedObjects"."relatedObjectType" = 'organizations' + AND "noteRelatedObjects"."relatedObjectUuid" = organizations.uuid + LEFT JOIN notes ON notes.uuid = "noteRelatedObjects"."noteUuid" + GROUP BY organizations.uuid + WITH DATA; + CREATE UNIQUE INDEX "UQ_mv_fts_organizations_uuid" ON mv_fts_organizations(uuid); + CREATE INDEX "FT_mv_fts_organizations" ON mv_fts_organizations USING gin(full_text); + CREATE INDEX "TR_organizations_uuid" ON mv_fts_organizations USING gin(uuid gin_trgm_ops); + + CREATE MATERIALIZED VIEW IF NOT EXISTS mv_fts_people(uuid, full_text) AS + SELECT + people.uuid, + people.full_text + || coalesce(tsvector_agg(positions.full_text), ''::tsvector) + || coalesce(tsvector_agg(organizations.full_text), ''::tsvector) + || coalesce(tsvector_agg(notes.full_text), ''::tsvector) + FROM people + LEFT JOIN positions ON positions."currentPersonUuid" = people.uuid + LEFT JOIN organizations ON organizations.uuid = positions."organizationUuid" + LEFT JOIN "noteRelatedObjects" ON "noteRelatedObjects"."relatedObjectType" = 'people' + AND "noteRelatedObjects"."relatedObjectUuid" = people.uuid + LEFT JOIN notes ON notes.uuid = "noteRelatedObjects"."noteUuid" + GROUP BY people.uuid + WITH DATA; + CREATE UNIQUE INDEX "UQ_mv_fts_people_uuid" ON mv_fts_people(uuid); + CREATE INDEX "FT_mv_fts_people" ON mv_fts_people USING gin(full_text); + CREATE INDEX "TR_people_uuid" ON mv_fts_people USING gin(uuid gin_trgm_ops); + + CREATE MATERIALIZED VIEW IF NOT EXISTS mv_fts_positions(uuid, full_text) AS + SELECT + positions.uuid, + positions.full_text + || coalesce(tsvector_agg(people.full_text), ''::tsvector) + || coalesce(tsvector_agg(organizations.full_text), ''::tsvector) + || coalesce(tsvector_agg(notes.full_text), ''::tsvector) + FROM positions + LEFT JOIN people ON people.uuid = positions."currentPersonUuid" + LEFT JOIN organizations ON organizations.uuid = positions."organizationUuid" + LEFT JOIN "noteRelatedObjects" ON "noteRelatedObjects"."relatedObjectType" = 'positions' + AND "noteRelatedObjects"."relatedObjectUuid" = positions.uuid + LEFT JOIN notes ON notes.uuid = "noteRelatedObjects"."noteUuid" + GROUP BY positions.uuid + WITH DATA; + CREATE UNIQUE INDEX "UQ_mv_fts_positions" ON mv_fts_positions(uuid); + CREATE INDEX "FT_mv_fts_positions" ON mv_fts_positions USING gin(full_text); + CREATE INDEX "TR_positions_uuid" ON mv_fts_positions USING gin(uuid gin_trgm_ops); + + CREATE MATERIALIZED VIEW IF NOT EXISTS mv_fts_reports(uuid, full_text) AS + SELECT + reports.uuid, + reports.full_text + || coalesce(tsvector_agg(notes.full_text), ''::tsvector) + FROM reports + LEFT JOIN "noteRelatedObjects" ON "noteRelatedObjects"."relatedObjectType" = 'reports' + AND "noteRelatedObjects"."relatedObjectUuid" = reports.uuid + LEFT JOIN notes ON notes.uuid = "noteRelatedObjects"."noteUuid" + GROUP BY reports.uuid + WITH DATA; + CREATE UNIQUE INDEX "UQ_mv_fts_reports_uuid" ON mv_fts_reports(uuid); + CREATE INDEX "FT_mv_fts_reports" ON mv_fts_reports USING gin(full_text); + CREATE INDEX "TR_reports_uuid" ON mv_fts_reports USING gin(uuid gin_trgm_ops); + + CREATE MATERIALIZED VIEW IF NOT EXISTS mv_fts_tags(uuid, full_text) AS + SELECT + tags.uuid, + tags.full_text + FROM tags + GROUP BY tags.uuid + WITH DATA; + CREATE UNIQUE INDEX "UQ_mv_fts_tags" ON mv_fts_tags(uuid); + CREATE INDEX "FT_mv_fts_tags" ON mv_fts_tags USING gin(full_text); + CREATE INDEX "TR_tags_uuid" ON mv_fts_tags USING gin(uuid gin_trgm_ops); + + CREATE MATERIALIZED VIEW IF NOT EXISTS mv_fts_tasks(uuid, full_text) AS + SELECT + tasks.uuid, + tasks.full_text + || coalesce(tsvector_agg(notes.full_text), ''::tsvector) + FROM tasks + LEFT JOIN "noteRelatedObjects" ON "noteRelatedObjects"."relatedObjectType" = 'tasks' + AND "noteRelatedObjects"."relatedObjectUuid" = tasks.uuid + LEFT JOIN notes ON notes.uuid = "noteRelatedObjects"."noteUuid" + GROUP BY tasks.uuid + WITH DATA; + CREATE UNIQUE INDEX "UQ_mv_fts_tasks" ON mv_fts_tasks(uuid); + CREATE INDEX "FT_mv_fts_tasks" ON mv_fts_tasks USING gin(full_text); + CREATE INDEX "TR_tasks_uuid" ON mv_fts_tasks USING gin(uuid gin_trgm_ops); + + + + diff --git a/src/test/java/mil/dds/anet/test/TestData.java b/src/test/java/mil/dds/anet/test/TestData.java index 21e78b6d37..d56e17c175 100644 --- a/src/test/java/mil/dds/anet/test/TestData.java +++ b/src/test/java/mil/dds/anet/test/TestData.java @@ -40,6 +40,13 @@ public static Task createTask(String shortName, String longName, String category return TestData.createTask(shortName, longName, category, null, null, Task.TaskStatus.ACTIVE); } + public static Task createTask(String shortName, String longName, String category, + String customFields) { + final Task p = TestData.createTask(shortName, longName, category); + p.setCustomFields(customFields); + return p; + } + public static Task createTask(String shortName, String longName, String category, Task customFieldRef1, List taskedOrganizations, Task.TaskStatus status) { Task p = new Task(); diff --git a/src/test/java/mil/dds/anet/test/resources/GraphQlResourceTest.java b/src/test/java/mil/dds/anet/test/resources/GraphQlResourceTest.java index 0157864b6f..f1ac858a5c 100644 --- a/src/test/java/mil/dds/anet/test/resources/GraphQlResourceTest.java +++ b/src/test/java/mil/dds/anet/test/resources/GraphQlResourceTest.java @@ -4,6 +4,7 @@ import static org.assertj.core.api.Assertions.fail; import com.google.common.collect.ImmutableMap; +import graphql.introspection.IntrospectionQuery; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -30,7 +31,37 @@ public class GraphQlResourceTest extends AbstractResourceTest { LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); @Test - public void test() { + public void testIntrospection() { + final Map introspectionQuery = new HashMap(); + introspectionQuery.put("operationName", "IntrospectionQuery"); + introspectionQuery.put("variables", ImmutableMap.of()); + introspectionQuery.put("query", IntrospectionQuery.INTROSPECTION_QUERY); + // only admin can do introspection query + try { + final Map resp = httpQuery("/graphql", admin) + .post(Entity.json(introspectionQuery), new GenericType>() {}); + assertThat(resp.get("data")).isNotNull(); // we could check a million things here + } catch (Exception e) { + fail("Unexpected exception", e); + } + try { + httpQuery("/graphql", getSuperUser()).post(Entity.json(introspectionQuery), + new GenericType>() {}); + fail("Expected exception"); + } catch (Exception e) { + // correct + } + try { + httpQuery("/graphql", getRegularUser()).post(Entity.json(introspectionQuery), + new GenericType>() {}); + fail("Expected exception"); + } catch (Exception e) { + // correct + } + } + + @Test + public void testGraphQlFiles() { final Person jack = getJackJackson(); final Person steve = getSteveSteveson(); final File testDir = new File(GraphQlResourceTest.class.getResource("/graphQLTests").getFile()); diff --git a/src/test/java/mil/dds/anet/test/resources/PersonResourceTest.java b/src/test/java/mil/dds/anet/test/resources/PersonResourceTest.java index 7f04fcccd3..1e133edd12 100644 --- a/src/test/java/mil/dds/anet/test/resources/PersonResourceTest.java +++ b/src/test/java/mil/dds/anet/test/resources/PersonResourceTest.java @@ -46,7 +46,8 @@ public class PersonResourceTest extends AbstractResourceTest { private static final String POSITION_FIELDS = "uuid name code type status"; private static final String PERSON_FIELDS = "uuid name status role emailAddress phoneNumber rank biography country avatar code" - + " gender endOfTourDate domainUsername pendingVerification createdAt updatedAt"; + + " gender endOfTourDate domainUsername pendingVerification createdAt updatedAt" + + " customFields"; private static final String FIELDS = PERSON_FIELDS + " position { " + POSITION_FIELDS + " }"; // 200 x 200 avatar @@ -67,7 +68,9 @@ public void testCreatePerson() throws IOException { newPerson.setRole(Role.ADVISOR); newPerson.setStatus(PersonStatus.ACTIVE); // set HTML of biography - newPerson.setBiography(UtilsTest.getCombinedTestCase().getInput()); + newPerson.setBiography(UtilsTest.getCombinedHtmlTestCase().getInput()); + // set JSON of customFields + newPerson.setCustomFields(UtilsTest.getCombinedJsonTestCase().getInput()); newPerson.setGender("Female"); newPerson.setCountry("Canada"); newPerson.setCode("123456"); @@ -81,7 +84,10 @@ public void testCreatePerson() throws IOException { assertThat(newPerson.getUuid()).isNotNull(); assertThat(newPerson.getName()).isEqualTo("testCreatePerson Person"); // check that HTML of biography is sanitized after create - assertThat(newPerson.getBiography()).isEqualTo(UtilsTest.getCombinedTestCase().getOutput()); + assertThat(newPerson.getBiography()).isEqualTo(UtilsTest.getCombinedHtmlTestCase().getOutput()); + // check that JSON of customFields is sanitized after create + assertThat(newPerson.getCustomFields()) + .isEqualTo(UtilsTest.getCombinedJsonTestCase().getOutput()); newPerson.setName("testCreatePerson updated name"); newPerson.setCountry("The Commonwealth of Canada"); @@ -93,7 +99,9 @@ public void testCreatePerson() throws IOException { newPerson.setAvatar(defaultAvatarData); // update HTML of biography - newPerson.setBiography(UtilsTest.getCombinedTestCase().getInput()); + newPerson.setBiography(UtilsTest.getCombinedHtmlTestCase().getInput()); + // update JSON of customFields + newPerson.setCustomFields(UtilsTest.getCombinedJsonTestCase().getInput()); Integer nrUpdated = graphQLHelper.updateObject(admin, "updatePerson", "person", "PersonInput", newPerson); @@ -105,7 +113,10 @@ public void testCreatePerson() throws IOException { assertThat(retPerson.getCode()).isEqualTo(newPerson.getCode()); assertThat(retPerson.getAvatar()).isNotNull(); // check that HTML of biography is sanitized after update - assertThat(retPerson.getBiography()).isEqualTo(UtilsTest.getCombinedTestCase().getOutput()); + assertThat(retPerson.getBiography()).isEqualTo(UtilsTest.getCombinedHtmlTestCase().getOutput()); + // check that JSON of customFields is sanitized after update + assertThat(retPerson.getCustomFields()) + .isEqualTo(UtilsTest.getCombinedJsonTestCase().getOutput()); // Test creating a person with a position already set. final OrganizationSearchQuery query = new OrganizationSearchQuery(); @@ -215,8 +226,7 @@ public void searchPerson() { .findFirst()).isNotEmpty(); final OrganizationSearchQuery queryOrgs = new OrganizationSearchQuery(); - // FIXME: decide what the search should do in both cases - queryOrgs.setText(DaoUtils.isPostgresql() ? "\"EF 1\" or \"EF 1.1\"" : "EF 1"); + queryOrgs.setText("EF 1"); queryOrgs.setType(OrganizationType.ADVISOR_ORG); final AnetBeanList orgs = graphQLHelper.searchObjects(jack, "organizationList", "query", "OrganizationSearchQueryInput", "uuid shortName", queryOrgs, diff --git a/src/test/java/mil/dds/anet/test/resources/PositionResourceTest.java b/src/test/java/mil/dds/anet/test/resources/PositionResourceTest.java index d35ffd2cf6..916ca3ea32 100644 --- a/src/test/java/mil/dds/anet/test/resources/PositionResourceTest.java +++ b/src/test/java/mil/dds/anet/test/resources/PositionResourceTest.java @@ -34,7 +34,6 @@ import mil.dds.anet.test.beans.OrganizationTest; import mil.dds.anet.test.beans.PositionTest; import mil.dds.anet.test.resources.utils.GraphQlResponse; -import mil.dds.anet.utils.DaoUtils; import org.junit.jupiter.api.Test; public class PositionResourceTest extends AbstractResourceTest { @@ -395,8 +394,7 @@ public void searchTest() { // Search by organization final OrganizationSearchQuery queryOrgs = new OrganizationSearchQuery(); - // FIXME: decide what the search should do in both cases - queryOrgs.setText(DaoUtils.isPostgresql() ? "\"ef 1\" or \"ef 1.1\"" : "ef 1"); + queryOrgs.setText("ef 1"); queryOrgs.setType(OrganizationType.ADVISOR_ORG); final AnetBeanList orgs = graphQLHelper.searchObjects(jack, "organizationList", "query", "OrganizationSearchQueryInput", ORGANIZATION_FIELDS, queryOrgs, diff --git a/src/test/java/mil/dds/anet/test/resources/ReportsResourceTest.java b/src/test/java/mil/dds/anet/test/resources/ReportsResourceTest.java index 896ffaaaa7..16906eaf68 100644 --- a/src/test/java/mil/dds/anet/test/resources/ReportsResourceTest.java +++ b/src/test/java/mil/dds/anet/test/resources/ReportsResourceTest.java @@ -85,7 +85,8 @@ public class ReportsResourceTest extends AbstractResourceTest { private static final String POSITION_FIELDS = "uuid"; private static final String REPORT_FIELDS = "uuid intent exsum state cancelledReason atmosphere atmosphereDetails" - + " engagementDate duration engagementDayOfWeek keyOutcomes nextSteps reportText createdAt updatedAt"; + + " engagementDate duration engagementDayOfWeek keyOutcomes nextSteps reportText createdAt updatedAt" + + " customFields"; private static final String _TASK_FIELDS = "uuid shortName longName category"; private static final String TASK_FIELDS = String.format("%1$s customFieldRef1 { %1$s }", _TASK_FIELDS); @@ -270,7 +271,9 @@ public void createReport() { r.setAtmosphereDetails("Everybody was super nice!"); r.setIntent("A testing report to test that reporting reports"); // set HTML of report text - r.setReportText(UtilsTest.getCombinedTestCase().getInput()); + r.setReportText(UtilsTest.getCombinedHtmlTestCase().getInput()); + // set JSON of customFields + r.setCustomFields(UtilsTest.getCombinedJsonTestCase().getInput()); r.setNextSteps("This is the next steps on a report"); r.setKeyOutcomes("These are the key outcomes of this engagement"); r.setAdvisorOrg(advisorOrg); @@ -285,7 +288,26 @@ public void createReport() { assertThat(created.getAdvisorOrgUuid()).isEqualTo(advisorOrg.getUuid()); assertThat(created.getPrincipalOrgUuid()).isEqualTo(principalOrg.getUuid()); // check that HTML of report text is sanitized after create - assertThat(created.getReportText()).isEqualTo(UtilsTest.getCombinedTestCase().getOutput()); + assertThat(created.getReportText()).isEqualTo(UtilsTest.getCombinedHtmlTestCase().getOutput()); + // check that JSON of customFields is sanitized after create + assertThat(created.getCustomFields()) + .isEqualTo(UtilsTest.getCombinedJsonTestCase().getOutput()); + + // Have another regular user try to submit the report + try { + graphQLHelper.updateObject(getRegularUser(), "submitReport", "uuid", FIELDS, "String", + created.getUuid(), new TypeReference>() {}); + fail("Expected ForbiddenException"); + } catch (ForbiddenException expectedException) { + } + + // Have a super-user of another AO try to submit the report + try { + graphQLHelper.updateObject(getSuperUser(), "submitReport", "uuid", FIELDS, "String", + created.getUuid(), new TypeReference>() {}); + fail("Expected ForbiddenException"); + } catch (ForbiddenException expectedException) { + } // Have the author submit the report Report submitted = graphQLHelper.updateObject(author, "submitReport", "uuid", FIELDS, "String", @@ -311,6 +333,14 @@ public void createReport() { new TypeReference>() {}); assertThat(returned.getState()).isEqualTo(ReportState.PENDING_APPROVAL); + // The author should not be able to submit the report now + try { + graphQLHelper.updateObject(author, "submitReport", "uuid", FIELDS, "String", + returned.getUuid(), new TypeReference>() {}); + fail("Expected BadRequestException"); + } catch (BadRequestException expectedException) { + } + logger.debug("Expecting report {} in step {} because of org {} on author {}", new Object[] { returned.getUuid(), approval.getUuid(), advisorOrg.getUuid(), author.getUuid()}); assertThat(returned.getApprovalStepUuid()).isEqualTo(approval.getUuid()); @@ -407,6 +437,14 @@ public void createReport() { assertThat(returned.getState()).isEqualTo(ReportState.APPROVED); assertThat(returned.getApprovalStepUuid()).isNull(); + // The author should not be able to submit the report now + try { + graphQLHelper.updateObject(author, "submitReport", "uuid", FIELDS, "String", + returned.getUuid(), new TypeReference>() {}); + fail("Expected BadRequestException"); + } catch (BadRequestException expectedException) { + } + // check on report status to see that it got approved. workflow = returned.getWorkflow(); // there were 5 actions on the report: submit, reject, submit, approve, approve @@ -547,8 +585,8 @@ public void testDefaultApprovalFlow() throws NumberFormatException { new TypeReference>() {}); assertThat(r.getUuid()).isNotNull(); - // Submit the report - Report submitted = graphQLHelper.updateObject(jack, "submitReport", "uuid", FIELDS, "String", + // Submit the report (by admin who can do that, as author doesn't have a position) + Report submitted = graphQLHelper.updateObject(admin, "submitReport", "uuid", FIELDS, "String", r.getUuid(), new TypeReference>() {}); assertThat(submitted).isNotNull(); @@ -589,8 +627,7 @@ public void testDefaultApprovalFlow() throws NumberFormatException { // Put billet in EF 1.1 final OrganizationSearchQuery queryOrgs = new OrganizationSearchQuery(); - // FIXME: decide what the search should do in both cases - queryOrgs.setText(DaoUtils.isPostgresql() ? "\"EF 1\" or \"EF 1.1\"" : "EF 1"); + queryOrgs.setText("EF 1"); queryOrgs.setType(OrganizationType.ADVISOR_ORG); final AnetBeanList results = graphQLHelper.searchObjects(admin, "organizationList", "query", "OrganizationSearchQueryInput", ORGANIZATION_FIELDS, queryOrgs, @@ -693,7 +730,9 @@ public void reportEditTest() { // Elizabeth edits the report (update locationUuid and text, addPerson, remove a Task) returned.setLocation(loc); // update HTML of report text - returned.setReportText(UtilsTest.getCombinedTestCase().getInput()); + returned.setReportText(UtilsTest.getCombinedHtmlTestCase().getInput()); + // u[date JSON of customFields + returned.setCustomFields(UtilsTest.getCombinedJsonTestCase().getInput()); returned.setAttendees(ImmutableList.of(PersonTest.personToPrimaryReportPerson(roger), PersonTest.personToReportPerson(nick), PersonTest.personToPrimaryReportPerson(elizabeth))); returned.setTasks(ImmutableList.of()); @@ -711,7 +750,11 @@ public void reportEditTest() { assertThat(returned2Attendees).hasSize(3); assertThat(returned2Attendees.contains(roger)); // check that HTML of report text is sanitized after update - assertThat(returned2.getReportText()).isEqualTo(UtilsTest.getCombinedTestCase().getOutput()); + assertThat(returned2.getReportText()) + .isEqualTo(UtilsTest.getCombinedHtmlTestCase().getOutput()); + // check that JSON of customFields is sanitized after update + assertThat(returned2.getCustomFields()) + .isEqualTo(UtilsTest.getCombinedJsonTestCase().getOutput()); // Elizabeth submits the report Report submitted = graphQLHelper.updateObject(elizabeth, "submitReport", "uuid", FIELDS, @@ -842,8 +885,7 @@ public void searchTest() { // Search by direct organization OrganizationSearchQuery queryOrgs = new OrganizationSearchQuery(); - // FIXME: decide what the search should do in both cases - queryOrgs.setText(DaoUtils.isPostgresql() ? "\"EF 1\" or \"EF 1.1\"" : "EF 1"); + queryOrgs.setText("EF 1"); queryOrgs.setType(OrganizationType.ADVISOR_ORG); AnetBeanList orgs = graphQLHelper.searchObjects(jack, "organizationList", "query", "OrganizationSearchQueryInput", ORGANIZATION_FIELDS, queryOrgs, @@ -1253,6 +1295,14 @@ public void reportCancelTest() { Report returned2 = graphQLHelper.getObjectById(liz, "report", FIELDS, saved.getUuid(), new TypeReference>() {}); assertThat(returned2.getState()).isEqualTo(ReportState.CANCELLED); + + // The author should not be able to submit the report now + try { + graphQLHelper.updateObject(liz, "submitReport", "uuid", FIELDS, "String", returned2.getUuid(), + new TypeReference>() {}); + fail("Expected BadRequestException"); + } catch (BadRequestException expectedException) { + } } @Test @@ -1468,7 +1518,7 @@ public void testSensitiveInformationByAuthor() { "This reportTest was generated by ReportsResourceTest#testSensitiveInformation"); final ReportSensitiveInformation rsi = new ReportSensitiveInformation(); // set HTML of report sensitive information - rsi.setText(UtilsTest.getCombinedTestCase().getInput()); + rsi.setText(UtilsTest.getCombinedHtmlTestCase().getInput()); r.setReportSensitiveInformation(rsi); String returnedUuid = graphQLHelper.createObject(elizabeth, "createReport", "report", "ReportInput", r, new TypeReference>() {}); @@ -1480,24 +1530,25 @@ public void testSensitiveInformationByAuthor() { assertThat(returned.getReportSensitiveInformation()).isNotNull(); // check that HTML of report sensitive information is sanitized after create assertThat(returned.getReportSensitiveInformation().getText()) - .isEqualTo(UtilsTest.getCombinedTestCase().getOutput()); + .isEqualTo(UtilsTest.getCombinedHtmlTestCase().getOutput()); final Report returned2 = graphQLHelper.getObjectById(elizabeth, "report", rsiFields, returned.getUuid(), new TypeReference>() {}); // elizabeth should be allowed to see it assertThat(returned2.getReportSensitiveInformation()).isNotNull(); assertThat(returned2.getReportSensitiveInformation().getText()) - .isEqualTo(UtilsTest.getCombinedTestCase().getOutput()); + .isEqualTo(UtilsTest.getCombinedHtmlTestCase().getOutput()); // update HTML of report sensitive information - returned2.getReportSensitiveInformation().setText(UtilsTest.getCombinedTestCase().getInput()); + returned2.getReportSensitiveInformation() + .setText(UtilsTest.getCombinedHtmlTestCase().getInput()); Report updated = graphQLHelper.updateObject(elizabeth, "updateReport", "report", rsiFields, "ReportInput", returned2, new TypeReference>() {}); assertThat(updated).isNotNull(); assertThat(updated.getReportSensitiveInformation()).isNotNull(); // check that HTML of report sensitive information is sanitized after update assertThat(updated.getReportSensitiveInformation().getText()) - .isEqualTo(UtilsTest.getCombinedTestCase().getOutput()); + .isEqualTo(UtilsTest.getCombinedHtmlTestCase().getOutput()); final Person jack = getJackJackson(); final Report returned3 = graphQLHelper.getObjectById(jack, "report", rsiFields, @@ -1701,7 +1752,7 @@ private void createTestReport() { r.setEngagementDate(engagementDate); r.setAttendees(Lists.newArrayList(attendee)); r.setAdvisorOrg(advisorOrganization); - final String createdUuid = graphQLHelper.createObject(author, "createReport", "report", + final String createdUuid = graphQLHelper.createObject(admin, "createReport", "report", "ReportInput", r, new TypeReference>() {}); assertThat(createdUuid).isNotNull(); } diff --git a/src/test/java/mil/dds/anet/test/resources/TagResourceTest.java b/src/test/java/mil/dds/anet/test/resources/TagResourceTest.java index 802cf5dfe6..4d083107bd 100644 --- a/src/test/java/mil/dds/anet/test/resources/TagResourceTest.java +++ b/src/test/java/mil/dds/anet/test/resources/TagResourceTest.java @@ -5,10 +5,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import java.io.UnsupportedEncodingException; -import javax.ws.rs.BadRequestException; -import javax.ws.rs.ForbiddenException; import javax.ws.rs.NotFoundException; -import mil.dds.anet.beans.Person; import mil.dds.anet.beans.Tag; import mil.dds.anet.beans.lists.AnetBeanList; import mil.dds.anet.beans.search.TagSearchQuery; @@ -19,42 +16,6 @@ public class TagResourceTest extends AbstractResourceTest { private static final String FIELDS = "uuid name description createdAt"; - @Test - public void tagCreateUpdateAdminSuperUserTest() throws UnsupportedEncodingException { - // Check admin - createTag(admin, "name", "desc"); - // Check super-user - createTag(getSuperUser(), "name2", "desc2"); - } - - private void createTag(Person user, String name, String description) { - final Tag t = new Tag(); - t.setName(name); - t.setDescription(description); - - // Create - final String tUuid = graphQLHelper.createObject(user, "createTag", "tag", "TagInput", t, - new TypeReference>() {}); - assertThat(tUuid).isNotNull(); - final Tag created = graphQLHelper.getObjectById(user, "tag", FIELDS, tUuid, - new TypeReference>() {}); - assertThat(created.getName()).isEqualTo(t.getName()); - assertThat(created.getDescription()).isEqualTo(t.getDescription()); - assertThat(created.getCreatedAt()).isNotNull(); - assertThat(created).isNotEqualTo(t); - - // Update - created.setName("eman"); - final Integer nrUpdated = - graphQLHelper.updateObject(user, "updateTag", "tag", "TagInput", created); - assertThat(nrUpdated).isEqualTo(1); - - // Get - final Tag updated = graphQLHelper.getObjectById(user, "tag", FIELDS, tUuid, - new TypeReference>() {}); - assertThat(updated).isEqualTo(created); - } - @Test public void tagExceptionTest() throws UnsupportedEncodingException { // Get with unknown uuid @@ -64,14 +25,6 @@ public void tagExceptionTest() throws UnsupportedEncodingException { fail("Expected NotFoundException"); } catch (NotFoundException expectedException) { } - - // Create with empty name - try { - graphQLHelper.createObject(admin, "createTag", "tag", "TagInput", new Tag(), - new TypeReference>() {}); - fail("Expected BadRequestException"); - } catch (BadRequestException expectedException) { - } } @Test @@ -86,38 +39,4 @@ public void tagSearchTest() throws UnsupportedEncodingException { assertThat(searchObjects.getList()).isNotEmpty(); } - @Test - public void tagCreateRegularUserPermissionTest() throws UnsupportedEncodingException { - final Tag t = new Tag(); - t.setName("name3"); - t.setDescription("desc3"); - - try { - graphQLHelper.createObject(getRegularUser(), "createTag", "tag", "TagInput", t, - new TypeReference>() {}); - fail("Expected ForbiddenException"); - } catch (ForbiddenException expectedException) { - } - } - - @Test - public void tagUpdateRegularUserPermissionTest() throws UnsupportedEncodingException { - // Search for a tag from the initial data - final TagSearchQuery query = new TagSearchQuery(); - query.setText("bribery"); - final AnetBeanList searchObjects = - graphQLHelper.searchObjects(admin, "tagList", "query", "TagSearchQueryInput", FIELDS, query, - new TypeReference>>() {}); - assertThat(searchObjects).isNotNull(); - assertThat(searchObjects.getList()).isNotEmpty(); - final Tag t = searchObjects.getList().get(0); - t.setName(t.getName() + "_update"); - - try { - graphQLHelper.updateObject(getRegularUser(), "updateTag", "tag", "TagInput", t); - fail("Expected ForbiddenException"); - } catch (ForbiddenException expectedException) { - } - } - } diff --git a/src/test/java/mil/dds/anet/test/resources/TaskResourceTest.java b/src/test/java/mil/dds/anet/test/resources/TaskResourceTest.java index b7528ce795..93f40392e9 100644 --- a/src/test/java/mil/dds/anet/test/resources/TaskResourceTest.java +++ b/src/test/java/mil/dds/anet/test/resources/TaskResourceTest.java @@ -23,23 +23,29 @@ import mil.dds.anet.beans.search.TaskSearchQuery; import mil.dds.anet.test.TestData; import mil.dds.anet.test.resources.utils.GraphQlResponse; +import mil.dds.anet.utils.UtilsTest; import org.junit.jupiter.api.Test; public class TaskResourceTest extends AbstractResourceTest { private static final String FIELDS = - "uuid shortName longName category customFieldRef1 { uuid } taskedOrganizations { uuid } status"; + "uuid shortName longName category customFieldRef1 { uuid } taskedOrganizations { uuid }" + + " status customFields"; @Test public void taskTest() { final Person jack = getJackJackson(); final String aUuid = graphQLHelper.createObject(admin, "createTask", "task", "TaskInput", - TestData.createTask("TestF1", "Do a thing with a person", "Test-EF"), + TestData.createTask("TestF1", "Do a thing with a person", "Test-EF", + // set JSON of customFields + UtilsTest.getCombinedJsonTestCase().getInput()), new TypeReference>() {}); assertThat(aUuid).isNotNull(); final Task a = graphQLHelper.getObjectById(admin, "task", FIELDS, aUuid, new TypeReference>() {}); + // check that JSON of customFields is sanitized after create + assertThat(a.getCustomFields()).isEqualTo(UtilsTest.getCombinedJsonTestCase().getOutput()); final String bUuid = graphQLHelper.createObject( admin, "createTask", "task", "TaskInput", TestData.createTask("TestM1", @@ -67,12 +73,17 @@ public void taskTest() { // modify a task. a.setLongName("Do a thing with a person modified"); + // update JSON of customFields + a.setCustomFields(UtilsTest.getCombinedJsonTestCase().getInput()); final Integer nrUpdated = graphQLHelper.updateObject(admin, "updateTask", "task", "TaskInput", a); assertThat(nrUpdated).isEqualTo(1); final Task returned = graphQLHelper.getObjectById(jack, "task", FIELDS, aUuid, new TypeReference>() {}); assertThat(returned.getLongName()).isEqualTo(a.getLongName()); + // check that JSON of customFields is sanitized after update + assertThat(returned.getCustomFields()) + .isEqualTo(UtilsTest.getCombinedJsonTestCase().getOutput()); // Assign the Task to the AO final OrganizationSearchQuery queryOrgs = new OrganizationSearchQuery(); @@ -99,7 +110,7 @@ public void taskTest() { final AnetBeanList tasks = graphQLHelper.searchObjects(jack, "taskList", "query", "TaskSearchQueryInput", FIELDS, queryTasks, new TypeReference>>() {}); - assertThat(tasks.getList()).contains(a); + assertThat(tasks.getList()).contains(returned); // Search for the task: diff --git a/src/test/java/mil/dds/anet/utils/UtilsTest.java b/src/test/java/mil/dds/anet/utils/UtilsTest.java index aadfc4bb98..45aebb4fdd 100644 --- a/src/test/java/mil/dds/anet/utils/UtilsTest.java +++ b/src/test/java/mil/dds/anet/utils/UtilsTest.java @@ -2,6 +2,7 @@ import static org.assertj.core.api.Assertions.assertThat; +import com.fasterxml.jackson.core.JsonProcessingException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -10,12 +11,11 @@ public class UtilsTest { public static class InOut { - String input; - String output; + private String input; + private String output; public InOut(String inputOutput) { - this.input = inputOutput; - this.output = inputOutput; + this(inputOutput, inputOutput); } public InOut(String input, String output) { @@ -40,17 +40,23 @@ public void setOutput(String output) { } } - private static List testCases = new ArrayList<>(); + public static InOut getCombinedHtmlTestCase() { + return getCombinedTestCase(getHtmlTestCases()); + } + + private static void addTestCase(List testCases, InOut inOut) { + testCases.add(inOut); + } - private static void addTestCase(String inputOutput) { + private static void addTestCase(List testCases, String inputOutput) { testCases.add(new InOut(inputOutput)); } - private static void addTestCase(String input, String output) { + private static void addTestCase(List testCases, String input, String output) { testCases.add(new InOut(input, output)); } - public static InOut getCombinedTestCase() { + private static InOut getCombinedTestCase(List testCases) { final StringBuilder input = new StringBuilder(); final StringBuilder output = new StringBuilder(); for (final InOut testCase : testCases) { @@ -60,48 +66,87 @@ public static InOut getCombinedTestCase() { return new InOut(input.toString(), output.toString()); } - // set up test cases (feel free to add more) - static { + // set up HMTL test cases (feel free to add more) + private static List getHtmlTestCases() { + final List testCases = new ArrayList<>(); //

tag is allowed - addTestCase("

test

"); + addTestCase(testCases, "

test

"); // tag is not allowed - addTestCase("test", "test"); + addTestCase(testCases, "test", "test"); // href's are allowed to http, https and mailto, but nofollow is added - addTestCase("
test", + addTestCase(testCases, "test", "test"); - addTestCase("test", + addTestCase(testCases, "test", "test"); - addTestCase("test", + addTestCase(testCases, "test", "test"); // href's to ftp and data are not allowed - addTestCase("test", "test"); - addTestCase("test", "test"); + addTestCase(testCases, "test", "test"); + addTestCase(testCases, "test", "test"); // but title is - addTestCase("test", "test"); + addTestCase(testCases, "test", + "test"); // in-line is allowed - addTestCase(""); + addTestCase(testCases, ""); // reference is not allowed - addTestCase("", ""); + addTestCase(testCases, "", ""); // allowed attributes - addTestCase( + addTestCase(testCases, "\"test\""); // disallowed attributes - addTestCase("", ""); - addTestCase("", ""); + addTestCase(testCases, "", ""); + addTestCase(testCases, "", ""); // ", ""); + addTestCase(testCases, "", + ""); + return testCases; } @Test public void testSanitizeHtml() { + final List testCases = getHtmlTestCases(); for (final InOut testCase : testCases) { assertThat(Utils.sanitizeHtml(testCase.getInput())).isEqualTo(testCase.getOutput()); } - final InOut combinedTestCase = getCombinedTestCase(); + final InOut combinedTestCase = getCombinedHtmlTestCase(); assertThat(Utils.sanitizeHtml(combinedTestCase.getInput())) .isEqualTo(combinedTestCase.getOutput()); } + public static InOut getCombinedJsonTestCase() { + final InOut combinedHtmlTestCase = getCombinedHtmlTestCase(); + final String input = String.format("{\"html\":\"%s\"}", + combinedHtmlTestCase.getInput().replaceAll("\"", "\\\\\"")); + final String output = String.format("{\"html\":\"%s\"}", + combinedHtmlTestCase.getOutput().replaceAll("\"", "\\\\\"")); + return new InOut(input, output); + } + + // set up JSON test cases (feel free to add more) + private static List getJsonTestCases() { + final List testCases = new ArrayList<>(); + // allowed + addTestCase(testCases, "{\"bool\":true}"); + // will be corrected + addTestCase(testCases, "{\"bool\":true", "{\"bool\":true}"); + // will be stripped down + addTestCase(testCases, "\"bool\":true}", "\"bool\""); + // will be stripped down + addTestCase(testCases, "\"bool\":true", "\"bool\""); + // check sanitized HTML + final InOut combinedJsonTestCase = getCombinedJsonTestCase(); + addTestCase(testCases, combinedJsonTestCase); + return testCases; + } + + @Test + public void testSanitizeJson() throws JsonProcessingException { + final List testCases = getJsonTestCases(); + for (final InOut testCase : testCases) { + assertThat(Utils.sanitizeJson(testCase.getInput())).isEqualTo(testCase.getOutput()); + } + } + @Test public void testWhitelistedEmailAddresses() { diff --git a/src/test/resources/graphQLTests/orgShow.gql b/src/test/resources/graphQLTests/orgShow.gql index 081a8e6f2c..1059150d8c 100644 --- a/src/test/resources/graphQLTests/orgShow.gql +++ b/src/test/resources/graphQLTests/orgShow.gql @@ -93,6 +93,33 @@ organization(uuid:"${orgUuid}") { noteUuid relatedObjectType relatedObjectUuid + relatedObject { + ... on AuthorizationGroup { + name + } + ... on Location { + name + } + ... on Organization { + shortName + } + ... on Person { + role + rank + name + } + ... on Position { + type + name + } + ... on Report { + intent + } + ... on Task { + shortName + longName + } + } } } } diff --git a/src/test/resources/graphQLTests/person-all-paged.gql b/src/test/resources/graphQLTests/person-all-paged.gql index af1107a257..17773c9e1b 100644 --- a/src/test/resources/graphQLTests/person-all-paged.gql +++ b/src/test/resources/graphQLTests/person-all-paged.gql @@ -1,5 +1,6 @@ personList(query:{pageNum:${pageNum}, pageSize:${pageSize}}) { list { uuid, name, rank, role, emailAddress, avatar(size: 32), position { uuid, name, type, code, location { uuid, name }, organization { uuid, shortName} } + customFields } } diff --git a/src/test/resources/graphQLTests/person-all.gql b/src/test/resources/graphQLTests/person-all.gql index e9802d5c30..d79f747ba6 100644 --- a/src/test/resources/graphQLTests/person-all.gql +++ b/src/test/resources/graphQLTests/person-all.gql @@ -1,5 +1,6 @@ personList(query:{pageSize:0}) { list { uuid, name, rank, role, emailAddress, avatar(size: 32), position { uuid, name, type, code, location { uuid, name }, organization { uuid, shortName} } + customFields } } diff --git a/src/test/resources/graphQLTests/person-recents-maxResults.gql b/src/test/resources/graphQLTests/person-recents-maxResults.gql index b849db6e38..8afe72bb13 100644 --- a/src/test/resources/graphQLTests/person-recents-maxResults.gql +++ b/src/test/resources/graphQLTests/person-recents-maxResults.gql @@ -21,5 +21,6 @@ personList(query: {pageSize: ${maxResults}, status: ACTIVE, inMyReports: true, s name } } + customFields } } diff --git a/src/test/resources/graphQLTests/person-recents.gql b/src/test/resources/graphQLTests/person-recents.gql index 26080b4bea..8f3be08bc6 100644 --- a/src/test/resources/graphQLTests/person-recents.gql +++ b/src/test/resources/graphQLTests/person-recents.gql @@ -21,5 +21,6 @@ personList(query: {status: ACTIVE, inMyReports: true, sortBy: RECENT, sortOrder: name } } + customFields } } diff --git a/src/test/resources/graphQLTests/person.gql b/src/test/resources/graphQLTests/person.gql index 01ba4690e8..94f9003c0a 100644 --- a/src/test/resources/graphQLTests/person.gql +++ b/src/test/resources/graphQLTests/person.gql @@ -61,6 +61,34 @@ person(uuid:"${personUuid}") { noteUuid relatedObjectType relatedObjectUuid + relatedObject { + ... on AuthorizationGroup { + name + } + ... on Location { + name + } + ... on Organization { + shortName + } + ... on Person { + role + rank + name + } + ... on Position { + type + name + } + ... on Report { + intent + } + ... on Task { + shortName + longName + } + } } } + customFields } diff --git a/src/test/resources/graphQLTests/positions.gql b/src/test/resources/graphQLTests/positions.gql index 0b257467ba..9ea20d617b 100644 --- a/src/test/resources/graphQLTests/positions.gql +++ b/src/test/resources/graphQLTests/positions.gql @@ -64,6 +64,33 @@ position(uuid:"${positionUuid}") { noteUuid relatedObjectType relatedObjectUuid + relatedObject { + ... on AuthorizationGroup { + name + } + ... on Location { + name + } + ... on Organization { + shortName + } + ... on Person { + role + rank + name + } + ... on Position { + type + name + } + ... on Report { + intent + } + ... on Task { + shortName + longName + } + } } } } diff --git a/src/test/resources/graphQLTests/report-all-recents.gql b/src/test/resources/graphQLTests/report-all-recents.gql index d18d1b998c..603071cc6c 100644 --- a/src/test/resources/graphQLTests/report-all-recents.gql +++ b/src/test/resources/graphQLTests/report-all-recents.gql @@ -27,6 +27,7 @@ personList(query: {pageSize: 6, status: ACTIVE, inMyReports: true, sortBy: RECEN name } } + customFields } } taskList(query: {pageSize: 6, status: ACTIVE, inMyReports: true, sortBy: RECENT, sortOrder: DESC}) { diff --git a/src/test/resources/graphQLTests/report.gql b/src/test/resources/graphQLTests/report.gql index ce8cdfea31..547769fa76 100644 --- a/src/test/resources/graphQLTests/report.gql +++ b/src/test/resources/graphQLTests/report.gql @@ -177,6 +177,34 @@ report(uuid:"${reportUuid}") { noteUuid relatedObjectType relatedObjectUuid + relatedObject { + ... on AuthorizationGroup { + name + } + ... on Location { + name + } + ... on Organization { + shortName + } + ... on Person { + role + rank + name + } + ... on Position { + type + name + } + ... on Report { + intent + } + ... on Task { + shortName + longName + } + } } } + customFields } diff --git a/src/test/resources/graphQLTests/reportsAll.gql b/src/test/resources/graphQLTests/reportsAll.gql index 6a8042d5ea..2c2ea5f2e3 100644 --- a/src/test/resources/graphQLTests/reportsAll.gql +++ b/src/test/resources/graphQLTests/reportsAll.gql @@ -46,6 +46,7 @@ reportList(query:{pageSize:100}) { tasks { uuid shortName + customFields } tags { uuid @@ -77,5 +78,6 @@ reportList(query:{pageSize:100}) { } } updatedAt + customFields } } diff --git a/src/test/resources/graphQLTests/tasks-with-positions.gql b/src/test/resources/graphQLTests/tasks-with-positions.gql index e31e3ec634..5308007201 100644 --- a/src/test/resources/graphQLTests/tasks-with-positions.gql +++ b/src/test/resources/graphQLTests/tasks-with-positions.gql @@ -22,5 +22,6 @@ taskList(query: {pageSize: 0}) { avatar(size: 32) } } + customFields } } diff --git a/src/test/resources/graphQLTests/tasks-with-reports.gql b/src/test/resources/graphQLTests/tasks-with-reports.gql index 34557ede69..30b6632f03 100644 --- a/src/test/resources/graphQLTests/tasks-with-reports.gql +++ b/src/test/resources/graphQLTests/tasks-with-reports.gql @@ -16,5 +16,6 @@ taskList(query: {text: "1.1.", pageSize: 0}) { textReportsCopy: reports(query: {text: "meet"}) { uuid } + customFields } } diff --git a/src/test/resources/graphQLTests/tasksAll-with-reports.gql b/src/test/resources/graphQLTests/tasksAll-with-reports.gql index 7e6493e7a4..57a33a5be3 100644 --- a/src/test/resources/graphQLTests/tasksAll-with-reports.gql +++ b/src/test/resources/graphQLTests/tasksAll-with-reports.gql @@ -25,5 +25,6 @@ taskList(query: {pageSize: 0}) { approvedReports: reports(query: {state: [APPROVED]}) { uuid } + customFields } } diff --git a/src/test/resources/graphQLTests/tasksAll.gql b/src/test/resources/graphQLTests/tasksAll.gql index 73dbba7348..13a56020a0 100644 --- a/src/test/resources/graphQLTests/tasksAll.gql +++ b/src/test/resources/graphQLTests/tasksAll.gql @@ -4,5 +4,6 @@ taskList(query: {pageSize: 0}) { uuid shortName longName + customFields } } diff --git a/src/test/resources/testJson/groups/groupA.json b/src/test/resources/testJson/groups/groupA.json deleted file mode 100644 index 845b71ea47..0000000000 --- a/src/test/resources/testJson/groups/groupA.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "uuid" : null, - "name" : "Group Alpha", - "members" : [ - {"uuid" : "1"}, - {"uuid" : "2"} - ] -} diff --git a/src/test/resources/testJson/groups/groupB.json b/src/test/resources/testJson/groups/groupB.json deleted file mode 100644 index df14a5d85b..0000000000 --- a/src/test/resources/testJson/groups/groupB.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name" : "Group Bravo", - "members" : { - {"uuid" : "2"}, - {"uuid" : "3"} - } -} diff --git a/src/test/resources/testJson/groups/loadAll.sh b/src/test/resources/testJson/groups/loadAll.sh deleted file mode 100755 index 341d4db09c..0000000000 --- a/src/test/resources/testJson/groups/loadAll.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -ls *.json | while read file -do - curl localhost:8080/groups/new --data @${file} -H "Content-Type: application/json" -done