From 304c413ad34d9b4f2ac2c2a0e4bcc715c1fa2b4c Mon Sep 17 00:00:00 2001 From: Vassil Iordanov Date: Fri, 28 Feb 2020 18:18:18 +0100 Subject: [PATCH 001/247] nci-agency/anet#2889: Add diagram library --- anet.yml | 2 + client/package.json | 8 + client/src/pages/Routing.js | 9 + .../src/pages/dashboards/BoardDashboard.css | 39 +++++ client/src/pages/dashboards/BoardDashboard.js | 44 +++++ client/yarn.lock | 154 +++++++++++++++++- src/main/resources/anet-schema.yml | 1 + 7 files changed, 255 insertions(+), 2 deletions(-) create mode 100644 client/src/pages/dashboards/BoardDashboard.css create mode 100644 client/src/pages/dashboards/BoardDashboard.js diff --git a/anet.yml b/anet.yml index 9b2b04196b..9096200de8 100644 --- a/anet.yml +++ b/anet.yml @@ -663,3 +663,5 @@ dictionary: - label: decisives data: /data/dashboards/decisives.json type: decisives + - label: process board + type: board \ No newline at end of file diff --git a/client/package.json b/client/package.json index 246c60c308..63e3a8a8b3 100644 --- a/client/package.json +++ b/client/package.json @@ -99,18 +99,23 @@ "@apollo/react-hooks": "3.1.3", "@blueprintjs/core": "3.24.0", "@blueprintjs/datetime": "3.15.2", + "@emotion/core": "^10.0.28", + "@emotion/styled": "^10.0.27", "@fullcalendar/core": "4.4.0", "@fullcalendar/daygrid": "4.4.0", "@fullcalendar/interaction": "4.4.0", "@fullcalendar/list": "4.4.0", "@fullcalendar/react": "4.4.0", "@fullcalendar/timegrid": "4.4.0", + "@projectstorm/react-diagrams": "^6.0.1-beta.7", "apollo-boost": "0.4.7", "bootstrap": "3.4.1", "change-case": "4.1.1", "classnames": "2.2.6", + "closest": "^0.0.1", "core-js": "3.6.4", "d3": "5.15.0", + "dagre": "^0.8.5", "draft-convert": "2.1.8", "draft-js": "0.10.5", "draft-js-buttons": "2.0.2", @@ -130,8 +135,11 @@ "leaflet.markercluster": "1.4.1", "locale-compare-polyfill": "0.0.2", "lodash": "4.17.15", + "mathjs": "^6.6.1", "milsymbol": "2.0.0", "moment": "2.24.0", + "pathfinding": "^0.4.18", + "paths-js": "^0.4.10", "pluralize": "8.0.0", "prop-types": "15.7.2", "react": "16.13.0", diff --git a/client/src/pages/Routing.js b/client/src/pages/Routing.js index 02feefa7dd..763585e1a4 100644 --- a/client/src/pages/Routing.js +++ b/client/src/pages/Routing.js @@ -6,6 +6,7 @@ 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 KanbanDashboard from "pages/dashboards/KanbanDashboard" import DecisivesDashboard from "pages/dashboards/DecisivesDashboard" import GraphiQL from "pages/GraphiQL" @@ -160,6 +161,14 @@ const BaseRouting = ({ currentUser }) => ( )} /> + ( + + + + )} + /> diff --git a/client/src/pages/dashboards/BoardDashboard.css b/client/src/pages/dashboards/BoardDashboard.css new file mode 100644 index 0000000000..5559267521 --- /dev/null +++ b/client/src/pages/dashboards/BoardDashboard.css @@ -0,0 +1,39 @@ + +.diagram-container{ + width: 100%; + height: 100%; +} + +.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..a99e0e30ea --- /dev/null +++ b/client/src/pages/dashboards/BoardDashboard.js @@ -0,0 +1,44 @@ +import { CanvasWidget } from "@projectstorm/react-canvas-core" +import createEngine, { + DefaultNodeModel, + DiagramModel +} from "@projectstorm/react-diagrams" +import "./BoardDashboard.css" +import { + mapPageDispatchersToProps, + PageDispatchersPropType +} from "components/Page" +import React from "react" +import { connect } from "react-redux" + +const BoardDashboard = ({ pageDispatchers }) => { + const engine = createEngine() + + const node1 = new DefaultNodeModel({ + name: "Node 1", + color: "rgb(0,192,255)" + }) + + node1.setPosition(100, 100) + const port1 = node1.addOutPort("Out") + + const node2 = new DefaultNodeModel({ + name: "Node 1", + color: "rgb(0,192,255)" + }) + + node2.setPosition(100, 100) + const port2 = node2.addOutPort("Out") + + const link = port1.link(port2) + + const model = new DiagramModel() + model.addAll(node1, node2, link) + engine.setModel(model) + + return +} + +BoardDashboard.propTypes = { pageDispatchers: PageDispatchersPropType } + +export default connect(null, mapPageDispatchersToProps)(BoardDashboard) diff --git a/client/yarn.lock b/client/yarn.lock index 0e8a0ef494..3219e653b7 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -2091,6 +2091,18 @@ "@emotion/sheet" "0.9.4" "@emotion/utils" "0.11.3" +"@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== + dependencies: + "@babel/runtime" "^7.5.5" + "@emotion/cache" "^10.0.27" + "@emotion/css" "^10.0.27" + "@emotion/serialize" "^0.11.15" + "@emotion/sheet" "0.9.4" + "@emotion/utils" "0.11.3" + "@emotion/css@^10.0.27": version "10.0.27" resolved "https://registry.yarnpkg.com/@emotion/css/-/css-10.0.27.tgz#3a7458198fbbebb53b01b2b87f64e5e21241e14c" @@ -2143,7 +2155,7 @@ "@emotion/serialize" "^0.11.15" "@emotion/utils" "0.11.3" -"@emotion/styled@^10.0.17": +"@emotion/styled@^10.0.17", "@emotion/styled@^10.0.27": 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== @@ -2450,6 +2462,51 @@ "@nodelib/fs.scandir" "2.1.3" fastq "^1.6.0" +"@projectstorm/geometry@^6.0.1-beta.7": + version "6.0.1-beta.7" + resolved "https://registry.yarnpkg.com/@projectstorm/geometry/-/geometry-6.0.1-beta.7.tgz#181f73798d3e792b7aee5ad4a07516ec6d3d9ffb" + integrity sha512-gWoD6tPx+4k0gWo0z9DCxp9zHqcsNLxGtgdmfIfwRQuPcXJcbhvc7cQ95QIAWVcbFDHMVPzURzaY/11UH+b9uQ== + +"@projectstorm/react-canvas-core@^6.0.1-beta.7": + version "6.0.1-beta.7" + resolved "https://registry.yarnpkg.com/@projectstorm/react-canvas-core/-/react-canvas-core-6.0.1-beta.7.tgz#e977fa6aa6ee362ce803397bc279651784473497" + integrity sha512-yogNt9N/86z+D9dhr0GO40txq9RImUaj4ZE43xiDnHOzf6LellLNXyrnYOwN0wjRiwMhznCbHsS4SoKMV1a/LQ== + dependencies: + "@projectstorm/geometry" "^6.0.1-beta.7" + +"@projectstorm/react-diagrams-core@^6.0.1-beta.7": + version "6.0.1-beta.7" + resolved "https://registry.yarnpkg.com/@projectstorm/react-diagrams-core/-/react-diagrams-core-6.0.1-beta.7.tgz#d157834307e238e76da9fd538451ec7a841296ba" + integrity sha512-lTsZr5JqPlKxe8DicxomedoDI9Gnf1OYxmTC819ChVqizj1mWV6jB+0p3VIPSPO+mRC8emX/onOkLh3Szj9QRQ== + dependencies: + "@projectstorm/geometry" "^6.0.1-beta.7" + "@projectstorm/react-canvas-core" "^6.0.1-beta.7" + +"@projectstorm/react-diagrams-defaults@^6.0.1-beta.7": + version "6.0.1-beta.7" + resolved "https://registry.yarnpkg.com/@projectstorm/react-diagrams-defaults/-/react-diagrams-defaults-6.0.1-beta.7.tgz#01ec4d47dc653b5caf1550a56707c62ee746d771" + integrity sha512-AueksmJj/jYje1KYOvQAL3OUufIko+04Iwz3qeTGUNipQprJsjL2ImCL5jfTv2qKLrzgz60E6w/H8XpmJwLHZg== + dependencies: + "@projectstorm/react-diagrams-core" "^6.0.1-beta.7" + +"@projectstorm/react-diagrams-routing@^6.0.1-beta.7": + version "6.0.1-beta.7" + resolved "https://registry.yarnpkg.com/@projectstorm/react-diagrams-routing/-/react-diagrams-routing-6.0.1-beta.7.tgz#08fbe8c811fab3fa24e8432974376aeb45b1af82" + integrity sha512-tmts3N7COIVzykEFwt3Du8q62HuSKQuIGCj/UHz7IvjvWTz8Szo/igr9lBIJWO6f7mr9EnDdWCK0SP7QWKQZpA== + dependencies: + "@projectstorm/geometry" "^6.0.1-beta.7" + "@projectstorm/react-diagrams-core" "^6.0.1-beta.7" + "@projectstorm/react-diagrams-defaults" "^6.0.1-beta.7" + +"@projectstorm/react-diagrams@^6.0.1-beta.7": + version "6.0.1-beta.7" + resolved "https://registry.yarnpkg.com/@projectstorm/react-diagrams/-/react-diagrams-6.0.1-beta.7.tgz#b6907415b1a0467dd25d58da6bf12a0f2ccc915d" + integrity sha512-aEQuRyNtzrlc6TNVji5Zme9fJkOcnCdiskPFXF14c0b9MJO4cz8yUrGZh0/MjsSH8pQl1sB71mnGFLQ20aAHmQ== + dependencies: + "@projectstorm/react-diagrams-core" "^6.0.1-beta.7" + "@projectstorm/react-diagrams-defaults" "^6.0.1-beta.7" + "@projectstorm/react-diagrams-routing" "^6.0.1-beta.7" + "@reach/router@^1.2.1": version "1.2.1" resolved "https://registry.yarnpkg.com/@reach/router/-/router-1.2.1.tgz#34ae3541a5ac44fa7796e5506a5d7274a162be4e" @@ -5766,6 +5823,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.0.4" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.0.4.tgz#0c0171f6d5cb2fe83848463c15fcc26b4df8c2ec" @@ -5912,6 +5976,11 @@ 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" @@ -6800,6 +6869,14 @@ d3@5.15.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.4: version "1.0.4" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz#03191c432cb6eea168bb77f3a55ffdccb8978514" @@ -6873,6 +6950,11 @@ decamelize@^1.1.1, decamelize@^1.2.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= +decimal.js@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.0.tgz#39466113a9e036111d02f82489b5fd6b0b5ed231" + integrity sha512-vDPw+rDgn3bZe1+F/pyEwb1oMG2XTlRVgAa6B4KccTEpYgF8w6eQllVbQcfIJnZyvzFtFpxnpGtx8dd7DJp/Rw== + decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" @@ -7727,6 +7809,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" @@ -8747,6 +8834,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" @@ -9316,6 +9408,13 @@ graphiql@0.17.5: markdown-it "^10.0.0" regenerator-runtime "^0.13.3" +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-cli-prepare@1.4.19: version "1.4.19" resolved "https://registry.yarnpkg.com/graphql-cli-prepare/-/graphql-cli-prepare-1.4.19.tgz#9df5d608ba42c4947d7ef24f9fc39e3df0c89301" @@ -9698,6 +9797,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" @@ -10840,6 +10944,11 @@ java-properties@^0.2.9: resolved "https://registry.yarnpkg.com/java-properties/-/java-properties-0.2.10.tgz#2551560c25fa1ad94d998218178f233ad9b18f60" integrity sha512-CpKJh9VRNhS+XqZtg1UMejETGEiqwCGDC/uwPEEQwc2nfdbSm73SIE29TplG2gLYuBOOTNDqxzG6A9NtEPLt0w== +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@^25.1.0: version "25.1.0" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-25.1.0.tgz#73dae9a7d9949fdfa5c278438ce8f2ff3ec78131" @@ -12177,11 +12286,30 @@ matcher@^2.1.0: dependencies: escape-string-regexp "^2.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.17" resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac" integrity sha1-3oGf282E3M2PrlnGrreWFbnSZqw= +mathjs@^6.6.1: + version "6.6.1" + resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-6.6.1.tgz#46675c9e97b8cb8cf9a66402b1360a6996abf103" + integrity sha512-RCFCYkf1IV3u0DAeqj2Rqqwyi302kFxHoYbfp/Bxm6kUg0ALYH7YT0bYzsO8qgCLv9RS3bWMZnAgUbLgiDjLcw== + 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 "^1.1.1" + md5-hex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-2.0.0.tgz#d0588e9f1c74954492ecd24ac0ac6ce997d92e33" @@ -13689,6 +13817,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.10: + version "0.4.10" + resolved "https://registry.yarnpkg.com/paths-js/-/paths-js-0.4.10.tgz#a3575f409b4a36f8aa795ba4d051989021be58c7" + integrity sha512-JZoqlRSHtx+bc+xKI9o4bropEbqZBF4ZfYImiB1T9RYpHB73h5I8XZ7FfSBbHbBMtdD1c04ujjAPH8wUuu4+Gw== + pathval@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" @@ -15632,6 +15772,11 @@ scuid@^1.0.2: resolved "https://registry.yarnpkg.com/scuid/-/scuid-1.1.0.tgz#d3f9f920956e737a60f72d0e4ad280bf324d5dab" integrity sha512-MuCAyrGZcTLfQoH2XoBlQ8C6bzwN88XT/0slOGz0pn8+gIP85BOAfYa44ZXQUTOwRwPU0QvgU+V+OSajl/59Xg== +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" @@ -16905,7 +17050,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== @@ -17178,6 +17323,11 @@ type-is@~1.6.17, type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" +typed-function@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/typed-function/-/typed-function-1.1.1.tgz#a1316187ec3628c9e219b91ca96918660a10138e" + integrity sha512-RbN7MaTQBZLJYzDENHPA0nUmWT0Ex80KHItprrgbTPufYhIlTePvCXZxyQK7wgn19FW5bnuaBIKcBb5mRWjB1Q== + typed-styles@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/typed-styles/-/typed-styles-0.0.7.tgz#93392a008794c4595119ff62dde6809dbc40a3d9" diff --git a/src/main/resources/anet-schema.yml b/src/main/resources/anet-schema.yml index 1b712794ca..7de1ea41a5 100644 --- a/src/main/resources/anet-schema.yml +++ b/src/main/resources/anet-schema.yml @@ -749,6 +749,7 @@ properties: type: type: string enum: + - board - kanban - decisives From ca800e0570d7465690c9590167f31eeb3df93edf Mon Sep 17 00:00:00 2001 From: vassil Date: Wed, 18 Mar 2020 17:32:41 +0100 Subject: [PATCH 002/247] nci-agency/anet#2889: Add serialization and rudimentary DnD to process boards --- anet.yml | 3 +- client/src/pages/dashboards/BoardDashboard.js | 141 +++++++++++++++--- data/dashboards/process.json | 138 +++++++++++++++++ 3 files changed, 260 insertions(+), 22 deletions(-) create mode 100644 data/dashboards/process.json diff --git a/anet.yml b/anet.yml index 9096200de8..2b35ce9114 100644 --- a/anet.yml +++ b/anet.yml @@ -664,4 +664,5 @@ dictionary: data: /data/dashboards/decisives.json type: decisives - label: process board - type: board \ No newline at end of file + type: board + data: /data/dashboards/process.json diff --git a/client/src/pages/dashboards/BoardDashboard.js b/client/src/pages/dashboards/BoardDashboard.js index a99e0e30ea..f98bdd1e86 100644 --- a/client/src/pages/dashboards/BoardDashboard.js +++ b/client/src/pages/dashboards/BoardDashboard.js @@ -3,40 +3,139 @@ import createEngine, { DefaultNodeModel, DiagramModel } from "@projectstorm/react-diagrams" -import "./BoardDashboard.css" +import { Settings } from "api" import { mapPageDispatchersToProps, PageDispatchersPropType } from "components/Page" -import React from "react" +import FileSaver from "file-saver" +import _keys from "lodash/keys" +import PropTypes from "prop-types" +import React, { useEffect, useState, useRef } from "react" +import { Button } from "react-bootstrap" import { connect } from "react-redux" +import { useParams } from "react-router-dom" +import DOWNLOAD_ICON from "resources/download.png" +import "./BoardDashboard.css" -const BoardDashboard = ({ pageDispatchers }) => { - const engine = createEngine() +const PrototypeNode = ({ name, model }) => ( +
{ + event.dataTransfer.setData("storm-diagram-node", JSON.stringify(model)) + }} + > + {name} +
+) - const node1 = new DefaultNodeModel({ - name: "Node 1", - color: "rgb(0,192,255)" - }) +PrototypeNode.propTypes = { + name: PropTypes.string, + model: PropTypes.object +} - node1.setPosition(100, 100) - const port1 = node1.addOutPort("Out") +const BoardDashboard = ({ pageDispatchers }) => { + const { dashboard } = useParams() + const dashboardSettings = Settings.dashboards.find(o => o.label === dashboard) + const [dropEvent, setDropEvent] = useState() + const engineRef = useRef(createEngine()) + const [model, setModel] = useState() - const node2 = new DefaultNodeModel({ - name: "Node 1", - color: "rgb(0,192,255)" - }) + useEffect(() => { + setModel(new DiagramModel()) + }, []) - node2.setPosition(100, 100) - const port2 = node2.addOutPort("Out") + useEffect(() => { + engineRef.current.setModel(model) + }, [model]) - const link = port1.link(port2) + 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]) - const model = new DiagramModel() - model.addAll(node1, node2, link) - engine.setModel(model) + useEffect(() => { + if (dropEvent) { + const data = JSON.parse( + dropEvent.dataTransfer.getData("storm-diagram-node") + ) + const nodesCount = _keys(model.getNodes()).length - return + let node = null + if (data.type === "in") { + node = new DefaultNodeModel( + "Node " + (nodesCount + 1), + "rgb(192,255,0)" + ) + node.addInPort("In") + } else { + node = new DefaultNodeModel( + "Node " + (nodesCount + 1), + "rgb(0,192,255)" + ) + node.addOutPort("Out") + } + const point = engineRef.current.getRelativeMousePoint(dropEvent) + node.setPosition(point) + engineRef.current.getModel().addNode(node) + setDropEvent(null) + } + }, [model, dropEvent]) + return ( +
+
+ + + +
+
{ + event.persist() + setDropEvent(event) + }} + onDragOver={event => { + event.preventDefault() + }} + > + {engineRef.current.getModel() && ( + + )} +
+
+ ) } BoardDashboard.propTypes = { pageDispatchers: PageDispatchersPropType } diff --git a/data/dashboards/process.json b/data/dashboards/process.json new file mode 100644 index 0000000000..159c8afa2e --- /dev/null +++ b/data/dashboards/process.json @@ -0,0 +1,138 @@ +{ + "id": "abcbacb3-9193-4e5a-af27-25beb91ffefd", + "offsetX": 0, + "offsetY": 0, + "zoom": 100, + "gridSize": 0, + "layers": [ + { + "id": "e5a4fb5a-be1b-4d55-8721-a82d4550ab9f", + "type": "diagram-links", + "isSvg": true, + "transformed": true, + "models": { + "c9140f61-31ef-4097-bc13-4097f609b65c": { + "id": "c9140f61-31ef-4097-bc13-4097f609b65c", + "type": "default", + "source": "65c4c390-4248-4424-83d1-79768ecc614f", + "sourcePort": "fe1e6f91-0ca8-4ac6-b6b5-331123841ebc", + "target": "3642c9ae-dc23-4918-ad01-7a09f26d97e0", + "targetPort": "9268bc0f-46be-4de0-aa64-0ccdf48d786a", + "points": [ + { + "id": "e6135fb0-4a17-4b04-a4d0-939c4a1efbcb", + "type": "point", + "x": 1178.421875, + "y": 500.5 + }, + { + "id": "b62fbbf7-3b65-4ec5-90fb-debd82f938ab", + "type": "point", + "x": 520.5, + "y": 243.5 + } + ], + "labels": [], + "width": 3, + "color": "gray", + "curvyness": 50, + "selectedColor": "rgb(0,192,255)" + } + } + }, + { + "id": "9e15b34a-fa1d-4780-942d-82823161faf1", + "type": "diagram-nodes", + "isSvg": false, + "transformed": true, + "models": { + "65c4c390-4248-4424-83d1-79768ecc614f": { + "id": "65c4c390-4248-4424-83d1-79768ecc614f", + "type": "default", + "selected": true, + "x": 1097, + "y": 466, + "ports": [ + { + "id": "fe1e6f91-0ca8-4ac6-b6b5-331123841ebc", + "type": "default", + "x": 1170.921875, + "y": 493, + "name": "Out", + "alignment": "right", + "parentNode": "65c4c390-4248-4424-83d1-79768ecc614f", + "links": [ + "c9140f61-31ef-4097-bc13-4097f609b65c" + ], + "in": false, + "label": "Out" + }, + { + "id": "c4b9ee46-4e2f-4d56-a67c-5ca2af64cd21", + "type": "default", + "x": 1099, + "y": 493, + "name": "In", + "alignment": "left", + "parentNode": "65c4c390-4248-4424-83d1-79768ecc614f", + "links": [], + "in": true, + "label": "In" + } + ], + "name": "Node 1", + "color": "rgb(0,192,255)", + "portsInOrder": [ + "c4b9ee46-4e2f-4d56-a67c-5ca2af64cd21" + ], + "portsOutOrder": [ + "fe1e6f91-0ca8-4ac6-b6b5-331123841ebc" + ] + }, + "3642c9ae-dc23-4918-ad01-7a09f26d97e0": { + "id": "3642c9ae-dc23-4918-ad01-7a09f26d97e0", + "type": "default", + "selected": false, + "x": 511, + "y": 209, + "ports": [ + { + "id": "9268bc0f-46be-4de0-aa64-0ccdf48d786a", + "type": "default", + "x": 513, + "y": 236, + "name": "In", + "alignment": "left", + "parentNode": "3642c9ae-dc23-4918-ad01-7a09f26d97e0", + "links": [ + "c9140f61-31ef-4097-bc13-4097f609b65c" + ], + "in": true, + "label": "In" + }, + { + "id": "de5daf16-dc2e-4f8e-8744-88f212a37cc5", + "type": "default", + "x": 584.921875, + "y": 236, + "name": "Out", + "alignment": "right", + "parentNode": "3642c9ae-dc23-4918-ad01-7a09f26d97e0", + "links": [], + "in": false, + "label": "Out" + } + ], + "name": "Node 1", + "color": "rgb(192,255,0)", + "portsInOrder": [ + "9268bc0f-46be-4de0-aa64-0ccdf48d786a" + ], + "portsOutOrder": [ + "de5daf16-dc2e-4f8e-8744-88f212a37cc5" + ] + } + } + } + ] +} From 71c4cb4a71bf0d90b8aeeda7ac554bb0e8fb7d6c Mon Sep 17 00:00:00 2001 From: vassil Date: Wed, 18 Mar 2020 18:23:10 +0100 Subject: [PATCH 003/247] nci-agency/anet#2889: Add edit mode --- client/src/pages/dashboards/BoardDashboard.js | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/client/src/pages/dashboards/BoardDashboard.js b/client/src/pages/dashboards/BoardDashboard.js index f98bdd1e86..4cfcc2ba54 100644 --- a/client/src/pages/dashboards/BoardDashboard.js +++ b/client/src/pages/dashboards/BoardDashboard.js @@ -4,10 +4,7 @@ import createEngine, { DiagramModel } from "@projectstorm/react-diagrams" import { Settings } from "api" -import { - mapPageDispatchersToProps, - PageDispatchersPropType -} from "components/Page" +import { mapPageDispatchersToProps } from "components/Page" import FileSaver from "file-saver" import _keys from "lodash/keys" import PropTypes from "prop-types" @@ -37,12 +34,13 @@ PrototypeNode.propTypes = { model: PropTypes.object } -const BoardDashboard = ({ pageDispatchers }) => { +const BoardDashboard = () => { const { dashboard } = useParams() const dashboardSettings = Settings.dashboards.find(o => o.label === dashboard) const [dropEvent, setDropEvent] = useState() const engineRef = useRef(createEngine()) const [model, setModel] = useState() + const [edit, setEdit] = useState(false) useEffect(() => { setModel(new DiagramModel()) @@ -52,6 +50,10 @@ const BoardDashboard = ({ pageDispatchers }) => { engineRef.current.setModel(model) }, [model]) + useEffect(() => { + model && model.setLocked(!edit) + }, [model, edit]) + useEffect(() => { async function fetchData() { await fetch(dashboardSettings.data) @@ -101,18 +103,24 @@ const BoardDashboard = ({ pageDispatchers }) => { }} >
- - - + + + {edit && ( + <> + + + + + )}
{ ) } -BoardDashboard.propTypes = { pageDispatchers: PageDispatchersPropType } - export default connect(null, mapPageDispatchersToProps)(BoardDashboard) From c9c52043303fe6b6a38650a89014976a812a23d7 Mon Sep 17 00:00:00 2001 From: vassil Date: Thu, 19 Mar 2020 00:10:42 +0100 Subject: [PATCH 004/247] nci-agency/anet#2889: Customize diagram nodes --- .../src/pages/dashboards/BoardDashboard.css | 1 + client/src/pages/dashboards/BoardDashboard.js | 120 +++++++------ client/src/pages/dashboards/DiagramNode.js | 163 ++++++++++++++++++ 3 files changed, 232 insertions(+), 52 deletions(-) create mode 100644 client/src/pages/dashboards/DiagramNode.js diff --git a/client/src/pages/dashboards/BoardDashboard.css b/client/src/pages/dashboards/BoardDashboard.css index 5559267521..85fbff78ef 100644 --- a/client/src/pages/dashboards/BoardDashboard.css +++ b/client/src/pages/dashboards/BoardDashboard.css @@ -2,6 +2,7 @@ .diagram-container{ width: 100%; height: 100%; + background: white; } .custom-node{ diff --git a/client/src/pages/dashboards/BoardDashboard.js b/client/src/pages/dashboards/BoardDashboard.js index 4cfcc2ba54..24adf86dfe 100644 --- a/client/src/pages/dashboards/BoardDashboard.js +++ b/client/src/pages/dashboards/BoardDashboard.js @@ -1,34 +1,58 @@ import { CanvasWidget } from "@projectstorm/react-canvas-core" +import * as Models from "models" import createEngine, { - DefaultNodeModel, - DiagramModel + DiagramModel, + PortModelAlignment } from "@projectstorm/react-diagrams" import { Settings } from "api" import { mapPageDispatchersToProps } from "components/Page" import FileSaver from "file-saver" -import _keys from "lodash/keys" import PropTypes from "prop-types" import React, { useEffect, useState, useRef } from "react" -import { Button } from "react-bootstrap" +import { Badge, Button } from "react-bootstrap" import { connect } from "react-redux" import { useParams } from "react-router-dom" import DOWNLOAD_ICON from "resources/download.png" +import { + DiagramNodeModel, + DiagramNodeFactory, + SimplePortFactory, + DiagramPortModel +} from "./DiagramNode" import "./BoardDashboard.css" const PrototypeNode = ({ name, model }) => ( -
{ - event.dataTransfer.setData("storm-diagram-node", JSON.stringify(model)) - }} - > - {name} -
+ +
{ + event.dataTransfer.setData("storm-diagram-node", JSON.stringify(model)) + }} + > + + {name} +
+
) +function bootstrapEngine() { + const engine = createEngine() + engine + .getPortFactories() + .registerFactory( + new SimplePortFactory( + "diamond", + config => new DiagramPortModel(PortModelAlignment.LEFT) + ) + ) + engine.getNodeFactories().registerFactory(new DiagramNodeFactory()) + return engine +} + PrototypeNode.propTypes = { name: PropTypes.string, model: PropTypes.object @@ -38,7 +62,7 @@ const BoardDashboard = () => { const { dashboard } = useParams() const dashboardSettings = Settings.dashboards.find(o => o.label === dashboard) const [dropEvent, setDropEvent] = useState() - const engineRef = useRef(createEngine()) + const engineRef = useRef(bootstrapEngine()) const [model, setModel] = useState() const [edit, setEdit] = useState(false) @@ -72,22 +96,8 @@ const BoardDashboard = () => { const data = JSON.parse( dropEvent.dataTransfer.getData("storm-diagram-node") ) - const nodesCount = _keys(model.getNodes()).length - - let node = null - if (data.type === "in") { - node = new DefaultNodeModel( - "Node " + (nodesCount + 1), - "rgb(192,255,0)" - ) - node.addInPort("In") - } else { - node = new DefaultNodeModel( - "Node " + (nodesCount + 1), - "rgb(0,192,255)" - ) - node.addOutPort("Out") - } + console.log(data) + const node = new DiagramNodeModel() const point = engineRef.current.getRelativeMousePoint(dropEvent) node.setPosition(point) engineRef.current.getModel().addNode(node) @@ -102,26 +112,6 @@ const BoardDashboard = () => { height: "100%" }} > -
- - - {edit && ( - <> - - - - - )} -
{ /> )}
+
+ + + {edit && ( + <> + + + + + + + + )} +
) } diff --git a/client/src/pages/dashboards/DiagramNode.js b/client/src/pages/dashboards/DiagramNode.js new file mode 100644 index 0000000000..07dc52a260 --- /dev/null +++ b/client/src/pages/dashboards/DiagramNode.js @@ -0,0 +1,163 @@ +import styled from "@emotion/styled" +import { + AbstractModelFactory, + AbstractReactFactory +} from "@projectstorm/react-canvas-core" +import { + DefaultLinkModel, + NodeModel, + PortModel, + PortModelAlignment, + PortWidget +} from "@projectstorm/react-diagrams" +import * as React from "react" +import PropTypes from "prop-types" + +export class DiagramPortModel extends PortModel { + constructor(alignment) { + super({ + type: "diamond", + name: alignment, + alignment: alignment + }) + } + + createLinkModel = () => new DefaultLinkModel() +} + +export class DiagramNodeModel extends NodeModel { + constructor() { + super({ + type: "diamond" + }) + this.addPort(new DiagramPortModel(PortModelAlignment.TOP)) + this.addPort(new DiagramPortModel(PortModelAlignment.LEFT)) + this.addPort(new DiagramPortModel(PortModelAlignment.BOTTOM)) + this.addPort(new DiagramPortModel(PortModelAlignment.RIGHT)) + } +} + +const Port = styled.div` + width: 16px; + height: 16px; + z-index: 10; + 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 }) => ( +
+ + + + + + ` + }} + /> + + + + + + + + + + + + +
+) + +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 class DiagramNodeFactory extends AbstractReactFactory { + constructor() { + super("diamond") + } + + generateReactWidget = event => { + return ( + + ) + } + + generateModel = event => new DiagramNodeModel() +} From ce43bbdf546c1214cb0e0a065dd3358b18e5e7fc Mon Sep 17 00:00:00 2001 From: Vassil Iordanov Date: Thu, 19 Mar 2020 22:17:07 +0100 Subject: [PATCH 005/247] nci-agency/anet#2889: Link nodes to ANET objects --- .../MultiTypeAdvancedSelectComponent.js | 164 ++++++++++++++++++ .../src/components/editor/LinkSourceAnet.js | 158 +---------------- client/src/pages/dashboards/BoardDashboard.js | 37 ++-- client/src/pages/dashboards/DiagramNode.js | 150 ++++++++-------- 4 files changed, 265 insertions(+), 244 deletions(-) create mode 100644 client/src/components/advancedSelectWidget/MultiTypeAdvancedSelectComponent.js diff --git a/client/src/components/advancedSelectWidget/MultiTypeAdvancedSelectComponent.js b/client/src/components/advancedSelectWidget/MultiTypeAdvancedSelectComponent.js new file mode 100644 index 0000000000..1fc389aca8 --- /dev/null +++ b/client/src/components/advancedSelectWidget/MultiTypeAdvancedSelectComponent.js @@ -0,0 +1,164 @@ +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 } 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.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 MultiTypeAdvancedSelectComponent = ({ onConfirm }) => { + const [objectType, setObjectType] = useState(ENTITY_TYPES.REPORTS) + const [advancedSelectProps, setAdvancedSelectProps] = useState( + widgetTypeMapping[objectType] + ) + + function changeObjectType(newObjectType) { + setObjectType(newObjectType) + setAdvancedSelectProps(widgetTypeMapping[newObjectType]) + } + + return ( + <> + + {Object.entries(ENTITY_TYPES).map((key, value) => { + const entityName = key[1] + const entityLabel = SEARCH_OBJECT_LABELS[key[0]] + return ( + + ) + })} + + + onConfirm(value, objectType)} + objectType={advancedSelectProps.objectType} + queryParams={advancedSelectProps.queryParams} + fields={advancedSelectProps.fields} + addon={advancedSelectProps.addon} + /> + + ) +} + +MultiTypeAdvancedSelectComponent.propTypes = { + onConfirm: PropTypes.func +} + +export default MultiTypeAdvancedSelectComponent 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/pages/dashboards/BoardDashboard.js b/client/src/pages/dashboards/BoardDashboard.js index 24adf86dfe..024a397c22 100644 --- a/client/src/pages/dashboards/BoardDashboard.js +++ b/client/src/pages/dashboards/BoardDashboard.js @@ -1,25 +1,26 @@ import { CanvasWidget } from "@projectstorm/react-canvas-core" -import * as Models from "models" import createEngine, { DiagramModel, PortModelAlignment } from "@projectstorm/react-diagrams" import { Settings } from "api" +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, useState, useRef } from "react" -import { Badge, Button } from "react-bootstrap" +import React, { useEffect, useRef, useState } from "react" +import { Badge, Button, Modal } from "react-bootstrap" import { connect } from "react-redux" import { useParams } from "react-router-dom" import DOWNLOAD_ICON from "resources/download.png" +import "./BoardDashboard.css" import { - DiagramNodeModel, DiagramNodeFactory, - SimplePortFactory, - DiagramPortModel + DiagramNodeModel, + DiagramPortModel, + SimplePortFactory } from "./DiagramNode" -import "./BoardDashboard.css" const PrototypeNode = ({ name, model }) => ( @@ -32,7 +33,7 @@ const PrototypeNode = ({ name, model }) => ( {name} @@ -61,10 +62,11 @@ PrototypeNode.propTypes = { const BoardDashboard = () => { const { dashboard } = useParams() const dashboardSettings = Settings.dashboards.find(o => o.label === dashboard) - const [dropEvent, setDropEvent] = useState() + const [dropEvent, setDropEvent] = useState(null) const engineRef = useRef(bootstrapEngine()) - const [model, setModel] = useState() + const [model, setModel] = useState(null) const [edit, setEdit] = useState(false) + const [editedNode, setEditedNode] = useState(null) useEffect(() => { setModel(new DiagramModel()) @@ -102,6 +104,7 @@ const BoardDashboard = () => { node.setPosition(point) engineRef.current.getModel().addNode(node) setDropEvent(null) + setEditedNode(node) } }, [model, dropEvent]) return ( @@ -158,6 +161,20 @@ const BoardDashboard = () => { )} + setEditedNode(null)}> + + Edit diagram node + + + { + editedNode.extras = value.uuid + editedNode.anetObject = value + editedNode.anetObjectType = objectType + }} + /> + + ) } diff --git a/client/src/pages/dashboards/DiagramNode.js b/client/src/pages/dashboards/DiagramNode.js index 07dc52a260..8bb95b4aea 100644 --- a/client/src/pages/dashboards/DiagramNode.js +++ b/client/src/pages/dashboards/DiagramNode.js @@ -6,12 +6,15 @@ import { import { DefaultLinkModel, NodeModel, + DefaultNodeModel, PortModel, PortModelAlignment, PortWidget } from "@projectstorm/react-diagrams" import * as React from "react" import PropTypes from "prop-types" +import * as Models from "models" +import LinkTo from "components/LinkTo" export class DiagramPortModel extends PortModel { constructor(alignment) { @@ -25,7 +28,7 @@ export class DiagramPortModel extends PortModel { createLinkModel = () => new DefaultLinkModel() } -export class DiagramNodeModel extends NodeModel { +export class DiagramNodeModel extends DefaultNodeModel { constructor() { super({ type: "diamond" @@ -49,89 +52,74 @@ const Port = styled.div` } ` -export const DiagramNodeWidget = ({ size, node, engine }) => ( -
- - - - - - ` - }} - /> - - - - - - - - - - { + const ModelClass = node.anetObjectType && Models[node.anetObjectType] + + const modelInstance = ModelClass && new ModelClass(node.anetObject) + return ( +
- - -
-) + + { node.anetObjectType && node.anetObject && } + + + + + + + + + + + + +
+ ) +} DiagramNodeWidget.propTypes = { size: PropTypes.number, From e9fd8bf4c9f80c01af6a1d00cbf3a9310eafa9e6 Mon Sep 17 00:00:00 2001 From: vassil Date: Fri, 20 Mar 2020 14:46:00 +0100 Subject: [PATCH 006/247] nci-agency#anet: Simplify ANET custom diagram model --- client/package.json | 4 +- client/src/pages/dashboards/BoardDashboard.js | 61 +++-- client/src/pages/dashboards/DiagramNode.js | 42 +++- client/yarn.lock | 215 ++++-------------- data/dashboards/process.json | 127 +---------- 5 files changed, 125 insertions(+), 324 deletions(-) diff --git a/client/package.json b/client/package.json index dfbd9395f5..681346b3e5 100644 --- a/client/package.json +++ b/client/package.json @@ -106,7 +106,9 @@ "@fullcalendar/list": "4.4.0", "@fullcalendar/react": "4.4.0", "@fullcalendar/timegrid": "4.4.0", - "@projectstorm/react-diagrams": "^6.0.1-beta.7", + "@projectstorm/react-diagrams-core": "^6.0.2", + "@projectstorm/react-diagrams-defaults": "^6.0.2", + "@projectstorm/react-diagrams-routing": "^6.0.2", "apollo-boost": "0.4.7", "bootstrap": "3.4.1", "change-case": "4.1.1", diff --git a/client/src/pages/dashboards/BoardDashboard.js b/client/src/pages/dashboards/BoardDashboard.js index 024a397c22..a57e2d97ac 100644 --- a/client/src/pages/dashboards/BoardDashboard.js +++ b/client/src/pages/dashboards/BoardDashboard.js @@ -1,8 +1,17 @@ -import { CanvasWidget } from "@projectstorm/react-canvas-core" -import createEngine, { +import { + DefaultDiagramState, + DiagramEngine, DiagramModel, + LinkLayerFactory, + NodeLayerFactory, PortModelAlignment -} from "@projectstorm/react-diagrams" +} from "@projectstorm/react-diagrams-core" +import { + DefaultLabelFactory, + DefaultLinkFactory +} from "@projectstorm/react-diagrams-defaults" +import { CanvasWidget, SelectionBoxLayerFactory } from "@projectstorm/react-canvas-core" +import { PathFindingLinkFactory } from "@projectstorm/react-diagrams-routing" import { Settings } from "api" import MultiTypeAdvancedSelectComponent from "components/advancedSelectWidget/MultiTypeAdvancedSelectComponent" import { mapPageDispatchersToProps } from "components/Page" @@ -22,6 +31,29 @@ import { 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 DefaultLinkFactory()) + 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 }) => (
( {name}
) -function bootstrapEngine() { - const engine = createEngine() - engine - .getPortFactories() - .registerFactory( - new SimplePortFactory( - "diamond", - config => new DiagramPortModel(PortModelAlignment.LEFT) - ) - ) - engine.getNodeFactories().registerFactory(new DiagramNodeFactory()) - return engine -} - PrototypeNode.propTypes = { name: PropTypes.string, model: PropTypes.object @@ -63,7 +86,7 @@ const BoardDashboard = () => { const { dashboard } = useParams() const dashboardSettings = Settings.dashboards.find(o => o.label === dashboard) const [dropEvent, setDropEvent] = useState(null) - const engineRef = useRef(bootstrapEngine()) + const engineRef = useRef(createEngine()) const [model, setModel] = useState(null) const [edit, setEdit] = useState(false) const [editedNode, setEditedNode] = useState(null) diff --git a/client/src/pages/dashboards/DiagramNode.js b/client/src/pages/dashboards/DiagramNode.js index 8bb95b4aea..d977b7401b 100644 --- a/client/src/pages/dashboards/DiagramNode.js +++ b/client/src/pages/dashboards/DiagramNode.js @@ -4,13 +4,12 @@ import { AbstractReactFactory } from "@projectstorm/react-canvas-core" import { - DefaultLinkModel, NodeModel, - DefaultNodeModel, PortModel, PortModelAlignment, PortWidget -} from "@projectstorm/react-diagrams" +} from "@projectstorm/react-diagrams-core" +import { DefaultLinkModel } from "@projectstorm/react-diagrams-defaults" import * as React from "react" import PropTypes from "prop-types" import * as Models from "models" @@ -19,7 +18,7 @@ import LinkTo from "components/LinkTo" export class DiagramPortModel extends PortModel { constructor(alignment) { super({ - type: "diamond", + type: "anet", name: alignment, alignment: alignment }) @@ -28,16 +27,30 @@ export class DiagramPortModel extends PortModel { createLinkModel = () => new DefaultLinkModel() } -export class DiagramNodeModel extends DefaultNodeModel { +export class DiagramNodeModel extends NodeModel { constructor() { super({ - type: "diamond" + type: "anet" }) 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) + this.options.anetObjectType = event.data.anetObjectType + this.options.color = event.data.color + } + + serialize = () => ({ + ...super.serialize(), + ports: undefined, + anetObjectUuid: this.options.anetObject.uuid, + anetObjectType: this.options.anetObjectType, + color: this.options.color + }) } const Port = styled.div` @@ -53,12 +66,12 @@ const Port = styled.div` ` export const DiagramNodeWidget = ({ size, node, engine }) => { - const ModelClass = node.anetObjectType && Models[node.anetObjectType] + const ModelClass = node.options.anetObjectType && Models[node.options.anetObjectType] - const modelInstance = ModelClass && new ModelClass(node.anetObject) + const modelInstance = ModelClass && new ModelClass(node.options.anetObject) return (
{ height={50} style={{ pointerEvents: "none" }} /> - { node.anetObjectType && node.anetObject && } + {node.anetObjectType && node.anetObject && ( + + )} { diff --git a/client/yarn.lock b/client/yarn.lock index 1766d35dfa..4ab11a403d 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -1247,19 +1247,7 @@ "@emotion/utils" "0.11.3" "@emotion/weak-memoize" "0.2.5" -"@emotion/core@^10.0.20": - version "10.0.28" - resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.0.28.tgz#bb65af7262a234593a9e952c041d0f1c9b9bef3d" - integrity sha512-pH8UueKYO5jgg0Iq+AmCLxBsvuGtvlmiDCOuv8fGNYn3cowFpLN98L8zO56U0H1PjDIyAlXymgL3Wu7u7v6hbA== - dependencies: - "@babel/runtime" "^7.5.5" - "@emotion/cache" "^10.0.27" - "@emotion/css" "^10.0.27" - "@emotion/serialize" "^0.11.15" - "@emotion/sheet" "0.9.4" - "@emotion/utils" "0.11.3" - -"@emotion/core@^10.0.28": +"@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== @@ -1609,50 +1597,41 @@ "@nodelib/fs.scandir" "2.1.3" fastq "^1.6.0" -"@projectstorm/geometry@^6.0.1-beta.7": - version "6.0.1-beta.7" - resolved "https://registry.yarnpkg.com/@projectstorm/geometry/-/geometry-6.0.1-beta.7.tgz#181f73798d3e792b7aee5ad4a07516ec6d3d9ffb" - integrity sha512-gWoD6tPx+4k0gWo0z9DCxp9zHqcsNLxGtgdmfIfwRQuPcXJcbhvc7cQ95QIAWVcbFDHMVPzURzaY/11UH+b9uQ== - -"@projectstorm/react-canvas-core@^6.0.1-beta.7": - version "6.0.1-beta.7" - resolved "https://registry.yarnpkg.com/@projectstorm/react-canvas-core/-/react-canvas-core-6.0.1-beta.7.tgz#e977fa6aa6ee362ce803397bc279651784473497" - integrity sha512-yogNt9N/86z+D9dhr0GO40txq9RImUaj4ZE43xiDnHOzf6LellLNXyrnYOwN0wjRiwMhznCbHsS4SoKMV1a/LQ== - dependencies: - "@projectstorm/geometry" "^6.0.1-beta.7" +"@projectstorm/geometry@^6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@projectstorm/geometry/-/geometry-6.0.2.tgz#7653d1156457aa7e5f4bea22b97a1d7d9bce1576" + integrity sha512-jEZCuTt7AuowScxXWeH0IJd04T54fb2Q/2uNWPhjah9rBcqgc7IH1Vd2BYy4rgtIISaIhNcncMdl2+KEs9Tnug== -"@projectstorm/react-diagrams-core@^6.0.1-beta.7": - version "6.0.1-beta.7" - resolved "https://registry.yarnpkg.com/@projectstorm/react-diagrams-core/-/react-diagrams-core-6.0.1-beta.7.tgz#d157834307e238e76da9fd538451ec7a841296ba" - integrity sha512-lTsZr5JqPlKxe8DicxomedoDI9Gnf1OYxmTC819ChVqizj1mWV6jB+0p3VIPSPO+mRC8emX/onOkLh3Szj9QRQ== +"@projectstorm/react-canvas-core@^6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@projectstorm/react-canvas-core/-/react-canvas-core-6.0.2.tgz#f60ab452a5e0b6faf41e123250af785c93e5a34a" + integrity sha512-6ljvQxbwf3H2UlMHJWMIDFWWo9eXZ6uWq5QwhPh1OZJGsHFb6yNv7mK/ITVPnKO5mIprgcDldpqTmM1+E3Ir9A== dependencies: - "@projectstorm/geometry" "^6.0.1-beta.7" - "@projectstorm/react-canvas-core" "^6.0.1-beta.7" + "@projectstorm/geometry" "^6.0.2" -"@projectstorm/react-diagrams-defaults@^6.0.1-beta.7": - version "6.0.1-beta.7" - resolved "https://registry.yarnpkg.com/@projectstorm/react-diagrams-defaults/-/react-diagrams-defaults-6.0.1-beta.7.tgz#01ec4d47dc653b5caf1550a56707c62ee746d771" - integrity sha512-AueksmJj/jYje1KYOvQAL3OUufIko+04Iwz3qeTGUNipQprJsjL2ImCL5jfTv2qKLrzgz60E6w/H8XpmJwLHZg== +"@projectstorm/react-diagrams-core@^6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@projectstorm/react-diagrams-core/-/react-diagrams-core-6.0.2.tgz#d18816e593791b7cc12f7dc142716faeb6bd0f89" + integrity sha512-oT2UYqKmeahITwHecPOEca4mtDO2XDUWYfbbzLG1opwNSTR2ui+wuWMjJMOuNxjwBsvxXbPY9wy4G5xMttIrCA== dependencies: - "@projectstorm/react-diagrams-core" "^6.0.1-beta.7" + "@projectstorm/geometry" "^6.0.2" + "@projectstorm/react-canvas-core" "^6.0.2" -"@projectstorm/react-diagrams-routing@^6.0.1-beta.7": - version "6.0.1-beta.7" - resolved "https://registry.yarnpkg.com/@projectstorm/react-diagrams-routing/-/react-diagrams-routing-6.0.1-beta.7.tgz#08fbe8c811fab3fa24e8432974376aeb45b1af82" - integrity sha512-tmts3N7COIVzykEFwt3Du8q62HuSKQuIGCj/UHz7IvjvWTz8Szo/igr9lBIJWO6f7mr9EnDdWCK0SP7QWKQZpA== +"@projectstorm/react-diagrams-defaults@^6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@projectstorm/react-diagrams-defaults/-/react-diagrams-defaults-6.0.2.tgz#7fbd599bc437153b64844b56feb3a02aeea389ad" + integrity sha512-cAc2qqv92JD3mDm9H0Yxsy2xa8VPmSyjMwjQdX0WCrrWu9lB5tKCgpBn+zmjKePEIKFmd3aqqeIYjYo1OQlIag== dependencies: - "@projectstorm/geometry" "^6.0.1-beta.7" - "@projectstorm/react-diagrams-core" "^6.0.1-beta.7" - "@projectstorm/react-diagrams-defaults" "^6.0.1-beta.7" + "@projectstorm/react-diagrams-core" "^6.0.2" -"@projectstorm/react-diagrams@^6.0.1-beta.7": - version "6.0.1-beta.7" - resolved "https://registry.yarnpkg.com/@projectstorm/react-diagrams/-/react-diagrams-6.0.1-beta.7.tgz#b6907415b1a0467dd25d58da6bf12a0f2ccc915d" - integrity sha512-aEQuRyNtzrlc6TNVji5Zme9fJkOcnCdiskPFXF14c0b9MJO4cz8yUrGZh0/MjsSH8pQl1sB71mnGFLQ20aAHmQ== +"@projectstorm/react-diagrams-routing@^6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@projectstorm/react-diagrams-routing/-/react-diagrams-routing-6.0.2.tgz#b6469c3d849904395bde84fe602487405403035e" + integrity sha512-xtmAqxmYwk3kFgFnkTBwVRh0QuOfyvZqUhvfOGgwbhoRRsJk2PlyFi9O16y0BOUOoHJJYxenoSGGgL8WGgjpKQ== dependencies: - "@projectstorm/react-diagrams-core" "^6.0.1-beta.7" - "@projectstorm/react-diagrams-defaults" "^6.0.1-beta.7" - "@projectstorm/react-diagrams-routing" "^6.0.1-beta.7" + "@projectstorm/geometry" "^6.0.2" + "@projectstorm/react-diagrams-core" "^6.0.2" + "@projectstorm/react-diagrams-defaults" "^6.0.2" "@reach/router@^1.2.1": version "1.3.3" @@ -2671,11 +2650,6 @@ abab@^2.0.0: resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg== -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: version "1.3.7" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" @@ -5810,7 +5784,7 @@ debug@3.1.0, debug@=3.1.0: dependencies: ms "2.0.0" -debug@3.2.6, debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6: +debug@3.2.6, debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== @@ -6016,7 +5990,7 @@ detect-file@^1.0.0: resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= -detect-libc@^1.0.2, detect-libc@^1.0.3: +detect-libc@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= @@ -7185,7 +7159,6 @@ extsprintf@^1.2.0: "faker@https://github.com/Marak/faker.js.git": version "4.1.0" - uid "3b2fa4aebccee52ae1bafc15d575061fb30c3cf1" resolved "https://github.com/Marak/faker.js.git#3b2fa4aebccee52ae1bafc15d575061fb30c3cf1" fast-deep-equal@^1.0.0: @@ -7714,13 +7687,6 @@ fs-extra@^8.0.1, fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-minipass@^1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" - integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== - dependencies: - minipass "^2.6.0" - fs-minipass@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" @@ -7750,7 +7716,6 @@ fsevents@^1.2.7: dependencies: bindings "^1.5.0" nan "^2.12.1" - node-pre-gyp "*" fsevents@^2.1.2, fsevents@~2.1.1, fsevents@~2.1.2: version "2.1.2" @@ -8816,7 +8781,7 @@ i18n-iso-countries@5.1.0: dependencies: diacritics "1.3.0" -iconv-lite@0.4, iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: +iconv-lite@0.4, iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -8850,13 +8815,6 @@ ignore-loader@0.1.2: resolved "https://registry.yarnpkg.com/ignore-loader/-/ignore-loader-0.1.2.tgz#d81f240376d0ba4f0d778972c3ad25874117a463" integrity sha1-2B8kA3bQuk8Nd4lyw60lh0EXpGM= -ignore-walk@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37" - integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== - dependencies: - minimatch "^3.0.4" - ignore@^3.3.5: version "3.3.10" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" @@ -11248,14 +11206,6 @@ minipass-pipeline@^1.2.2: dependencies: minipass "^3.0.0" -minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" - integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - minipass@^3.0.0, minipass@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.1.tgz#7607ce778472a185ad6d89082aa2070f79cedcd5" @@ -11263,13 +11213,6 @@ minipass@^3.0.0, minipass@^3.1.1: dependencies: yallist "^4.0.0" -minizlib@^1.2.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" - integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== - dependencies: - minipass "^2.9.0" - minizlib@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.0.tgz#fd52c645301ef09a63a2c209697c294c6ce02cf3" @@ -11310,7 +11253,7 @@ mixin-object@^2.0.1: for-in "^0.1.3" is-extendable "^0.1.1" -mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: +mkdirp@0.5.1, mkdirp@^0.5.1, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= @@ -11441,15 +11384,6 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -needle@^2.2.1: - version "2.3.3" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.3.3.tgz#a041ad1d04a871b0ebb666f40baaf1fb47867117" - integrity sha512-EkY0GeSq87rWp1hoq/sH/wnTWgFVhYlnIkbJ0YJFfRgEFlz2RraCjBpFQ+vrEgEdp0ThfyHADmkChEhcb7PKyw== - dependencies: - debug "^3.2.6" - iconv-lite "^0.4.4" - sax "^1.2.4" - negotiator@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" @@ -11568,22 +11502,6 @@ node-notifier@^6.0.0: shellwords "^0.1.1" which "^1.3.1" -node-pre-gyp@*: - version "0.14.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83" - integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4.4.2" - node-releases@^1.1.29, node-releases@^1.1.50: version "1.1.52" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.52.tgz#bcffee3e0a758e92e44ecfaecd0a47554b0bcba9" @@ -11601,14 +11519,6 @@ nodent-runtime@^3.0.4: resolved "https://registry.yarnpkg.com/nodent-runtime/-/nodent-runtime-3.2.1.tgz#9e2755d85e39f764288f0d4752ebcfe3e541e00e" integrity sha512-7Ws63oC+215smeKJQCxzrK21VFVlCFBkwl0MOObt0HOpVQXs3u483sAmtkF33nNqZ5rSOQjB76fgyPBmAUrtCA== -nopt@^4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" - integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg== - dependencies: - abbrev "1" - osenv "^0.1.4" - normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -11656,27 +11566,6 @@ normalize.css@^8.0.1: resolved "https://registry.yarnpkg.com/normalize.css/-/normalize.css-8.0.1.tgz#9b98a208738b9cc2634caacbc42d131c97487bf3" integrity sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg== -npm-bundled@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b" - integrity sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA== - dependencies: - npm-normalize-package-bin "^1.0.1" - -npm-normalize-package-bin@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" - integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== - -npm-packlist@^1.1.6: - version "1.4.8" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e" - integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - npm-normalize-package-bin "^1.0.1" - npm-path@^2.0.2, npm-path@^2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/npm-path/-/npm-path-2.0.4.tgz#c641347a5ff9d6a09e4d9bce5580c4f505278e64" @@ -11727,7 +11616,7 @@ npm-which@^3.0.1: npm-path "^2.0.2" which "^1.2.10" -npmlog@^4.0.2, npmlog@^4.1.2: +npmlog@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== @@ -11997,11 +11886,6 @@ os-browserify@^0.3.0: resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - os-locale@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" @@ -12020,19 +11904,11 @@ os-locale@^3.0.0, os-locale@^3.1.0: lcid "^2.0.0" mem "^4.0.0" -os-tmpdir@^1.0.0, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: +os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= -osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - p-cancelable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" @@ -13005,7 +12881,7 @@ raw-loader@^3.1.0: loader-utils "^1.1.0" schema-utils "^2.0.1" -rc@^1.0.1, rc@^1.1.6, rc@^1.2.7, rc@^1.2.8: +rc@^1.0.1, rc@^1.1.6, rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== @@ -13988,7 +13864,7 @@ rimraf@2.6.3: dependencies: glob "^7.1.3" -rimraf@2.7.1, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3, rimraf@^2.7.1: +rimraf@2.7.1, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3, rimraf@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -14095,7 +13971,7 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" -sax@^1.2.4, sax@~1.2.4: +sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== @@ -14190,7 +14066,7 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0: +"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -15122,19 +14998,6 @@ tar-stream@^2.1.0: inherits "^2.0.3" readable-stream "^3.1.1" -tar@^4.4.2: - version "4.4.13" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" - integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== - dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.8.6" - minizlib "^1.2.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.3" - tar@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.1.tgz#7b3bd6c313cb6e0153770108f8d70ac298607efa" @@ -16481,7 +16344,7 @@ yallist@^2.1.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= -yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: +yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== diff --git a/data/dashboards/process.json b/data/dashboards/process.json index 159c8afa2e..907cb10053 100644 --- a/data/dashboards/process.json +++ b/data/dashboards/process.json @@ -1,136 +1,29 @@ { - "id": "abcbacb3-9193-4e5a-af27-25beb91ffefd", + "id": "863d307e-bd6a-467c-ad44-d5749cb63d06", + "locked": false, "offsetX": 0, "offsetY": 0, "zoom": 100, "gridSize": 0, "layers": [ { - "id": "e5a4fb5a-be1b-4d55-8721-a82d4550ab9f", + "id": "0baf2283-8319-4f46-ac44-922291574762", "type": "diagram-links", "isSvg": true, "transformed": true, - "models": { - "c9140f61-31ef-4097-bc13-4097f609b65c": { - "id": "c9140f61-31ef-4097-bc13-4097f609b65c", - "type": "default", - "source": "65c4c390-4248-4424-83d1-79768ecc614f", - "sourcePort": "fe1e6f91-0ca8-4ac6-b6b5-331123841ebc", - "target": "3642c9ae-dc23-4918-ad01-7a09f26d97e0", - "targetPort": "9268bc0f-46be-4de0-aa64-0ccdf48d786a", - "points": [ - { - "id": "e6135fb0-4a17-4b04-a4d0-939c4a1efbcb", - "type": "point", - "x": 1178.421875, - "y": 500.5 - }, - { - "id": "b62fbbf7-3b65-4ec5-90fb-debd82f938ab", - "type": "point", - "x": 520.5, - "y": 243.5 - } - ], - "labels": [], - "width": 3, - "color": "gray", - "curvyness": 50, - "selectedColor": "rgb(0,192,255)" - } - } + "models": {} }, { - "id": "9e15b34a-fa1d-4780-942d-82823161faf1", + "id": "786e4bbb-7064-4b4e-b4fc-5576885dac3f", "type": "diagram-nodes", "isSvg": false, "transformed": true, "models": { - "65c4c390-4248-4424-83d1-79768ecc614f": { - "id": "65c4c390-4248-4424-83d1-79768ecc614f", - "type": "default", - "selected": true, - "x": 1097, - "y": 466, - "ports": [ - { - "id": "fe1e6f91-0ca8-4ac6-b6b5-331123841ebc", - "type": "default", - "x": 1170.921875, - "y": 493, - "name": "Out", - "alignment": "right", - "parentNode": "65c4c390-4248-4424-83d1-79768ecc614f", - "links": [ - "c9140f61-31ef-4097-bc13-4097f609b65c" - ], - "in": false, - "label": "Out" - }, - { - "id": "c4b9ee46-4e2f-4d56-a67c-5ca2af64cd21", - "type": "default", - "x": 1099, - "y": 493, - "name": "In", - "alignment": "left", - "parentNode": "65c4c390-4248-4424-83d1-79768ecc614f", - "links": [], - "in": true, - "label": "In" - } - ], - "name": "Node 1", - "color": "rgb(0,192,255)", - "portsInOrder": [ - "c4b9ee46-4e2f-4d56-a67c-5ca2af64cd21" - ], - "portsOutOrder": [ - "fe1e6f91-0ca8-4ac6-b6b5-331123841ebc" - ] - }, - "3642c9ae-dc23-4918-ad01-7a09f26d97e0": { - "id": "3642c9ae-dc23-4918-ad01-7a09f26d97e0", - "type": "default", - "selected": false, - "x": 511, - "y": 209, - "ports": [ - { - "id": "9268bc0f-46be-4de0-aa64-0ccdf48d786a", - "type": "default", - "x": 513, - "y": 236, - "name": "In", - "alignment": "left", - "parentNode": "3642c9ae-dc23-4918-ad01-7a09f26d97e0", - "links": [ - "c9140f61-31ef-4097-bc13-4097f609b65c" - ], - "in": true, - "label": "In" - }, - { - "id": "de5daf16-dc2e-4f8e-8744-88f212a37cc5", - "type": "default", - "x": 584.921875, - "y": 236, - "name": "Out", - "alignment": "right", - "parentNode": "3642c9ae-dc23-4918-ad01-7a09f26d97e0", - "links": [], - "in": false, - "label": "Out" - } - ], - "name": "Node 1", - "color": "rgb(192,255,0)", - "portsInOrder": [ - "9268bc0f-46be-4de0-aa64-0ccdf48d786a" - ], - "portsOutOrder": [ - "de5daf16-dc2e-4f8e-8744-88f212a37cc5" - ] + "8b9a7ca4-2aef-469c-947e-33b4c59a27a9": { + "id": "8b9a7ca4-2aef-469c-947e-33b4c59a27a9", + "type": "anet", + "x": 925, + "y": 107.71665954589844, } } } From 18432d0703a89bc74f8dd74c96079d10af3e93a3 Mon Sep 17 00:00:00 2001 From: vassil Date: Fri, 20 Mar 2020 17:20:40 +0100 Subject: [PATCH 007/247] nci-agency/anet#2889: Handle diagram de/serialization --- client/src/components/Model.js | 26 +- .../src/components/editor/LinkAnetEntity.js | 21 +- client/src/pages/dashboards/BoardDashboard.js | 18 +- client/src/pages/dashboards/DiagramNode.js | 105 ++++++- client/src/utils_links.js | 94 +------ data/dashboards/process.json | 261 +++++++++++++++++- 6 files changed, 401 insertions(+), 124 deletions(-) diff --git a/client/src/components/Model.js b/client/src/components/Model.js index fb6ca5651a..c5104b6ebe 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -1,8 +1,11 @@ -import encodeQuery from "querystring/encode" +import API from "api" +import { gql } from "apollo-boost" import _forEach from "lodash/forEach" import _isEmpty from "lodash/isEmpty" +import * as Models from "models" import moment from "moment" import PropTypes from "prop-types" +import encodeQuery from "querystring/encode" import utils from "utils" import * as yup from "yup" @@ -270,6 +273,27 @@ export default class Model { return a && b && a.uuid === b.uuid } + static fetchByUuid(uuid, ENTITY_GQL_FIELDS) { + console.log("getting resources for " + this.resourceName) + const fields = ENTITY_GQL_FIELDS[this.resourceName] + if (!fields) { + return 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) { diff --git a/client/src/components/editor/LinkAnetEntity.js b/client/src/components/editor/LinkAnetEntity.js index 52ab87e97a..cd5c442cde 100644 --- a/client/src/components/editor/LinkAnetEntity.js +++ b/client/src/components/editor/LinkAnetEntity.js @@ -1,16 +1,27 @@ import LinkTo from "components/LinkTo" +import * as Models from "models" import PropTypes from "prop-types" import React, { useEffect, useState } from "react" -import { getEntityByUuid } from "utils_links" + +// Entity type --> GQL query +const ENTITY_GQL_FIELDS = { + Report: "uuid, intent", + Person: "uuid, name, role, avatar(size: 32)", + Organization: "uuid, shortName", + Position: "uuid, name", + Location: "uuid, name", + Task: "uuid, shortName, longName" +} 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, ENTITY_GQL_FIELDS) + .then(data => setEntity(data)) }, [type, uuid]) return ( diff --git a/client/src/pages/dashboards/BoardDashboard.js b/client/src/pages/dashboards/BoardDashboard.js index a57e2d97ac..8f8b9e0659 100644 --- a/client/src/pages/dashboards/BoardDashboard.js +++ b/client/src/pages/dashboards/BoardDashboard.js @@ -6,11 +6,11 @@ import { NodeLayerFactory, PortModelAlignment } from "@projectstorm/react-diagrams-core" +import { DefaultLabelFactory } from "@projectstorm/react-diagrams-defaults" import { - DefaultLabelFactory, - DefaultLinkFactory -} from "@projectstorm/react-diagrams-defaults" -import { CanvasWidget, SelectionBoxLayerFactory } from "@projectstorm/react-canvas-core" + CanvasWidget, + SelectionBoxLayerFactory +} from "@projectstorm/react-canvas-core" import { PathFindingLinkFactory } from "@projectstorm/react-diagrams-routing" import { Settings } from "api" import MultiTypeAdvancedSelectComponent from "components/advancedSelectWidget/MultiTypeAdvancedSelectComponent" @@ -27,11 +27,12 @@ import "./BoardDashboard.css" import { DiagramNodeFactory, DiagramNodeModel, + DiagramLinkFactory, DiagramPortModel, SimplePortFactory } from "./DiagramNode" -const createEngine = (options) => { +const createEngine = options => { const engine = new DiagramEngine({}) engine.getLayerFactories().registerFactory(new NodeLayerFactory()) engine.getLayerFactories().registerFactory(new LinkLayerFactory()) @@ -39,7 +40,7 @@ const createEngine = (options) => { engine.getLabelFactories().registerFactory(new DefaultLabelFactory()) engine.getNodeFactories().registerFactory(new DiagramNodeFactory()) - engine.getLinkFactories().registerFactory(new DefaultLinkFactory()) + engine.getLinkFactories().registerFactory(new DiagramLinkFactory()) engine.getLinkFactories().registerFactory(new PathFindingLinkFactory()) engine .getPortFactories() @@ -191,9 +192,8 @@ const BoardDashboard = () => { { - editedNode.extras = value.uuid - editedNode.anetObject = value - editedNode.anetObjectType = objectType + editedNode.options.anetObject = value + editedNode.options.anetObjectType = objectType }} /> diff --git a/client/src/pages/dashboards/DiagramNode.js b/client/src/pages/dashboards/DiagramNode.js index d977b7401b..d8e42bfc74 100644 --- a/client/src/pages/dashboards/DiagramNode.js +++ b/client/src/pages/dashboards/DiagramNode.js @@ -1,3 +1,4 @@ +import { css, keyframes } from "@emotion/core" import styled from "@emotion/styled" import { AbstractModelFactory, @@ -9,11 +10,24 @@ import { PortModelAlignment, PortWidget } from "@projectstorm/react-diagrams-core" -import { DefaultLinkModel } from "@projectstorm/react-diagrams-defaults" -import * as React from "react" -import PropTypes from "prop-types" -import * as Models from "models" +import { + DefaultLinkFactory, + DefaultLinkModel, + DefaultLinkWidget +} from "@projectstorm/react-diagrams-defaults" import LinkTo from "components/LinkTo" +import * as Models from "models" +import PropTypes from "prop-types" +import * as React from "react" + +const ENTITY_GQL_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 class DiagramPortModel extends PortModel { constructor(alignment) { @@ -24,9 +38,16 @@ export class DiagramPortModel extends PortModel { }) } - createLinkModel = () => new DefaultLinkModel() + createLinkModel = () => new DiagramLinkModel() } +export class DiagramLinkModel extends DefaultLinkModel { + constructor() { + super({ + type: "anet" + }) + } +} export class DiagramNodeModel extends NodeModel { constructor() { super({ @@ -40,14 +61,24 @@ export class DiagramNodeModel extends NodeModel { deserialize = event => { super.deserialize(event) - this.options.anetObjectType = event.data.anetObjectType - this.options.color = event.data.color + 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] + console.log(" deserializing ..." + modelClass.resourceName) + modelClass && + modelClass + .fetchByUuid(event.data.anetObjectUuid, ENTITY_GQL_FIELDS) + .then(function(entity) { + options.anetObject = entity + console.log(" deserialized ..." + event.data.anetObjectUuid) + }) } serialize = () => ({ ...super.serialize(), - ports: undefined, - anetObjectUuid: this.options.anetObject.uuid, + anetObjectUuid: this.options.anetObject?.uuid, anetObjectType: this.options.anetObjectType, color: this.options.color }) @@ -66,7 +97,8 @@ const Port = styled.div` ` export const DiagramNodeWidget = ({ size, node, engine }) => { - const ModelClass = node.options.anetObjectType && Models[node.options.anetObjectType] + const ModelClass = + node.options.anetObjectType && Models[node.options.anetObjectType] const modelInstance = ModelClass && new ModelClass(node.options.anetObject) return ( @@ -85,10 +117,10 @@ export const DiagramNodeWidget = ({ size, node, engine }) => { height={50} style={{ pointerEvents: "none" }} /> - {node.anetObjectType && node.anetObject && ( + {node.options.anetObjectType && node.options.anetObject && ( @@ -156,6 +188,53 @@ export class SimplePortFactory extends AbstractModelFactory { 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") diff --git a/client/src/utils_links.js b/client/src/utils_links.js index 20f1996ca3..5ca3a28bd2 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(/[\\/]/) @@ -121,15 +53,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/data/dashboards/process.json b/data/dashboards/process.json index 907cb10053..366e453980 100644 --- a/data/dashboards/process.json +++ b/data/dashboards/process.json @@ -1,29 +1,272 @@ { - "id": "863d307e-bd6a-467c-ad44-d5749cb63d06", + "id": "5e8f4298-b397-4f02-b710-382c7953d721", "locked": false, - "offsetX": 0, + "offsetX": 1, "offsetY": 0, "zoom": 100, "gridSize": 0, "layers": [ { - "id": "0baf2283-8319-4f46-ac44-922291574762", + "id": "d5357380-94c7-492e-962e-fd73336fe104", "type": "diagram-links", "isSvg": true, "transformed": true, - "models": {} + "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": "786e4bbb-7064-4b4e-b4fc-5576885dac3f", + "id": "10c5a688-a891-429a-9c50-605fadc1c29e", "type": "diagram-nodes", "isSvg": false, "transformed": true, "models": { - "8b9a7ca4-2aef-469c-947e-33b4c59a27a9": { - "id": "8b9a7ca4-2aef-469c-947e-33b4c59a27a9", + "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", - "x": 925, - "y": 107.71665954589844, + "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" } } } From 391ccc158ca22e8e2ab1cf93ce4f7a0c2baadc0d Mon Sep 17 00:00:00 2001 From: vassil Date: Sat, 21 Mar 2020 01:53:34 +0100 Subject: [PATCH 008/247] nci-agency/anet#2889: Improve diagram node layout --- client/src/components/Model.js | 1 - .../MultiTypeAdvancedSelectComponent.js | 12 +++- client/src/pages/dashboards/BoardDashboard.js | 49 ++++++++++++++-- client/src/pages/dashboards/DiagramNode.js | 56 ++++++++++++------- 4 files changed, 88 insertions(+), 30 deletions(-) diff --git a/client/src/components/Model.js b/client/src/components/Model.js index c5104b6ebe..5b4c4dacba 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -274,7 +274,6 @@ export default class Model { } static fetchByUuid(uuid, ENTITY_GQL_FIELDS) { - console.log("getting resources for " + this.resourceName) const fields = ENTITY_GQL_FIELDS[this.resourceName] if (!fields) { return null diff --git a/client/src/components/advancedSelectWidget/MultiTypeAdvancedSelectComponent.js b/client/src/components/advancedSelectWidget/MultiTypeAdvancedSelectComponent.js index 1fc389aca8..3e1180ea65 100644 --- a/client/src/components/advancedSelectWidget/MultiTypeAdvancedSelectComponent.js +++ b/client/src/components/advancedSelectWidget/MultiTypeAdvancedSelectComponent.js @@ -112,8 +112,13 @@ const widgetTypeMapping = { [ENTITY_TYPES.TASKS]: widgetPropsTask } -const MultiTypeAdvancedSelectComponent = ({ onConfirm }) => { - const [objectType, setObjectType] = useState(ENTITY_TYPES.REPORTS) +const MultiTypeAdvancedSelectComponent = ({ + onConfirm, + objectType: objectTypeArg +}) => { + const [objectType, setObjectType] = useState( + objectTypeArg || ENTITY_TYPES.REPORTS + ) const [advancedSelectProps, setAdvancedSelectProps] = useState( widgetTypeMapping[objectType] ) @@ -158,7 +163,8 @@ const MultiTypeAdvancedSelectComponent = ({ onConfirm }) => { } MultiTypeAdvancedSelectComponent.propTypes = { - onConfirm: PropTypes.func + onConfirm: PropTypes.func, + objectType: PropTypes.string } export default MultiTypeAdvancedSelectComponent diff --git a/client/src/pages/dashboards/BoardDashboard.js b/client/src/pages/dashboards/BoardDashboard.js index 8f8b9e0659..f511256fd7 100644 --- a/client/src/pages/dashboards/BoardDashboard.js +++ b/client/src/pages/dashboards/BoardDashboard.js @@ -4,7 +4,9 @@ import { DiagramModel, LinkLayerFactory, NodeLayerFactory, - PortModelAlignment + PortModelAlignment, + LinkModel, + NodeModel } from "@projectstorm/react-diagrams-core" import { DefaultLabelFactory } from "@projectstorm/react-diagrams-defaults" import { @@ -18,12 +20,13 @@ 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 React, { useEffect, useRef, useState, useCallback } from "react" import { Badge, Button, Modal } from "react-bootstrap" import { connect } from "react-redux" import { useParams } from "react-router-dom" import DOWNLOAD_ICON from "resources/download.png" import "./BoardDashboard.css" +import _forEach from "lodash/forEach" import { DiagramNodeFactory, DiagramNodeModel, @@ -60,7 +63,10 @@ const PrototypeNode = ({ name, model }) => (
{ - event.dataTransfer.setData("storm-diagram-node", JSON.stringify(model)) + event.dataTransfer.setData( + "storm-diagram-node", + JSON.stringify({ anetObjectType: model.constructor.resourceName }) + ) }} > { const [model, setModel] = useState(null) const [edit, setEdit] = useState(false) const [editedNode, setEditedNode] = useState(null) + const [, updateState] = React.useState() + const forceUpdate = useCallback(() => updateState({}), []) useEffect(() => { setModel(new DiagramModel()) @@ -122,8 +130,7 @@ const BoardDashboard = () => { const data = JSON.parse( dropEvent.dataTransfer.getData("storm-diagram-node") ) - console.log(data) - const node = new DiagramNodeModel() + const node = new DiagramNodeModel(data) const point = engineRef.current.getRelativeMousePoint(dropEvent) node.setPosition(point) engineRef.current.getModel().addNode(node) @@ -131,6 +138,32 @@ const BoardDashboard = () => { setEditedNode(node) } }, [model, dropEvent]) + + const cloneSelected = () => { + const offset = { x: 100, y: 100 } + const itemMap = {} + _forEach(model.getSelectedEntities(), item => { + const newItem = item.clone(itemMap) + + // offset the nodes slightly + if (newItem instanceof NodeModel) { + newItem.setPosition( + newItem.getX() + offset.x, + newItem.getY() + offset.y + ) + model.addNode(newItem) + } else if (newItem instanceof LinkModel) { + // offset the link points + newItem.getPoints().forEach(p => { + p.setPosition(p.getX() + offset.x, p.getY() + offset.y) + }) + model.addLink(newItem) + } + newItem.setSelected(false) + forceUpdate() + }) + } + return (
{ )}
- + {edit && ( <> + + + drag and drop into diafgram: @@ -195,6 +231,7 @@ const BoardDashboard = () => { editedNode.options.anetObject = value editedNode.options.anetObjectType = objectType }} + objectType={editedNode?.options.anetObjectType} /> diff --git a/client/src/pages/dashboards/DiagramNode.js b/client/src/pages/dashboards/DiagramNode.js index d8e42bfc74..b1858aa004 100644 --- a/client/src/pages/dashboards/DiagramNode.js +++ b/client/src/pages/dashboards/DiagramNode.js @@ -19,10 +19,11 @@ import LinkTo from "components/LinkTo" import * as Models from "models" import PropTypes from "prop-types" import * as React from "react" +import AvatarDisplayComponent from "components/AvatarDisplayComponent" const ENTITY_GQL_FIELDS = { Report: "uuid, intent", - Person: "uuid, name, role, avatar(size: 32)", + Person: "uuid, name, role, avatar(size: 64)", Organization: "uuid, shortName", Position: "uuid, name", Location: "uuid, name", @@ -49,9 +50,10 @@ export class DiagramLinkModel extends DefaultLinkModel { } } export class DiagramNodeModel extends NodeModel { - constructor() { + constructor(options) { super({ - type: "anet" + type: "anet", + ...options }) this.addPort(new DiagramPortModel(PortModelAlignment.TOP)) this.addPort(new DiagramPortModel(PortModelAlignment.LEFT)) @@ -66,13 +68,13 @@ export class DiagramNodeModel extends NodeModel { options.color = event.data.color // TODO: batch-process all queries as one const modelClass = Models[event.data.anetObjectType] - console.log(" deserializing ..." + modelClass.resourceName) modelClass && modelClass .fetchByUuid(event.data.anetObjectUuid, ENTITY_GQL_FIELDS) .then(function(entity) { options.anetObject = entity - console.log(" deserialized ..." + event.data.anetObjectUuid) + // TODO: fire an event instead + event.engine.repaintCanvas() }) } @@ -88,6 +90,7 @@ 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; @@ -107,23 +110,36 @@ export const DiagramNodeWidget = ({ size, node, engine }) => { style={{ position: "relative", width: size, - height: size + height: size, + backgroundColor: node.isSelected() ? "rgba(0, 0, 255, 0.3)" : "white" }} > - - {node.options.anetObjectType && node.options.anetObject && ( - + ) : ( + + )} + {node.options.anetObjectType && node.options.anetObject && ( +
+ +
)} { return ( - + ) } From e0f28ba73d92d2f1c350b82a66310fd7dba81e6d Mon Sep 17 00:00:00 2001 From: Vassil Iordanov Date: Tue, 24 Mar 2020 15:18:03 +0100 Subject: [PATCH 009/247] nci-agency/anet#2889: Improve diagram editor palette --- client/src/pages/dashboards/BoardDashboard.js | 101 ++++++------------ 1 file changed, 34 insertions(+), 67 deletions(-) diff --git a/client/src/pages/dashboards/BoardDashboard.js b/client/src/pages/dashboards/BoardDashboard.js index f511256fd7..a60ebfb48b 100644 --- a/client/src/pages/dashboards/BoardDashboard.js +++ b/client/src/pages/dashboards/BoardDashboard.js @@ -1,39 +1,23 @@ -import { - DefaultDiagramState, - DiagramEngine, - DiagramModel, - LinkLayerFactory, - NodeLayerFactory, - PortModelAlignment, - LinkModel, - NodeModel -} from "@projectstorm/react-diagrams-core" +import { Icon } from "@blueprintjs/core" +import { IconNames } from "@blueprintjs/icons" +import { CanvasWidget, SelectionBoxLayerFactory } from "@projectstorm/react-canvas-core" +import { DefaultDiagramState, DiagramEngine, DiagramModel, LinkLayerFactory, LinkModel, NodeLayerFactory, NodeModel, PortModelAlignment } from "@projectstorm/react-diagrams-core" import { DefaultLabelFactory } from "@projectstorm/react-diagrams-defaults" -import { - CanvasWidget, - SelectionBoxLayerFactory -} from "@projectstorm/react-canvas-core" import { PathFindingLinkFactory } from "@projectstorm/react-diagrams-routing" import { Settings } from "api" import MultiTypeAdvancedSelectComponent from "components/advancedSelectWidget/MultiTypeAdvancedSelectComponent" import { mapPageDispatchersToProps } from "components/Page" import FileSaver from "file-saver" +import _forEach from "lodash/forEach" import * as Models from "models" import PropTypes from "prop-types" -import React, { useEffect, useRef, useState, useCallback } from "react" +import React, { useCallback, useEffect, useRef, useState } from "react" import { Badge, Button, Modal } from "react-bootstrap" import { connect } from "react-redux" import { useParams } from "react-router-dom" import DOWNLOAD_ICON from "resources/download.png" import "./BoardDashboard.css" -import _forEach from "lodash/forEach" -import { - DiagramNodeFactory, - DiagramNodeModel, - DiagramLinkFactory, - DiagramPortModel, - SimplePortFactory -} from "./DiagramNode" +import { DiagramLinkFactory, DiagramNodeFactory, DiagramNodeModel, DiagramPortModel, SimplePortFactory } from "./DiagramNode" const createEngine = options => { const engine = new DiagramEngine({}) @@ -58,10 +42,11 @@ const createEngine = options => { return engine } -const PrototypeNode = ({ name, model }) => ( +const PrototypeNode = ({ name, model, onClick }) => (
{ event.dataTransfer.setData( "storm-diagram-node", @@ -86,7 +71,8 @@ const PrototypeNode = ({ name, model }) => ( PrototypeNode.propTypes = { name: PropTypes.string, - model: PropTypes.object + model: PropTypes.object, + onClick: PropTypes.func } const BoardDashboard = () => { @@ -127,11 +113,9 @@ const BoardDashboard = () => { useEffect(() => { if (dropEvent) { - const data = JSON.parse( - dropEvent.dataTransfer.getData("storm-diagram-node") - ) + const { data, point } = dropEvent const node = new DiagramNodeModel(data) - const point = engineRef.current.getRelativeMousePoint(dropEvent) + node.setPosition(point) engineRef.current.getModel().addNode(node) setDropEvent(null) @@ -139,31 +123,6 @@ const BoardDashboard = () => { } }, [model, dropEvent]) - const cloneSelected = () => { - const offset = { x: 100, y: 100 } - const itemMap = {} - _forEach(model.getSelectedEntities(), item => { - const newItem = item.clone(itemMap) - - // offset the nodes slightly - if (newItem instanceof NodeModel) { - newItem.setPosition( - newItem.getX() + offset.x, - newItem.getY() + offset.y - ) - model.addNode(newItem) - } else if (newItem instanceof LinkModel) { - // offset the link points - newItem.getPoints().forEach(p => { - p.setPosition(p.getX() + offset.x, p.getY() + offset.y) - }) - model.addLink(newItem) - } - newItem.setSelected(false) - forceUpdate() - }) - } - return (
{ }} onDrop={event => { event.persist() - setDropEvent(event) + const data = JSON.parse( + event.dataTransfer.getData("storm-diagram-node") + ) + const point = engineRef.current.getRelativeMousePoint(event) + setDropEvent({ data, point }) }} onDragOver={event => { event.preventDefault() @@ -193,21 +156,25 @@ const BoardDashboard = () => { )}
- + {edit && ( <> - - - drag and drop into diafgram: - - - - - + {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 }) + }} + />) + })} +
- + {edit && ( <> {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 }) - }} - />) + return ( + instance.iconUrl() && ( + { + const data = { anetObjectType: modelName } + const point = { x: 150, y: 150 } + setDropEvent({ data, point }) + }} + /> + ) + ) })} - +
+
+ {editedNode && ( + + Selected node editor + +
+ +
+
+ setSelectingEntity(false)} + > + + Edit diagram node + + + { + editedNode.options.anetObject = value + editedNode.options.anetObjectType = objectType + setSelectingEntity(false) + }} + objectType={editedNode?.options.anetObjectType} + /> + + +
+ )} )}
- setEditedNode(null)}> - - Edit diagram node - - - { - editedNode.options.anetObject = value - editedNode.options.anetObjectType = objectType - }} - objectType={editedNode?.options.anetObjectType} - /> - -
) } From aa9af4a0151470cc41dfa22d9972a0347693b42a Mon Sep 17 00:00:00 2001 From: vassil Date: Fri, 3 Apr 2020 23:38:38 +0200 Subject: [PATCH 011/247] nci-agency/anet#2889: Fix bug when deleting node An extra clearing of listeners when deleting a node was throwing an error. Also, hide editor when an item is just deleted. Added a drag cusror to palette items and align them to the left. --- client/src/pages/dashboards/BoardDashboard.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/client/src/pages/dashboards/BoardDashboard.js b/client/src/pages/dashboards/BoardDashboard.js index ee42bd1c57..7d2f58675a 100644 --- a/client/src/pages/dashboards/BoardDashboard.js +++ b/client/src/pages/dashboards/BoardDashboard.js @@ -69,6 +69,7 @@ const PrototypeNode = ({ name, model, onClick }) => ( JSON.stringify({ anetObjectType: model.constructor.resourceName }) ) }} + style={{ textAlign: "left", cursor: "grab" }} > { if (event.isCreated) { event.node.registerListener(selectionListener) } else { - event.node.clearListeners() + if ( + editedNode?.options.anetObject.uuid === + event.node.anetObject?.uuid + ) { + setEditedNode(null) + } } } }) @@ -199,7 +205,7 @@ const BoardDashboard = () => { )}
- From f4c736fd6f1de23f78bd4e0fc2e6075af2553e81 Mon Sep 17 00:00:00 2001 From: vassil Date: Fri, 3 Apr 2020 23:57:27 +0200 Subject: [PATCH 012/247] nci-agency/anet#2889: Diagram node background should not be opaque --- client/src/pages/dashboards/DiagramNode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/pages/dashboards/DiagramNode.js b/client/src/pages/dashboards/DiagramNode.js index b1858aa004..6d9e194013 100644 --- a/client/src/pages/dashboards/DiagramNode.js +++ b/client/src/pages/dashboards/DiagramNode.js @@ -111,7 +111,7 @@ export const DiagramNodeWidget = ({ size, node, engine }) => { position: "relative", width: size, height: size, - backgroundColor: node.isSelected() ? "rgba(0, 0, 255, 0.3)" : "white" + backgroundColor: node.isSelected() ? "rgba(0, 0, 255, 0.3)" : null }} > {modelInstance && From 7320ab31c8f73c85cb2a997b2f4d62c862a47664 Mon Sep 17 00:00:00 2001 From: vassil Date: Sat, 4 Apr 2020 00:39:54 +0200 Subject: [PATCH 013/247] nci-agency/anet#2889: Organize sidebar into panels and add zoom to fit button --- client/src/pages/dashboards/BoardDashboard.js | 137 ++++++++++-------- 1 file changed, 80 insertions(+), 57 deletions(-) diff --git a/client/src/pages/dashboards/BoardDashboard.js b/client/src/pages/dashboards/BoardDashboard.js index 7d2f58675a..7829daa0c1 100644 --- a/client/src/pages/dashboards/BoardDashboard.js +++ b/client/src/pages/dashboards/BoardDashboard.js @@ -204,47 +204,66 @@ const BoardDashboard = () => { /> )}
-
- {edit && ( <> - {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 }) - }} - /> - ) - ) - })} - -
-
- {editedNode && ( - - Selected node editor - + + Diagram tools + + + + + + + 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 ? (
-
- setSelectingEntity(false)} - > - - Edit diagram node - - - { - editedNode.options.anetObject = value - editedNode.options.anetObjectType = objectType - setSelectingEntity(false) - }} - objectType={editedNode?.options.anetObjectType} - /> - - -
- )} + ) : ( + + Select an item on diagram + + )} +
+ setSelectingEntity(false)} + > + + Edit diagram node + + + { + editedNode.options.anetObject = value + editedNode.options.anetObjectType = objectType + setSelectingEntity(false) + }} + objectType={editedNode?.options.anetObjectType} + /> + + +
)}
From 342bb1bfbbb220d518ca6eca76e1b9dc31c9183a Mon Sep 17 00:00:00 2001 From: vassil Date: Sat, 4 Apr 2020 02:12:37 +0200 Subject: [PATCH 014/247] nci-agency/anet#2889: Improve side panel layout and add initial auto routing support --- client/src/pages/dashboards/BoardDashboard.js | 85 ++++++++++++------- 1 file changed, 56 insertions(+), 29 deletions(-) diff --git a/client/src/pages/dashboards/BoardDashboard.js b/client/src/pages/dashboards/BoardDashboard.js index 7829daa0c1..a42459d8eb 100644 --- a/client/src/pages/dashboards/BoardDashboard.js +++ b/client/src/pages/dashboards/BoardDashboard.js @@ -13,7 +13,10 @@ import { PortModelAlignment } from "@projectstorm/react-diagrams-core" import { DefaultLabelFactory } from "@projectstorm/react-diagrams-defaults" -import { PathFindingLinkFactory } from "@projectstorm/react-diagrams-routing" +import { + PathFindingLinkFactory, + DagreEngine +} from "@projectstorm/react-diagrams-routing" import { Settings } from "api" import MultiTypeAdvancedSelectComponent from "components/advancedSelectWidget/MultiTypeAdvancedSelectComponent" import { mapPageDispatchersToProps } from "components/Page" @@ -101,6 +104,17 @@ const BoardDashboard = () => { 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()) @@ -205,35 +219,46 @@ const BoardDashboard = () => { )}
- + + + + {edit && ( + <> + + + + + )} + {edit && ( <> - - Diagram tools - - - - - Node palette @@ -264,7 +289,9 @@ const BoardDashboard = () => { Node editor {editedNode ? ( -
+ <> + ANET entity: +
-
+ ) : ( Select an item on diagram From 8366701964d5237af96060c6c1d33817a5570376 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Mon, 6 Apr 2020 14:21:44 +0200 Subject: [PATCH 015/247] NCI-Agency/anet#2954: Add monthly assessment to people --- anet.yml | 40 ++++++++++++++ client/src/components/Model.js | 28 ++++++++++ .../assessments/AddAssessmentModal.js | 7 ++- .../assessments/AssessmentResultsTable.js | 27 +++++----- client/src/models/Person.js | 39 +++++++++++++- client/src/models/Task.js | 54 ++++++------------- client/src/pages/people/Show.js | 27 ++++++++++ src/main/resources/anet-schema.yml | 4 ++ 8 files changed, 173 insertions(+), 53 deletions(-) diff --git a/anet.yml b/anet.yml index a5f7283c60..76ec47f63a 100644 --- a/anet.yml +++ b/anet.yml @@ -647,6 +647,46 @@ dictionary: - value: "3" label: three color: '#ff8279' + customFields: + 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' position: name: Afghan Tashkil diff --git a/client/src/components/Model.js b/client/src/components/Model.js index 02f05d8ba2..3a90809593 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -139,6 +139,16 @@ export const createYupObjectShape = (config, prefix = "formCustomFields") => { return yup.object().shape(objShape) } +export const createAssessmentSchema = ( + assessmentConfig, + prefix = "entityAssessment" +) => { + const assessmentSchemaShape = createYupObjectShape(assessmentConfig, prefix) + return yup.object().shape({ + prefix: assessmentSchemaShape + }) +} + export default class Model { static schema = { notes: [] @@ -301,4 +311,22 @@ export default class Model { toString() { return this.name || this.uuid } + + 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(note => ({ + uuid: note.uuid, + assessment: JSON.parse(note.text) + })) + return notesToAssessments.length ? notesToAssessments[0].assessment : null + } } diff --git a/client/src/components/assessments/AddAssessmentModal.js b/client/src/components/assessments/AddAssessmentModal.js index 1a10cf7e3c..e4a8f37f4d 100644 --- a/client/src/components/assessments/AddAssessmentModal.js +++ b/client/src/components/assessments/AddAssessmentModal.js @@ -6,7 +6,7 @@ import { 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 { Person, Task } from "models" import PropTypes from "prop-types" import React, { useMemo, useState } from "react" import { Button, Modal } from "react-bootstrap" @@ -124,7 +124,10 @@ const AddAssessmentModal = ({ } } AddAssessmentModal.propTypes = { - entity: PropTypes.oneOfType([PropTypes.instanceOf(Task)]).isRequired, + entity: PropTypes.oneOfType([ + PropTypes.instanceOf(Person), + PropTypes.instanceOf(Task) + ]).isRequired, entityType: PropTypes.func.isRequired, yupSchema: PropTypes.object.isRequired, assessmentConfig: PropTypes.object.isRequired, diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index aefa9308c2..311138c1e6 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -19,8 +19,8 @@ import "components/assessments/AssessmentResultsTable.css" * 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() + * the config and yupSchema for these assessments is to be found in + * entity.getPeriodAssessmentDetails() */ const AssessmentsTableHeader = ({ periods }) => ( @@ -97,7 +97,10 @@ const MonthlyAssessmentRows = ({ canAddAssessment, onAddAssessment }) => { - const periodAssessmentConfig = entity.periodAssessmentConfig() + const { + assessmentConfig, + assessmentYupSchema + } = entity.getPeriodAssessmentDetails() const [showAssessmentModal, setShowAssessmentModal] = useState(false) const periodsLastAssessment = [] const periodsAllowNewAssessment = [] @@ -112,7 +115,7 @@ const MonthlyAssessmentRows = ({ }) ) periodsAllowNewAssessment.push( - periodAssessmentConfig && canAddAssessment && period.allowNewAssessments + assessmentConfig && canAddAssessment && period.allowNewAssessments ) }) const hasLastAssessments = !_isEmpty( @@ -127,7 +130,7 @@ const MonthlyAssessmentRows = ({ const lastAssessmentPrefix = `lastAssessment-${entity.uuid}-${index}` return ( - {periodAssessmentConfig && lastAssessment && ( + {assessmentConfig && lastAssessment && ( ( @@ -171,11 +174,11 @@ const MonthlyAssessmentRows = ({ setShowAssessmentModal(false)} onSuccess={() => { @@ -225,7 +228,7 @@ const EntityAssessmentResults = ({ <> - + {Object.keys(assessmentDefinition || {}).map(key => ( diff --git a/client/src/models/Person.js b/client/src/models/Person.js index 74837a8fdd..8e046e8c24 100644 --- a/client/src/models/Person.js +++ b/client/src/models/Person.js @@ -1,5 +1,9 @@ import { Settings } from "api" -import Model, { createYupObjectShape, yupDate } from "components/Model" +import Model, { + createAssessmentSchema, + createYupObjectShape, + yupDate +} from "components/Model" import _isEmpty from "lodash/isEmpty" import { Organization, Position } from "models" import AFG_ICON from "resources/afg_small.png" @@ -30,6 +34,20 @@ export default class Person extends Model { static nameDelimiter = "," + static advisorAssessmentConfig = + Settings.fields.advisor.person.assessment?.customFields + + static principalAssessmentConfig = + Settings.fields.principal.person.assessment?.customFields + + static advisorAssessmentSchema = createAssessmentSchema( + Person.advisorAssessmentConfig + ) + + static principalAssessmentSchema = createAssessmentSchema( + Person.principalAssessmentConfig + ) + // create yup schema for the customFields, based on the customFields config static customFieldsSchema = createYupObjectShape( Settings.fields.person.customFields @@ -255,6 +273,25 @@ export default class Person extends Model { return orgUuids.includes(org.uuid) } + getPeriodAssessmentDetails() { + if (this.isAdvisor()) { + return { + assessmentConfig: Person.advisorAssessmentConfig, + assessmentYupSchema: Person.advisorAssessmentSchema + } + } else if (this.isPrincipal()) { + return { + assessmentConfig: Person.principalAssessmentConfig, + assessmentYupSchema: Person.principalAssessmentSchema + } + } else { + return { + assessmentConfig: null, + assessmentYupSchema: null + } + } + } + iconUrl() { if (this.isAdvisor()) { return RS_ICON diff --git a/client/src/models/Task.js b/client/src/models/Task.js index f1ac902120..ac6bdf8b70 100644 --- a/client/src/models/Task.js +++ b/client/src/models/Task.js @@ -1,5 +1,6 @@ import { Settings } from "api" import Model, { + createAssessmentSchema, createYupObjectShape, NOTE_TYPE, yupDate @@ -10,16 +11,6 @@ import TASKS_ICON from "resources/tasks.png" 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, @@ -57,11 +48,11 @@ export default class Task extends Model { Settings.fields.task.customFields ) - static topLevelAssessmentCustomFieldsSchema = createTaskAssessmentSchema( + static topLevelAssessmentCustomFieldsSchema = createAssessmentSchema( Settings.fields.task.topLevel.assessment.customFields ) - static subLevelAssessmentCustomFieldsSchema = createTaskAssessmentSchema( + static subLevelAssessmentCustomFieldsSchema = createAssessmentSchema( Settings.fields.task.subLevel.assessment.customFields ) @@ -188,14 +179,19 @@ export default class Task extends Model { : Settings.fields.task.subLevel } - periodAssessmentYupSchema() { - return this.isTopLevelTask() - ? Task.topLevelAssessmentCustomFieldsSchema - : Task.subLevelAssessmentCustomFieldsSchema - } - - periodAssessmentConfig() { - return this.fieldSettings().assessment?.customFields + getPeriodAssessmentDetails() { + const assessmentConfig = this.fieldSettings().assessment?.customFields + if (this.isTopLevelTask()) { + return { + assessmentConfig: assessmentConfig, + assessmentYupSchema: Task.topLevelAssessmentCustomFieldsSchema + } + } else { + return { + assessmentConfig: assessmentConfig, + assessmentYupSchema: Task.subLevelAssessmentCustomFieldsSchema + } + } } iconUrl() { @@ -231,22 +227,4 @@ export default class Task extends Model { ) return assessmentResults } - - 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 - } } diff --git a/client/src/pages/people/Show.js b/client/src/pages/people/Show.js index 0eb17c5f86..ca8fda9405 100644 --- a/client/src/pages/people/Show.js +++ b/client/src/pages/people/Show.js @@ -2,6 +2,7 @@ import { DEFAULT_PAGE_PROPS, DEFAULT_SEARCH_PROPS } from "actions" import API, { Settings } from "api" import { gql } from "apollo-boost" import AppContext from "components/AppContext" +import AssessmentResultsTable from "components/assessments/AssessmentResultsTable" import AssignPositionModal from "components/AssignPositionModal" import AvatarDisplayComponent from "components/AvatarDisplayComponent" import { ReadonlyCustomFields } from "components/CustomFields" @@ -146,6 +147,23 @@ const BasePersonShow = ({ pageDispatchers, currentUser }) => { (!hasPosition && currentUser.isSuperUser()) || (hasPosition && currentUser.isSuperUserForOrg(position.organization)) || (person.role === Person.ROLE.PRINCIPAL && currentUser.isSuperUser()) + const assessmentPeriods = [ + { + start: moment().subtract(2, "months").startOf("month"), + end: moment().subtract(2, "months").endOf("month"), + allowNewAssessments: false + }, + { + start: moment().subtract(1, "months").startOf("month"), + end: moment().subtract(1, "months").endOf("month"), + allowNewAssessments: true + }, + { + start: moment().startOf("month"), + end: moment().endOf("month"), + allowNewAssessments: false + } + ] return ( @@ -413,6 +431,15 @@ const BasePersonShow = ({ pageDispatchers, currentUser }) => { )} + +
) }} diff --git a/src/main/resources/anet-schema.yml b/src/main/resources/anet-schema.yml index 0925fbfc0a..09fe7ae800 100644 --- a/src/main/resources/anet-schema.yml +++ b/src/main/resources/anet-schema.yml @@ -611,6 +611,10 @@ properties: type: string color: type: string + customFields: + type: object + additionalProperties: + "$ref": "#/definitions/customField" position: type: object From 06df1e59cecd2600ec6f505abe03bcf186e5a230 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 7 Apr 2020 09:49:39 +0200 Subject: [PATCH 016/247] NCI-Agency/anet#2954: Core refactoring assessments terminology This renames the assessments made on tasks when working on reports (in the context of the report form) to measurements. It also makes the difference in terminology more clear in the AssessmentResultsTable. Measurements are assessments made on an entity in relation with another entity: so measurements of an engagement's related tasks while filling the engagement form, or measurements of an engagement's attendees while filling the engagement form. Further we call assessments the assessments made about an entity related to a given period of time: like month assessments of a task or of a person. --- .../assessments/AssessmentResultsTable.js | 20 ++++--- client/src/models/Report.js | 29 +++++----- client/src/models/Task.js | 18 +++--- client/src/pages/reports/Edit.js | 5 +- client/src/pages/reports/Form.js | 57 ++++++++++--------- client/src/pages/reports/New.js | 5 +- client/src/pages/reports/Show.js | 12 ++-- 7 files changed, 79 insertions(+), 67 deletions(-) diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index 311138c1e6..23b1118b98 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -15,7 +15,7 @@ import "components/assessments/AssessmentResultsTable.css" * - aggregation of the measurements 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 + * the configuration of these measurements 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; @@ -67,7 +67,7 @@ const MeasurementRow = ({ !_isEmpty(x)) ) - const hasAddAssessment = !_isEmpty(periodsAllowNewAssessment.filter(x => x)) + const rowHasAddAssessment = !_isEmpty( + periodsAllowNewAssessment.filter(x => x) + ) return ( <> - {hasLastAssessments && ( + {rowHasLastAssessments && ( {periodsLastAssessment.map((lastAssessment, index) => { const lastAssessmentPrefix = `lastAssessment-${entity.uuid}-${index}` @@ -152,7 +154,7 @@ const MonthlyAssessmentRows = ({ })} )} - {hasAddAssessment && ( + {rowHasAddAssessment && ( {assessmentPeriods.map((period, index) => { const assessmentLabelPrefix = periodsLastAssessment[index] @@ -221,7 +223,7 @@ const EntityAssessmentResults = ({ if (!entity) { return null } - const assessmentDefinition = JSON.parse( + const measurementsConfig = JSON.parse( JSON.parse(entity.customFields || "{}").assessmentDefinition || "{}" ) return ( @@ -231,11 +233,11 @@ const EntityAssessmentResults = ({ - {Object.keys(assessmentDefinition || {}).map(key => ( + {Object.keys(measurementsConfig || {}).map(key => ( diff --git a/client/src/models/Report.js b/client/src/models/Report.js index 0f0bd870e4..5247051a6c 100644 --- a/client/src/models/Report.js +++ b/client/src/models/Report.js @@ -382,8 +382,8 @@ export default class Report extends Model { } } - getTaskAssessments() { - const notesToAssessments = this.notes + getTasksMeasurements() { + const notesToMeasurements = this.notes .filter( n => n.type === NOTE_TYPE.ASSESSMENT && @@ -391,23 +391,24 @@ export default class Report extends Model { ro => ro.relatedObjectType === Task.relatedObjectType ).length ) - .map(ta => ({ + .map(n => ({ taskUuid: [ - ta.noteRelatedObjects.filter( + n.noteRelatedObjects.filter( ro => ro.relatedObjectType === Task.relatedObjectType )[0].relatedObjectUuid ], - assessmentUuid: ta.uuid, - assessment: JSON.parse(ta.text) + measurementUuid: n.uuid, + measurement: JSON.parse(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 + // When updating the measurements, we need for each task the uuid of the + // related engagement measurement + const taskToMeasurementUuid = {} + // Get initial tasks measurements values + const tasksMeasurements = {} + notesToMeasurements.forEach(m => { + taskToMeasurementUuid[m.taskUuid] = m.measurementUuid + tasksMeasurements[m.taskUuid] = m.measurement }) - return { taskToAssessmentUuid, taskAssessments } + return { taskToMeasurementUuid, tasksMeasurements } } } diff --git a/client/src/models/Task.js b/client/src/models/Task.js index ac6bdf8b70..54d57411f8 100644 --- a/client/src/models/Task.js +++ b/client/src/models/Task.js @@ -202,9 +202,9 @@ export default class Task extends Model { return `${this.shortName}` } - getAssessmentResults(dateRange) { + getMeasurementsResults(dateRange) { const publishedReportsUuids = this.publishedReports.map(r => r.uuid) - const taskAssessmentNotes = this.notes + const measurementsNotes = this.notes .filter( n => n.type === NOTE_TYPE.ASSESSMENT && @@ -217,14 +217,14 @@ export default class Task extends Model { (!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 => { - assessmentResults[k] = assessmentResults[k] || [] - assessmentResults[k].push(o[k]) + .map(n => JSON.parse(n.text)) + const measurementsResults = {} + measurementsNotes.forEach(n => + Object.keys(n).forEach(k => { + measurementsResults[k] = measurementsResults[k] || [] + measurementsResults[k].push(n[k]) }) ) - return assessmentResults + return measurementsResults } } diff --git a/client/src/pages/reports/Edit.js b/client/src/pages/reports/Edit.js index ce053a647a..2a5f2d6e6a 100644 --- a/client/src/pages/reports/Edit.js +++ b/client/src/pages/reports/Edit.js @@ -122,7 +122,10 @@ const ReportEdit = ({ pageDispatchers }) => { data.report.formCustomFields = JSON.parse(data.report.customFields) } const report = new Report(data ? data.report : {}) - const reportInitialValues = Object.assign(report, report.getTaskAssessments()) + const reportInitialValues = Object.assign( + report, + report.getTasksMeasurements() + ) return (
diff --git a/client/src/pages/reports/Form.js b/client/src/pages/reports/Form.js index c347d6a34e..111bfb7699 100644 --- a/client/src/pages/reports/Form.js +++ b/client/src/pages/reports/Form.js @@ -200,7 +200,7 @@ const BaseReportForm = ({ 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 in order to be able to dynamically update the yup schema for the selected tasks measurements const [reportTasks, setReportTasks] = useState(initialValues.tasks) // some autosave settings const defaultTimeout = moment.duration(30, "seconds") @@ -328,23 +328,23 @@ const BaseReportForm = ({ })) } - // Update the task assessments schema according to the selected report tasks - const taskAssessmentsSchemaShape = {} + // Update the task measurements schema according to the selected report tasks + const tasksMeasurementsSchemaShape = {} reportTasks .filter(t => t.customFields) .forEach(t => { - taskAssessmentsSchemaShape[t.uuid] = createYupObjectShape( + tasksMeasurementsSchemaShape[t.uuid] = createYupObjectShape( JSON.parse(JSON.parse(t.customFields).assessmentDefinition), - `taskAssessments.${t.uuid}` + `tasksMeasurements.${t.uuid}` ) }) - const reportSchema = _isEmpty(taskAssessmentsSchemaShape) + const reportSchema = _isEmpty(tasksMeasurementsSchemaShape) ? Report.yupSchema : Report.yupSchema.concat( yup.object().shape({ - taskAssessments: yup + tasksMeasurements: yup .object() - .shape(taskAssessmentsSchemaShape) + .shape(tasksMeasurementsSchemaShape) .nullable() .default(null) }) @@ -1072,14 +1072,14 @@ const BaseReportForm = ({ if (!taskCustomFields.assessmentDefinition) { return null } - const taskAssessmentDefinition = JSON.parse( + const taskMeasurementConfig = JSON.parse( taskCustomFields.assessmentDefinition ) return ( t.uuid) - return Object.keys(values.taskAssessments) + return Object.keys(values.tasksMeasurements) .filter( key => selectedTasksUuids.includes(key) && - !isEmptyTaskAssessment(values.taskAssessments[key]) + !isEmptyTaskMeasurement(values.tasksMeasurements[key]) ) .map(key => { const noteObj = { @@ -1297,11 +1297,15 @@ const BaseReportForm = ({ relatedObjectUuid: reportUuid } ], - text: customFieldsJSONString(values, true, `taskAssessments.${key}`) + text: customFieldsJSONString( + values, + true, + `tasksMeasurements.${key}` + ) } - const initialAssessmentUuid = values.taskToAssessmentUuid[key] - if (initialAssessmentUuid) { - noteObj.uuid = initialAssessmentUuid + const initialMeasurementUuid = values.taskToMeasurementUuid[key] + if (initialMeasurementUuid) { + noteObj.uuid = initialMeasurementUuid } return noteObj }) @@ -1317,8 +1321,8 @@ const BaseReportForm = ({ "tasks", "customFields", // initial JSON from the db "formCustomFields", - "taskAssessments", - "taskToAssessmentUuid" + "tasksMeasurements", + "taskToMeasurementUuid" ) if (Report.isFuture(values.engagementDate)) { // Empty fields which should not be set for future reports. @@ -1361,7 +1365,7 @@ const BaseReportForm = ({ return _saveReport(edit, variables, sendEmail).then(response => { const report = response[operation] const updateNotesVariables = { report } - updateNotesVariables.notes = createTaskAssessmentsNotes( + updateNotesVariables.notes = createTasksMeasurementsNotes( values, report.uuid ) @@ -1375,7 +1379,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) diff --git a/client/src/pages/reports/New.js b/client/src/pages/reports/New.js index e6e818cfa3..47eeea416a 100644 --- a/client/src/pages/reports/New.js +++ b/client/src/pages/reports/New.js @@ -26,7 +26,10 @@ const BaseReportNew = ({ pageDispatchers, currentUser }) => { person.primary = true report.attendees.push(person) } - const reportInitialValues = Object.assign(report, report.getTaskAssessments()) + const reportInitialValues = Object.assign( + report, + report.getTasksMeasurements() + ) return (
diff --git a/client/src/pages/reports/Show.js b/client/src/pages/reports/Show.js index f004805296..2278cb0878 100644 --- a/client/src/pages/reports/Show.js +++ b/client/src/pages/reports/Show.js @@ -350,8 +350,8 @@ 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 task measurements values + report = Object.assign(report, report.getTasksMeasurements()) return ( { if (!taskCustomFields.assessmentDefinition) { return null } - const taskAssessmentDefinition = JSON.parse( + const taskMeasurementsConfig = JSON.parse( taskCustomFields.assessmentDefinition ) return ( ) From 759df995f2da5aec8b4c08e3d1c24a7cb7f6d9c3 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 7 Apr 2020 11:06:51 +0200 Subject: [PATCH 017/247] NCI-Agency/anet#2954: Fix monthly assessment yup schema Was desproyed by commit 8366701964d5237af96060c6c1d33817a5570376. --- client/src/components/Model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/Model.js b/client/src/components/Model.js index 3a90809593..468fe2b7ee 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -145,7 +145,7 @@ export const createAssessmentSchema = ( ) => { const assessmentSchemaShape = createYupObjectShape(assessmentConfig, prefix) return yup.object().shape({ - prefix: assessmentSchemaShape + [prefix]: assessmentSchemaShape }) } From 2697c9222579dc54f310366979744719e541a606 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 7 Apr 2020 11:51:39 +0200 Subject: [PATCH 018/247] NCI-Agency/anet#2954: Change canAddAssessment condition for people For a person one can only add assessments if the person to be assessed is a counterpart of the logged in user. --- client/src/pages/people/Show.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/client/src/pages/people/Show.js b/client/src/pages/people/Show.js index ca8fda9405..cc78fad33e 100644 --- a/client/src/pages/people/Show.js +++ b/client/src/pages/people/Show.js @@ -164,7 +164,10 @@ const BasePersonShow = ({ pageDispatchers, currentUser }) => { allowNewAssessments: false } ] - + const canAddAssessment = currentUser.position.associatedPositions + .filter(ap => ap.person) + .map(ap => ap.person.uuid) + .includes(person.uuid) return ( {({ values }) => { @@ -437,7 +440,7 @@ const BasePersonShow = ({ pageDispatchers, currentUser }) => { entity={person} entityType={Person} assessmentPeriods={assessmentPeriods} - canAddAssessment + canAddAssessment={canAddAssessment} onAddAssessment={refetch} />
From 7b2fabd226e4999bf108a14ffee4b1c2e5d38c69 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 7 Apr 2020 14:48:06 +0200 Subject: [PATCH 019/247] NCI-Agency/anet#2954: Conditionally display assessment results table This makes sure that if there is no measurements config or assessment config for the current entity, the assessment results table is not being displayed. --- .../assessments/AssessmentResultsTable.js | 79 +++++++++++-------- client/src/models/Person.js | 42 +++++----- client/src/models/Task.js | 40 ++++++---- client/src/pages/reports/Show.js | 14 ++-- 4 files changed, 98 insertions(+), 77 deletions(-) diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index 23b1118b98..63f803d89a 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -15,8 +15,8 @@ import "components/assessments/AssessmentResultsTable.css" * - aggregation of the measurements 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 configuration of these measurements is to be found in - * entity.customFields.assessmentDefinition + * the configuration of these measurements can be retrieved using + * entity.getMeasurementsConfig() * - display of the last monthly assessment made on the entity/subentities * as a conclusion about the given period of time; * the config and yupSchema for these assessments is to be found in @@ -223,9 +223,7 @@ const EntityAssessmentResults = ({ if (!entity) { return null } - const measurementsConfig = JSON.parse( - JSON.parse(entity.customFields || "{}").assessmentDefinition || "{}" - ) + const measurementsConfig = entity.getMeasurementsConfig() return ( <> @@ -279,36 +277,49 @@ const AssessmentResultsTable = ({ if (!entity) { return null } + const entityMeasurementsConfig = entity.getMeasurementsConfig() + const subentitiesMeasurementsConfig = subEntities + ?.map(s => s.getMeasurementsConfig()) + .filter(mc => !_isEmpty(mc)) + const { assessmentConfig } = entity.getPeriodAssessmentDetails() + const showAssessmentResults = + !_isEmpty(entityMeasurementsConfig) || + !_isEmpty(subentitiesMeasurementsConfig) || + !_isEmpty(assessmentConfig) return ( -
-
- - - - {!_isEmpty(subEntities) && ( - <> - {subEntities?.map(subEntity => ( - - ))} - - )} - - -
-
-
+ <> + {showAssessmentResults && ( +
+
+ + + + {!_isEmpty(subEntities) && ( + <> + {subEntities?.map(subEntity => ( + + ))} + + )} + + +
+
+
+ )} + ) } AssessmentResultsTable.propTypes = { diff --git a/client/src/models/Person.js b/client/src/models/Person.js index 8e046e8c24..d914742513 100644 --- a/client/src/models/Person.js +++ b/client/src/models/Person.js @@ -273,25 +273,6 @@ export default class Person extends Model { return orgUuids.includes(org.uuid) } - getPeriodAssessmentDetails() { - if (this.isAdvisor()) { - return { - assessmentConfig: Person.advisorAssessmentConfig, - assessmentYupSchema: Person.advisorAssessmentSchema - } - } else if (this.isPrincipal()) { - return { - assessmentConfig: Person.principalAssessmentConfig, - assessmentYupSchema: Person.principalAssessmentSchema - } - } else { - return { - assessmentConfig: null, - assessmentYupSchema: null - } - } - } - iconUrl() { if (this.isAdvisor()) { return RS_ICON @@ -353,4 +334,27 @@ export default class Person extends Model { firstName: firstName.trim() } } + + getMeasurementsConfig() { + return {} + } + + getPeriodAssessmentDetails() { + if (this.isAdvisor()) { + return { + assessmentConfig: Person.advisorAssessmentConfig, + assessmentYupSchema: Person.advisorAssessmentSchema + } + } else if (this.isPrincipal()) { + return { + assessmentConfig: Person.principalAssessmentConfig, + assessmentYupSchema: Person.principalAssessmentSchema + } + } else { + return { + assessmentConfig: null, + assessmentYupSchema: null + } + } + } } diff --git a/client/src/models/Task.js b/client/src/models/Task.js index 54d57411f8..ea00837e0a 100644 --- a/client/src/models/Task.js +++ b/client/src/models/Task.js @@ -179,21 +179,6 @@ export default class Task extends Model { : Settings.fields.task.subLevel } - getPeriodAssessmentDetails() { - const assessmentConfig = this.fieldSettings().assessment?.customFields - if (this.isTopLevelTask()) { - return { - assessmentConfig: assessmentConfig, - assessmentYupSchema: Task.topLevelAssessmentCustomFieldsSchema - } - } else { - return { - assessmentConfig: assessmentConfig, - assessmentYupSchema: Task.subLevelAssessmentCustomFieldsSchema - } - } - } - iconUrl() { return TASKS_ICON } @@ -202,6 +187,16 @@ export default class Task extends Model { return `${this.shortName}` } + static getMeasurementsConfig(customFields) { + return JSON.parse( + JSON.parse(customFields || "{}").assessmentDefinition || "{}" + ) + } + + getMeasurementsConfig() { + return Task.getMeasurementsConfig(this.customFields) + } + getMeasurementsResults(dateRange) { const publishedReportsUuids = this.publishedReports.map(r => r.uuid) const measurementsNotes = this.notes @@ -227,4 +222,19 @@ export default class Task extends Model { ) return measurementsResults } + + getPeriodAssessmentDetails() { + const assessmentConfig = this.fieldSettings().assessment?.customFields + if (this.isTopLevelTask()) { + return { + assessmentConfig: assessmentConfig, + assessmentYupSchema: Task.topLevelAssessmentCustomFieldsSchema + } + } else { + return { + assessmentConfig: assessmentConfig, + assessmentYupSchema: Task.subLevelAssessmentCustomFieldsSchema + } + } + } } diff --git a/client/src/pages/reports/Show.js b/client/src/pages/reports/Show.js index 2278cb0878..07ea65b775 100644 --- a/client/src/pages/reports/Show.js +++ b/client/src/pages/reports/Show.js @@ -30,7 +30,7 @@ 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" @@ -657,16 +657,12 @@ const BaseReportShow = ({ currentUser, setSearchQuery, pageDispatchers }) => { id="engagement-assessments" > {values.tasks.map(task => { - if (!task.customFields) { - return null - } - const taskCustomFields = JSON.parse(task.customFields) - if (!taskCustomFields.assessmentDefinition) { + const taskMeasurementsConfig = Task.getMeasurementsConfig( + task.customFields + ) + if (_isEmpty(taskMeasurementsConfig)) { return null } - const taskMeasurementsConfig = JSON.parse( - taskCustomFields.assessmentDefinition - ) return ( Date: Thu, 9 Apr 2020 07:46:55 +0200 Subject: [PATCH 020/247] NCI-Agency/anet#2954: Simplify return statement of getLastAssessment Use optional chaining operator when returning the last assessment. --- client/src/components/Model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/Model.js b/client/src/components/Model.js index 468fe2b7ee..9e09dec494 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -327,6 +327,6 @@ export default class Model { uuid: note.uuid, assessment: JSON.parse(note.text) })) - return notesToAssessments.length ? notesToAssessments[0].assessment : null + return notesToAssessments?.[0]?.assessment } } From ca3d2e8007d5fdb63cc6b8ee792c442d96380bd4 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 9 Apr 2020 07:52:34 +0200 Subject: [PATCH 021/247] NCI-Agency/anet#2954: Refactor assessment field name Use a constant for the ENTITY_ASSESSMENT_FIELD, instead of reusing the hardcoded value in several files. --- client/src/components/Model.js | 4 +++- .../components/assessments/AddAssessmentModal.js | 14 +++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/client/src/components/Model.js b/client/src/components/Model.js index 9e09dec494..612056dca8 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -139,9 +139,11 @@ export const createYupObjectShape = (config, prefix = "formCustomFields") => { return yup.object().shape(objShape) } +export const ENTITY_ASSESSMENT_FIELD = "entityAssessment" + export const createAssessmentSchema = ( assessmentConfig, - prefix = "entityAssessment" + prefix = ENTITY_ASSESSMENT_FIELD ) => { const assessmentSchemaShape = createYupObjectShape(assessmentConfig, prefix) return yup.object().shape({ diff --git a/client/src/components/assessments/AddAssessmentModal.js b/client/src/components/assessments/AddAssessmentModal.js index e4a8f37f4d..d992e2229c 100644 --- a/client/src/components/assessments/AddAssessmentModal.js +++ b/client/src/components/assessments/AddAssessmentModal.js @@ -3,7 +3,11 @@ import { CustomFieldsContainer, customFieldsJSONString } from "components/CustomFields" -import Model, { GQL_CREATE_NOTE, NOTE_TYPE } from "components/Model" +import Model, { + ENTITY_ASSESSMENT_FIELD, + GQL_CREATE_NOTE, + NOTE_TYPE +} from "components/Model" import Messages from "components/Messages" import { Form, Formik } from "formik" import { Person, Task } from "models" @@ -59,7 +63,7 @@ const AddAssessmentModal = ({ Date: Thu, 9 Apr 2020 10:12:51 +0200 Subject: [PATCH 022/247] NCI-Agency/anet#2954: Update custom fields terminology We used to use the prefix term, which was actually containing the name of the parent field containing the custom fields. Changed the term to make the code better understandable. --- client/src/components/CustomFields.js | 44 +++++++++---------- client/src/components/Model.js | 27 ++++++++---- .../assessments/AddAssessmentModal.js | 6 +-- .../assessments/AssessmentResultsTable.js | 6 +-- client/src/pages/reports/Form.js | 2 +- client/src/pages/reports/Show.js | 2 +- 6 files changed, 48 insertions(+), 39 deletions(-) diff --git a/client/src/components/CustomFields.js b/client/src/components/CustomFields.js index 20671e4c64..3be85faf2a 100644 --- a/client/src/components/CustomFields.js +++ b/client/src/components/CustomFields.js @@ -34,7 +34,7 @@ const SPECIAL_WIDGET_COMPONENTS = { } const RENDERERS = {} -const DEFAULT_CUSTOM_FIELDS_PREFIX = "formCustomFields" +const DEFAULT_CUSTOM_FIELDS_PARENT = "formCustomFields" const SpecialField = ({ name, widget, formikProps, ...otherFieldProps }) => { const WidgetComponent = SPECIAL_WIDGET_COMPONENTS[widget] @@ -285,7 +285,7 @@ const ArrayObject = ({ invisibleFields={invisibleFields} updateInvisibleFields={updateInvisibleFields} vertical={vertical} - fieldNamePrefix={`${fieldName}.${index}`} + parentFieldName={`${fieldName}.${index}`} /> ) @@ -344,7 +344,7 @@ const ReadonlyArrayObject = ({
@@ -373,7 +373,7 @@ const FIELD_COMPONENTS = { function getInvisibleFields( invisibleFields, fieldsConfig, - fieldNamePrefix, + parentFieldName, formikValues ) { const prevInvisibleFields = _cloneDeep(invisibleFields) @@ -382,7 +382,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 +404,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}.invisibleCustomFields` useEffect(() => { setFieldValue(invisibleFieldsFieldName, invisibleFields, true) }, [invisibleFieldsFieldName, invisibleFields, setFieldValue]) @@ -431,11 +431,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 } @@ -521,7 +521,7 @@ CustomField.propTypes = { const CustomFields = ({ fieldsConfig, formikProps, - fieldNamePrefix, + parentFieldName, invisibleFields, updateInvisibleFields, vertical @@ -539,10 +539,10 @@ const CustomFields = ({ getInvisibleFields( invisibleFields, fieldsConfig, - fieldNamePrefix, + parentFieldName, formikValues ), - [invisibleFields, fieldsConfig, fieldNamePrefix, formikValues] + [invisibleFields, fieldsConfig, parentFieldName, formikValues] ) const invisibleFieldsUnchanged = _isEqualWith( latestInvisibleFieldsProp.current, @@ -566,7 +566,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 +628,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) + const filteredCustomFieldsValues = Object.get(clonedValues, parentFieldName) if (filteredCustomFieldsValues.invisibleCustomFields) { filteredCustomFieldsValues.invisibleCustomFields.forEach(f => _set(clonedValues, f.split("."), undefined) diff --git a/client/src/components/Model.js b/client/src/components/Model.js index 612056dca8..1d51c78e44 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -82,14 +82,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)) { @@ -118,7 +118,7 @@ const createFieldYupSchema = (fieldKey, fieldConfig, fieldPrefix) => { (invisibleCustomFields, schema) => { return invisibleCustomFields === null || (invisibleCustomFields && - invisibleCustomFields.includes(`${fieldPrefix}.${fieldKey}`)) + invisibleCustomFields.includes(`${parentFieldName}.${fieldKey}`)) ? schema : schema.concat(fieldTypeYupSchema) } @@ -126,12 +126,18 @@ const createFieldYupSchema = (fieldKey, fieldConfig, fieldPrefix) => { return fieldYupSchema } -export const createYupObjectShape = (config, prefix = "formCustomFields") => { +export const createYupObjectShape = ( + config, + parentFieldName = "formCustomFields" +) => { 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) @@ -139,15 +145,18 @@ export const createYupObjectShape = (config, prefix = "formCustomFields") => { return yup.object().shape(objShape) } -export const ENTITY_ASSESSMENT_FIELD = "entityAssessment" +export const ENTITY_ASSESSMENT_PARENT_FIELD = "entityAssessment" export const createAssessmentSchema = ( assessmentConfig, - prefix = ENTITY_ASSESSMENT_FIELD + parentFieldName = ENTITY_ASSESSMENT_PARENT_FIELD ) => { - const assessmentSchemaShape = createYupObjectShape(assessmentConfig, prefix) + const assessmentSchemaShape = createYupObjectShape( + assessmentConfig, + parentFieldName + ) return yup.object().shape({ - [prefix]: assessmentSchemaShape + [parentFieldName]: assessmentSchemaShape }) } diff --git a/client/src/components/assessments/AddAssessmentModal.js b/client/src/components/assessments/AddAssessmentModal.js index d992e2229c..a565c40275 100644 --- a/client/src/components/assessments/AddAssessmentModal.js +++ b/client/src/components/assessments/AddAssessmentModal.js @@ -4,7 +4,7 @@ import { customFieldsJSONString } from "components/CustomFields" import Model, { - ENTITY_ASSESSMENT_FIELD, + ENTITY_ASSESSMENT_PARENT_FIELD, GQL_CREATE_NOTE, NOTE_TYPE } from "components/Model" @@ -63,7 +63,7 @@ const AddAssessmentModal = ({ {periodsLastAssessment.map((lastAssessment, index) => { - const lastAssessmentPrefix = `lastAssessment-${entity.uuid}-${index}` + const lastAssessmentParentFieldName = `lastAssessment-${entity.uuid}-${index}` return ( {assessmentConfig && lastAssessment && ( {({ values }) => ( { ) From d2b7257eb54da43e2880528031706ce2e49e092d Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 9 Apr 2020 11:57:33 +0200 Subject: [PATCH 023/247] NCI-Agency/anet#2954: Code refactoring formCustomFields This makes sure that we no longer use in lots of places in the code the hardcoded "formCustomFields" value for the custom fields parent field. The code is now better understandable and better maintainable. --- client/src/components/CustomFields.js | 5 ++--- client/src/components/Model.js | 12 +++++++++++- client/src/models/Person.js | 10 +++++----- client/src/models/Report.js | 10 +++++----- client/src/models/Task.js | 10 +++++----- client/src/pages/people/Edit.js | 5 ++++- client/src/pages/people/Form.js | 3 ++- client/src/pages/people/Show.js | 5 ++++- client/src/pages/reports/Edit.js | 5 ++++- client/src/pages/reports/Form.js | 11 +++++++---- client/src/pages/reports/Show.js | 5 ++++- client/src/pages/tasks/Edit.js | 3 ++- client/src/pages/tasks/Form.js | 8 ++++++-- client/src/pages/tasks/Show.js | 3 ++- 14 files changed, 63 insertions(+), 32 deletions(-) diff --git a/client/src/components/CustomFields.js b/client/src/components/CustomFields.js index 3be85faf2a..2a264a0fd4 100644 --- a/client/src/components/CustomFields.js +++ b/client/src/components/CustomFields.js @@ -5,7 +5,8 @@ import Fieldset from "components/Fieldset" import LikertScale from "components/graphs/LikertScale" import Model, { CUSTOM_FIELD_TYPE, - createYupObjectShape + createYupObjectShape, + DEFAULT_CUSTOM_FIELDS_PARENT } from "components/Model" import RichTextEditor from "components/RichTextEditor" import { FastField, FieldArray } from "formik" @@ -34,8 +35,6 @@ const SPECIAL_WIDGET_COMPONENTS = { } const RENDERERS = {} -const DEFAULT_CUSTOM_FIELDS_PARENT = "formCustomFields" - const SpecialField = ({ name, widget, formikProps, ...otherFieldProps }) => { const WidgetComponent = SPECIAL_WIDGET_COMPONENTS[widget] const widgetProps = {} diff --git a/client/src/components/Model.js b/client/src/components/Model.js index 1d51c78e44..10813c2f5d 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -52,6 +52,9 @@ export const NOTE_TYPE = { PARTNER_ASSESSMENT: "PARTNER_ASSESSMENT", ASSESSMENT: "ASSESSMENT" } + +export const DEFAULT_CUSTOM_FIELDS_PARENT = "formCustomFields" + export const yupDate = yup.date().transform(function(value, originalValue) { if (this.isType(value)) { return value @@ -128,7 +131,7 @@ const createFieldYupSchema = (fieldKey, fieldConfig, parentFieldName) => { export const createYupObjectShape = ( config, - parentFieldName = "formCustomFields" + parentFieldName = DEFAULT_CUSTOM_FIELDS_PARENT ) => { let objShape = {} if (config) { @@ -160,6 +163,13 @@ export const createAssessmentSchema = ( }) } +export const createCustomFieldsSchema = customFieldsConfig => + yup.object().shape({ + [DEFAULT_CUSTOM_FIELDS_PARENT]: createYupObjectShape( + customFieldsConfig + ).nullable() + }) + export default class Model { static schema = { notes: [] diff --git a/client/src/models/Person.js b/client/src/models/Person.js index d914742513..61a7c92bb6 100644 --- a/client/src/models/Person.js +++ b/client/src/models/Person.js @@ -1,7 +1,7 @@ import { Settings } from "api" import Model, { createAssessmentSchema, - createYupObjectShape, + createCustomFieldsSchema, yupDate } from "components/Model" import _isEmpty from "lodash/isEmpty" @@ -49,7 +49,7 @@ export default class Person extends Model { ) // create yup schema for the customFields, based on the customFields config - static customFieldsSchema = createYupObjectShape( + static customFieldsSchema = createCustomFieldsSchema( Settings.fields.person.customFields ) @@ -160,10 +160,10 @@ 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 = diff --git a/client/src/models/Report.js b/client/src/models/Report.js index 5247051a6c..f1af730e02 100644 --- a/client/src/models/Report.js +++ b/client/src/models/Report.js @@ -1,6 +1,6 @@ import { Settings } from "api" import Model, { - createYupObjectShape, + createCustomFieldsSchema, NOTE_TYPE, yupDate } from "components/Model" @@ -50,7 +50,7 @@ export default class Report extends Model { } // create yup schema for the customFields, based on the customFields config - static customFieldsSchema = createYupObjectShape( + static customFieldsSchema = createCustomFieldsSchema( Settings.fields.report.customFields ) @@ -238,10 +238,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({ diff --git a/client/src/models/Task.js b/client/src/models/Task.js index aadd98c56a..2e24ff3332 100644 --- a/client/src/models/Task.js +++ b/client/src/models/Task.js @@ -1,7 +1,7 @@ import { Settings } from "api" import Model, { createAssessmentSchema, - createYupObjectShape, + createCustomFieldsSchema, NOTE_TYPE, yupDate } from "components/Model" @@ -44,7 +44,7 @@ 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 ) @@ -152,10 +152,10 @@ 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 = diff --git a/client/src/pages/people/Edit.js b/client/src/pages/people/Edit.js index 489754b436..db09cad104 100644 --- a/client/src/pages/people/Edit.js +++ b/client/src/pages/people/Edit.js @@ -1,6 +1,7 @@ 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, @@ -74,7 +75,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] = JSON.parse( + data.person.customFields + ) } const person = new Person(data ? data.person : {}) const legendText = person.isNewUser() diff --git a/client/src/pages/people/Form.js b/client/src/pages/people/Form.js index bea5b0caa1..73a439a02e 100644 --- a/client/src/pages/people/Form.js +++ b/client/src/pages/people/Form.js @@ -9,6 +9,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" @@ -594,7 +595,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 diff --git a/client/src/pages/people/Show.js b/client/src/pages/people/Show.js index cc78fad33e..3ee5ef1646 100644 --- a/client/src/pages/people/Show.js +++ b/client/src/pages/people/Show.js @@ -12,6 +12,7 @@ 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, @@ -119,7 +120,9 @@ const BasePersonShow = ({ pageDispatchers, currentUser }) => { return result } if (data) { - data.person.formCustomFields = JSON.parse(data.person.customFields) + data.person[DEFAULT_CUSTOM_FIELDS_PARENT] = JSON.parse( + data.person.customFields + ) } const person = new Person(data ? data.person : {}) const stateSuccess = routerLocation.state && routerLocation.state.success diff --git a/client/src/pages/reports/Edit.js b/client/src/pages/reports/Edit.js index 2a5f2d6e6a..3b22e68a69 100644 --- a/client/src/pages/reports/Edit.js +++ b/client/src/pages/reports/Edit.js @@ -1,6 +1,7 @@ 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, @@ -119,7 +120,9 @@ const ReportEdit = ({ pageDispatchers }) => { id: tag.uuid.toString(), text: tag.name })) - data.report.formCustomFields = JSON.parse(data.report.customFields) + data.report[DEFAULT_CUSTOM_FIELDS_PARENT] = JSON.parse( + data.report.customFields + ) } const report = new Report(data ? data.report : {}) const reportInitialValues = Object.assign( diff --git a/client/src/pages/reports/Form.js b/client/src/pages/reports/Form.js index d36d607298..9c4273579e 100644 --- a/client/src/pages/reports/Form.js +++ b/client/src/pages/reports/Form.js @@ -20,7 +20,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 { + createYupObjectShape, + DEFAULT_CUSTOM_FIELDS_PARENT, + NOTE_TYPE +} from "components/Model" import NavigationWarning from "components/NavigationWarning" import { jumpToTop, @@ -241,7 +245,6 @@ const BaseReportForm = ({ text: "__should_not_match_anything__" // TODO: Do this more gracefully } } - const { loading, error, data } = API.useApiQuery(GQL_GET_RECENTS, { taskQuery: recentTasksVarUser }) @@ -1320,7 +1323,7 @@ const BaseReportForm = ({ "attendees", "tasks", "customFields", // initial JSON from the db - "formCustomFields", + DEFAULT_CUSTOM_FIELDS_PARENT, "tasksMeasurements", "taskToMeasurementUuid" ) @@ -1352,7 +1355,7 @@ const BaseReportForm = ({ "lastName", "position", "customFields", - "formCustomFields" + DEFAULT_CUSTOM_FIELDS_PARENT ) ) // strip tasks fields not in data model diff --git a/client/src/pages/reports/Show.js b/client/src/pages/reports/Show.js index 3020fc9516..0e74d11c9d 100644 --- a/client/src/pages/reports/Show.js +++ b/client/src/pages/reports/Show.js @@ -13,6 +13,7 @@ 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, @@ -299,7 +300,9 @@ const BaseReportShow = ({ currentUser, setSearchQuery, pageDispatchers }) => { text: tag.name })) data.report.to = "" - data.report.formCustomFields = JSON.parse(data.report.customFields) + data.report[DEFAULT_CUSTOM_FIELDS_PARENT] = JSON.parse( + data.report.customFields + ) report = new Report(data.report) try { Report.yupSchema.validateSync(report, { abortEarly: false }) diff --git a/client/src/pages/tasks/Edit.js b/client/src/pages/tasks/Edit.js index 5deb9d4923..ef76aea50b 100644 --- a/client/src/pages/tasks/Edit.js +++ b/client/src/pages/tasks/Edit.js @@ -1,6 +1,7 @@ import { DEFAULT_SEARCH_PROPS, PAGE_PROPS_NO_NAV } from "actions" import API, { Settings } from "api" import { gql } from "apollo-boost" +import { DEFAULT_CUSTOM_FIELDS_PARENT } from "components/Model" import { PageDispatchersPropType, mapPageDispatchersToProps, @@ -110,7 +111,7 @@ const TaskEdit = ({ pageDispatchers }) => { return result } if (data) { - data.task.formCustomFields = JSON.parse(data.task.customFields) + data.task[DEFAULT_CUSTOM_FIELDS_PARENT] = JSON.parse(data.task.customFields) } const task = new Task(data ? data.task : {}) diff --git a/client/src/pages/tasks/Form.js b/client/src/pages/tasks/Form.js index f616078930..59cc040353 100644 --- a/client/src/pages/tasks/Form.js +++ b/client/src/pages/tasks/Form.js @@ -17,7 +17,11 @@ 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" @@ -493,7 +497,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) diff --git a/client/src/pages/tasks/Show.js b/client/src/pages/tasks/Show.js index d10cb88ad9..dac87fcd74 100644 --- a/client/src/pages/tasks/Show.js +++ b/client/src/pages/tasks/Show.js @@ -8,6 +8,7 @@ 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 { mapPageDispatchersToProps, PageDispatchersPropType, @@ -156,7 +157,7 @@ const BaseTaskShow = ({ pageDispatchers, currentUser }) => { } if (data) { - data.task.formCustomFields = JSON.parse(data.task.customFields) // TODO: Maybe move this code to Task() + data.task[DEFAULT_CUSTOM_FIELDS_PARENT] = 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() } const task = new Task(data ? data.task : {}) From a580ab184e8b61b0fc8c25a40d3c481462af9d3b Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Fri, 10 Apr 2020 18:33:43 +0200 Subject: [PATCH 024/247] NCI-Agency/anet#2954: Change assessments terminology From now on what we used to call measurements is being called instant assessment (as they are actually also assessments but assess an entity instantly, not over a period of time). Next to it we have periodic assessments (assess an entity over a period of time). --- .../assessments/AssessmentResultsTable.js | 79 ++++++++++--------- client/src/models/Person.js | 4 +- client/src/models/Report.js | 26 +++--- client/src/models/Task.js | 24 +++--- client/src/pages/reports/Edit.js | 2 +- client/src/pages/reports/Form.js | 56 ++++++------- client/src/pages/reports/New.js | 2 +- client/src/pages/reports/Show.js | 14 ++-- 8 files changed, 103 insertions(+), 104 deletions(-) diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index 439e11fa84..43aa14ac69 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -15,15 +15,16 @@ 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 configuration of these measurements can be retrieved using - * entity.getMeasurementsConfig() - * - display of the last monthly assessment made on the entity/subentities - * as a conclusion about the given period of time; + * 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.getPeriodAssessmentDetails() + * entity.getPeriodicAssessmentDetails() */ const PERIOD_FORMAT = "MMM-YYYY" @@ -43,26 +44,26 @@ AssessmentsTableHeader.propTypes = { periods: PropTypes.array } -const MeasurementRow = ({ - measurementKey, - measurementDef, +const InstantAssessmentRow = ({ + questionKey, + questionConfig, entity, assessmentPeriods }) => { const aggWidgetProps = { - widget: measurementDef.aggregation?.widget || measurementDef.widget, - aggregationType: measurementDef.aggregation?.aggregationType, + widget: questionConfig.aggregation?.widget || questionConfig.widget, + aggregationType: questionConfig.aggregation?.aggregationType, vertical: true } - const fieldProps = getFieldPropsFromFieldConfig(measurementDef) + const fieldProps = getFieldPropsFromFieldConfig(questionConfig) return ( {assessmentPeriods.map((assessmentPeriod, index) => ( ) } -MeasurementRow.propTypes = { +InstantAssessmentRow.propTypes = { entity: PropTypes.object, assessmentPeriods: PropTypes.arrayOf( PropTypes.shape({ @@ -81,8 +82,8 @@ MeasurementRow.propTypes = { allowNewAssessments: PropTypes.bool }) ), - measurementKey: PropTypes.string, - measurementDef: PropTypes.object + questionKey: PropTypes.string, + questionConfig: PropTypes.object } const MonthlyAssessmentRows = ({ @@ -93,9 +94,9 @@ const MonthlyAssessmentRows = ({ onAddAssessment }) => { const { - assessmentConfig, - assessmentYupSchema - } = entity.getPeriodAssessmentDetails() + assessmentConfig: periodicAssessmentConfig, + assessmentYupSchema: periodicAssessmentYupSchema + } = entity.getPeriodicAssessmentDetails() const [showAssessmentModal, setShowAssessmentModal] = useState(false) const periodsLastAssessment = [] const periodsAllowNewAssessment = [] @@ -110,7 +111,7 @@ const MonthlyAssessmentRows = ({ }) ) periodsAllowNewAssessment.push( - assessmentConfig && canAddAssessment && period.allowNewAssessments + periodicAssessmentConfig && canAddAssessment && period.allowNewAssessments ) }) const rowHasLastAssessments = !_isEmpty( @@ -127,7 +128,7 @@ const MonthlyAssessmentRows = ({ const lastAssessmentParentFieldName = `lastAssessment-${entity.uuid}-${index}` return ( - {assessmentConfig && lastAssessment && ( + {periodicAssessmentConfig && lastAssessment && ( ( @@ -174,8 +175,8 @@ const MonthlyAssessmentRows = ({ title={`Assessment for ${entity.toString()} for ${period.start.format( PERIOD_FORMAT )}`} - yupSchema={assessmentYupSchema} - assessmentConfig={assessmentConfig} + yupSchema={periodicAssessmentYupSchema} + assessmentConfig={periodicAssessmentConfig} showModal={showAssessmentModal} onCancel={() => setShowAssessmentModal(false)} onSuccess={() => { @@ -218,7 +219,7 @@ const EntityAssessmentResults = ({ if (!entity) { return null } - const measurementsConfig = entity.getMeasurementsConfig() + const instantAssessmentConfig = entity.getInstantAssessmentConfig() return ( <> @@ -226,11 +227,11 @@ const EntityAssessmentResults = ({ - {Object.keys(measurementsConfig || {}).map(key => ( - ( + @@ -272,15 +273,17 @@ const AssessmentResultsTable = ({ if (!entity) { return null } - const entityMeasurementsConfig = entity.getMeasurementsConfig() - const subentitiesMeasurementsConfig = subEntities - ?.map(s => s.getMeasurementsConfig()) + const entityInstantAssessmentConfig = entity.getInstantAssessmentConfig() + const subentitiesInstantAssessmentConfig = subEntities + ?.map(s => s.getInstantAssessmentConfig()) .filter(mc => !_isEmpty(mc)) - const { assessmentConfig } = entity.getPeriodAssessmentDetails() + const { + assessmentConfig: periodicAssessmentConfig + } = entity.getPeriodicAssessmentDetails() const showAssessmentResults = - !_isEmpty(entityMeasurementsConfig) || - !_isEmpty(subentitiesMeasurementsConfig) || - !_isEmpty(assessmentConfig) + !_isEmpty(entityInstantAssessmentConfig) || + !_isEmpty(subentitiesInstantAssessmentConfig) || + !_isEmpty(periodicAssessmentConfig) return ( <> {showAssessmentResults && ( diff --git a/client/src/models/Person.js b/client/src/models/Person.js index 61a7c92bb6..280f84553f 100644 --- a/client/src/models/Person.js +++ b/client/src/models/Person.js @@ -335,11 +335,11 @@ export default class Person extends Model { } } - getMeasurementsConfig() { + getInstantAssessmentConfig() { return {} } - getPeriodAssessmentDetails() { + getPeriodicAssessmentDetails() { if (this.isAdvisor()) { return { assessmentConfig: Person.advisorAssessmentConfig, diff --git a/client/src/models/Report.js b/client/src/models/Report.js index f1af730e02..e345219b89 100644 --- a/client/src/models/Report.js +++ b/client/src/models/Report.js @@ -382,8 +382,8 @@ export default class Report extends Model { } } - getTasksMeasurements() { - const notesToMeasurements = this.notes + getTasksInstantAssessments() { + const notesToAssessments = this.notes .filter( n => n.type === NOTE_TYPE.ASSESSMENT && @@ -397,18 +397,18 @@ export default class Report extends Model { ro => ro.relatedObjectType === Task.relatedObjectType )[0].relatedObjectUuid ], - measurementUuid: n.uuid, - measurement: JSON.parse(n.text) + assessmentUuid: n.uuid, + assessment: JSON.parse(n.text) })) - // When updating the measurements, we need for each task the uuid of the - // related engagement measurement - const taskToMeasurementUuid = {} - // Get initial tasks measurements values - const tasksMeasurements = {} - notesToMeasurements.forEach(m => { - taskToMeasurementUuid[m.taskUuid] = m.measurementUuid - tasksMeasurements[m.taskUuid] = m.measurement + // When updating the instant assessments, we need for each task the uuid of the + // related instant assessment + const taskToAssessmentUuid = {} + // Get initial tasks assessments values + const tasksAssessments = {} + notesToAssessments.forEach(m => { + taskToAssessmentUuid[m.taskUuid] = m.assessmentUuid + tasksAssessments[m.taskUuid] = m.assessment }) - return { taskToMeasurementUuid, tasksMeasurements } + return { taskToAssessmentUuid, tasksAssessments } } } diff --git a/client/src/models/Task.js b/client/src/models/Task.js index 2e24ff3332..d61d558e7b 100644 --- a/client/src/models/Task.js +++ b/client/src/models/Task.js @@ -187,19 +187,19 @@ export default class Task extends Model { return `${this.shortName}` } - static getMeasurementsConfig(customFields) { + static getInstantAssessmentConfig(customFields) { return JSON.parse( JSON.parse(customFields || "{}").assessmentDefinition || "{}" ) } - getMeasurementsConfig() { - return Task.getMeasurementsConfig(this.customFields) + getInstantAssessmentConfig() { + return Task.getInstantAssessmentConfig(this.customFields) } - getMeasurementsResults(dateRange) { + getInstantAssessmentResults(dateRange) { const publishedReportsUuids = this.publishedReports.map(r => r.uuid) - const measurementsNotes = this.notes + const assessmentsNotes = this.notes .filter( n => n.type === NOTE_TYPE.ASSESSMENT && @@ -213,19 +213,19 @@ export default class Task extends Model { (n.createdAt <= dateRange.end && n.createdAt >= dateRange.start)) ) .map(n => JSON.parse(n.text)) - const measurementsResults = {} - measurementsNotes.forEach(n => + const assessmentsResults = {} + assessmentsNotes.forEach(n => Object.keys(n).forEach(k => { - if (!Object.prototype.hasOwnProperty.call(measurementsResults, k)) { - measurementsResults[k] = [] + if (!Object.prototype.hasOwnProperty.call(assessmentsResults, k)) { + assessmentsResults[k] = [] } - measurementsResults[k].push(n[k]) + assessmentsResults[k].push(n[k]) }) ) - return measurementsResults + return assessmentsResults } - getPeriodAssessmentDetails() { + getPeriodicAssessmentDetails() { const assessmentConfig = this.fieldSettings().assessment?.customFields if (this.isTopLevelTask()) { return { diff --git a/client/src/pages/reports/Edit.js b/client/src/pages/reports/Edit.js index 3b22e68a69..fd7c5e2ba8 100644 --- a/client/src/pages/reports/Edit.js +++ b/client/src/pages/reports/Edit.js @@ -127,7 +127,7 @@ const ReportEdit = ({ pageDispatchers }) => { const report = new Report(data ? data.report : {}) const reportInitialValues = Object.assign( report, - report.getTasksMeasurements() + report.getTasksInstantAssessments() ) return ( diff --git a/client/src/pages/reports/Form.js b/client/src/pages/reports/Form.js index 9c4273579e..2ca061bd7b 100644 --- a/client/src/pages/reports/Form.js +++ b/client/src/pages/reports/Form.js @@ -204,7 +204,7 @@ const BaseReportForm = ({ 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 tasks measurements + // We need the report tasks in order to be able to dynamically update the yup schema for the selected tasks instant assessments const [reportTasks, setReportTasks] = useState(initialValues.tasks) // some autosave settings const defaultTimeout = moment.duration(30, "seconds") @@ -331,23 +331,23 @@ const BaseReportForm = ({ })) } - // Update the task measurements schema according to the selected report tasks - const tasksMeasurementsSchemaShape = {} + // Update the task instant assessment schema according to the selected report tasks + const tasksInstantAssessmentsSchemaShape = {} reportTasks .filter(t => t.customFields) .forEach(t => { - tasksMeasurementsSchemaShape[t.uuid] = createYupObjectShape( + tasksInstantAssessmentsSchemaShape[t.uuid] = createYupObjectShape( JSON.parse(JSON.parse(t.customFields).assessmentDefinition), - `tasksMeasurements.${t.uuid}` + `tasksAssessments.${t.uuid}` ) }) - const reportSchema = _isEmpty(tasksMeasurementsSchemaShape) + const reportSchema = _isEmpty(tasksInstantAssessmentsSchemaShape) ? Report.yupSchema : Report.yupSchema.concat( yup.object().shape({ - tasksMeasurements: yup + tasksAssessments: yup .object() - .shape(tasksMeasurementsSchemaShape) + .shape(tasksInstantAssessmentsSchemaShape) .nullable() .default(null) }) @@ -1075,14 +1075,14 @@ const BaseReportForm = ({ if (!taskCustomFields.assessmentDefinition) { return null } - const taskMeasurementConfig = JSON.parse( + const taskInstantAssessmentConfig = JSON.parse( taskCustomFields.assessmentDefinition ) return ( t.uuid) - return Object.keys(values.tasksMeasurements) + return Object.keys(values.tasksAssessments) .filter( key => selectedTasksUuids.includes(key) && - !isEmptyTaskMeasurement(values.tasksMeasurements[key]) + !isEmptyTaskAssessment(values.tasksAssessments[key]) ) .map(key => { const noteObj = { @@ -1300,15 +1300,11 @@ const BaseReportForm = ({ relatedObjectUuid: reportUuid } ], - text: customFieldsJSONString( - values, - true, - `tasksMeasurements.${key}` - ) + text: customFieldsJSONString(values, true, `tasksAssessments.${key}`) } - const initialMeasurementUuid = values.taskToMeasurementUuid[key] - if (initialMeasurementUuid) { - noteObj.uuid = initialMeasurementUuid + const initialAssessmentUuid = values.taskToAssessmentUuid[key] + if (initialAssessmentUuid) { + noteObj.uuid = initialAssessmentUuid } return noteObj }) @@ -1324,8 +1320,8 @@ const BaseReportForm = ({ "tasks", "customFields", // initial JSON from the db DEFAULT_CUSTOM_FIELDS_PARENT, - "tasksMeasurements", - "taskToMeasurementUuid" + "tasksAssessments", + "taskToAssessmentUuid" ) if (Report.isFuture(values.engagementDate)) { // Empty fields which should not be set for future reports. @@ -1368,7 +1364,7 @@ const BaseReportForm = ({ return _saveReport(edit, variables, sendEmail).then(response => { const report = response[operation] const updateNotesVariables = { report } - updateNotesVariables.notes = createTasksMeasurementsNotes( + updateNotesVariables.notes = createTasksInstantAssessments( values, report.uuid ) diff --git a/client/src/pages/reports/New.js b/client/src/pages/reports/New.js index 47eeea416a..82f62d7c4a 100644 --- a/client/src/pages/reports/New.js +++ b/client/src/pages/reports/New.js @@ -28,7 +28,7 @@ const BaseReportNew = ({ pageDispatchers, currentUser }) => { } const reportInitialValues = Object.assign( report, - report.getTasksMeasurements() + report.getTasksInstantAssessments() ) return ( diff --git a/client/src/pages/reports/Show.js b/client/src/pages/reports/Show.js index 0e74d11c9d..5d4fe07e01 100644 --- a/client/src/pages/reports/Show.js +++ b/client/src/pages/reports/Show.js @@ -353,8 +353,8 @@ const BaseReportShow = ({ currentUser, setSearchQuery, pageDispatchers }) => { const hasAuthorizationGroups = report.authorizationGroups && report.authorizationGroups.length > 0 - // Get initial task measurements values - report = Object.assign(report, report.getTasksMeasurements()) + // Get initial tasks instant assessments values + report = Object.assign(report, report.getTasksInstantAssessments()) return ( { id="engagement-assessments" > {values.tasks.map(task => { - const taskMeasurementsConfig = Task.getMeasurementsConfig( + const taskInstantAssessmentConfig = Task.getInstantAssessmentConfig( task.customFields ) - if (_isEmpty(taskMeasurementsConfig)) { + if (_isEmpty(taskInstantAssessmentConfig)) { return null } return ( ) From 91c12e49e0be0af15350f8f02e5bbd22d1d5a48f Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Fri, 10 Apr 2020 22:03:12 +0200 Subject: [PATCH 025/247] NCI-Agency/anet#2954: Add task assessments custom field This adds an assessments customField to task, which makes it possible to define different types of assessments for a task. The field is an array_of_objects type of field, and each object will be the definition of a new assessments. If these assessments are being defined for a task, we use them, otherwise we use the old way of defining the instant assessments and the periodic monthly assessments. --- anet.yml | 41 ++++++++++++++++++++++++++++++++ client/src/models/Task.js | 40 +++++++++++++++---------------- client/src/pages/reports/Form.js | 12 +++------- insertBaseData-mssql.sql | 4 ++-- 4 files changed, 65 insertions(+), 32 deletions(-) diff --git a/anet.yml b/anet.yml index acac304d57..44da239b0d 100644 --- a/anet.yml +++ b/anet.yml @@ -304,6 +304,47 @@ dictionary: label: Responsible positions placeholder: Search for a position... customFields: + assessments: + type: array_of_objects + label: Assessments definition + addButtonLabel: Add an assessment + objectLabel: Assessment + objectFields: + assessmentType: + type: enum + label: Assessment type + helpText: Select an assessement type for this assessment + choices: + periodic: + label: Periodic + instant: + label: Instant + validations: + - type: required + params: [You must provide the assessment type] + periodicity: + type: enum + label: Periodicity + helpText: Select a periodicity for this periodic assessment + choices: + weekly: + label: Weekly + monthly: + label: Monthly + quarterly: + label: quarterly + by_annually: + label: By-annually + validations: + - type: required + params: [You must provide the assessment periodicity] + questions: + type: text + label: Questions + placeholder: JSON that defines the assessment (you need to know what you are doing) + componentClass: textarea + style: + height: 200px assessmentDefinition: type: text label: Assessment definition diff --git a/client/src/models/Task.js b/client/src/models/Task.js index d61d558e7b..ff6d5df96c 100644 --- a/client/src/models/Task.js +++ b/client/src/models/Task.js @@ -48,14 +48,6 @@ export default class Task extends Model { Settings.fields.task.customFields ) - static topLevelAssessmentCustomFieldsSchema = createAssessmentSchema( - Settings.fields.task.topLevel.assessment.customFields - ) - - static subLevelAssessmentCustomFieldsSchema = createAssessmentSchema( - Settings.fields.task.subLevel.assessment.customFields - ) - static yupSchema = yup .object() .shape({ @@ -187,9 +179,20 @@ export default class Task extends Model { return `${this.shortName}` } + static getAssessmentsConfig(customFields) { + const assessments = JSON.parse(customFields || "{}").assessments || [] + return Object.fromEntries( + assessments.map(a => [ + `${a.assessmentType}-${a.periodicity}`, + JSON.parse(a.questions || {}) + ]) + ) + } + static getInstantAssessmentConfig(customFields) { - return JSON.parse( - JSON.parse(customFields || "{}").assessmentDefinition || "{}" + return ( + Task.getAssessmentsConfig(customFields)["instant-null"] || + JSON.parse(JSON.parse(customFields || "{}").assessmentDefinition || "{}") ) } @@ -226,17 +229,12 @@ export default class Task extends Model { } getPeriodicAssessmentDetails() { - const assessmentConfig = this.fieldSettings().assessment?.customFields - if (this.isTopLevelTask()) { - return { - assessmentConfig: assessmentConfig, - assessmentYupSchema: Task.topLevelAssessmentCustomFieldsSchema - } - } else { - return { - assessmentConfig: assessmentConfig, - assessmentYupSchema: Task.subLevelAssessmentCustomFieldsSchema - } + const assessmentConfig = + Task.getAssessmentsConfig(this.customFields)["periodic-monthly"] || + this.fieldSettings().assessment?.customFields + return { + assessmentConfig: assessmentConfig, + assessmentYupSchema: createAssessmentSchema(assessmentConfig) } } } diff --git a/client/src/pages/reports/Form.js b/client/src/pages/reports/Form.js index 2ca061bd7b..874a2448f2 100644 --- a/client/src/pages/reports/Form.js +++ b/client/src/pages/reports/Form.js @@ -337,7 +337,7 @@ const BaseReportForm = ({ .filter(t => t.customFields) .forEach(t => { tasksInstantAssessmentsSchemaShape[t.uuid] = createYupObjectShape( - JSON.parse(JSON.parse(t.customFields).assessmentDefinition), + t.getInstantAssessmentConfig(), `tasksAssessments.${t.uuid}` ) }) @@ -1068,16 +1068,10 @@ const BaseReportForm = ({ id="engagement-assessments" > {values.tasks.map(task => { - if (!task.customFields) { + const taskInstantAssessmentConfig = task.getInstantAssessmentConfig() + if (!taskInstantAssessmentConfig) { return null } - const taskCustomFields = JSON.parse(task.customFields) - if (!taskCustomFields.assessmentDefinition) { - return null - } - const taskInstantAssessmentConfig = JSON.parse( - taskCustomFields.assessmentDefinition - ) return ( Date: Thu, 16 Apr 2020 08:13:58 +0200 Subject: [PATCH 026/247] NCI-Agency/anet#2977: Add general assessments definitions to tasks We now added the possibility to add assessments definitions for a task on a more general level: per task level. In anet.yml these assessments definitions can be configured using the assessments property for fields.task.topLevel and fields.task.subLevel. When a task also has assessments defintions at an instance level (by filling the task's assessments custom field), we make the union of the general and the instance specific defintions and the instance specific definition has priority. --- anet.yml | 105 +++++++++++++++++------------ client/src/models/Task.js | 69 ++++++++++++++----- client/src/pages/reports/Form.js | 7 +- client/src/pages/reports/Show.js | 2 +- src/main/resources/anet-schema.yml | 32 ++++++--- 5 files changed, 143 insertions(+), 72 deletions(-) diff --git a/anet.yml b/anet.yml index 44da239b0d..1a612abac7 100644 --- a/anet.yml +++ b/anet.yml @@ -225,35 +225,21 @@ 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: + - assessmentType: periodic + periodicity: by_annualy + 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 +252,50 @@ 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: + - assessmentType: periodic + periodicity: 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 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] + - assessmentType: periodic + periodicity: 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 @@ -333,8 +350,8 @@ dictionary: label: Monthly quarterly: label: quarterly - by_annually: - label: By-annually + by_annualy: + label: By-annualy validations: - type: required params: [You must provide the assessment periodicity] diff --git a/client/src/models/Task.js b/client/src/models/Task.js index ff6d5df96c..17b38f2393 100644 --- a/client/src/models/Task.js +++ b/client/src/models/Task.js @@ -161,16 +161,24 @@ export default class Task extends Model { super(Model.fillObject(props, Task.yupSchema)) } + static isTopLevelTask(task) { + return _isEmpty(task.customFieldRef1) + } + isTopLevelTask() { - return _isEmpty(this.customFieldRef1) + return Task.isTopLevelTask(this) } - fieldSettings() { - return this.isTopLevelTask() + static fieldSettings(task) { + return Task.isTopLevelTask(task) ? Settings.fields.task.topLevel : Settings.fields.task.subLevel } + fieldSettings() { + return Task.fieldSettings(this) + } + iconUrl() { return TASKS_ICON } @@ -179,25 +187,52 @@ export default class Task extends Model { return `${this.shortName}` } - static getAssessmentsConfig(customFields) { - const assessments = JSON.parse(customFields || "{}").assessments || [] + static parseAssessmentsConfig(assessmentsConfig) { return Object.fromEntries( - assessments.map(a => [ - `${a.assessmentType}-${a.periodicity}`, - JSON.parse(a.questions || {}) - ]) + assessmentsConfig.map(a => { + const assessmentKey = a.periodicity + ? `${a.assessmentType}_${a.periodicity}` + : a.assessmentType + const questions = a.questions || {} + return [ + assessmentKey, + typeof questions === "object" ? questions : JSON.parse(questions) + ] + }) ) } - static getInstantAssessmentConfig(customFields) { + static getGeneralAssessmentsConfig(task) { + return Task.parseAssessmentsConfig( + Task.fieldSettings(task).assessments || [] + ) + } + + static getInstanceAssessmentsConfig(task) { + // The given task instance might have a specific assessments config + return Task.parseAssessmentsConfig( + JSON.parse(task.customFields || "{}").assessments || [] + ) + } + + static getAssessmentsConfig(task) { + return Object.assign( + Task.getGeneralAssessmentsConfig(task), + Task.getInstanceAssessmentsConfig(task) + ) + } + + static getInstantAssessmentConfig(task) { return ( - Task.getAssessmentsConfig(customFields)["instant-null"] || - JSON.parse(JSON.parse(customFields || "{}").assessmentDefinition || "{}") + Task.getAssessmentsConfig(task).instant || + JSON.parse( + JSON.parse(task.customFields || "{}").assessmentDefinition || "{}" + ) ) } getInstantAssessmentConfig() { - return Task.getInstantAssessmentConfig(this.customFields) + return Task.getInstantAssessmentConfig(this) } getInstantAssessmentResults(dateRange) { @@ -228,10 +263,10 @@ export default class Task extends Model { return assessmentsResults } - getPeriodicAssessmentDetails() { - const assessmentConfig = - Task.getAssessmentsConfig(this.customFields)["periodic-monthly"] || - this.fieldSettings().assessment?.customFields + getPeriodicAssessmentDetails(periodicity = "monthly") { + const assessmentConfig = Task.getAssessmentsConfig(this)[ + `periodic_${periodicity}` + ] return { assessmentConfig: assessmentConfig, assessmentYupSchema: createAssessmentSchema(assessmentConfig) diff --git a/client/src/pages/reports/Form.js b/client/src/pages/reports/Form.js index 874a2448f2..ab8d5711ca 100644 --- a/client/src/pages/reports/Form.js +++ b/client/src/pages/reports/Form.js @@ -334,10 +334,11 @@ const BaseReportForm = ({ // Update the task instant assessment schema according to the selected report tasks const tasksInstantAssessmentsSchemaShape = {} reportTasks + // TODO: even tasks without custom fields may have assessments .filter(t => t.customFields) .forEach(t => { tasksInstantAssessmentsSchemaShape[t.uuid] = createYupObjectShape( - t.getInstantAssessmentConfig(), + Task.getInstantAssessmentConfig(t), `tasksAssessments.${t.uuid}` ) }) @@ -1068,7 +1069,9 @@ const BaseReportForm = ({ id="engagement-assessments" > {values.tasks.map(task => { - const taskInstantAssessmentConfig = task.getInstantAssessmentConfig() + const taskInstantAssessmentConfig = Task.getInstantAssessmentConfig( + task + ) if (!taskInstantAssessmentConfig) { return null } diff --git a/client/src/pages/reports/Show.js b/client/src/pages/reports/Show.js index 5d4fe07e01..52467541db 100644 --- a/client/src/pages/reports/Show.js +++ b/client/src/pages/reports/Show.js @@ -661,7 +661,7 @@ const BaseReportShow = ({ currentUser, setSearchQuery, pageDispatchers }) => { > {values.tasks.map(task => { const taskInstantAssessmentConfig = Task.getInstantAssessmentConfig( - task.customFields + task ) if (_isEmpty(taskInstantAssessmentConfig)) { return null diff --git a/src/main/resources/anet-schema.yml b/src/main/resources/anet-schema.yml index cf5e8e02f6..1bd9f5526f 100644 --- a/src/main/resources/anet-schema.yml +++ b/src/main/resources/anet-schema.yml @@ -201,6 +201,26 @@ definitions: type: string required: [levels] +# definition for assessment configuration + assessmentDef: + type: object + additionalProperties: false + required: [assessmentType, periodicity, questions] + properties: + assessmentType: + title: type of assessment + type: string + enum: [instant, periodic] + periodicity: + title: period of the periodic assessment + type: string + enum: [weekly, monthly, quarterly, by_annualy] + questions: + title: questions to respond when assessing + type: object + additionalProperties: + "$ref": "#/definitions/customField" + ######################################################### ### schema root ######################################################### @@ -350,14 +370,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: From ada3419c439dc6f7ba9611d47c360d1b95f40559 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 16 Apr 2020 09:23:00 +0200 Subject: [PATCH 027/247] NCI-Agency/anet#2977: Remove invisibleCustomFields from assessments config They are not needed there. --- insertBaseData-mssql.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/insertBaseData-mssql.sql b/insertBaseData-mssql.sql index 7ebbf7d9f7..285738a20d 100644 --- a/insertBaseData-mssql.sql +++ b/insertBaseData-mssql.sql @@ -321,7 +321,7 @@ INSERT INTO tasks (uuid, shortName, longName, category, createdAt, updatedAt, cu 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'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":[{"invisibleCustomFields":null,"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\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Monthly assessment Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }","periodicity":"monthly","assessmentType":"periodic"},{"invisibleCustomFields":null,"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\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Weekly assessment Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }","periodicity":"weekly","assessmentType":"periodic"},{"invisibleCustomFields":null,"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\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Instant assessment Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }","periodicity":null,"assessmentType":"instant"}] }'); + (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\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Monthly assessment Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }","periodicity":"monthly","assessmentType":"periodic"},{"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\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Weekly assessment Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }","periodicity":"weekly","assessmentType":"periodic"},{"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\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Instant assessment Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }","periodicity":null,"assessmentType":"instant"}] }'); INSERT INTO tasks (uuid, shortName, longName, category, createdAt, updatedAt, customFieldRef1Uuid) VALUES From e9a3e346210a808c0574659932f7e9dfe3f13338 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 16 Apr 2020 09:34:13 +0200 Subject: [PATCH 028/247] NCI-Agency/anet#2977: Remove task customFields.assessmentDefinition It is no longer used since we've introduced the customFields.assessments for adding the instance specific assessments configuration. No need for a migration script as where this was implemented already they start with a new set of tasks. --- anet.yml | 7 ------- client/src/models/Task.js | 7 +------ insertBaseData-mssql.sql | 4 ++-- 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/anet.yml b/anet.yml index 1a612abac7..0d347bcf55 100644 --- a/anet.yml +++ b/anet.yml @@ -362,13 +362,6 @@ dictionary: componentClass: textarea style: height: 200px - 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 report: intent: Engagement purpose diff --git a/client/src/models/Task.js b/client/src/models/Task.js index 17b38f2393..ec1fdfae53 100644 --- a/client/src/models/Task.js +++ b/client/src/models/Task.js @@ -223,12 +223,7 @@ export default class Task extends Model { } static getInstantAssessmentConfig(task) { - return ( - Task.getAssessmentsConfig(task).instant || - JSON.parse( - JSON.parse(task.customFields || "{}").assessmentDefinition || "{}" - ) - ) + return Task.getAssessmentsConfig(task).instant } getInstantAssessmentConfig() { diff --git a/insertBaseData-mssql.sql b/insertBaseData-mssql.sql index 285738a20d..1c74af2546 100644 --- a/insertBaseData-mssql.sql +++ b/insertBaseData-mssql.sql @@ -319,8 +319,8 @@ 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\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Test Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }","periodicity":null,"assessmentType":"instant"}] }'), + (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\" } }","periodicity":null,"assessmentType":"instant"}] }'), (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\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Monthly assessment Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }","periodicity":"monthly","assessmentType":"periodic"},{"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\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Weekly assessment Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }","periodicity":"weekly","assessmentType":"periodic"},{"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\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Instant assessment Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }","periodicity":null,"assessmentType":"instant"}] }'); INSERT INTO tasks (uuid, shortName, longName, category, createdAt, updatedAt, customFieldRef1Uuid) From 4a73a9769ac611d1195be4bbfd47fbc9662e49bd Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 16 Apr 2020 09:40:25 +0200 Subject: [PATCH 029/247] NCI-Agency/anet#2977: Code refactoring in parseAssessmentsConfig Only parse JSON if the questions value is a string. --- client/src/models/Task.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/src/models/Task.js b/client/src/models/Task.js index ec1fdfae53..bf7141a94b 100644 --- a/client/src/models/Task.js +++ b/client/src/models/Task.js @@ -196,7 +196,11 @@ export default class Task extends Model { const questions = a.questions || {} return [ assessmentKey, - typeof questions === "object" ? questions : JSON.parse(questions) + typeof questions === "object" + ? questions + : typeof questions === "string" + ? JSON.parse(questions) + : {} ] }) ) From 4b60926de1fc36d387838aba9feeeae2855ccf93 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Fri, 17 Apr 2020 10:57:07 +0200 Subject: [PATCH 030/247] NCI-Agency/anet#2977: Add assessment period details to assessment This adds the __assessmentType and __assessmentPeriodStart to the note's text when saving an assessment. This will make it possible to better filter the assessments later. --- .../components/assessments/AddAssessmentModal.js | 13 ++++++++++++- .../assessments/AssessmentResultsTable.js | 2 ++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/client/src/components/assessments/AddAssessmentModal.js b/client/src/components/assessments/AddAssessmentModal.js index a565c40275..f4b5d0f373 100644 --- a/client/src/components/assessments/AddAssessmentModal.js +++ b/client/src/components/assessments/AddAssessmentModal.js @@ -10,6 +10,7 @@ import Model, { } from "components/Model" import Messages from "components/Messages" import { Form, Formik } from "formik" +import _cloneDeep from "lodash/cloneDeep" import { Person, Task } from "models" import PropTypes from "prop-types" import React, { useMemo, useState } from "react" @@ -19,6 +20,8 @@ const AddAssessmentModal = ({ entity, entityType, yupSchema, + assessmentType, + assessmentPeriod, assessmentConfig, title, showModal, @@ -121,8 +124,14 @@ const AddAssessmentModal = ({ } ] } + const clonedValues = _cloneDeep(values) + clonedValues[ + ENTITY_ASSESSMENT_PARENT_FIELD + ].__assessmentType = assessmentType + clonedValues[ENTITY_ASSESSMENT_PARENT_FIELD].__assessmentPeriodStart = + assessmentPeriod.start updatedNote.text = customFieldsJSONString( - values, + clonedValues, true, ENTITY_ASSESSMENT_PARENT_FIELD ) @@ -138,6 +147,8 @@ AddAssessmentModal.propTypes = { ]).isRequired, entityType: PropTypes.func.isRequired, yupSchema: PropTypes.object.isRequired, + assessmentType: PropTypes.string.isRequired, + assessmentPeriod: PropTypes.object.isRequired, assessmentConfig: PropTypes.object.isRequired, title: PropTypes.string, showModal: PropTypes.bool, diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index 43aa14ac69..1a8dd56170 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -176,6 +176,8 @@ const MonthlyAssessmentRows = ({ PERIOD_FORMAT )}`} yupSchema={periodicAssessmentYupSchema} + assessmentType="monthly" + assessmentPeriod={period} assessmentConfig={periodicAssessmentConfig} showModal={showAssessmentModal} onCancel={() => setShowAssessmentModal(false)} From 257ee474e3a3b794513e8decf18d989abcf7b42c Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Fri, 17 Apr 2020 13:14:16 +0200 Subject: [PATCH 031/247] NCI-Agency/anet#2977: Change assessments schema Changed the assessments schema to be conform new wishes. an assessment has now the following properties: recurrence, relatedObjectTypes and questions. --- anet.yml | 47 +++++++++++++----------------- client/src/models/Task.js | 19 ++++++------ insertBaseData-mssql.sql | 6 ++-- src/main/resources/anet-schema.yml | 16 +++++----- 4 files changed, 43 insertions(+), 45 deletions(-) diff --git a/anet.yml b/anet.yml index 0d347bcf55..d1f61aa340 100644 --- a/anet.yml +++ b/anet.yml @@ -226,8 +226,7 @@ dictionary: style: height: 400px assessments: - - assessmentType: periodic - periodicity: by_annualy + - recurrence: biannualy questions: issues: type: special_field @@ -253,8 +252,7 @@ dictionary: style: height: 400px assessments: - - assessmentType: periodic - periodicity: monthly + - recurrence: monthly questions: issues: type: special_field @@ -283,8 +281,7 @@ dictionary: validations: - type: required params: [You must provide the assessment status] - - assessmentType: periodic - periodicity: weekly + - recurrence: weekly questions: issues: type: special_field @@ -327,34 +324,32 @@ dictionary: addButtonLabel: Add an assessment objectLabel: Assessment objectFields: - assessmentType: + recurrence: type: enum - label: Assessment type - helpText: Select an assessement type for this assessment - choices: - periodic: - label: Periodic - instant: - label: Instant - validations: - - type: required - params: [You must provide the assessment type] - periodicity: - type: enum - label: Periodicity - helpText: Select a periodicity for this periodic assessment + label: Recurrence + helpText: Select a recurrence for this periodic assessment choices: + once: + label: Once weekly: label: Weekly + biweekly: + label: Bi-weekly monthly: label: Monthly quarterly: label: quarterly - by_annualy: - label: By-annualy - validations: - - type: required - params: [You must provide the assessment periodicity] + bi_annualy: + label: Bi-annualy + 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 diff --git a/client/src/models/Task.js b/client/src/models/Task.js index bf7141a94b..2bd4556152 100644 --- a/client/src/models/Task.js +++ b/client/src/models/Task.js @@ -190,9 +190,11 @@ export default class Task extends Model { static parseAssessmentsConfig(assessmentsConfig) { return Object.fromEntries( assessmentsConfig.map(a => { - const assessmentKey = a.periodicity - ? `${a.assessmentType}_${a.periodicity}` - : a.assessmentType + // FIXME: do not hardcode once + const recurrence = a.recurrence || "once" + const assessmentKey = a.relatedObjectType + ? `${a.relatedObjectType}_${recurrence}` + : recurrence const questions = a.questions || {} return [ assessmentKey, @@ -226,8 +228,9 @@ export default class Task extends Model { ) } - static getInstantAssessmentConfig(task) { - return Task.getAssessmentsConfig(task).instant + static getInstantAssessmentConfig(task, relatedObjectType = "report") { + // FIXME: do not hardcode once and report + return Task.getAssessmentsConfig(task)[`${relatedObjectType}_once`] } getInstantAssessmentConfig() { @@ -262,10 +265,8 @@ export default class Task extends Model { return assessmentsResults } - getPeriodicAssessmentDetails(periodicity = "monthly") { - const assessmentConfig = Task.getAssessmentsConfig(this)[ - `periodic_${periodicity}` - ] + getPeriodicAssessmentDetails(recurrence = "monthly") { + const assessmentConfig = Task.getAssessmentsConfig(this)[recurrence] return { assessmentConfig: assessmentConfig, assessmentYupSchema: createAssessmentSchema(assessmentConfig) diff --git a/insertBaseData-mssql.sql b/insertBaseData-mssql.sql index 1c74af2546..a70e4a58c2 100644 --- a/insertBaseData-mssql.sql +++ b/insertBaseData-mssql.sql @@ -319,9 +319,9 @@ 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', '{ "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\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Test Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }","periodicity":null,"assessmentType":"instant"}] }'), - (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\" } }","periodicity":null,"assessmentType":"instant"}] }'), - (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\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Monthly assessment Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }","periodicity":"monthly","assessmentType":"periodic"},{"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\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Weekly assessment Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }","periodicity":"weekly","assessmentType":"periodic"},{"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\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Instant assessment Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }","periodicity":null,"assessmentType":"instant"}] }'); + (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\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Test Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }","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\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Monthly assessment Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }","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\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Weekly assessment Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }","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\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Instant assessment Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }","relatedObjectType":"report"}] }'); INSERT INTO tasks (uuid, shortName, longName, category, createdAt, updatedAt, customFieldRef1Uuid) VALUES diff --git a/src/main/resources/anet-schema.yml b/src/main/resources/anet-schema.yml index 1bd9f5526f..eb6738572e 100644 --- a/src/main/resources/anet-schema.yml +++ b/src/main/resources/anet-schema.yml @@ -205,16 +205,18 @@ definitions: assessmentDef: type: object additionalProperties: false - required: [assessmentType, periodicity, questions] + required: [questions] properties: - assessmentType: - title: type of assessment + recurrence: + title: recurrence of an assessment type: string - enum: [instant, periodic] - periodicity: - title: period of the periodic assessment + enum: [once, weekly, biweekly, monthly, quarterly, biannualy] + default: once + relatedObjectType: + title: object type context in which the assessment will be made type: string - enum: [weekly, monthly, quarterly, by_annualy] + enum: [report, null] + default: null questions: title: questions to respond when assessing type: object From 0715589bf180a64d6136670cdf02c419ed63cab7 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Fri, 17 Apr 2020 14:48:39 +0200 Subject: [PATCH 032/247] NCI-Agency/anet#2977: Change terminology in assessment content In order to be consistent with the new assessments schema we've changed the terminology in the assessment content too. --- .../src/components/assessments/AddAssessmentModal.js | 10 ++++------ .../components/assessments/AssessmentResultsTable.js | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/client/src/components/assessments/AddAssessmentModal.js b/client/src/components/assessments/AddAssessmentModal.js index f4b5d0f373..ae011380f8 100644 --- a/client/src/components/assessments/AddAssessmentModal.js +++ b/client/src/components/assessments/AddAssessmentModal.js @@ -20,7 +20,7 @@ const AddAssessmentModal = ({ entity, entityType, yupSchema, - assessmentType, + recurrence, assessmentPeriod, assessmentConfig, title, @@ -125,10 +125,8 @@ const AddAssessmentModal = ({ ] } const clonedValues = _cloneDeep(values) - clonedValues[ - ENTITY_ASSESSMENT_PARENT_FIELD - ].__assessmentType = assessmentType - clonedValues[ENTITY_ASSESSMENT_PARENT_FIELD].__assessmentPeriodStart = + clonedValues[ENTITY_ASSESSMENT_PARENT_FIELD].__recurrence = recurrence + clonedValues[ENTITY_ASSESSMENT_PARENT_FIELD].__periodStart = assessmentPeriod.start updatedNote.text = customFieldsJSONString( clonedValues, @@ -147,7 +145,7 @@ AddAssessmentModal.propTypes = { ]).isRequired, entityType: PropTypes.func.isRequired, yupSchema: PropTypes.object.isRequired, - assessmentType: PropTypes.string.isRequired, + recurrence: PropTypes.string.isRequired, assessmentPeriod: PropTypes.object.isRequired, assessmentConfig: PropTypes.object.isRequired, title: PropTypes.string, diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index 1a8dd56170..d28a4632eb 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -176,7 +176,7 @@ const MonthlyAssessmentRows = ({ PERIOD_FORMAT )}`} yupSchema={periodicAssessmentYupSchema} - assessmentType="monthly" + recurrence="monthly" assessmentPeriod={period} assessmentConfig={periodicAssessmentConfig} showModal={showAssessmentModal} From 489488d93f0199002c6241ebf82bd645958a1837 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Fri, 17 Apr 2020 15:17:06 +0200 Subject: [PATCH 033/247] NCI-Agency/anet#2977: Remove the test monthly assessment for now Removed the monthly assessment from the intial data as it's data is no longer complete, and filling the proper __periodStart for the assessment through sql is not really easy. --- insertBaseData-mssql.sql | 9 --------- 1 file changed, 9 deletions(-) diff --git a/insertBaseData-mssql.sql b/insertBaseData-mssql.sql index a70e4a58c2..7caf7f6ad1 100644 --- a/insertBaseData-mssql.sql +++ b/insertBaseData-mssql.sql @@ -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) From 4327a85df9ddf364d911fa0e9840734b784c8312 Mon Sep 17 00:00:00 2001 From: Vassil Iordanov Date: Sat, 18 Apr 2020 08:03:57 +0200 Subject: [PATCH 034/247] nci-agency/anet#2954: Refine possible recurrence values in schema Also, fix indentation in schema --- anet.yml | 16 +++++++++------- src/main/resources/anet-schema.yml | 8 ++++---- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/anet.yml b/anet.yml index d1f61aa340..2e19e4aff1 100644 --- a/anet.yml +++ b/anet.yml @@ -226,7 +226,7 @@ dictionary: style: height: 400px assessments: - - recurrence: biannualy + - recurrence: semiannualy questions: issues: type: special_field @@ -330,17 +330,19 @@ dictionary: helpText: Select a recurrence for this periodic assessment choices: once: - label: Once + label: once + daily: + label: daily weekly: - label: Weekly + label: weekly biweekly: - label: Bi-weekly + label: biweekly monthly: - label: Monthly + label: monthly quarterly: label: quarterly - bi_annualy: - label: Bi-annualy + semiannualy: + label: semiannualy relatedObjectType: type: enum label: Related object type diff --git a/src/main/resources/anet-schema.yml b/src/main/resources/anet-schema.yml index eb6738572e..1e6b5cd2b2 100644 --- a/src/main/resources/anet-schema.yml +++ b/src/main/resources/anet-schema.yml @@ -109,9 +109,9 @@ definitions: - properties: type: enum: [numberAggregation] - aggregationType: - type: string - enum: [sum, avg, min, max] + 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 @@ -210,7 +210,7 @@ definitions: recurrence: title: recurrence of an assessment type: string - enum: [once, weekly, biweekly, monthly, quarterly, biannualy] + enum: [once, daily, weekly, biweekly, monthly, quarterly, semiannualy, annually] default: once relatedObjectType: title: object type context in which the assessment will be made From 07b21bcf10cda5135427a0cdf008d223e838d865 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Mon, 20 Apr 2020 17:05:43 +0200 Subject: [PATCH 035/247] NCI-Agency/anet#2977: Display assessemnt tables for each defined recurrence We used to only display the monthly assessments. We now display one assessments results table for each recurrence for which the current task has an assessment definition. --- .../assessments/AssessmentResultsContainer.js | 190 ++++++++++++++++++ .../assessments/AssessmentResultsTable.js | 103 +++++----- client/src/models/Task.js | 9 +- client/src/pages/people/Show.js | 23 +-- client/src/pages/tasks/Show.js | 48 +++-- 5 files changed, 271 insertions(+), 102 deletions(-) create mode 100644 client/src/components/assessments/AssessmentResultsContainer.js diff --git a/client/src/components/assessments/AssessmentResultsContainer.js b/client/src/components/assessments/AssessmentResultsContainer.js new file mode 100644 index 0000000000..da6f33b768 --- /dev/null +++ b/client/src/components/assessments/AssessmentResultsContainer.js @@ -0,0 +1,190 @@ +import AssessmentResultsTable from "components/assessments/AssessmentResultsTable" +import moment from "moment" +import PropTypes from "prop-types" +import React from "react" + +/* The AssessmentResultsTable component displays the results of two types of + * assessments made on a given entity and subentities: + * - 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; + * 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() + */ + +const now = moment() +const ASSESSMENT_PERIODS_CONFIG = [ + { + recurrence: "daily", + displayFormat: "DD-MM-YYYY", + periods: [ + { + start: now.clone().subtract(2, "days").startOf("day"), + end: now.clone().subtract(2, "days").endOf("day"), + allowNewAssessments: false + }, + { + start: now.clone().subtract(1, "days").startOf("day"), + end: now.clone().subtract(1, "days").endOf("day"), + allowNewAssessments: true + }, + { + start: now.clone().startOf("day"), + end: now.clone().endOf("day"), + allowNewAssessments: false + } + ] + }, + { + recurrence: "weekly", + displayFormat: "DD-MM-YYYY", + periods: [ + { + start: now.clone().subtract(2, "weeks").startOf("week"), + end: now.clone().subtract(2, "weeks").endOf("week"), + allowNewAssessments: false + }, + { + start: now.clone().subtract(1, "weeks").startOf("week"), + end: now.clone().subtract(1, "weeks").endOf("week"), + allowNewAssessments: true + }, + { + start: now.clone().startOf("week"), + end: now.clone().endOf("week"), + allowNewAssessments: false + } + ] + }, + { + recurrence: "biweekly", + displayFormat: "DD-MM-YYYY", + periods: [ + { + start: now.clone().subtract(4, "weeks").startOf("week"), + end: now.clone().subtract(4, "weeks").endOf("week"), + allowNewAssessments: false + }, + { + start: now.clone().subtract(2, "weeks").startOf("week"), + end: now.clone().subtract(2, "weeks").endOf("week"), + allowNewAssessments: true + }, + { + start: now.clone().startOf("week"), + end: now.clone().endOf("week"), + allowNewAssessments: false + } + ] + }, + { + recurrence: "monthly", + displayFormat: "MMM-YYYY", + periods: [ + { + 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 + } + ] + }, + { + recurrence: "quarterly", + displayFormat: "DD-MM-YYYY", + periods: [ + { + start: now.clone().subtract(2, "quarters").startOf("quarter"), + end: now.clone().subtract(2, "quarters").endOf("quarter"), + allowNewAssessments: false + }, + { + start: now.clone().subtract(1, "quarters").startOf("quarter"), + end: now.clone().subtract(1, "quarters").endOf("quarter"), + allowNewAssessments: true + }, + { + start: now.clone().startOf("quarter"), + end: now.clone().endOf("quarter"), + allowNewAssessments: false + } + ] + }, + { + recurrence: "semiannualy", + displayFormat: "DD-MM-YYYY", + periods: [ + { + start: now.clone().subtract(4, "quarters").startOf("quarter"), + end: now.clone().subtract(4, "quarters").endOf("quarter"), + allowNewAssessments: false + }, + { + start: now.clone().subtract(2, "quarters").startOf("quarter"), + end: now.clone().subtract(2, "quarters").endOf("quarter"), + allowNewAssessments: true + }, + { + start: now.clone().startOf("quarter"), + end: now.clone().endOf("quarter"), + allowNewAssessments: false + } + ] + } +] + +const AssessmentResultsContainer = ({ + entity, + entityType, + subEntities, + canAddAssessment, + onAddAssessment +}) => { + if (!entity) { + return null + } + const assessmentsTypes = Object.keys(entity.getAssessmentsConfig()) + return ( + <> + {ASSESSMENT_PERIODS_CONFIG.map(periodsConfig => { + return ( + assessmentsTypes.includes(periodsConfig.recurrence) && ( + + ) + ) + })} + + ) +} +AssessmentResultsContainer.propTypes = { + entity: PropTypes.object, + entityType: PropTypes.func.isRequired, + subEntities: PropTypes.array, + onAddAssessment: PropTypes.func, + canAddAssessment: PropTypes.bool +} + +export default AssessmentResultsContainer diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index d28a4632eb..7082674bb3 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -29,26 +29,41 @@ import "components/assessments/AssessmentResultsTable.css" const PERIOD_FORMAT = "MMM-YYYY" -const AssessmentsTableHeader = ({ periods }) => ( +const periodsPropType = PropTypes.arrayOf( + PropTypes.shape({ + start: PropTypes.object, + end: PropTypes.object, + allowNewAssessments: PropTypes.bool + }) +) +const periodsConfigPropTypes = PropTypes.shape({ + recurrence: PropTypes.string, + displayFormat: PropTypes.string, + periods: periodsPropType +}) + +const AssessmentsTableHeader = ({ periodsConfig }) => ( <> - {periods.map(period => ( - {period.start.format(PERIOD_FORMAT)} + {periodsConfig.periods.map(period => ( + + {period.start.format(periodsConfig.displayFormat)} + ))} ) AssessmentsTableHeader.propTypes = { - periods: PropTypes.array + periodsConfig: periodsConfigPropTypes } const InstantAssessmentRow = ({ questionKey, questionConfig, entity, - assessmentPeriods + periods }) => { const aggWidgetProps = { widget: questionConfig.aggregation?.widget || questionConfig.widget, @@ -58,13 +73,11 @@ const InstantAssessmentRow = ({ const fieldProps = getFieldPropsFromFieldConfig(questionConfig) return ( - {assessmentPeriods.map((assessmentPeriod, index) => ( + {periods.map((period, index) => ( @@ -75,32 +88,27 @@ const InstantAssessmentRow = ({ } InstantAssessmentRow.propTypes = { entity: PropTypes.object, - assessmentPeriods: PropTypes.arrayOf( - PropTypes.shape({ - start: PropTypes.object, - end: PropTypes.object, - allowNewAssessments: PropTypes.bool - }) - ), + periods: periodsPropType, questionKey: PropTypes.string, questionConfig: PropTypes.object } -const MonthlyAssessmentRows = ({ +const PeriodicAssessmentRows = ({ entity, entityType, - assessmentPeriods, + periodsConfig, canAddAssessment, onAddAssessment }) => { + const { recurrence, periods } = periodsConfig const { assessmentConfig: periodicAssessmentConfig, assessmentYupSchema: periodicAssessmentYupSchema - } = entity.getPeriodicAssessmentDetails() + } = entity.getPeriodicAssessmentDetails(recurrence) const [showAssessmentModal, setShowAssessmentModal] = useState(false) const periodsLastAssessment = [] const periodsAllowNewAssessment = [] - assessmentPeriods.forEach(period => { + periods.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. @@ -152,7 +160,7 @@ const MonthlyAssessmentRows = ({ )} {rowHasAddAssessment && ( - {assessmentPeriods.map((period, index) => { + {periods.map((period, index) => { const assessmentLabelPrefix = periodsLastAssessment[index] ? "Add a" : "Make a new" @@ -196,16 +204,10 @@ const MonthlyAssessmentRows = ({ ) } -MonthlyAssessmentRows.propTypes = { +PeriodicAssessmentRows.propTypes = { entity: PropTypes.object, entityType: PropTypes.func.isRequired, - assessmentPeriods: PropTypes.arrayOf( - PropTypes.shape({ - start: PropTypes.object, - end: PropTypes.object, - allowNewAssessments: PropTypes.bool - }) - ), + periodsConfig: periodsConfigPropTypes, canAddAssessment: PropTypes.bool, onAddAssessment: PropTypes.func } @@ -214,7 +216,7 @@ const EntityAssessmentResults = ({ entity, entityType, style, - assessmentPeriods, + periodsConfig, canAddAssessment, onAddAssessment }) => { @@ -222,10 +224,11 @@ const EntityAssessmentResults = ({ return null } const instantAssessmentConfig = entity.getInstantAssessmentConfig() + const { periods } = periodsConfig return ( <> - + @@ -234,14 +237,14 @@ const EntityAssessmentResults = ({ key={key} questionKey={key} questionConfig={instantAssessmentConfig[key]} - assessmentPeriods={assessmentPeriods} + periods={periods} entity={entity} /> ))} - @@ -252,13 +255,7 @@ EntityAssessmentResults.propTypes = { style: PropTypes.object, entity: PropTypes.object, entityType: PropTypes.func.isRequired, - assessmentPeriods: PropTypes.arrayOf( - PropTypes.shape({ - start: PropTypes.object, - end: PropTypes.object, - allowNewAssessments: PropTypes.bool - }) - ), + periodsConfig: periodsConfigPropTypes, onAddAssessment: PropTypes.func, canAddAssessment: PropTypes.bool } @@ -268,20 +265,21 @@ const AssessmentResultsTable = ({ entityType, subEntities, style, - assessmentPeriods, + periodsConfig, canAddAssessment, onAddAssessment }) => { if (!entity) { return null } + const { recurrence } = periodsConfig const entityInstantAssessmentConfig = entity.getInstantAssessmentConfig() const subentitiesInstantAssessmentConfig = subEntities ?.map(s => s.getInstantAssessmentConfig()) .filter(mc => !_isEmpty(mc)) const { assessmentConfig: periodicAssessmentConfig - } = entity.getPeriodicAssessmentDetails() + } = entity.getPeriodicAssessmentDetails(recurrence) const showAssessmentResults = !_isEmpty(entityInstantAssessmentConfig) || !_isEmpty(subentitiesInstantAssessmentConfig) || @@ -290,9 +288,12 @@ const AssessmentResultsTable = ({ <> {showAssessmentResults && (
-
+
- + {!_isEmpty(subEntities) && ( <> @@ -301,7 +302,7 @@ const AssessmentResultsTable = ({ key={`subassessment-${subEntity.uuid}`} entity={subEntity} entityType={entityType} - assessmentPeriods={assessmentPeriods} + periodsConfig={periodsConfig} canAddAssessment={false} /> ))} @@ -310,7 +311,7 @@ const AssessmentResultsTable = ({ @@ -327,13 +328,7 @@ AssessmentResultsTable.propTypes = { entity: PropTypes.object, entityType: PropTypes.func.isRequired, subEntities: PropTypes.array, - assessmentPeriods: PropTypes.arrayOf( - PropTypes.shape({ - start: PropTypes.object, - end: PropTypes.object, - allowNewAssessments: PropTypes.bool - }) - ), + periodsConfig: periodsConfigPropTypes, onAddAssessment: PropTypes.func, canAddAssessment: PropTypes.bool } diff --git a/client/src/models/Task.js b/client/src/models/Task.js index 2bd4556152..1f4256ce80 100644 --- a/client/src/models/Task.js +++ b/client/src/models/Task.js @@ -228,6 +228,10 @@ export default class Task extends Model { ) } + getAssessmentsConfig() { + return Task.getAssessmentsConfig(this) + } + static getInstantAssessmentConfig(task, relatedObjectType = "report") { // FIXME: do not hardcode once and report return Task.getAssessmentsConfig(task)[`${relatedObjectType}_once`] @@ -266,10 +270,11 @@ export default class Task extends Model { } getPeriodicAssessmentDetails(recurrence = "monthly") { - const assessmentConfig = Task.getAssessmentsConfig(this)[recurrence] + const assessmentConfig = this.getAssessmentsConfig()[recurrence] return { assessmentConfig: assessmentConfig, - assessmentYupSchema: createAssessmentSchema(assessmentConfig) + assessmentYupSchema: + assessmentConfig && createAssessmentSchema(assessmentConfig) } } } diff --git a/client/src/pages/people/Show.js b/client/src/pages/people/Show.js index 3ee5ef1646..d36e546b54 100644 --- a/client/src/pages/people/Show.js +++ b/client/src/pages/people/Show.js @@ -2,7 +2,7 @@ import { DEFAULT_PAGE_PROPS, DEFAULT_SEARCH_PROPS } from "actions" import API, { Settings } from "api" import { gql } from "apollo-boost" import AppContext from "components/AppContext" -import AssessmentResultsTable from "components/assessments/AssessmentResultsTable" +import AssessmentResultsContainer from "components/assessments/AssessmentResultsContainer" import AssignPositionModal from "components/AssignPositionModal" import AvatarDisplayComponent from "components/AvatarDisplayComponent" import { ReadonlyCustomFields } from "components/CustomFields" @@ -150,23 +150,6 @@ const BasePersonShow = ({ pageDispatchers, currentUser }) => { (!hasPosition && currentUser.isSuperUser()) || (hasPosition && currentUser.isSuperUserForOrg(position.organization)) || (person.role === Person.ROLE.PRINCIPAL && currentUser.isSuperUser()) - const assessmentPeriods = [ - { - start: moment().subtract(2, "months").startOf("month"), - end: moment().subtract(2, "months").endOf("month"), - allowNewAssessments: false - }, - { - start: moment().subtract(1, "months").startOf("month"), - end: moment().subtract(1, "months").endOf("month"), - allowNewAssessments: true - }, - { - start: moment().startOf("month"), - end: moment().endOf("month"), - allowNewAssessments: false - } - ] const canAddAssessment = currentUser.position.associatedPositions .filter(ap => ap.person) .map(ap => ap.person.uuid) @@ -438,11 +421,9 @@ const BasePersonShow = ({ pageDispatchers, currentUser }) => { )} - diff --git a/client/src/pages/tasks/Show.js b/client/src/pages/tasks/Show.js index dac87fcd74..169b4a1248 100644 --- a/client/src/pages/tasks/Show.js +++ b/client/src/pages/tasks/Show.js @@ -3,7 +3,7 @@ import API, { Settings } 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" @@ -157,15 +157,33 @@ const BaseTaskShow = ({ pageDispatchers, currentUser }) => { } if (data) { - data.task[DEFAULT_CUSTOM_FIELDS_PARENT] = 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] = 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() } 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.customFields = JSON.parse(note.text))) // TODO: + // Maybe + // move + // this + // code + // to + // Task() subTasks.push(new Task(subTask)) }) @@ -191,24 +209,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 }) => { @@ -349,12 +349,10 @@ const BaseTaskShow = ({ pageDispatchers, currentUser }) => { - From b870f9ff06e2398cb0af0a225e6b1855fa9a3162 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Mon, 20 Apr 2020 21:02:56 +0200 Subject: [PATCH 036/247] NCI-Agency/anet#2977: Change assessments period display The period display has been changed in order to make it more suitable for different types of recurrences. --- .../assessments/AssessmentResultsContainer.js | 6 --- .../assessments/AssessmentResultsTable.js | 46 ++++++++++++------- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/client/src/components/assessments/AssessmentResultsContainer.js b/client/src/components/assessments/AssessmentResultsContainer.js index da6f33b768..52fe19e88f 100644 --- a/client/src/components/assessments/AssessmentResultsContainer.js +++ b/client/src/components/assessments/AssessmentResultsContainer.js @@ -21,7 +21,6 @@ const now = moment() const ASSESSMENT_PERIODS_CONFIG = [ { recurrence: "daily", - displayFormat: "DD-MM-YYYY", periods: [ { start: now.clone().subtract(2, "days").startOf("day"), @@ -42,7 +41,6 @@ const ASSESSMENT_PERIODS_CONFIG = [ }, { recurrence: "weekly", - displayFormat: "DD-MM-YYYY", periods: [ { start: now.clone().subtract(2, "weeks").startOf("week"), @@ -63,7 +61,6 @@ const ASSESSMENT_PERIODS_CONFIG = [ }, { recurrence: "biweekly", - displayFormat: "DD-MM-YYYY", periods: [ { start: now.clone().subtract(4, "weeks").startOf("week"), @@ -84,7 +81,6 @@ const ASSESSMENT_PERIODS_CONFIG = [ }, { recurrence: "monthly", - displayFormat: "MMM-YYYY", periods: [ { start: now.clone().subtract(2, "months").startOf("month"), @@ -105,7 +101,6 @@ const ASSESSMENT_PERIODS_CONFIG = [ }, { recurrence: "quarterly", - displayFormat: "DD-MM-YYYY", periods: [ { start: now.clone().subtract(2, "quarters").startOf("quarter"), @@ -126,7 +121,6 @@ const ASSESSMENT_PERIODS_CONFIG = [ }, { recurrence: "semiannualy", - displayFormat: "DD-MM-YYYY", periods: [ { start: now.clone().subtract(4, "quarters").startOf("quarter"), diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index 7082674bb3..0248fd6665 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -27,7 +27,26 @@ import "components/assessments/AssessmentResultsTable.css" * entity.getPeriodicAssessmentDetails() */ -const PERIOD_FORMAT = "MMM-YYYY" +const PERIOD_START_SHORT_FORMAT = "D" +const PERIOD_START_MIDDLE_FORMAT = "D MMMM" +const PERIOD_START_LONG_FORMAT = "D MMMM YYYY" +const PERIOD_END_FORMAT = "D MMMM YYYY" + +const periodToString = period => { + if (period.start.isSame(period.end, "day")) { + return period.end.format(PERIOD_END_FORMAT) + } else { + const periodStartFormat = + period.start.year() !== period.end.year() + ? PERIOD_START_LONG_FORMAT + : period.start.month() !== period.end.month() + ? PERIOD_START_MIDDLE_FORMAT + : PERIOD_START_SHORT_FORMAT + return `${period.start.format(periodStartFormat)} - ${period.end.format( + PERIOD_END_FORMAT + )}` + } +} const periodsPropType = PropTypes.arrayOf( PropTypes.shape({ @@ -36,9 +55,8 @@ const periodsPropType = PropTypes.arrayOf( allowNewAssessments: PropTypes.bool }) ) -const periodsConfigPropTypes = PropTypes.shape({ +const periodsConfigPropType = PropTypes.shape({ recurrence: PropTypes.string, - displayFormat: PropTypes.string, periods: periodsPropType }) @@ -47,16 +65,14 @@ const AssessmentsTableHeader = ({ periodsConfig }) => ( <> {periodsConfig.periods.map(period => ( - + ))} ) AssessmentsTableHeader.propTypes = { - periodsConfig: periodsConfigPropTypes + periodsConfig: periodsConfigPropType } const InstantAssessmentRow = ({ @@ -128,6 +144,7 @@ const PeriodicAssessmentRows = ({ const rowHasAddAssessment = !_isEmpty( periodsAllowNewAssessment.filter(x => x) ) + return ( <> {rowHasLastAssessments && ( @@ -161,12 +178,11 @@ const PeriodicAssessmentRows = ({ {rowHasAddAssessment && ( {periods.map((period, index) => { + const periodDisplay = periodToString(period) const assessmentLabelPrefix = periodsLastAssessment[index] ? "Add a" : "Make a new" - const addAssessmentLabel = `${assessmentLabelPrefix} ${entity?.toString()} assessment for the month of ${period.start.format( - PERIOD_FORMAT - )}` + const addAssessmentLabel = `${assessmentLabelPrefix} ${entity?.toString()} assessment for ${periodDisplay}` return ( ) From b21ffa1498460d8e9de4dd83e681d2514f0b4474 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 21 Apr 2020 22:31:51 +0200 Subject: [PATCH 044/247] NCI-Agency/anet#2977: Add constant for invisibleCustomFields No longer hard code in lots of places the name of the field, bu use a constant for it. --- client/src/components/CustomFields.js | 13 +++++++------ client/src/components/Model.js | 12 ++++++++---- client/src/components/RelatedObjectNotes.js | 7 +++++-- client/src/pages/reports/Form.js | 3 ++- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/client/src/components/CustomFields.js b/client/src/components/CustomFields.js index 2a264a0fd4..62fda30b45 100644 --- a/client/src/components/CustomFields.js +++ b/client/src/components/CustomFields.js @@ -6,7 +6,8 @@ import LikertScale from "components/graphs/LikertScale" import Model, { CUSTOM_FIELD_TYPE, createYupObjectShape, - DEFAULT_CUSTOM_FIELDS_PARENT + DEFAULT_CUSTOM_FIELDS_PARENT, + INVISIBLE_CUSTOM_FIELDS_FIELD } from "components/Model" import RichTextEditor from "components/RichTextEditor" import { FastField, FieldArray } from "formik" @@ -406,7 +407,7 @@ export const CustomFieldsContainer = props => { const { parentFieldName, formikProps } = props const [invisibleFields, setInvisibleFields] = useState([]) const { setFieldValue } = formikProps - const invisibleFieldsFieldName = `${parentFieldName}.invisibleCustomFields` + const invisibleFieldsFieldName = `${parentFieldName}.${INVISIBLE_CUSTOM_FIELDS_FIELD}` useEffect(() => { setFieldValue(invisibleFieldsFieldName, invisibleFields, true) }, [invisibleFieldsFieldName, invisibleFields, setFieldValue]) @@ -650,7 +651,7 @@ ReadonlyCustomFields.defaultProps = { } // customFields should contain the JSON of all the visible custom fields. -// When used for notes text, it should not contain the invisibleCustomFields. +// When used for notes text, it should not contain the INVISIBLE_CUSTOM_FIELDS_FIELD. export const customFieldsJSONString = ( values, forNoteText = false, @@ -660,12 +661,12 @@ export const customFieldsJSONString = ( if (customFieldsValues && typeof customFieldsValues === "object") { const clonedValues = _cloneDeep(values) const filteredCustomFieldsValues = Object.get(clonedValues, parentFieldName) - if (filteredCustomFieldsValues.invisibleCustomFields) { - filteredCustomFieldsValues.invisibleCustomFields.forEach(f => + 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/Model.js b/client/src/components/Model.js index d40d37e77d..e5c1d36c92 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -54,6 +54,7 @@ export const NOTE_TYPE = { } export const DEFAULT_CUSTOM_FIELDS_PARENT = "formCustomFields" +export const INVISIBLE_CUSTOM_FIELDS_FIELD = "invisibleCustomFields" export const ASSESSMENTS_RECURRENCE_TYPE = { ONCE: "once", @@ -125,12 +126,12 @@ const createFieldYupSchema = (fieldKey, fieldConfig, parentFieldName) => { 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 && @@ -156,7 +157,10 @@ export const createYupObjectShape = ( ]) .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) } diff --git a/client/src/components/RelatedObjectNotes.js b/client/src/components/RelatedObjectNotes.js index 8ad513d404..a686a3cc0f 100644 --- a/client/src/components/RelatedObjectNotes.js +++ b/client/src/components/RelatedObjectNotes.js @@ -7,7 +7,10 @@ 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 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" @@ -35,7 +38,7 @@ export { GRAPHQL_NOTES_FIELDS } from "components/Model" const EXCLUDED_ASSESSMENT_FIELDS = [ "__recurrence", "__periodStart", - "invisibleCustomFields" + INVISIBLE_CUSTOM_FIELDS_FIELD ] const BaseRelatedObjectNotes = ({ diff --git a/client/src/pages/reports/Form.js b/client/src/pages/reports/Form.js index 3a0b24826d..0df35bdf29 100644 --- a/client/src/pages/reports/Form.js +++ b/client/src/pages/reports/Form.js @@ -23,6 +23,7 @@ import Messages from "components/Messages" import { createYupObjectShape, DEFAULT_CUSTOM_FIELDS_PARENT, + INVISIBLE_CUSTOM_FIELDS_FIELD, NOTE_TYPE } from "components/Model" import NavigationWarning from "components/NavigationWarning" @@ -1269,7 +1270,7 @@ const BaseReportForm = ({ function isEmptyTaskAssessment(assessment) { return ( (Object.keys(assessment).length === 1 && - Object.keys(assessment)[0] === "invisibleCustomFields") || + Object.keys(assessment)[0] === INVISIBLE_CUSTOM_FIELDS_FIELD) || _isEmpty(assessment) ) } From dcc6751b768927e7de1fdbaa853ac71c3ad41ded Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 21 Apr 2020 23:00:27 +0200 Subject: [PATCH 045/247] NCI-Agency/anet#2954: Implement multiple assessments for people This makes sure that next to taks, we can now also define multiple assessments also for people. For people we now only have general assessments defined. Note: instant assessments are not being used for people, but can be defined. --- anet.yml | 82 +++++++++++++++--------------- client/src/components/Model.js | 15 +++++- client/src/models/Person.js | 40 +++------------ client/src/models/Task.js | 13 ----- src/main/resources/anet-schema.yml | 8 +-- 5 files changed, 66 insertions(+), 92 deletions(-) diff --git a/anet.yml b/anet.yml index 2e19e4aff1..231325d2ef 100644 --- a/anet.yml +++ b/anet.yml @@ -695,46 +695,48 @@ dictionary: - value: "3" label: three color: '#ff8279' - customFields: - 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' + 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' position: name: Afghan Tashkil diff --git a/client/src/components/Model.js b/client/src/components/Model.js index e5c1d36c92..e124f0bb5c 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -372,12 +372,12 @@ export default class Model { generalAssessmentsConfig() { // assessments configuration defined for more than one instance - return {} + return [] } instanceAssessmentsConfig() { // assessments configuration defined for one specific instance - return {} + return [] } getAssessmentsConfig() { @@ -395,6 +395,17 @@ export default class Model { ] } + getPeriodicAssessmentDetails( + recurrence = ASSESSMENTS_RECURRENCE_TYPE.MONTHLY + ) { + const assessmentConfig = this.getAssessmentsConfig()[recurrence] + return { + assessmentConfig: assessmentConfig, + assessmentYupSchema: + assessmentConfig && createAssessmentSchema(assessmentConfig) + } + } + getLastAssessment(recurrence, period) { const notesToAssessments = this.notes .filter(n => { diff --git a/client/src/models/Person.js b/client/src/models/Person.js index 280f84553f..23dae864d5 100644 --- a/client/src/models/Person.js +++ b/client/src/models/Person.js @@ -1,9 +1,5 @@ import { Settings } from "api" -import Model, { - createAssessmentSchema, - createCustomFieldsSchema, - yupDate -} from "components/Model" +import Model, { createCustomFieldsSchema, yupDate } from "components/Model" import _isEmpty from "lodash/isEmpty" import { Organization, Position } from "models" import AFG_ICON from "resources/afg_small.png" @@ -34,19 +30,10 @@ export default class Person extends Model { static nameDelimiter = "," - static advisorAssessmentConfig = - Settings.fields.advisor.person.assessment?.customFields + static advisorAssessmentConfig = Settings.fields.advisor.person.assessments static principalAssessmentConfig = - Settings.fields.principal.person.assessment?.customFields - - static advisorAssessmentSchema = createAssessmentSchema( - Person.advisorAssessmentConfig - ) - - static principalAssessmentSchema = createAssessmentSchema( - Person.principalAssessmentConfig - ) + Settings.fields.principal.person.assessments // create yup schema for the customFields, based on the customFields config static customFieldsSchema = createCustomFieldsSchema( @@ -335,26 +322,13 @@ export default class Person extends Model { } } - getInstantAssessmentConfig() { - return {} - } - - getPeriodicAssessmentDetails() { + generalAssessmentsConfig() { if (this.isAdvisor()) { - return { - assessmentConfig: Person.advisorAssessmentConfig, - assessmentYupSchema: Person.advisorAssessmentSchema - } + return Person.advisorAssessmentConfig || [] } else if (this.isPrincipal()) { - return { - assessmentConfig: Person.principalAssessmentConfig, - assessmentYupSchema: Person.principalAssessmentSchema - } + return Person.principalAssessmentConfig || [] } else { - return { - assessmentConfig: null, - assessmentYupSchema: null - } + return [] } } } diff --git a/client/src/models/Task.js b/client/src/models/Task.js index 67cf00a2e5..6cdcd88531 100644 --- a/client/src/models/Task.js +++ b/client/src/models/Task.js @@ -1,7 +1,5 @@ import { Settings } from "api" import Model, { - ASSESSMENTS_RECURRENCE_TYPE, - createAssessmentSchema, createCustomFieldsSchema, NOTE_TYPE, yupDate @@ -216,15 +214,4 @@ export default class Task extends Model { ) return assessmentsResults } - - getPeriodicAssessmentDetails( - recurrence = ASSESSMENTS_RECURRENCE_TYPE.MONTHLY - ) { - const assessmentConfig = this.getAssessmentsConfig()[recurrence] - return { - assessmentConfig: assessmentConfig, - assessmentYupSchema: - assessmentConfig && createAssessmentSchema(assessmentConfig) - } - } } diff --git a/src/main/resources/anet-schema.yml b/src/main/resources/anet-schema.yml index 1e6b5cd2b2..2aa08fcf9f 100644 --- a/src/main/resources/anet-schema.yml +++ b/src/main/resources/anet-schema.yml @@ -638,10 +638,10 @@ properties: type: string color: type: string - customFields: - type: object - additionalProperties: - "$ref": "#/definitions/customField" + assessments: + type: array + items: + "$ref": "#/definitions/assessmentDef" position: type: object From 9973aace1b5175bb47ce02ee91f3419f63f9a89a Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 23 Apr 2020 00:18:34 +0200 Subject: [PATCH 046/247] NCI-Agency/anet#2977: Display all assessments for a period This makes sure we no longer display only the last assessment for a period but all assessments: more users can make an assessment for a period. This also makes sure that each user can only make one assignment, by only displaying the add assessment button when the user didn't already make an assessment for the given period. The laout of the periodic has also changed: we now use a panel to make it easier to distinuish between different assessments and also in order to make it possible to display the author and an eventual edit/delete icon. --- client/src/components/Model.js | 14 +- .../assessments/AddAssessmentModal.js | 2 + .../assessments/AssessmentResultsTable.js | 198 ++++++++++++++---- 3 files changed, 171 insertions(+), 43 deletions(-) diff --git a/client/src/components/Model.js b/client/src/components/Model.js index e124f0bb5c..2ef3939916 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -406,21 +406,21 @@ export default class Model { } } - getLastAssessment(recurrence, period) { - const notesToAssessments = this.notes + 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 => JSON.parse(note.text)) + .map(note => ({ note: note, assessment: JSON.parse(note.text) })) .filter( - assessment => + obj => // FIXME: make a nicer implementation of the check on period start - assessment.__recurrence === recurrence && - assessment.__periodStart === JSON.parse(JSON.stringify(period.start)) + obj.assessment.__recurrence === recurrence && + obj.assessment.__periodStart === + JSON.parse(JSON.stringify(period.start)) ) - return notesToAssessments?.[0] } } diff --git a/client/src/components/assessments/AddAssessmentModal.js b/client/src/components/assessments/AddAssessmentModal.js index 651d0b3880..1a5f6b4a1b 100644 --- a/client/src/components/assessments/AddAssessmentModal.js +++ b/client/src/components/assessments/AddAssessmentModal.js @@ -17,6 +17,7 @@ import React, { useMemo, useState } from "react" import { Button, Modal } from "react-bootstrap" const AddAssessmentModal = ({ + note, entity, entityType, yupSchema, @@ -146,6 +147,7 @@ const AddAssessmentModal = ({ } } AddAssessmentModal.propTypes = { + note: Model.notePropTypes, entity: PropTypes.oneOfType([ PropTypes.instanceOf(Person), PropTypes.instanceOf(Task) diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index dd375f0bc6..a7a0891440 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -1,5 +1,9 @@ +import { Icon } from "@blueprintjs/core" +import { IconNames } from "@blueprintjs/icons" import AggregationWidget from "components/AggregationWidget" +import AppContext from "components/AppContext" import AddAssessmentModal from "components/assessments/AddAssessmentModal" +import ConfirmDelete from "components/ConfirmDelete" import { getFieldPropsFromFieldConfig, ReadonlyCustomFields @@ -7,10 +11,14 @@ import { import Fieldset from "components/Fieldset" import { Formik } from "formik" import LinkTo from "components/LinkTo" +import Model from "components/Model" +import { Person } from "models" +import moment from "moment" import _isEmpty from "lodash/isEmpty" import PropTypes from "prop-types" import React from "react" -import { Table } from "react-bootstrap" +import { Button, Panel, Table } from "react-bootstrap" +import REMOVE_ICON from "resources/delete.png" import "components/assessments/AssessmentResultsTable.css" /* The AssessmentResultsTable component displays the results of two types of @@ -109,71 +117,177 @@ InstantAssessmentRow.propTypes = { questionConfig: PropTypes.object } -const PeriodicAssessmentRows = ({ +const BasePeriodicAssessment = ({ + assessment, + assessmentConfig, + note, + currentUser +}) => { + const byMe = Person.isEqual(currentUser, note.author) + const parentFieldName = `assessment-${note.uuid}` + return ( + + + <> + {moment(note.updatedAt).fromNow()}{" "} + + {byMe && ( + <> + + console.log("to be implemented")} + objectType="note" + objectDisplay={"#" + note.uuid} + title="Delete note" + bsSize="xsmall" + bsStyle="primary" + > + Delete assessment + + + )} + + + +
+ + {({ values }) => { + return ( + + ) + }} + +
+
+
+ ) +} +BasePeriodicAssessment.propTypes = { + assessment: PropTypes.object, + assessmentConfig: PropTypes.object, + note: Model.notePropTypes, + currentUser: PropTypes.instanceOf(Person) +} + +const PeriodicAssessment = props => ( + + {context => ( + + )} + +) + +const BasePeriodicAssessmentRows = ({ entity, entityType, periodsConfig, canAddAssessment, - onAddAssessment + onAddAssessment, + currentUser }) => { const { recurrence, periods } = periodsConfig const { assessmentConfig: periodicAssessmentConfig, assessmentYupSchema: periodicAssessmentYupSchema } = entity.getPeriodicAssessmentDetails(recurrence) - const periodsLastAssessment = [] + if (!periodicAssessmentConfig) { + return null + } + + const periodsAssessments = [] const periodsAllowNewAssessment = [] periods.forEach(period => { - periodsLastAssessment.push(entity.getLastAssessment(recurrence, 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( - periodicAssessmentConfig && canAddAssessment && period.allowNewAssessments + canAddAssessment && + period.allowNewAssessments && + _isEmpty(myPeriodAssessments) ) }) - const rowHasLastAssessments = !_isEmpty( - periodsLastAssessment.filter(x => !_isEmpty(x)) + const hasPeriodicAssessmentsRow = !_isEmpty( + periodsAssessments.filter(x => !_isEmpty(x)) ) - const rowHasAddAssessment = !_isEmpty( + const hasAddAssessmentRow = !_isEmpty( periodsAllowNewAssessment.filter(x => x) ) - return ( <> - {rowHasLastAssessments && ( + {hasPeriodicAssessmentsRow && (
- {periodsLastAssessment.map((lastAssessment, index) => { - const lastAssessmentParentFieldName = `lastAssessment-${entity.uuid}-${index}` + {periodsAssessments.map((periodAssessments, index) => { return ( ) })} )} - {rowHasAddAssessment && ( + {hasAddAssessmentRow && ( {periods.map((period, index) => { const periodDisplay = periodToString(period) - const assessmentLabelPrefix = periodsLastAssessment[index] - ? "Add a" - : "Make a new" - const addAssessmentLabel = `${assessmentLabelPrefix} ${entity?.toString()} assessment for ${periodDisplay}` + const addAssessmentLabel = `Make a new ${entity?.toString()} assessment for ${periodDisplay}` return ( ) @@ -316,9 +207,9 @@ const BasePeriodicAssessmentRows = ({ BasePeriodicAssessmentRows.propTypes = { entity: PropTypes.object, entityType: PropTypes.func.isRequired, - periodsConfig: periodsConfigPropType, + periodsConfig: PeriodsConfigPropType, canAddAssessment: PropTypes.bool, - onAddAssessment: PropTypes.func, + onUpdateAssessment: PropTypes.func, currentUser: PropTypes.instanceOf(Person) } @@ -339,7 +230,7 @@ const EntityAssessmentResults = ({ style, periodsConfig, canAddAssessment, - onAddAssessment + onUpdateAssessment }) => { if (!entity) { return null @@ -367,7 +258,7 @@ const EntityAssessmentResults = ({ entityType={entityType} periodsConfig={periodsConfig} canAddAssessment={canAddAssessment} - onAddAssessment={onAddAssessment} + onUpdateAssessment={onUpdateAssessment} /> ) @@ -376,8 +267,8 @@ EntityAssessmentResults.propTypes = { style: PropTypes.object, entity: PropTypes.object, entityType: PropTypes.func.isRequired, - periodsConfig: periodsConfigPropType, - onAddAssessment: PropTypes.func, + periodsConfig: PeriodsConfigPropType, + onUpdateAssessment: PropTypes.func, canAddAssessment: PropTypes.bool } @@ -388,7 +279,7 @@ const AssessmentResultsTable = ({ style, periodsConfig, canAddAssessment, - onAddAssessment + onUpdateAssessment }) => { if (!entity) { return null @@ -398,13 +289,11 @@ const AssessmentResultsTable = ({ const subentitiesInstantAssessmentConfig = subEntities ?.map(s => s.getInstantAssessmentConfig()) .filter(mc => !_isEmpty(mc)) - const { - assessmentConfig: periodicAssessmentConfig - } = entity.getPeriodicAssessmentDetails(recurrence) + const { assessmentConfig } = entity.getPeriodicAssessmentDetails(recurrence) const showAssessmentResults = !_isEmpty(entityInstantAssessmentConfig) || !_isEmpty(subentitiesInstantAssessmentConfig) || - !_isEmpty(periodicAssessmentConfig) + !_isEmpty(assessmentConfig) return ( <> {showAssessmentResults && ( @@ -434,7 +323,7 @@ const AssessmentResultsTable = ({ entityType={entityType} periodsConfig={periodsConfig} canAddAssessment={canAddAssessment} - onAddAssessment={onAddAssessment} + onUpdateAssessment={onUpdateAssessment} />
- {period.start.format(periodsConfig.displayFormat)} - {periodToString(period)}
{periodsAllowNewAssessment[index] && ( @@ -180,9 +196,7 @@ const PeriodicAssessmentRows = ({ Date: Mon, 20 Apr 2020 22:42:57 +0200 Subject: [PATCH 037/247] NCI-Agency/anet#2977: Exclude some assessment notes fields This makes sure that JSON fields saved in a note's text property which are note part of the real assessment made by the user but details about the made assessment (like period details and the invisibleCustomFields) are not being displayed in RelatedObjectNotes. --- client/src/components/RelatedObjectNotes.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/client/src/components/RelatedObjectNotes.js b/client/src/components/RelatedObjectNotes.js index 49138995e8..8ad513d404 100644 --- a/client/src/components/RelatedObjectNotes.js +++ b/client/src/components/RelatedObjectNotes.js @@ -32,6 +32,12 @@ const GQL_DELETE_NOTE = gql` export { GRAPHQL_NOTES_FIELDS } from "components/Model" +const EXCLUDED_ASSESSMENT_FIELDS = [ + "__recurrence", + "__periodStart", + "invisibleCustomFields" +] + const BaseRelatedObjectNotes = ({ currentUser, notesElemId, @@ -345,7 +351,9 @@ const BaseRelatedObjectNotes = ({ {Object.keys(jsonFields) - .filter(field => field !== "text") + .filter( + field => !EXCLUDED_ASSESSMENT_FIELDS.includes(field) + ) .map(field => (

{field}: {jsonFields[field]} From 26792d78c78767be31f727641e5856db27c3918e Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Mon, 20 Apr 2020 23:25:53 +0200 Subject: [PATCH 038/247] NCI-Agency/anet#2977: Change retrieval of last assessment The last assessments for a period are now retrieved based on the given recurrence type and on the period's start date. This information is also being saved in the assessment so we can filter on it. --- client/src/components/Model.js | 20 +++++++++---------- .../assessments/AssessmentResultsTable.js | 12 ++--------- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/client/src/components/Model.js b/client/src/components/Model.js index 10813c2f5d..f3eb63db51 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -333,21 +333,21 @@ export default class Model { return this.name || this.uuid } - getLastAssessment(dateRange) { + getLastAssessment(recurrence, period) { 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)) + n.type === NOTE_TYPE.ASSESSMENT && n.noteRelatedObjects.length === 1 ) }) .sort((a, b) => b.createdAt - a.createdAt) // desc sorted - .map(note => ({ - uuid: note.uuid, - assessment: JSON.parse(note.text) - })) - return notesToAssessments?.[0]?.assessment + .map(note => JSON.parse(note.text)) + .filter( + assessment => + // FIXME: make a nicer implementation of the check on period start + assessment.__recurrence === recurrence && + assessment.__periodStart === JSON.parse(JSON.stringify(period.start)) + ) + return notesToAssessments?.[0] } } diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index 0248fd6665..1832de01d2 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -125,15 +125,7 @@ const PeriodicAssessmentRows = ({ const periodsLastAssessment = [] const periodsAllowNewAssessment = [] periods.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") - }) - ) + periodsLastAssessment.push(entity.getLastAssessment(recurrence, period)) periodsAllowNewAssessment.push( periodicAssessmentConfig && canAddAssessment && period.allowNewAssessments ) @@ -198,7 +190,7 @@ const PeriodicAssessmentRows = ({ entityType={entityType} title={`Assessment for ${entity.toString()} for ${periodDisplay}`} yupSchema={periodicAssessmentYupSchema} - recurrence="monthly" + recurrence={recurrence} assessmentPeriod={period} assessmentConfig={periodicAssessmentConfig} showModal={showAssessmentModal} From fcea042958ae83d19fb628e1fe2a7607caaeddcf Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 21 Apr 2020 11:27:09 +0200 Subject: [PATCH 039/247] NCI-Agency/anet#2977: Remove left-over comment Removed comment from AssessmentResultsContainer which doesn't belong to this component. --- .../assessments/AssessmentResultsContainer.js | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/client/src/components/assessments/AssessmentResultsContainer.js b/client/src/components/assessments/AssessmentResultsContainer.js index 52fe19e88f..5e2f6828f5 100644 --- a/client/src/components/assessments/AssessmentResultsContainer.js +++ b/client/src/components/assessments/AssessmentResultsContainer.js @@ -3,20 +3,6 @@ import moment from "moment" import PropTypes from "prop-types" import React from "react" -/* The AssessmentResultsTable component displays the results of two types of - * assessments made on a given entity and subentities: - * - 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; - * 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() - */ - const now = moment() const ASSESSMENT_PERIODS_CONFIG = [ { From 0709be32232709a14dbb44ecbc6fdd6d2aaad1eb Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 21 Apr 2020 14:46:31 +0200 Subject: [PATCH 040/247] NCI-Agency/anet#2977: Simplify retrieval of assessments config Because the report tasks on the report form and on the show page were not always Task instances the code for retrieving the assessments configuration for tasks was quite complicated, making it possible to be run on both Task instances as just objects. We now made sure that the report tasks on these pages are always task instances. --- client/src/components/Model.js | 43 ++++++++++++ .../assessments/AssessmentResultsTable.js | 2 +- client/src/models/Task.js | 67 ++----------------- client/src/pages/reports/Edit.js | 3 +- client/src/pages/reports/Form.js | 6 +- client/src/pages/reports/Show.js | 5 +- 6 files changed, 57 insertions(+), 69 deletions(-) diff --git a/client/src/components/Model.js b/client/src/components/Model.js index f3eb63db51..89b496dfad 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -333,6 +333,49 @@ export default class Model { return this.name || this.uuid } + static parseAssessmentsConfig(assessmentsConfig) { + return Object.fromEntries( + assessmentsConfig.map(a => { + // FIXME: do not hardcode once + const recurrence = a.recurrence || "once" + const assessmentKey = a.relatedObjectType + ? `${a.relatedObjectType}_${recurrence}` + : recurrence + const questions = a.questions || {} + return [ + assessmentKey, + typeof questions === "object" + ? questions + : typeof questions === "string" + ? JSON.parse(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 = "report") { + // FIXME: do not hardcode once and report + return this.getAssessmentsConfig()[`${relatedObjectType}_once`] + } + getLastAssessment(recurrence, period) { const notesToAssessments = this.notes .filter(n => { diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index 1832de01d2..b5e35ff569 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -24,7 +24,7 @@ import "components/assessments/AssessmentResultsTable.css" * - 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() + * entity.getPeriodicAssessmentDetails(recurrence) */ const PERIOD_START_SHORT_FORMAT = "D" diff --git a/client/src/models/Task.js b/client/src/models/Task.js index 1f4256ce80..74bcbb5072 100644 --- a/client/src/models/Task.js +++ b/client/src/models/Task.js @@ -161,24 +161,16 @@ export default class Task extends Model { super(Model.fillObject(props, Task.yupSchema)) } - static isTopLevelTask(task) { - return _isEmpty(task.customFieldRef1) - } - isTopLevelTask() { - return Task.isTopLevelTask(this) + return _isEmpty(this.customFieldRef1) } - static fieldSettings(task) { - return Task.isTopLevelTask(task) + fieldSettings() { + return this.isTopLevelTask() ? Settings.fields.task.topLevel : Settings.fields.task.subLevel } - fieldSettings() { - return Task.fieldSettings(this) - } - iconUrl() { return TASKS_ICON } @@ -187,58 +179,13 @@ export default class Task extends Model { return `${this.shortName}` } - static parseAssessmentsConfig(assessmentsConfig) { - return Object.fromEntries( - assessmentsConfig.map(a => { - // FIXME: do not hardcode once - const recurrence = a.recurrence || "once" - const assessmentKey = a.relatedObjectType - ? `${a.relatedObjectType}_${recurrence}` - : recurrence - const questions = a.questions || {} - return [ - assessmentKey, - typeof questions === "object" - ? questions - : typeof questions === "string" - ? JSON.parse(questions) - : {} - ] - }) - ) - } - - static getGeneralAssessmentsConfig(task) { - return Task.parseAssessmentsConfig( - Task.fieldSettings(task).assessments || [] - ) + generalAssessmentsConfig() { + return this.fieldSettings().assessments || [] } - static getInstanceAssessmentsConfig(task) { + instanceAssessmentsConfig() { // The given task instance might have a specific assessments config - return Task.parseAssessmentsConfig( - JSON.parse(task.customFields || "{}").assessments || [] - ) - } - - static getAssessmentsConfig(task) { - return Object.assign( - Task.getGeneralAssessmentsConfig(task), - Task.getInstanceAssessmentsConfig(task) - ) - } - - getAssessmentsConfig() { - return Task.getAssessmentsConfig(this) - } - - static getInstantAssessmentConfig(task, relatedObjectType = "report") { - // FIXME: do not hardcode once and report - return Task.getAssessmentsConfig(task)[`${relatedObjectType}_once`] - } - - getInstantAssessmentConfig() { - return Task.getInstantAssessmentConfig(this) + return JSON.parse(this.customFields || "{}").assessments || [] } getInstantAssessmentResults(dateRange) { diff --git a/client/src/pages/reports/Edit.js b/client/src/pages/reports/Edit.js index fd7c5e2ba8..270ae06a0b 100644 --- a/client/src/pages/reports/Edit.js +++ b/client/src/pages/reports/Edit.js @@ -10,7 +10,7 @@ import { import RelatedObjectNotes, { GRAPHQL_NOTES_FIELDS } from "components/RelatedObjectNotes" -import { Report } from "models" +import { Report, Task } from "models" import React from "react" import { connect } from "react-redux" import { useParams } from "react-router-dom" @@ -129,6 +129,7 @@ const ReportEdit = ({ pageDispatchers }) => { report, report.getTasksInstantAssessments() ) + reportInitialValues.tasks = Task.fromArray(reportInitialValues.tasks) return (

diff --git a/client/src/pages/reports/Form.js b/client/src/pages/reports/Form.js index ab8d5711ca..3a0b24826d 100644 --- a/client/src/pages/reports/Form.js +++ b/client/src/pages/reports/Form.js @@ -338,7 +338,7 @@ const BaseReportForm = ({ .filter(t => t.customFields) .forEach(t => { tasksInstantAssessmentsSchemaShape[t.uuid] = createYupObjectShape( - Task.getInstantAssessmentConfig(t), + t.getInstantAssessmentConfig(), `tasksAssessments.${t.uuid}` ) }) @@ -1069,9 +1069,7 @@ const BaseReportForm = ({ id="engagement-assessments" > {values.tasks.map(task => { - const taskInstantAssessmentConfig = Task.getInstantAssessmentConfig( - task - ) + const taskInstantAssessmentConfig = task.getInstantAssessmentConfig() if (!taskInstantAssessmentConfig) { return null } diff --git a/client/src/pages/reports/Show.js b/client/src/pages/reports/Show.js index 52467541db..8859870ae1 100644 --- a/client/src/pages/reports/Show.js +++ b/client/src/pages/reports/Show.js @@ -299,6 +299,7 @@ const BaseReportShow = ({ currentUser, setSearchQuery, pageDispatchers }) => { id: tag.uuid.toString(), text: tag.name })) + data.report.tasks = Task.fromArray(data.report.tasks) data.report.to = "" data.report[DEFAULT_CUSTOM_FIELDS_PARENT] = JSON.parse( data.report.customFields @@ -660,9 +661,7 @@ const BaseReportShow = ({ currentUser, setSearchQuery, pageDispatchers }) => { id="engagement-assessments" > {values.tasks.map(task => { - const taskInstantAssessmentConfig = Task.getInstantAssessmentConfig( - task - ) + const taskInstantAssessmentConfig = task.getInstantAssessmentConfig() if (_isEmpty(taskInstantAssessmentConfig)) { return null } From 5de20c679ca2eddd92d1ba688372e2fa52cbc096 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 21 Apr 2020 15:27:06 +0200 Subject: [PATCH 041/247] NCI-Agency/anet#2977: Use constants for period related values This makes sure we no longer use hardcoded strings in the code for assessment period recurrences and telated object type. We've defined constants for them. --- client/src/components/Model.js | 25 +++++++++++++++---- .../assessments/AssessmentResultsContainer.js | 13 +++++----- client/src/models/Task.js | 5 +++- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/client/src/components/Model.js b/client/src/components/Model.js index 89b496dfad..d40d37e77d 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -55,6 +55,19 @@ export const NOTE_TYPE = { export const DEFAULT_CUSTOM_FIELDS_PARENT = "formCustomFields" +export const ASSESSMENTS_RECURRENCE_TYPE = { + ONCE: "once", + DAILY: "daily", + WEEKLY: "weekly", + BIWEEKLY: "biweekly", + MONTHLY: "monthly", + QUARTERLY: "quarterly", + SEMIANNUALY: "semiannualy" +} +const ASSESSMENTS_RELATED_OBJECT_TYPE = { + REPORT: "report" +} + export const yupDate = yup.date().transform(function(value, originalValue) { if (this.isType(value)) { return value @@ -336,8 +349,7 @@ export default class Model { static parseAssessmentsConfig(assessmentsConfig) { return Object.fromEntries( assessmentsConfig.map(a => { - // FIXME: do not hardcode once - const recurrence = a.recurrence || "once" + const recurrence = a.recurrence || ASSESSMENTS_RECURRENCE_TYPE.ONCE const assessmentKey = a.relatedObjectType ? `${a.relatedObjectType}_${recurrence}` : recurrence @@ -371,9 +383,12 @@ export default class Model { ) } - getInstantAssessmentConfig(relatedObjectType = "report") { - // FIXME: do not hardcode once and report - return this.getAssessmentsConfig()[`${relatedObjectType}_once`] + getInstantAssessmentConfig( + relatedObjectType = ASSESSMENTS_RELATED_OBJECT_TYPE.REPORT + ) { + return this.getAssessmentsConfig()[ + `${relatedObjectType}_${ASSESSMENTS_RECURRENCE_TYPE.ONCE}` + ] } getLastAssessment(recurrence, period) { diff --git a/client/src/components/assessments/AssessmentResultsContainer.js b/client/src/components/assessments/AssessmentResultsContainer.js index 5e2f6828f5..8ad8312f25 100644 --- a/client/src/components/assessments/AssessmentResultsContainer.js +++ b/client/src/components/assessments/AssessmentResultsContainer.js @@ -1,4 +1,5 @@ import AssessmentResultsTable from "components/assessments/AssessmentResultsTable" +import { ASSESSMENTS_RECURRENCE_TYPE } from "components/Model" import moment from "moment" import PropTypes from "prop-types" import React from "react" @@ -6,7 +7,7 @@ import React from "react" const now = moment() const ASSESSMENT_PERIODS_CONFIG = [ { - recurrence: "daily", + recurrence: ASSESSMENTS_RECURRENCE_TYPE.DAILY, periods: [ { start: now.clone().subtract(2, "days").startOf("day"), @@ -26,7 +27,7 @@ const ASSESSMENT_PERIODS_CONFIG = [ ] }, { - recurrence: "weekly", + recurrence: ASSESSMENTS_RECURRENCE_TYPE.WEEKLY, periods: [ { start: now.clone().subtract(2, "weeks").startOf("week"), @@ -46,7 +47,7 @@ const ASSESSMENT_PERIODS_CONFIG = [ ] }, { - recurrence: "biweekly", + recurrence: ASSESSMENTS_RECURRENCE_TYPE.BIWEEKLY, periods: [ { start: now.clone().subtract(4, "weeks").startOf("week"), @@ -66,7 +67,7 @@ const ASSESSMENT_PERIODS_CONFIG = [ ] }, { - recurrence: "monthly", + recurrence: ASSESSMENTS_RECURRENCE_TYPE.MONTHLY, periods: [ { start: now.clone().subtract(2, "months").startOf("month"), @@ -86,7 +87,7 @@ const ASSESSMENT_PERIODS_CONFIG = [ ] }, { - recurrence: "quarterly", + recurrence: ASSESSMENTS_RECURRENCE_TYPE.QUARTERLY, periods: [ { start: now.clone().subtract(2, "quarters").startOf("quarter"), @@ -106,7 +107,7 @@ const ASSESSMENT_PERIODS_CONFIG = [ ] }, { - recurrence: "semiannualy", + recurrence: ASSESSMENTS_RECURRENCE_TYPE.SEMIANNUALY, periods: [ { start: now.clone().subtract(4, "quarters").startOf("quarter"), diff --git a/client/src/models/Task.js b/client/src/models/Task.js index 74bcbb5072..67cf00a2e5 100644 --- a/client/src/models/Task.js +++ b/client/src/models/Task.js @@ -1,5 +1,6 @@ import { Settings } from "api" import Model, { + ASSESSMENTS_RECURRENCE_TYPE, createAssessmentSchema, createCustomFieldsSchema, NOTE_TYPE, @@ -216,7 +217,9 @@ export default class Task extends Model { return assessmentsResults } - getPeriodicAssessmentDetails(recurrence = "monthly") { + getPeriodicAssessmentDetails( + recurrence = ASSESSMENTS_RECURRENCE_TYPE.MONTHLY + ) { const assessmentConfig = this.getAssessmentsConfig()[recurrence] return { assessmentConfig: assessmentConfig, From 73fbe80875f82f977d51f4eb6d38f7e863cf2411 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 21 Apr 2020 17:18:54 +0200 Subject: [PATCH 042/247] NCI-Agency/anet#2977: Change rule for displaying add assessment button The add assessment button is now displayed by default for each period in the past (where period end < start of today). It is still possible to configure a different rule for a period by setting the allowNewAssessments property of the period. --- .../assessments/AssessmentResultsContainer.js | 63 ++++++++----------- 1 file changed, 27 insertions(+), 36 deletions(-) diff --git a/client/src/components/assessments/AssessmentResultsContainer.js b/client/src/components/assessments/AssessmentResultsContainer.js index 8ad8312f25..22bb26136e 100644 --- a/client/src/components/assessments/AssessmentResultsContainer.js +++ b/client/src/components/assessments/AssessmentResultsContainer.js @@ -11,18 +11,15 @@ const ASSESSMENT_PERIODS_CONFIG = [ periods: [ { start: now.clone().subtract(2, "days").startOf("day"), - end: now.clone().subtract(2, "days").endOf("day"), - allowNewAssessments: false + end: now.clone().subtract(2, "days").endOf("day") }, { start: now.clone().subtract(1, "days").startOf("day"), - end: now.clone().subtract(1, "days").endOf("day"), - allowNewAssessments: true + end: now.clone().subtract(1, "days").endOf("day") }, { start: now.clone().startOf("day"), - end: now.clone().endOf("day"), - allowNewAssessments: false + end: now.clone().endOf("day") } ] }, @@ -31,38 +28,33 @@ const ASSESSMENT_PERIODS_CONFIG = [ periods: [ { start: now.clone().subtract(2, "weeks").startOf("week"), - end: now.clone().subtract(2, "weeks").endOf("week"), - allowNewAssessments: false + end: now.clone().subtract(2, "weeks").endOf("week") }, { start: now.clone().subtract(1, "weeks").startOf("week"), - end: now.clone().subtract(1, "weeks").endOf("week"), - allowNewAssessments: true + end: now.clone().subtract(1, "weeks").endOf("week") }, { start: now.clone().startOf("week"), - end: now.clone().endOf("week"), - allowNewAssessments: false + end: now.clone().endOf("week") } ] }, { + // FIXME: biweekly should be each 2 weeks from the beginning of the year recurrence: ASSESSMENTS_RECURRENCE_TYPE.BIWEEKLY, periods: [ { start: now.clone().subtract(4, "weeks").startOf("week"), - end: now.clone().subtract(4, "weeks").endOf("week"), - allowNewAssessments: false + end: now.clone().subtract(4, "weeks").endOf("week") }, { start: now.clone().subtract(2, "weeks").startOf("week"), - end: now.clone().subtract(2, "weeks").endOf("week"), - allowNewAssessments: true + end: now.clone().subtract(2, "weeks").endOf("week") }, { start: now.clone().startOf("week"), - end: now.clone().endOf("week"), - allowNewAssessments: false + end: now.clone().endOf("week") } ] }, @@ -71,18 +63,15 @@ const ASSESSMENT_PERIODS_CONFIG = [ periods: [ { start: now.clone().subtract(2, "months").startOf("month"), - end: now.clone().subtract(2, "months").endOf("month"), - allowNewAssessments: false + end: now.clone().subtract(2, "months").endOf("month") }, { start: now.clone().subtract(1, "months").startOf("month"), - end: now.clone().subtract(1, "months").endOf("month"), - allowNewAssessments: true + end: now.clone().subtract(1, "months").endOf("month") }, { start: now.clone().startOf("month"), - end: now.clone().endOf("month"), - allowNewAssessments: false + end: now.clone().endOf("month") } ] }, @@ -91,18 +80,15 @@ const ASSESSMENT_PERIODS_CONFIG = [ periods: [ { start: now.clone().subtract(2, "quarters").startOf("quarter"), - end: now.clone().subtract(2, "quarters").endOf("quarter"), - allowNewAssessments: false + end: now.clone().subtract(2, "quarters").endOf("quarter") }, { start: now.clone().subtract(1, "quarters").startOf("quarter"), - end: now.clone().subtract(1, "quarters").endOf("quarter"), - allowNewAssessments: true + end: now.clone().subtract(1, "quarters").endOf("quarter") }, { start: now.clone().startOf("quarter"), - end: now.clone().endOf("quarter"), - allowNewAssessments: false + end: now.clone().endOf("quarter") } ] }, @@ -111,22 +97,27 @@ const ASSESSMENT_PERIODS_CONFIG = [ periods: [ { start: now.clone().subtract(4, "quarters").startOf("quarter"), - end: now.clone().subtract(4, "quarters").endOf("quarter"), - allowNewAssessments: false + end: now.clone().subtract(4, "quarters").endOf("quarter") }, { start: now.clone().subtract(2, "quarters").startOf("quarter"), - end: now.clone().subtract(2, "quarters").endOf("quarter"), - allowNewAssessments: true + end: now.clone().subtract(2, "quarters").endOf("quarter") }, { start: now.clone().startOf("quarter"), - end: now.clone().endOf("quarter"), - allowNewAssessments: false + end: now.clone().endOf("quarter") } ] } ] +// set default allowNewAssessments when this one is not configured for a period +ASSESSMENT_PERIODS_CONFIG.forEach(periodConfig => + periodConfig.periods.forEach(period => { + if (period.allowNewAssessments === undefined) { + period.allowNewAssessments = period.end < now.clone().startOf("day") + } + }) +) const AssessmentResultsContainer = ({ entity, From 5d430de21a35ce1b25566e74319cbc8f0a79918a Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 21 Apr 2020 17:51:12 +0200 Subject: [PATCH 043/247] NCI-Agency/anet#2977: Fix AddAssessmentModal for multiple periods When using the AddAssessmentModal for more than one periods it was always opening the modal for the last period, and therefore also using that period's details when saving the assessment => all assessments were belonging to the same period. Fixed this by moving the button to open the modal in the modal component itself. --- .../assessments/AddAssessmentModal.js | 136 +++++++++--------- .../assessments/AssessmentResultsTable.js | 41 ++---- 2 files changed, 86 insertions(+), 91 deletions(-) diff --git a/client/src/components/assessments/AddAssessmentModal.js b/client/src/components/assessments/AddAssessmentModal.js index ae011380f8..651d0b3880 100644 --- a/client/src/components/assessments/AddAssessmentModal.js +++ b/client/src/components/assessments/AddAssessmentModal.js @@ -24,81 +24,87 @@ const AddAssessmentModal = ({ assessmentPeriod, assessmentConfig, title, - showModal, - onCancel, + addAssessmentLabel, onSuccess }) => { + const [showModal, setShowModal] = useState(false) const [assessmentError, setAssessmentError] = useState(null) const initialValues = useMemo(() => Model.fillObject({}, yupSchema), [ yupSchema ]) + return ( - - - {({ - isSubmitting, - isValid, - setFieldValue, - setFieldTouched, - validateForm, - values, - submitForm - }) => { - return ( -
- - {title} - - -
- - + + + + {({ + isSubmitting, + isValid, + setFieldValue, + setFieldTouched, + validateForm, + values, + submitForm + }) => { + return ( + + + {title} + + +
-
-
- - - - - - ) - }} -
-
+ > + + +
+
+ + + + + + ) + }} +
+
+ ) function closeModal() { setAssessmentError(null) - onCancel() + setShowModal(false) } function onAssessmentSubmit(values, form) { @@ -111,6 +117,7 @@ const AddAssessmentModal = ({ } function onSubmitSuccess(response, values, form) { + setShowModal(false) onSuccess() } @@ -149,8 +156,7 @@ AddAssessmentModal.propTypes = { assessmentPeriod: PropTypes.object.isRequired, assessmentConfig: PropTypes.object.isRequired, title: PropTypes.string, - showModal: PropTypes.bool, - onCancel: PropTypes.func.isRequired, + addAssessmentLabel: PropTypes.string, onSuccess: PropTypes.func.isRequired } AddAssessmentModal.defaultProps = { diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index b5e35ff569..dd375f0bc6 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -9,8 +9,8 @@ import { Formik } from "formik" import LinkTo from "components/LinkTo" import _isEmpty from "lodash/isEmpty" import PropTypes from "prop-types" -import React, { useState } from "react" -import { Button, Table } from "react-bootstrap" +import React from "react" +import { Table } from "react-bootstrap" import "components/assessments/AssessmentResultsTable.css" /* The AssessmentResultsTable component displays the results of two types of @@ -121,7 +121,6 @@ const PeriodicAssessmentRows = ({ assessmentConfig: periodicAssessmentConfig, assessmentYupSchema: periodicAssessmentYupSchema } = entity.getPeriodicAssessmentDetails(recurrence) - const [showAssessmentModal, setShowAssessmentModal] = useState(false) const periodsLastAssessment = [] const periodsAllowNewAssessment = [] periods.forEach(period => { @@ -178,29 +177,19 @@ const PeriodicAssessmentRows = ({ return (
{periodsAllowNewAssessment[index] && ( - <> - - setShowAssessmentModal(false)} - onSuccess={() => { - setShowAssessmentModal(false) - onAddAssessment() - }} - /> - + { + onAddAssessment() + }} + /> )}
- {periodicAssessmentConfig && lastAssessment && ( - - {({ values }) => ( - ( +
+ - )} - - )} +
+ ))}
{periodsAllowNewAssessment[index] && ( @@ -199,14 +313,26 @@ const PeriodicAssessmentRows = ({ ) } -PeriodicAssessmentRows.propTypes = { +BasePeriodicAssessmentRows.propTypes = { entity: PropTypes.object, entityType: PropTypes.func.isRequired, periodsConfig: periodsConfigPropType, canAddAssessment: PropTypes.bool, - onAddAssessment: PropTypes.func + onAddAssessment: PropTypes.func, + currentUser: PropTypes.instanceOf(Person) } +const PeriodicAssessmentRows = props => ( + + {context => ( + + )} + +) + const EntityAssessmentResults = ({ entity, entityType, From 7ce6f5bb44e1eec7007bf90b7d8cc248261ea11d Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 23 Apr 2020 13:51:25 +0200 Subject: [PATCH 047/247] NCI-Agency/anet#2977: Implement edit periodic assessment This adds the possibility to edit an own periodic assessment for a task or person. --- ...dAssessmentModal.js => AssessmentModal.js} | 83 +++--- .../assessments/AssessmentResultsContainer.js | 6 +- .../assessments/AssessmentResultsTable.js | 245 +++++------------- .../assessments/PeriodicAssessment.js | 146 +++++++++++ client/src/components/assessments/utils.js | 28 ++ client/src/pages/people/Show.js | 2 +- client/src/pages/tasks/Show.js | 2 +- 7 files changed, 284 insertions(+), 228 deletions(-) rename client/src/components/assessments/{AddAssessmentModal.js => AssessmentModal.js} (75%) create mode 100644 client/src/components/assessments/PeriodicAssessment.js create mode 100644 client/src/components/assessments/utils.js diff --git a/client/src/components/assessments/AddAssessmentModal.js b/client/src/components/assessments/AssessmentModal.js similarity index 75% rename from client/src/components/assessments/AddAssessmentModal.js rename to client/src/components/assessments/AssessmentModal.js index 1a5f6b4a1b..7c437ff56a 100644 --- a/client/src/components/assessments/AddAssessmentModal.js +++ b/client/src/components/assessments/AssessmentModal.js @@ -6,44 +6,42 @@ import { import Model, { ENTITY_ASSESSMENT_PARENT_FIELD, GQL_CREATE_NOTE, - NOTE_TYPE + GQL_UPDATE_NOTE } from "components/Model" import Messages from "components/Messages" import { Form, Formik } from "formik" import _cloneDeep from "lodash/cloneDeep" -import { Person, Task } from "models" import PropTypes from "prop-types" import React, { useMemo, useState } from "react" import { Button, Modal } from "react-bootstrap" -const AddAssessmentModal = ({ +const AssessmentModal = ({ + showModal, note, - entity, - entityType, - yupSchema, - recurrence, - assessmentPeriod, + assessment, + assessmentYupSchema, assessmentConfig, + assessmentPeriod, + recurrence, title, - addAssessmentLabel, - onSuccess + onSuccess, + onCancel }) => { - const [showModal, setShowModal] = useState(false) const [assessmentError, setAssessmentError] = useState(null) - const initialValues = useMemo(() => Model.fillObject({}, yupSchema), [ - yupSchema - ]) - + const edit = !!note.uuid + const initialValues = useMemo( + () => + ({ [ENTITY_ASSESSMENT_PARENT_FIELD]: assessment } || + Model.fillObject({}, assessmentYupSchema)), + [assessment, assessmentYupSchema] + ) return ( <> - {({ @@ -105,7 +103,7 @@ const AddAssessmentModal = ({ function closeModal() { setAssessmentError(null) - setShowModal(false) + onCancel() } function onAssessmentSubmit(values, form) { @@ -118,20 +116,18 @@ const AddAssessmentModal = ({ } function onSubmitSuccess(response, values, form) { - setShowModal(false) - onSuccess() + const operation = edit ? "updateNote" : "createNote" + onSuccess(response[operation]) } function saveAssessment(values, form) { const updatedNote = { - type: NOTE_TYPE.ASSESSMENT, - noteRelatedObjects: [ - { - relatedObjectType: entityType.relatedObjectType, - relatedObjectUuid: entity.uuid - } - ] + uuid: note.uuid, + author: note.author, + type: note.type, + noteRelatedObjects: note.noteRelatedObjects } + // values contains the assessment fields const clonedValues = _cloneDeep(values) clonedValues[ENTITY_ASSESSMENT_PARENT_FIELD].__recurrence = recurrence clonedValues[ENTITY_ASSESSMENT_PARENT_FIELD].__periodStart = @@ -141,29 +137,26 @@ const AddAssessmentModal = ({ true, ENTITY_ASSESSMENT_PARENT_FIELD ) - return API.mutation(GQL_CREATE_NOTE, { + return API.mutation(edit ? GQL_UPDATE_NOTE : GQL_CREATE_NOTE, { note: updatedNote }) } } -AddAssessmentModal.propTypes = { +AssessmentModal.propTypes = { + showModal: PropTypes.bool, note: Model.notePropTypes, - entity: PropTypes.oneOfType([ - PropTypes.instanceOf(Person), - PropTypes.instanceOf(Task) - ]).isRequired, - entityType: PropTypes.func.isRequired, - yupSchema: PropTypes.object.isRequired, - recurrence: PropTypes.string.isRequired, - assessmentPeriod: PropTypes.object.isRequired, + assessment: PropTypes.object, + assessmentYupSchema: PropTypes.object.isRequired, assessmentConfig: PropTypes.object.isRequired, + assessmentPeriod: PropTypes.object.isRequired, + recurrence: PropTypes.string.isRequired, title: PropTypes.string, - addAssessmentLabel: PropTypes.string, - onSuccess: PropTypes.func.isRequired + onSuccess: PropTypes.func.isRequired, + onCancel: PropTypes.func.isRequired } -AddAssessmentModal.defaultProps = { - title: "Assessment", - showModal: false +AssessmentModal.defaultProps = { + showModal: false, + title: "Assessment" } -export default AddAssessmentModal +export default AssessmentModal diff --git a/client/src/components/assessments/AssessmentResultsContainer.js b/client/src/components/assessments/AssessmentResultsContainer.js index 22bb26136e..4b7309f55a 100644 --- a/client/src/components/assessments/AssessmentResultsContainer.js +++ b/client/src/components/assessments/AssessmentResultsContainer.js @@ -124,7 +124,7 @@ const AssessmentResultsContainer = ({ entityType, subEntities, canAddAssessment, - onAddAssessment + onUpdateAssessment }) => { if (!entity) { return null @@ -143,7 +143,7 @@ const AssessmentResultsContainer = ({ subEntities={subEntities} periodsConfig={periodsConfig} canAddAssessment={canAddAssessment} - onAddAssessment={onAddAssessment} + onUpdateAssessment={onUpdateAssessment} /> ) ) @@ -155,7 +155,7 @@ AssessmentResultsContainer.propTypes = { entity: PropTypes.object, entityType: PropTypes.func.isRequired, subEntities: PropTypes.array, - onAddAssessment: PropTypes.func, + onUpdateAssessment: PropTypes.func, canAddAssessment: PropTypes.bool } diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index a7a0891440..8810c51ec0 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -1,24 +1,17 @@ -import { Icon } from "@blueprintjs/core" -import { IconNames } from "@blueprintjs/icons" import AggregationWidget from "components/AggregationWidget" import AppContext from "components/AppContext" -import AddAssessmentModal from "components/assessments/AddAssessmentModal" -import ConfirmDelete from "components/ConfirmDelete" -import { - getFieldPropsFromFieldConfig, - ReadonlyCustomFields -} from "components/CustomFields" +import AssessmentModal from "components/assessments/AssessmentModal" +import PeriodicAssessment from "components/assessments/PeriodicAssessment" +import { PeriodPropType, periodToString } from "components/assessments/utils" +import { getFieldPropsFromFieldConfig } from "components/CustomFields" import Fieldset from "components/Fieldset" -import { Formik } from "formik" import LinkTo from "components/LinkTo" -import Model from "components/Model" +import { NOTE_TYPE } from "components/Model" import { Person } from "models" -import moment from "moment" import _isEmpty from "lodash/isEmpty" import PropTypes from "prop-types" -import React from "react" -import { Button, Panel, Table } from "react-bootstrap" -import REMOVE_ICON from "resources/delete.png" +import React, { useState } from "react" +import { Button, Table } from "react-bootstrap" import "components/assessments/AssessmentResultsTable.css" /* The AssessmentResultsTable component displays the results of two types of @@ -35,37 +28,10 @@ import "components/assessments/AssessmentResultsTable.css" * entity.getPeriodicAssessmentDetails(recurrence) */ -const PERIOD_START_SHORT_FORMAT = "D" -const PERIOD_START_MIDDLE_FORMAT = "D MMMM" -const PERIOD_START_LONG_FORMAT = "D MMMM YYYY" -const PERIOD_END_FORMAT = "D MMMM YYYY" - -const periodToString = period => { - if (period.start.isSame(period.end, "day")) { - return period.end.format(PERIOD_END_FORMAT) - } else { - const periodStartFormat = - period.start.year() !== period.end.year() - ? PERIOD_START_LONG_FORMAT - : period.start.month() !== period.end.month() - ? PERIOD_START_MIDDLE_FORMAT - : PERIOD_START_SHORT_FORMAT - return `${period.start.format(periodStartFormat)} - ${period.end.format( - PERIOD_END_FORMAT - )}` - } -} - -const periodsPropType = PropTypes.arrayOf( - PropTypes.shape({ - start: PropTypes.object, - end: PropTypes.object, - allowNewAssessments: PropTypes.bool - }) -) -const periodsConfigPropType = PropTypes.shape({ +const PeriodsPropType = PropTypes.arrayOf(PeriodPropType) +const PeriodsConfigPropType = PropTypes.shape({ recurrence: PropTypes.string, - periods: periodsPropType + periods: PeriodsPropType }) const AssessmentsTableHeader = ({ periodsConfig }) => ( @@ -80,7 +46,7 @@ const AssessmentsTableHeader = ({ periodsConfig }) => ( ) AssessmentsTableHeader.propTypes = { - periodsConfig: periodsConfigPropType + periodsConfig: PeriodsConfigPropType } const InstantAssessmentRow = ({ @@ -112,125 +78,26 @@ const InstantAssessmentRow = ({ } InstantAssessmentRow.propTypes = { entity: PropTypes.object, - periods: periodsPropType, + periods: PeriodsPropType, questionKey: PropTypes.string, questionConfig: PropTypes.object } -const BasePeriodicAssessment = ({ - assessment, - assessmentConfig, - note, - currentUser -}) => { - const byMe = Person.isEqual(currentUser, note.author) - const parentFieldName = `assessment-${note.uuid}` - return ( - - - <> - {moment(note.updatedAt).fromNow()}{" "} - - {byMe && ( - <> - - console.log("to be implemented")} - objectType="note" - objectDisplay={"#" + note.uuid} - title="Delete note" - bsSize="xsmall" - bsStyle="primary" - > - Delete assessment - - - )} - - - -
- - {({ values }) => { - return ( - - ) - }} - -
-
-
- ) -} -BasePeriodicAssessment.propTypes = { - assessment: PropTypes.object, - assessmentConfig: PropTypes.object, - note: Model.notePropTypes, - currentUser: PropTypes.instanceOf(Person) -} - -const PeriodicAssessment = props => ( - - {context => ( - - )} - -) - const BasePeriodicAssessmentRows = ({ entity, entityType, periodsConfig, canAddAssessment, - onAddAssessment, + onUpdateAssessment, currentUser }) => { + const [showAssessmentModalKey, setShowAssessmentModalKey] = useState(null) const { recurrence, periods } = periodsConfig const { - assessmentConfig: periodicAssessmentConfig, - assessmentYupSchema: periodicAssessmentYupSchema + assessmentConfig, + assessmentYupSchema } = entity.getPeriodicAssessmentDetails(recurrence) - if (!periodicAssessmentConfig) { + if (!assessmentConfig) { return null } @@ -274,7 +141,12 @@ const BasePeriodicAssessmentRows = ({ ))} @@ -288,22 +160,41 @@ const BasePeriodicAssessmentRows = ({ {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] && ( - { - onAddAssessment() - }} - /> + <> + + { + setShowAssessmentModalKey(null) + onUpdateAssessment() + }} + onCancel={() => setShowAssessmentModalKey(null)} + /> + )}
@@ -449,8 +338,8 @@ AssessmentResultsTable.propTypes = { entity: PropTypes.object, entityType: PropTypes.func.isRequired, subEntities: PropTypes.array, - periodsConfig: periodsConfigPropType, - onAddAssessment: PropTypes.func, + periodsConfig: PeriodsConfigPropType, + onUpdateAssessment: PropTypes.func, canAddAssessment: PropTypes.bool } diff --git a/client/src/components/assessments/PeriodicAssessment.js b/client/src/components/assessments/PeriodicAssessment.js new file mode 100644 index 0000000000..78f3eb492b --- /dev/null +++ b/client/src/components/assessments/PeriodicAssessment.js @@ -0,0 +1,146 @@ +import { Icon } from "@blueprintjs/core" +import { IconNames } from "@blueprintjs/icons" +import AppContext from "components/AppContext" +import AssessmentModal from "components/assessments/AssessmentModal" +import { PeriodPropType, periodToString } from "components/assessments/utils" +import ConfirmDelete from "components/ConfirmDelete" +import { ReadonlyCustomFields } from "components/CustomFields" +import { Formik } from "formik" +import LinkTo from "components/LinkTo" +import Model from "components/Model" +import { Person } from "models" +import moment from "moment" +import PropTypes from "prop-types" +import React, { useState } from "react" +import { Button, Panel } from "react-bootstrap" +import REMOVE_ICON from "resources/delete.png" +import "components/assessments/AssessmentResultsTable.css" + +const BasePeriodicAssessment = ({ + assessment, + assessmentYupSchema, + assessmentConfig, + note, + entity, + period, + recurrence, + onUpdateAssessment, + currentUser +}) => { + 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)} + /> + console.log("to be implemented")} + objectType="note" + objectDisplay={"#" + note.uuid} + title="Delete note" + bsSize="xsmall" + bsStyle="primary" + > + Delete assessment + + + )} + + + +
+ + {({ values }) => { + return ( + + ) + }} + +
+
+
+ ) +} +BasePeriodicAssessment.propTypes = { + assessment: PropTypes.object.isRequired, + assessmentConfig: PropTypes.object.isRequired, + assessmentYupSchema: PropTypes.object.isRequired, + note: Model.notePropTypes.isRequired, + entity: PropTypes.object.isRequired, + period: PeriodPropType.isRequired, + recurrence: PropTypes.string.isRequired, + onUpdateAssessment: PropTypes.func, + currentUser: PropTypes.instanceOf(Person) +} + +const PeriodicAssessment = props => ( + + {context => ( + + )} + +) +export default PeriodicAssessment diff --git a/client/src/components/assessments/utils.js b/client/src/components/assessments/utils.js new file mode 100644 index 0000000000..0b95b6c541 --- /dev/null +++ b/client/src/components/assessments/utils.js @@ -0,0 +1,28 @@ +import PropTypes from "prop-types" + +const PERIOD_START_SHORT_FORMAT = "D" +const PERIOD_START_MIDDLE_FORMAT = "D MMMM" +const PERIOD_START_LONG_FORMAT = "D MMMM YYYY" +const PERIOD_END_FORMAT = "D MMMM YYYY" + +export const periodToString = period => { + if (period.start.isSame(period.end, "day")) { + return period.end.format(PERIOD_END_FORMAT) + } else { + const periodStartFormat = + period.start.year() !== period.end.year() + ? PERIOD_START_LONG_FORMAT + : period.start.month() !== period.end.month() + ? PERIOD_START_MIDDLE_FORMAT + : PERIOD_START_SHORT_FORMAT + return `${period.start.format(periodStartFormat)} - ${period.end.format( + PERIOD_END_FORMAT + )}` + } +} + +export const PeriodPropType = PropTypes.shape({ + start: PropTypes.object, + end: PropTypes.object, + allowNewAssessments: PropTypes.bool +}) diff --git a/client/src/pages/people/Show.js b/client/src/pages/people/Show.js index d36e546b54..308b382039 100644 --- a/client/src/pages/people/Show.js +++ b/client/src/pages/people/Show.js @@ -425,7 +425,7 @@ const BasePersonShow = ({ pageDispatchers, currentUser }) => { entity={person} entityType={Person} canAddAssessment={canAddAssessment} - onAddAssessment={refetch} + onUpdateAssessment={refetch} />
) diff --git a/client/src/pages/tasks/Show.js b/client/src/pages/tasks/Show.js index 169b4a1248..ef96fbcdaa 100644 --- a/client/src/pages/tasks/Show.js +++ b/client/src/pages/tasks/Show.js @@ -354,7 +354,7 @@ const BaseTaskShow = ({ pageDispatchers, currentUser }) => { entityType={Task} subEntities={subTasks} canAddAssessment={canEdit} - onAddAssessment={refetch} + onUpdateAssessment={refetch} />
From efb6712ba6e220cd41bcb14251ea16762bf3dd23 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 23 Apr 2020 22:52:28 +0200 Subject: [PATCH 048/247] NCI-Agency/anet#2954: Code refactoring for tasks assessments retrieval This makes sure that retrieving the instantAssessmentConfig for a task is not being done multiple times in the report form. --- client/src/pages/reports/Form.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/client/src/pages/reports/Form.js b/client/src/pages/reports/Form.js index 0df35bdf29..4118484e7e 100644 --- a/client/src/pages/reports/Form.js +++ b/client/src/pages/reports/Form.js @@ -333,16 +333,17 @@ const BaseReportForm = ({ } // Update the task instant assessment schema according to the selected report tasks + const tasksInstantAssessmentsConfig = {} const tasksInstantAssessmentsSchemaShape = {} - reportTasks - // TODO: even tasks without custom fields may have assessments - .filter(t => t.customFields) - .forEach(t => { + reportTasks.forEach(t => { + tasksInstantAssessmentsConfig[t.uuid] = t.getInstantAssessmentConfig() + if (!_isEmpty(tasksInstantAssessmentsConfig[t.uuid])) { tasksInstantAssessmentsSchemaShape[t.uuid] = createYupObjectShape( - t.getInstantAssessmentConfig(), + tasksInstantAssessmentsConfig[t.uuid], `tasksAssessments.${t.uuid}` ) - }) + } + }) const reportSchema = _isEmpty(tasksInstantAssessmentsSchemaShape) ? Report.yupSchema : Report.yupSchema.concat( @@ -1070,7 +1071,8 @@ const BaseReportForm = ({ id="engagement-assessments" > {values.tasks.map(task => { - const taskInstantAssessmentConfig = task.getInstantAssessmentConfig() + const taskInstantAssessmentConfig = + tasksInstantAssessmentsConfig[task.uuid] if (!taskInstantAssessmentConfig) { return null } From ffe04bd844497c5e7222807299291f3530b22bcd Mon Sep 17 00:00:00 2001 From: vassil Date: Fri, 24 Apr 2020 01:20:16 +0200 Subject: [PATCH 049/247] nci-agency/anet#2954: Add semimonthly periods --- anet.yml | 2 ++ client/src/components/Model.js | 1 + .../assessments/AssessmentResultsContainer.js | 35 +++++++++++++++++++ src/main/resources/anet-schema.yml | 2 +- 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/anet.yml b/anet.yml index 231325d2ef..c4141d904f 100644 --- a/anet.yml +++ b/anet.yml @@ -337,6 +337,8 @@ dictionary: label: weekly biweekly: label: biweekly + semimonthly: + label: semimonthly monthly: label: monthly quarterly: diff --git a/client/src/components/Model.js b/client/src/components/Model.js index 2ef3939916..676b76d49b 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -61,6 +61,7 @@ export const ASSESSMENTS_RECURRENCE_TYPE = { DAILY: "daily", WEEKLY: "weekly", BIWEEKLY: "biweekly", + SEMIMONTHLY: "semimonthly", MONTHLY: "monthly", QUARTERLY: "quarterly", SEMIANNUALY: "semiannualy" diff --git a/client/src/components/assessments/AssessmentResultsContainer.js b/client/src/components/assessments/AssessmentResultsContainer.js index 4b7309f55a..5027ca232a 100644 --- a/client/src/components/assessments/AssessmentResultsContainer.js +++ b/client/src/components/assessments/AssessmentResultsContainer.js @@ -58,6 +58,41 @@ const ASSESSMENT_PERIODS_CONFIG = [ } ] }, + { + recurrence: ASSESSMENTS_RECURRENCE_TYPE.SEMIMONTHLY, + periods: [ + { + start: + now.date() < 15 + ? now.clone().subtract(2, "months").startOf("month") + : now.clone().subtract(2, "months").startOf("month").date(15), + end: + now.date() < 15 + ? now.clone().subtract(2, "months").startOf("month").date(14) + : now.clone().subtract(2, "months").endOf("month") + }, + { + start: + now.date() < 15 + ? now.clone().subtract(1, "months").startOf("month") + : now.clone().subtract(1, "months").startOf("month").date(15), + end: + now.date() < 15 + ? now.clone().subtract(1, "months").startOf("month").date(14) + : now.clone().subtract(1, "months").endOf("month") + }, + { + start: + now.date() < 15 + ? now.clone().startOf("month") + : now.clone().startOf("month").date(15), + end: + now.date() < 15 + ? now.clone().startOf("month").date(14) + : now.clone().endOf("month") + } + ] + }, { recurrence: ASSESSMENTS_RECURRENCE_TYPE.MONTHLY, periods: [ diff --git a/src/main/resources/anet-schema.yml b/src/main/resources/anet-schema.yml index 2aa08fcf9f..31c9d15aa3 100644 --- a/src/main/resources/anet-schema.yml +++ b/src/main/resources/anet-schema.yml @@ -210,7 +210,7 @@ definitions: recurrence: title: recurrence of an assessment type: string - enum: [once, daily, weekly, biweekly, monthly, quarterly, semiannualy, annually] + enum: [once, daily, weekly, biweekly, semimonthly, monthly, quarterly, semiannualy, annually] default: once relatedObjectType: title: object type context in which the assessment will be made From 5b06478fa618417e2936304fc284f2a05aac487a Mon Sep 17 00:00:00 2001 From: vassil Date: Fri, 24 Apr 2020 02:19:53 +0200 Subject: [PATCH 050/247] nci-agency/anet#2954: Add period factories --- .../assessments/AssessmentResultsContainer.js | 228 ++++++------------ 1 file changed, 74 insertions(+), 154 deletions(-) diff --git a/client/src/components/assessments/AssessmentResultsContainer.js b/client/src/components/assessments/AssessmentResultsContainer.js index 5027ca232a..02a0696fc2 100644 --- a/client/src/components/assessments/AssessmentResultsContainer.js +++ b/client/src/components/assessments/AssessmentResultsContainer.js @@ -5,154 +5,56 @@ import PropTypes from "prop-types" import React from "react" const now = moment() -const ASSESSMENT_PERIODS_CONFIG = [ - { - recurrence: ASSESSMENTS_RECURRENCE_TYPE.DAILY, - periods: [ - { - start: now.clone().subtract(2, "days").startOf("day"), - end: now.clone().subtract(2, "days").endOf("day") - }, - { - start: now.clone().subtract(1, "days").startOf("day"), - end: now.clone().subtract(1, "days").endOf("day") - }, - { - start: now.clone().startOf("day"), - end: now.clone().endOf("day") - } - ] - }, - { - recurrence: ASSESSMENTS_RECURRENCE_TYPE.WEEKLY, - periods: [ - { - start: now.clone().subtract(2, "weeks").startOf("week"), - end: now.clone().subtract(2, "weeks").endOf("week") - }, - { - start: now.clone().subtract(1, "weeks").startOf("week"), - end: now.clone().subtract(1, "weeks").endOf("week") - }, - { - start: now.clone().startOf("week"), - end: now.clone().endOf("week") - } - ] - }, - { - // FIXME: biweekly should be each 2 weeks from the beginning of the year - recurrence: ASSESSMENTS_RECURRENCE_TYPE.BIWEEKLY, - periods: [ - { - start: now.clone().subtract(4, "weeks").startOf("week"), - end: now.clone().subtract(4, "weeks").endOf("week") - }, - { - start: now.clone().subtract(2, "weeks").startOf("week"), - end: now.clone().subtract(2, "weeks").endOf("week") - }, - { - start: now.clone().startOf("week"), - end: now.clone().endOf("week") - } - ] - }, - { - recurrence: ASSESSMENTS_RECURRENCE_TYPE.SEMIMONTHLY, - periods: [ - { - start: - now.date() < 15 - ? now.clone().subtract(2, "months").startOf("month") - : now.clone().subtract(2, "months").startOf("month").date(15), - end: - now.date() < 15 - ? now.clone().subtract(2, "months").startOf("month").date(14) - : now.clone().subtract(2, "months").endOf("month") - }, - { - start: - now.date() < 15 - ? now.clone().subtract(1, "months").startOf("month") - : now.clone().subtract(1, "months").startOf("month").date(15), - end: - now.date() < 15 - ? now.clone().subtract(1, "months").startOf("month").date(14) - : now.clone().subtract(1, "months").endOf("month") - }, - { - start: - now.date() < 15 - ? now.clone().startOf("month") - : now.clone().startOf("month").date(15), - end: - now.date() < 15 - ? now.clone().startOf("month").date(14) - : now.clone().endOf("month") - } - ] - }, - { - recurrence: ASSESSMENTS_RECURRENCE_TYPE.MONTHLY, - periods: [ - { - start: now.clone().subtract(2, "months").startOf("month"), - end: now.clone().subtract(2, "months").endOf("month") - }, - { - start: now.clone().subtract(1, "months").startOf("month"), - end: now.clone().subtract(1, "months").endOf("month") - }, - { - start: now.clone().startOf("month"), - end: now.clone().endOf("month") - } - ] - }, - { - recurrence: ASSESSMENTS_RECURRENCE_TYPE.QUARTERLY, - periods: [ - { - start: now.clone().subtract(2, "quarters").startOf("quarter"), - end: now.clone().subtract(2, "quarters").endOf("quarter") - }, - { - start: now.clone().subtract(1, "quarters").startOf("quarter"), - end: now.clone().subtract(1, "quarters").endOf("quarter") - }, - { - start: now.clone().startOf("quarter"), - end: now.clone().endOf("quarter") - } - ] - }, - { - recurrence: ASSESSMENTS_RECURRENCE_TYPE.SEMIANNUALY, - periods: [ - { - start: now.clone().subtract(4, "quarters").startOf("quarter"), - end: now.clone().subtract(4, "quarters").endOf("quarter") - }, - { - start: now.clone().subtract(2, "quarters").startOf("quarter"), - end: now.clone().subtract(2, "quarters").endOf("quarter") - }, - { - start: now.clone().startOf("quarter"), - end: now.clone().endOf("quarter") - } - ] - } -] -// set default allowNewAssessments when this one is not configured for a period -ASSESSMENT_PERIODS_CONFIG.forEach(periodConfig => - periodConfig.periods.forEach(period => { - if (period.allowNewAssessments === undefined) { - period.allowNewAssessments = period.end < now.clone().startOf("day") - } + +const ASSESSMENT_PERIOD_FACTORIES = { + [ASSESSMENTS_RECURRENCE_TYPE.DAILY]: (date, offset) => ({ + start: date.clone().subtract(offset, "days").startOf("day"), + end: date.clone().subtract(offset, "days").endOf("day") + }), + [ASSESSMENTS_RECURRENCE_TYPE.WEEKLY]: (date, offset) => ({ + start: date.clone().subtract(offset, "weeks").startOf("week"), + end: date.clone().subtract(offset, "weeks").endOf("week") + }), + // FIXME: biweekly should be each 2 weeks from the beginning of the year + [ASSESSMENTS_RECURRENCE_TYPE.BIWEEKLY]: (date, offset) => ({ + start: date + .clone() + .subtract(2 * offset, "weeks") + .startOf("week"), + end: date + .clone() + .subtract(2 * offset, "weeks") + .endOf("week") + }), + [ASSESSMENTS_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") + }), + [ASSESSMENTS_RECURRENCE_TYPE.MONTHLY]: (date, offset) => ({ + start: date.clone().subtract(offset, "months").startOf("month"), + end: date.clone().subtract(offset, "months").endOf("month") + }), + [ASSESSMENTS_RECURRENCE_TYPE.QUARTERLY]: (date, offset) => ({ + start: date.clone().subtract(offset, "quarters").startOf("quarter"), + end: date.clone().subtract(offset, "quarters").endOf("quarter") + }), + [ASSESSMENTS_RECURRENCE_TYPE.SEMIANNUALY]: (date, offset) => ({ + start: date + .clone() + .subtract(2 * offset, "quarters") + .startOf("quarter"), + end: date + .clone() + .subtract(2 * offset, "quarters") + .endOf("quarter") }) -) +} const AssessmentResultsContainer = ({ entity, @@ -167,22 +69,40 @@ const AssessmentResultsContainer = ({ const assessmentsTypes = Object.keys(entity.getAssessmentsConfig()) return ( <> - {ASSESSMENT_PERIODS_CONFIG.map(periodsConfig => { - return ( - assessmentsTypes.includes(periodsConfig.recurrence) && ( + {assessmentsTypes.map( + assessmentsType => + ASSESSMENT_PERIOD_FACTORIES[assessmentsType] && ( ) - ) - })} + )} ) } From a3114af2278989248bb5d4b9c3de0ef9f9eefa37 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Fri, 24 Apr 2020 13:00:05 +0200 Subject: [PATCH 051/247] NCI-Agency/anet#2977: Save extra instant assessment details This makes sure that for instant assessments we also save the __recurrence and __relatedObjectType in the assessment text. These JSON fields are not being displayed, but used for filtering the proper assessments. --- client/src/components/Model.js | 2 +- client/src/components/RelatedObjectNotes.js | 1 + client/src/models/Task.js | 24 +++++++++++++++------ client/src/pages/reports/Form.js | 6 ++++++ insertBaseData-mssql.sql | 4 ++-- 5 files changed, 27 insertions(+), 10 deletions(-) diff --git a/client/src/components/Model.js b/client/src/components/Model.js index 676b76d49b..2dd1cbe715 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -66,7 +66,7 @@ export const ASSESSMENTS_RECURRENCE_TYPE = { QUARTERLY: "quarterly", SEMIANNUALY: "semiannualy" } -const ASSESSMENTS_RELATED_OBJECT_TYPE = { +export const ASSESSMENTS_RELATED_OBJECT_TYPE = { REPORT: "report" } diff --git a/client/src/components/RelatedObjectNotes.js b/client/src/components/RelatedObjectNotes.js index a686a3cc0f..54e8876a3c 100644 --- a/client/src/components/RelatedObjectNotes.js +++ b/client/src/components/RelatedObjectNotes.js @@ -38,6 +38,7 @@ export { GRAPHQL_NOTES_FIELDS } from "components/Model" const EXCLUDED_ASSESSMENT_FIELDS = [ "__recurrence", "__periodStart", + "__relatedObjectType", INVISIBLE_CUSTOM_FIELDS_FIELD ] diff --git a/client/src/models/Task.js b/client/src/models/Task.js index 6cdcd88531..9a09d3f1d6 100644 --- a/client/src/models/Task.js +++ b/client/src/models/Task.js @@ -1,5 +1,7 @@ import { Settings } from "api" import Model, { + ASSESSMENTS_RECURRENCE_TYPE, + ASSESSMENTS_RELATED_OBJECT_TYPE, createCustomFieldsSchema, NOTE_TYPE, yupDate @@ -187,13 +189,15 @@ export default class Task extends Model { return JSON.parse(this.customFields || "{}").assessments || [] } - getInstantAssessmentResults(dateRange) { + getInstantAssessmentResults( + dateRange, + relatedObjectType = ASSESSMENTS_RELATED_OBJECT_TYPE.REPORT + ) { const publishedReportsUuids = this.publishedReports.map(r => r.uuid) const assessmentsNotes = this.notes .filter( n => n.type === NOTE_TYPE.ASSESSMENT && - n.noteRelatedObjects.length === 2 && n.noteRelatedObjects.filter( ro => ro.relatedObjectType === Report.relatedObjectType && @@ -202,16 +206,22 @@ export default class Task extends Model { (!dateRange || (n.createdAt <= dateRange.end && n.createdAt >= dateRange.start)) ) - .map(n => JSON.parse(n.text)) + .map(note => ({ note: note, assessment: JSON.parse(note.text) })) + .filter( + obj => + obj.assessment.__recurrence === ASSESSMENTS_RECURRENCE_TYPE.ONCE && + obj.assessment.__relatedObjectType === relatedObjectType + ) const assessmentsResults = {} - assessmentsNotes.forEach(n => - Object.keys(n).forEach(k => { + assessmentsNotes.forEach(n => { + const a = n.assessment + Object.keys(a).forEach(k => { if (!Object.prototype.hasOwnProperty.call(assessmentsResults, k)) { assessmentsResults[k] = [] } - assessmentsResults[k].push(n[k]) + assessmentsResults[k].push(a[k]) }) - ) + }) return assessmentsResults } } diff --git a/client/src/pages/reports/Form.js b/client/src/pages/reports/Form.js index 4118484e7e..8c1d15dc22 100644 --- a/client/src/pages/reports/Form.js +++ b/client/src/pages/reports/Form.js @@ -21,6 +21,8 @@ import * as FieldHelper from "components/FieldHelper" import Fieldset from "components/Fieldset" import Messages from "components/Messages" import { + ASSESSMENTS_RECURRENCE_TYPE, + ASSESSMENTS_RELATED_OBJECT_TYPE, createYupObjectShape, DEFAULT_CUSTOM_FIELDS_PARENT, INVISIBLE_CUSTOM_FIELDS_FIELD, @@ -1286,6 +1288,10 @@ const BaseReportForm = ({ !isEmptyTaskAssessment(values.tasksAssessments[key]) ) .map(key => { + values[`tasksAssessments.${key}`].__recurrence = + ASSESSMENTS_RECURRENCE_TYPE.ONCE + values[`tasksAssessments.${key}`].__relatedObjectType = + ASSESSMENTS_RELATED_OBJECT_TYPE.REPORT const noteObj = { type: NOTE_TYPE.ASSESSMENT, noteRelatedObjects: [ diff --git a/insertBaseData-mssql.sql b/insertBaseData-mssql.sql index 7caf7f6ad1..182af58d98 100644 --- a/insertBaseData-mssql.sql +++ b/insertBaseData-mssql.sql @@ -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 From 7448f17b6f70dd078a6f9a19d57a2acfdba1b5b0 Mon Sep 17 00:00:00 2001 From: Vassil Iordanov Date: Sat, 25 Apr 2020 17:57:57 +0200 Subject: [PATCH 052/247] nci-angency/anet#2954: Make graphql for recents use autocompleteQuery fields --- client/src/models/Tag.js | 2 +- client/src/pages/reports/Form.js | 48 ++++---------------------------- 2 files changed, 7 insertions(+), 43 deletions(-) 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/pages/reports/Form.js b/client/src/pages/reports/Form.js index 8c1d15dc22..69a083815a 100644 --- a/client/src/pages/reports/Form.js +++ b/client/src/pages/reports/Form.js @@ -44,7 +44,7 @@ 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 pluralize from "pluralize" import PropTypes from "prop-types" @@ -73,8 +73,7 @@ const GQL_GET_RECENTS = gql` } ) { list { - uuid - name + ${Location.autocompleteQuery} } } personList( @@ -87,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( @@ -136,9 +104,7 @@ const GQL_GET_RECENTS = gql` } ) { list { - uuid - name - description + ${AuthorizationGroup.autocompleteQuery} } } tagList( @@ -147,9 +113,7 @@ const GQL_GET_RECENTS = gql` } ) { list { - uuid - name - description + ${Tag.autocompleteQuery} } } } From 9bcafb0c35ac4748adca7e384b65b266a00282ff Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Wed, 1 Apr 2020 12:15:00 +0200 Subject: [PATCH 053/247] Remove obsolete test JSON --- src/test/resources/testJson/groups/groupA.json | 8 -------- src/test/resources/testJson/groups/groupB.json | 7 ------- src/test/resources/testJson/groups/loadAll.sh | 6 ------ 3 files changed, 21 deletions(-) delete mode 100644 src/test/resources/testJson/groups/groupA.json delete mode 100644 src/test/resources/testJson/groups/groupB.json delete mode 100755 src/test/resources/testJson/groups/loadAll.sh 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 From e936e6add487ba2f80c2a348320fbbaa3164173c Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Wed, 1 Apr 2020 12:18:12 +0200 Subject: [PATCH 054/247] Show error in the standard way --- client/src/components/RelatedObjectNotes.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/components/RelatedObjectNotes.js b/client/src/components/RelatedObjectNotes.js index 49138995e8..4ef3915efc 100644 --- a/client/src/components/RelatedObjectNotes.js +++ b/client/src/components/RelatedObjectNotes.js @@ -7,6 +7,7 @@ import AppContext from "components/AppContext" import ConfirmDelete from "components/ConfirmDelete" import Pie from "components/graphs/Pie" import LinkTo from "components/LinkTo" +import Messages from "components/Messages" import Model, { NOTE_TYPE } from "components/Model" import RelatedObjectNoteModal from "components/RelatedObjectNoteModal" import { JSONPath } from "jsonpath-plus" @@ -46,9 +47,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, @@ -137,6 +136,7 @@ const BaseRelatedObjectNotes = ({
+
Date: Wed, 1 Apr 2020 16:12:05 +0200 Subject: [PATCH 055/247] Fix double callback on advanced select Also show the entire table row as clickable. --- .../advancedSelectWidget/AdvancedSelectOverlayTable.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) 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)} From f40ba15a5c102acef50173b8432203bdd31b4422 Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Wed, 1 Apr 2020 12:15:21 +0200 Subject: [PATCH 056/247] Add RelatableObject union to GraphQL schema Add accessor to retrieve the related object of a NoteRelatedObject. --- .../mil/dds/anet/beans/AuthorizationGroup.java | 2 +- src/main/java/mil/dds/anet/beans/Location.java | 2 +- .../mil/dds/anet/beans/NoteRelatedObject.java | 17 +++++++++++++++++ .../java/mil/dds/anet/beans/Organization.java | 2 +- src/main/java/mil/dds/anet/beans/Person.java | 2 +- src/main/java/mil/dds/anet/beans/Position.java | 2 +- .../mil/dds/anet/beans/RelatableObject.java | 7 +++++++ src/main/java/mil/dds/anet/beans/Report.java | 2 +- src/main/java/mil/dds/anet/beans/Task.java | 2 +- 9 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 src/main/java/mil/dds/anet/beans/RelatableObject.java 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 938821b1c1..e2472a52e7 100644 --- a/src/main/java/mil/dds/anet/beans/Organization.java +++ b/src/main/java/mil/dds/anet/beans/Organization.java @@ -21,7 +21,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 25ef027635..8728cfcc60 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 7ecb425029..9bf73ade9b 100644 --- a/src/main/java/mil/dds/anet/beans/Report.java +++ b/src/main/java/mil/dds/anet/beans/Report.java @@ -23,7 +23,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, // - 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"; From 3407049f2f5210e96dabc2986ec26c92775a54a5 Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Wed, 1 Apr 2020 12:18:49 +0200 Subject: [PATCH 057/247] Allow editing of the related objects of a note --- client/src/components/LinkTo.js | 4 +- client/src/components/Model.js | 65 +++++++++++-- .../src/components/RelatedObjectNoteModal.js | 73 ++++++++++++--- client/src/components/RelatedObjectNotes.js | 20 ++-- client/src/components/RelatedObjectsTable.js | 93 +++++++++++++++++++ .../pages/admin/authorizationgroup/Edit.js | 3 +- .../pages/admin/authorizationgroup/Show.js | 3 +- client/src/pages/locations/Edit.js | 3 +- client/src/pages/locations/Show.js | 3 +- client/src/pages/organizations/Edit.js | 3 +- client/src/pages/organizations/Show.js | 3 +- client/src/pages/people/Edit.js | 3 +- client/src/pages/people/Show.js | 3 +- client/src/pages/positions/Edit.js | 3 +- client/src/pages/positions/Show.js | 3 +- client/src/pages/reports/Edit.js | 3 +- client/src/pages/reports/Show.js | 3 +- client/src/pages/tasks/Edit.js | 3 +- client/src/pages/tasks/Show.js | 3 +- src/test/resources/graphQLTests/orgShow.gql | 27 ++++++ src/test/resources/graphQLTests/person.gql | 27 ++++++ src/test/resources/graphQLTests/positions.gql | 27 ++++++ src/test/resources/graphQLTests/report.gql | 27 ++++++ 23 files changed, 364 insertions(+), 41 deletions(-) create mode 100644 client/src/components/RelatedObjectsTable.js 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 c606d9846d..54c5f24761 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -26,6 +26,34 @@ 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 + } + ... on Task { + shortName + longName + } + } } ` export const GRAPHQL_NOTES_FIELDS = /* GraphQL */ ` @@ -49,6 +77,20 @@ 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", @@ -113,7 +155,7 @@ const createFieldYupSchema = (fieldKey, fieldConfig, fieldPrefix) => { } // Field type specific validation not needed when the field is invisible or // when invisibleCustomFields hasn't even been filled (like when the report - // has been created via sevrer side tests, or later maybe imported from an + // has been created via server side tests, or later maybe imported from an // external system (and never went through the edit/create form which normally // fills the invisibleCustomFields) fieldYupSchema = fieldYupSchema.when( @@ -170,7 +212,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, @@ -180,13 +233,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 diff --git a/client/src/components/RelatedObjectNoteModal.js b/client/src/components/RelatedObjectNoteModal.js index 7684e6d8cc..02b823759f 100644 --- a/client/src/components/RelatedObjectNoteModal.js +++ b/client/src/components/RelatedObjectNoteModal.js @@ -1,13 +1,17 @@ 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" @@ -15,9 +19,11 @@ import * as yup from "yup" const RelatedObjectNoteModal = ({ note, + currentObject, showModal, onCancel, onSuccess, + onDelete, questions }) => { const yupSchema = yup.object().shape({ @@ -25,6 +31,9 @@ const RelatedObjectNoteModal = ({ text: yup.string().default("") }) const [error, setError] = useState(null) + const [relatedObjects, setRelatedObjects] = useState( + note.noteRelatedObjects || [] + ) const edit = !!note.uuid return ( @@ -68,7 +77,6 @@ const RelatedObjectNoteModal = ({ }} > - {note.type === NOTE_TYPE.PARTNER_ASSESSMENT && ( <> {questions.map(question => ( @@ -89,7 +97,6 @@ const RelatedObjectNoteModal = ({ ))} )} - +
- + {_isEmpty(relatedObjects) ? ( + onDelete(note.uuid)} + objectType="note" + objectDisplay={"#" + note.uuid} + bsStyle="warning" + buttonLabel="Delete note" + /> + ) : ( + + )} ) @@ -126,6 +150,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 +185,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 +209,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 4ef3915efc..0029a86833 100644 --- a/client/src/components/RelatedObjectNotes.js +++ b/client/src/components/RelatedObjectNotes.js @@ -172,6 +172,7 @@ const BaseRelatedObjectNotes = ({ type: noteType, noteRelatedObjects: [{ ...relatedObject }] }} + currentObject={relatedObject} questions={questions} showModal={showRelatedObjectNoteModalKey === "new"} onCancel={cancelRelatedObjectNoteModal} @@ -283,10 +284,12 @@ const BaseRelatedObjectNotes = ({ deleteNote(note.uuid)} @@ -399,13 +402,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,11 +432,8 @@ const BaseRelatedObjectNotes = ({ BaseRelatedObjectNotes.propTypes = { currentUser: PropTypes.instanceOf(Person), 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, diff --git a/client/src/components/RelatedObjectsTable.js b/client/src/components/RelatedObjectsTable.js new file mode 100644 index 0000000000..739d26105d --- /dev/null +++ b/client/src/components/RelatedObjectsTable.js @@ -0,0 +1,93 @@ +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" + +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: PropTypes.func +} + +RelatedObjectsTable.defaultProps = { + showDelete: false +} + +export default RelatedObjectsTable diff --git a/client/src/pages/admin/authorizationgroup/Edit.js b/client/src/pages/admin/authorizationgroup/Edit.js index 12a7e200b6..c76ed3c06c 100644 --- a/client/src/pages/admin/authorizationgroup/Edit.js +++ b/client/src/pages/admin/authorizationgroup/Edit.js @@ -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/Show.js b/client/src/pages/admin/authorizationgroup/Show.js index 8f296cb270..3b5184a907 100644 --- a/client/src/pages/admin/authorizationgroup/Show.js +++ b/client/src/pages/admin/authorizationgroup/Show.js @@ -100,7 +100,8 @@ const BaseAuthorizationGroupShow = ({ pageDispatchers, currentUser }) => { relatedObject={ authorizationGroup.uuid && { relatedObjectType: AuthorizationGroup.relatedObjectType, - relatedObjectUuid: authorizationGroup.uuid + relatedObjectUuid: authorizationGroup.uuid, + relatedObject: authorizationGroup } } /> diff --git a/client/src/pages/locations/Edit.js b/client/src/pages/locations/Edit.js index 9f18895a86..d65e4052bb 100644 --- a/client/src/pages/locations/Edit.js +++ b/client/src/pages/locations/Edit.js @@ -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/Show.js b/client/src/pages/locations/Show.js index e892630314..48dc3e8268 100644 --- a/client/src/pages/locations/Show.js +++ b/client/src/pages/locations/Show.js @@ -138,7 +138,8 @@ const BaseLocationShow = ({ pageDispatchers, currentUser }) => { relatedObject={ location.uuid && { relatedObjectType: Location.relatedObjectType, - relatedObjectUuid: location.uuid + relatedObjectUuid: location.uuid, + relatedObject: location } } /> diff --git a/client/src/pages/organizations/Edit.js b/client/src/pages/organizations/Edit.js index 011e3a4e6c..c29b0a647c 100644 --- a/client/src/pages/organizations/Edit.js +++ b/client/src/pages/organizations/Edit.js @@ -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/Show.js b/client/src/pages/organizations/Show.js index 9b2e62d693..f7639c9736 100644 --- a/client/src/pages/organizations/Show.js +++ b/client/src/pages/organizations/Show.js @@ -246,7 +246,8 @@ const BaseOrganizationShow = ({ pageDispatchers, currentUser }) => { relatedObject={ organization.uuid && { relatedObjectType: Organization.relatedObjectType, - relatedObjectUuid: organization.uuid + relatedObjectUuid: organization.uuid, + relatedObject: organization } } /> diff --git a/client/src/pages/people/Edit.js b/client/src/pages/people/Edit.js index 489754b436..332a366425 100644 --- a/client/src/pages/people/Edit.js +++ b/client/src/pages/people/Edit.js @@ -89,7 +89,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/Show.js b/client/src/pages/people/Show.js index 0eb17c5f86..23f234f599 100644 --- a/client/src/pages/people/Show.js +++ b/client/src/pages/people/Show.js @@ -188,7 +188,8 @@ const BasePersonShow = ({ pageDispatchers, currentUser }) => { relatedObject={ person.uuid && { relatedObjectType: Person.relatedObjectType, - relatedObjectUuid: person.uuid + relatedObjectUuid: person.uuid, + relatedObject: person } } relatedObjectValue={person} diff --git a/client/src/pages/positions/Edit.js b/client/src/pages/positions/Edit.js index ae16ce59c3..b9a1617fc2 100644 --- a/client/src/pages/positions/Edit.js +++ b/client/src/pages/positions/Edit.js @@ -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/Show.js b/client/src/pages/positions/Show.js index f3e6247a04..1207486471 100644 --- a/client/src/pages/positions/Show.js +++ b/client/src/pages/positions/Show.js @@ -181,7 +181,8 @@ const BasePositionShow = ({ pageDispatchers, currentUser }) => { relatedObject={ position.uuid && { relatedObjectType: Position.relatedObjectType, - relatedObjectUuid: position.uuid + relatedObjectUuid: position.uuid, + relatedObject: position } } /> diff --git a/client/src/pages/reports/Edit.js b/client/src/pages/reports/Edit.js index ce053a647a..ab08a42328 100644 --- a/client/src/pages/reports/Edit.js +++ b/client/src/pages/reports/Edit.js @@ -131,7 +131,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/Show.js b/client/src/pages/reports/Show.js index f004805296..9ddafcf902 100644 --- a/client/src/pages/reports/Show.js +++ b/client/src/pages/reports/Show.js @@ -387,7 +387,8 @@ const BaseReportShow = ({ currentUser, setSearchQuery, pageDispatchers }) => { relatedObject={ uuid && { relatedObjectType: Report.relatedObjectType, - relatedObjectUuid: uuid + relatedObjectUuid: uuid, + relatedObject: report } } /> diff --git a/client/src/pages/tasks/Edit.js b/client/src/pages/tasks/Edit.js index 5deb9d4923..f95e2adca3 100644 --- a/client/src/pages/tasks/Edit.js +++ b/client/src/pages/tasks/Edit.js @@ -121,7 +121,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/Show.js b/client/src/pages/tasks/Show.js index d10cb88ad9..3c685e1c14 100644 --- a/client/src/pages/tasks/Show.js +++ b/client/src/pages/tasks/Show.js @@ -223,7 +223,8 @@ const BaseTaskShow = ({ pageDispatchers, currentUser }) => { relatedObject={ task.uuid && { relatedObjectType: Task.relatedObjectType, - relatedObjectUuid: task.uuid + relatedObjectUuid: task.uuid, + relatedObject: task } } /> 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.gql b/src/test/resources/graphQLTests/person.gql index 01ba4690e8..452d709123 100644 --- a/src/test/resources/graphQLTests/person.gql +++ b/src/test/resources/graphQLTests/person.gql @@ -61,6 +61,33 @@ 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 + } + } } } } 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.gql b/src/test/resources/graphQLTests/report.gql index ce8cdfea31..e2eabe7223 100644 --- a/src/test/resources/graphQLTests/report.gql +++ b/src/test/resources/graphQLTests/report.gql @@ -177,6 +177,33 @@ 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 + } + } } } } From ee4e7347d77f259fda812316a46a0e5bdf3ab8b3 Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Tue, 28 Apr 2020 13:35:35 +0200 Subject: [PATCH 058/247] Remove duplicate import --- client/src/components/Model.js | 1 - 1 file changed, 1 deletion(-) diff --git a/client/src/components/Model.js b/client/src/components/Model.js index 54c5f24761..83b47119ae 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -8,7 +8,6 @@ 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 From a27ce7c5533c5db247414876a7312aea42a09fd8 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 29 Apr 2020 10:45:21 +0200 Subject: [PATCH 059/247] NCI-Agency/anet#2954: Fix saving report task assessments Saving the __recurrence and __relatedObjectType property for a report task assessment was giving an error. --- client/src/pages/reports/Form.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/pages/reports/Form.js b/client/src/pages/reports/Form.js index 69a083815a..c5daecf568 100644 --- a/client/src/pages/reports/Form.js +++ b/client/src/pages/reports/Form.js @@ -1252,9 +1252,9 @@ const BaseReportForm = ({ !isEmptyTaskAssessment(values.tasksAssessments[key]) ) .map(key => { - values[`tasksAssessments.${key}`].__recurrence = + values.tasksAssessments[key].__recurrence = ASSESSMENTS_RECURRENCE_TYPE.ONCE - values[`tasksAssessments.${key}`].__relatedObjectType = + values.tasksAssessments[key].__relatedObjectType = ASSESSMENTS_RELATED_OBJECT_TYPE.REPORT const noteObj = { type: NOTE_TYPE.ASSESSMENT, From 56b70f5283f74625dda2e7e8d8ad720dc4c55a83 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 29 Apr 2020 11:31:54 +0200 Subject: [PATCH 060/247] NCI-Agency/anet#2954: Fix adding report task assessments for recents When adding a task from the recents list the task assessments were not being updated, this has been fixed now. We now also make sure that when adding items from FieldShortcuts we always return an instance of the given object type, just as the advanced select widget also does. This has been done as right now the field shortcuts are used in combination with the advanced select widget, and we would expect from both the same return type. --- client/src/components/FieldHelper.js | 6 +++--- client/src/pages/reports/Form.js | 9 +++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/client/src/components/FieldHelper.js b/client/src/components/FieldHelper.js index 7a3d10c06a..425d657edf 100644 --- a/client/src/components/FieldHelper.js +++ b/client/src/components/FieldHelper.js @@ -487,7 +487,7 @@ export const FieldShortcuts = ({ shortcuts.length > 0 && (
{title}
- {shortcuts.map(shortcut => ( + {objectType.map(shortcuts, (shortcut, idx) => ( )} + {viewFormats.includes(FORMAT_STATISTICS) && ( + + )} )} @@ -107,6 +116,36 @@ const ReportCollection = ({ marginBottom={marginBottom} /> )} + {viewFormat === FORMAT_STATISTICS && statisticsRecurrence.length && ( + <> + {statisticsRecurrence.map(recurrence => ( + + ))} + + )}
diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js new file mode 100644 index 0000000000..ede0b92180 --- /dev/null +++ b/client/src/components/ReportStatistics.js @@ -0,0 +1,265 @@ +import AggregationWidget from "components/AggregationWidget" +import API, { Settings } from "api" +import { gql } from "apollo-boost" +import { PeriodPropType, periodToString } from "components/assessments/utils" +import { getFieldPropsFromFieldConfig } from "components/CustomFields" +import { PageDispatchersPropType, useBoilerplate } from "components/Page" +import _get from "lodash/get" +import _isEqual from "lodash/isEqual" +import { Report } from "models" +import PropTypes from "prop-types" +import React, { useEffect, useRef } from "react" +import { Table } from "react-bootstrap" + +// TODO +const PeriodsPropType = PropTypes.arrayOf(PeriodPropType) +const PeriodsConfigPropType = PropTypes.shape({ + recurrence: PropTypes.string, + periods: PeriodsPropType +}) + +const STATISTICS_REPORT_FIELDS = { + state: { + aggregation: { widget: "default" }, + label: "state" + }, + atmosphere: { + aggregation: { widget: "default" }, + label: "atmosphere" + } +} + +const GQL_GET_REPORT_LIST = gql` + query($reportQuery: ReportSearchQueryInput) { + reportList(query: $reportQuery) { + pageNum + pageSize + totalCount + list { + uuid + intent + engagementDate + duration + keyOutcomes + nextSteps + cancelledReason + atmosphere + atmosphereDetails + state + author { + uuid + name + rank + role + } + primaryAdvisor { + uuid + name + rank + role + } + primaryPrincipal { + uuid + name + rank + role + } + advisorOrg { + uuid + shortName + } + principalOrg { + uuid + shortName + } + location { + uuid + name + lat + lng + } + tasks { + uuid + shortName + } + tags { + uuid + name + description + } + updatedAt + customFields + } + } + } +` +// TODO: +const AssessmentsTableHeader = ({ periodsConfig }) => ( + + + <> + {periodsConfig.periods.map(period => ( + {periodToString(period)} + ))} + + + +) +AssessmentsTableHeader.propTypes = { + periodsConfig: PeriodsConfigPropType +} + +const FieldStatisticsRow = ({ + periodsData, + fieldKey, + fieldConfig, + periods +}) => { + if (!fieldConfig.aggregation) { + return null + } + const aggWidgetProps = { + widget: fieldConfig.aggregation.widget || fieldConfig.widget, + aggregationType: fieldConfig.aggregation.aggregationType, + vertical: true + } + const fieldProps = getFieldPropsFromFieldConfig(fieldConfig) + return ( + + {periods.map((period, index) => ( + + + + ))} + + ) +} +FieldStatisticsRow.propTypes = { + fieldConfig: PropTypes.object, + fieldKey: PropTypes.string, + periods: PeriodsPropType, + periodsData: PropTypes.array +} + +const ReportStatistics = ({ + pageDispatchers, + queryParams, + setTotalCount, + showAuthors, + showStatus, + periodsConfig +}) => { + const { periods } = periodsConfig + const latestQueryParams = useRef(queryParams) + const queryParamsUnchanged = _isEqual(latestQueryParams.current, queryParams) + + useEffect(() => { + if (!queryParamsUnchanged) { + latestQueryParams.current = queryParams + } + }, [queryParams, queryParamsUnchanged]) + const reportQuery = Object.assign({}, queryParams, { pageSize: 0 }) + 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 + } + + const reports = data ? Report.fromArray(data.reportList.list) : [] + if (_get(reports, "length", 0) === 0) { + return No reports found + } + const customFieldsConfig = Settings.fields.report.customFields + + const getPeriodStatistics = (reports, dateRange) => { + const reportsForDateRange = reports.filter( + elem => + elem.engagementDate <= dateRange.end && + elem.engagementDate >= dateRange.start + ) + reportsForDateRange.map( + report => (report.customFieldsJson = JSON.parse(report.customFields)) + ) + const periodStatistics = {} + reportsForDateRange.forEach(report => { + const customFieldsValues = report.customFieldsJson + if (customFieldsValues && typeof customFieldsValues === "object") { + // TODO: make the key custom fields specific, to make sure we don't have both a normal as a custom field with the same name + Object.keys(customFieldsConfig).forEach(key => { + if (!Object.prototype.hasOwnProperty.call(periodStatistics, key)) { + periodStatistics[key] = [] + } + periodStatistics[key].push(Object.get(customFieldsValues, key)) + }) + } + // TODO: combine with above to reduce code duplication + Object.keys(STATISTICS_REPORT_FIELDS).forEach(key => { + if (!Object.prototype.hasOwnProperty.call(periodStatistics, key)) { + periodStatistics[key] = [] + } + periodStatistics[key].push(report[key]) + }) + }) + return periodStatistics + } + + const periodsStatistics = [] + periodsConfig.periods.forEach(period => + periodsStatistics.push(getPeriodStatistics(reports, period)) + ) + return ( + + + + <> + {Object.keys(STATISTICS_REPORT_FIELDS || {}).map(key => ( + + ))} + {Object.keys(customFieldsConfig || {}).map(key => ( + + ))} + + +
+ ) +} + +ReportStatistics.propTypes = { + pageDispatchers: PageDispatchersPropType, + queryParams: PropTypes.object, + setTotalCount: PropTypes.func, + showAuthors: PropTypes.bool, + showStatus: PropTypes.bool, + periodsConfig: PeriodsConfigPropType +} + +export default ReportStatistics diff --git a/client/src/components/assessments/AssessmentResultsContainer.js b/client/src/components/assessments/AssessmentResultsContainer.js index 02a0696fc2..b2a5beb701 100644 --- a/client/src/components/assessments/AssessmentResultsContainer.js +++ b/client/src/components/assessments/AssessmentResultsContainer.js @@ -6,7 +6,7 @@ import React from "react" const now = moment() -const ASSESSMENT_PERIOD_FACTORIES = { +export const ASSESSMENT_PERIOD_FACTORIES = { [ASSESSMENTS_RECURRENCE_TYPE.DAILY]: (date, offset) => ({ start: date.clone().subtract(offset, "days").startOf("day"), end: date.clone().subtract(offset, "days").endOf("day") diff --git a/client/src/pages/organizations/Show.js b/client/src/pages/organizations/Show.js index 9b2e62d693..77f4b5f06b 100644 --- a/client/src/pages/organizations/Show.js +++ b/client/src/pages/organizations/Show.js @@ -18,10 +18,11 @@ import RelatedObjectNotes, { GRAPHQL_NOTES_FIELDS } from "components/RelatedObjectNotes" import ReportCollection, { + FORMAT_CALENDAR, FORMAT_MAP, + FORMAT_STATISTICS, FORMAT_SUMMARY, - FORMAT_TABLE, - FORMAT_CALENDAR + FORMAT_TABLE } from "components/ReportCollection" import SubNav from "components/SubNav" import { Field, Form, Formik } from "formik" @@ -379,6 +380,7 @@ const BaseOrganizationShow = ({ pageDispatchers, currentUser }) => { paginationKey={`r_${uuid}`} queryParams={reportQueryParams} viewFormats={[ + FORMAT_STATISTICS, FORMAT_CALENDAR, FORMAT_SUMMARY, FORMAT_TABLE, From ec0f23fdb1ae9b8cdc5af9367d55209b45d9d710 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 13 May 2020 17:11:38 +0200 Subject: [PATCH 071/247] NCI-Agency/anet#2971: Implement report statistics on org page --- anet.yml | 10 + client/src/components/ReportCollection.js | 38 ++++ client/src/components/ReportStatistics.js | 188 ++++++++++++++++++ .../assessments/AssessmentResultsContainer.js | 2 +- .../assessments/AssessmentResultsTable.js | 25 +-- .../assessments/PeriodicAssessment.js | 4 +- client/src/components/assessments/utils.js | 5 + client/src/pages/organizations/Show.js | 6 +- client/src/periodUtils.js | 64 ++++++ 9 files changed, 319 insertions(+), 23 deletions(-) create mode 100644 client/src/components/ReportStatistics.js create mode 100644 client/src/periodUtils.js diff --git a/anet.yml b/anet.yml index 29f9d50f3e..69412edc1e 100644 --- a/anet.yml +++ b/anet.yml @@ -385,6 +385,8 @@ dictionary: label: Assist other: label: Other + aggregation: + widget: default trainingEvent: type: enum label: Training event @@ -394,6 +396,8 @@ dictionary: label: "Yes" NO: label: "No" + aggregation: + widget: default numberTrained: type: number typeError: Number trained must be a number @@ -404,6 +408,8 @@ dictionary: - type: min params: [1] visibleWhen: $[?(@.multipleButtons && @.multipleButtons.indexOf('train') != -1)] + aggregation: + widget: default levelTrained: type: special_field widget: likertScale @@ -420,6 +426,8 @@ dictionary: - color: lightGray endValue: 10 label: advanced advanced advanced advanced + aggregation: + widget: likertScale systemProcess: type: enum label: System / process @@ -429,6 +437,8 @@ dictionary: label: System NO: label: Process + aggregation: + widget: default echelons: type: text label: Issue echelon to fix diff --git a/client/src/components/ReportCollection.js b/client/src/components/ReportCollection.js index 013a87c922..d074967f34 100644 --- a/client/src/components/ReportCollection.js +++ b/client/src/components/ReportCollection.js @@ -1,4 +1,5 @@ import { setPagination } from "actions" +import { ASSESSMENT_PERIOD_FACTORIES } from "components/assessments/AssessmentResultsContainer" import ButtonToggleGroup from "components/ButtonToggleGroup" import { PageDispatchersPropType, @@ -6,8 +7,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 moment from "moment" import PropTypes from "prop-types" import React, { useState } from "react" import { Button } from "react-bootstrap" @@ -17,6 +20,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,6 +38,8 @@ const ReportCollection = ({ }) => { const [viewFormat, setViewFormat] = useState(viewFormats[0]) const showHeader = viewFormats.length > 1 || reportsFilter + const statisticsRecurrence = ["monthly"] + const now = moment() return (
@@ -58,6 +64,9 @@ const ReportCollection = ({ {viewFormats.includes(FORMAT_MAP) && ( )} + {viewFormats.includes(FORMAT_STATISTICS) && ( + + )} )} @@ -107,6 +116,35 @@ const ReportCollection = ({ marginBottom={marginBottom} /> )} + {viewFormat === FORMAT_STATISTICS && statisticsRecurrence.length && ( + <> + {statisticsRecurrence.map(recurrence => ( + + ))} + + )}
diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js new file mode 100644 index 0000000000..e1bb452599 --- /dev/null +++ b/client/src/components/ReportStatistics.js @@ -0,0 +1,188 @@ +import AggregationWidget from "components/AggregationWidget" +import API, { Settings } from "api" +import { gql } from "apollo-boost" +import { getFieldPropsFromFieldConfig } from "components/CustomFields" +import { PageDispatchersPropType, useBoilerplate } from "components/Page" +import _get from "lodash/get" +import { Report } from "models" +import { + PeriodsConfigPropType, + PeriodsPropType, + PeriodsTableHeader +} from "periodUtils" +import PropTypes from "prop-types" +import React, { useEffect } from "react" +import { Table } from "react-bootstrap" + +const REPORT_FIELDS_FOR_STATISTICS = { + state: { + aggregation: { widget: "default" }, + label: "State" + }, + atmosphere: { + aggregation: { widget: "default" }, + label: Settings.fields.report.atmosphere + } +} + +const GQL_GET_REPORT_LIST = gql` + query($reportQuery: ReportSearchQueryInput) { + reportList(query: $reportQuery) { + pageNum + pageSize + totalCount + list { + uuid + intent + engagementDate + atmosphere + state + customFields + } + } + } +` + +const FieldStatisticsRow = ({ + fieldConfig, + fieldKey, + periods, + periodsData +}) => { + if (!fieldConfig.aggregation) { + return null + } + const aggWidgetProps = { + widget: fieldConfig.aggregation.widget || fieldConfig.widget, + aggregationType: fieldConfig.aggregation.aggregationType, + vertical: true + } + const fieldProps = getFieldPropsFromFieldConfig(fieldConfig) + return ( + + {periods.map((period, index) => ( + + + + ))} + + ) +} +FieldStatisticsRow.propTypes = { + fieldConfig: PropTypes.object, + fieldKey: PropTypes.string, + periods: PeriodsPropType, + periodsData: PropTypes.array +} + +const ReportStatistics = ({ + pageDispatchers, + periodsConfig, + setTotalCount, + queryParams +}) => { + const reportQuery = Object.assign({}, queryParams, { pageSize: 0 }) + 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 + } + + const reports = data ? Report.fromArray(data.reportList.list) : [] + if (_get(reports, "length", 0) === 0) { + return No reports found + } + + const customFieldsConfig = Settings.fields.report.customFields + + const getPeriodStatistics = (reports, dateRange) => { + const reportsForDateRange = reports.filter( + elem => + elem.engagementDate <= dateRange.end && + elem.engagementDate >= dateRange.start + ) + reportsForDateRange.map( + report => (report.customFieldsJson = JSON.parse(report.customFields)) + ) + const periodStatistics = {} + reportsForDateRange.forEach(report => { + const customFieldsValues = report.customFieldsJson + if (customFieldsValues && typeof customFieldsValues === "object") { + // TODO: make the key custom fields specific, to make sure we don't have both a normal as a custom field with the same name + Object.keys(customFieldsConfig).forEach(key => { + if (!Object.prototype.hasOwnProperty.call(periodStatistics, key)) { + periodStatistics[key] = [] + } + periodStatistics[key].push(Object.get(customFieldsValues, key)) + }) + } + // TODO: combine with above to reduce code duplication + Object.keys(REPORT_FIELDS_FOR_STATISTICS).forEach(key => { + if (!Object.prototype.hasOwnProperty.call(periodStatistics, key)) { + periodStatistics[key] = [] + } + periodStatistics[key].push(report[key]) + }) + }) + return periodStatistics + } + const { periods } = periodsConfig + const periodsStatistics = [] + periodsConfig.periods.forEach(period => + periodsStatistics.push(getPeriodStatistics(reports, period)) + ) + + return ( + + + + <> + {Object.keys(REPORT_FIELDS_FOR_STATISTICS || {}).map(key => ( + + ))} + {Object.keys(customFieldsConfig || {}).map(key => ( + + ))} + + +
+ ) +} + +ReportStatistics.propTypes = { + pageDispatchers: PageDispatchersPropType, + periodsConfig: PeriodsConfigPropType, + setTotalCount: PropTypes.func, + queryParams: PropTypes.object +} + +export default ReportStatistics diff --git a/client/src/components/assessments/AssessmentResultsContainer.js b/client/src/components/assessments/AssessmentResultsContainer.js index 02a0696fc2..b2a5beb701 100644 --- a/client/src/components/assessments/AssessmentResultsContainer.js +++ b/client/src/components/assessments/AssessmentResultsContainer.js @@ -6,7 +6,7 @@ import React from "react" const now = moment() -const ASSESSMENT_PERIOD_FACTORIES = { +export const ASSESSMENT_PERIOD_FACTORIES = { [ASSESSMENTS_RECURRENCE_TYPE.DAILY]: (date, offset) => ({ start: date.clone().subtract(offset, "days").startOf("day"), end: date.clone().subtract(offset, "days").endOf("day") diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index 8810c51ec0..10a1dc28e2 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -2,13 +2,17 @@ import AggregationWidget from "components/AggregationWidget" import AppContext from "components/AppContext" import AssessmentModal from "components/assessments/AssessmentModal" import PeriodicAssessment from "components/assessments/PeriodicAssessment" -import { PeriodPropType, periodToString } from "components/assessments/utils" import { getFieldPropsFromFieldConfig } from "components/CustomFields" import Fieldset from "components/Fieldset" import LinkTo from "components/LinkTo" import { NOTE_TYPE } from "components/Model" import { Person } from "models" import _isEmpty from "lodash/isEmpty" +import { + AssessmentPeriodPropType, + PeriodsTableHeader, + periodToString +} from "periodUtils" import PropTypes from "prop-types" import React, { useState } from "react" import { Button, Table } from "react-bootstrap" @@ -28,27 +32,12 @@ import "components/assessments/AssessmentResultsTable.css" * entity.getPeriodicAssessmentDetails(recurrence) */ -const PeriodsPropType = PropTypes.arrayOf(PeriodPropType) +const PeriodsPropType = PropTypes.arrayOf(AssessmentPeriodPropType) const PeriodsConfigPropType = PropTypes.shape({ recurrence: PropTypes.string, periods: PeriodsPropType }) -const AssessmentsTableHeader = ({ periodsConfig }) => ( - - - <> - {periodsConfig.periods.map(period => ( - {periodToString(period)} - ))} - - - -) -AssessmentsTableHeader.propTypes = { - periodsConfig: PeriodsConfigPropType -} - const InstantAssessmentRow = ({ questionKey, questionConfig, @@ -303,7 +292,7 @@ const AssessmentResultsTable = ({ id={`"entity-assessments-results-${recurrence}`} > - + {!_isEmpty(subEntities) && ( <> diff --git a/client/src/components/assessments/PeriodicAssessment.js b/client/src/components/assessments/PeriodicAssessment.js index f8aba72138..e934677f07 100644 --- a/client/src/components/assessments/PeriodicAssessment.js +++ b/client/src/components/assessments/PeriodicAssessment.js @@ -2,13 +2,13 @@ import { Icon } from "@blueprintjs/core" import { IconNames } from "@blueprintjs/icons" import AppContext from "components/AppContext" import AssessmentModal from "components/assessments/AssessmentModal" -import { PeriodPropType, periodToString } from "components/assessments/utils" import { ReadonlyCustomFields } from "components/CustomFields" import { Formik } from "formik" import LinkTo from "components/LinkTo" import Model from "components/Model" import { Person } from "models" import moment from "moment" +import { AssessmentPeriodPropType, periodToString } from "periodUtils" import PropTypes from "prop-types" import React, { useState } from "react" import { Button, Panel } from "react-bootstrap" @@ -117,7 +117,7 @@ BasePeriodicAssessment.propTypes = { assessmentYupSchema: PropTypes.object.isRequired, note: Model.notePropTypes.isRequired, entity: PropTypes.object.isRequired, - period: PeriodPropType.isRequired, + period: AssessmentPeriodPropType.isRequired, recurrence: PropTypes.string.isRequired, onUpdateAssessment: PropTypes.func, currentUser: PropTypes.instanceOf(Person) diff --git a/client/src/components/assessments/utils.js b/client/src/components/assessments/utils.js index 0b95b6c541..d4ca1d7c65 100644 --- a/client/src/components/assessments/utils.js +++ b/client/src/components/assessments/utils.js @@ -22,6 +22,11 @@ export const periodToString = period => { } export const PeriodPropType = PropTypes.shape({ + start: PropTypes.object, + end: PropTypes.object +}) + +export const AssessmentPeriodPropType = PropTypes.shape({ start: PropTypes.object, end: PropTypes.object, allowNewAssessments: PropTypes.bool diff --git a/client/src/pages/organizations/Show.js b/client/src/pages/organizations/Show.js index 9b2e62d693..77f4b5f06b 100644 --- a/client/src/pages/organizations/Show.js +++ b/client/src/pages/organizations/Show.js @@ -18,10 +18,11 @@ import RelatedObjectNotes, { GRAPHQL_NOTES_FIELDS } from "components/RelatedObjectNotes" import ReportCollection, { + FORMAT_CALENDAR, FORMAT_MAP, + FORMAT_STATISTICS, FORMAT_SUMMARY, - FORMAT_TABLE, - FORMAT_CALENDAR + FORMAT_TABLE } from "components/ReportCollection" import SubNav from "components/SubNav" import { Field, Form, Formik } from "formik" @@ -379,6 +380,7 @@ const BaseOrganizationShow = ({ pageDispatchers, currentUser }) => { paginationKey={`r_${uuid}`} queryParams={reportQueryParams} viewFormats={[ + FORMAT_STATISTICS, FORMAT_CALENDAR, FORMAT_SUMMARY, FORMAT_TABLE, diff --git a/client/src/periodUtils.js b/client/src/periodUtils.js new file mode 100644 index 0000000000..c9ccecc3fb --- /dev/null +++ b/client/src/periodUtils.js @@ -0,0 +1,64 @@ +import PropTypes from "prop-types" +import React from "react" + +export const PeriodPropType = PropTypes.shape({ + start: PropTypes.object, + end: PropTypes.object +}) +export const AssessmentPeriodPropType = PropTypes.shape({ + start: PropTypes.object, + end: PropTypes.object, + allowNewAssessments: PropTypes.bool +}) + +export const PeriodsPropType = PropTypes.arrayOf(PeriodPropType) +export const PeriodsConfigPropType = PropTypes.shape({ + recurrence: PropTypes.string, + periods: PeriodsPropType +}) +export const AssessmentPeriodsPropType = PropTypes.arrayOf( + AssessmentPeriodPropType +) +export const AssessmentPeriodsConfigPropType = PropTypes.shape({ + recurrence: PropTypes.string, + periods: AssessmentPeriodsPropType +}) + +const PERIOD_START_SHORT_FORMAT = "D" +const PERIOD_START_MIDDLE_FORMAT = "D MMMM" +const PERIOD_START_LONG_FORMAT = "D MMMM YYYY" +const PERIOD_END_FORMAT = "D MMMM YYYY" + +export const periodToString = period => { + if (period.start.isSame(period.end, "day")) { + return period.end.format(PERIOD_END_FORMAT) + } else { + const periodStartFormat = + period.start.year() !== period.end.year() + ? PERIOD_START_LONG_FORMAT + : period.start.month() !== period.end.month() + ? PERIOD_START_MIDDLE_FORMAT + : PERIOD_START_SHORT_FORMAT + return `${period.start.format(periodStartFormat)} - ${period.end.format( + PERIOD_END_FORMAT + )}` + } +} + +export const PeriodsTableHeader = ({ periodsConfig }) => ( + + + <> + {periodsConfig.periods.map(period => ( + + ))} + + + +) +PeriodsTableHeader.propTypes = { + periodsConfig: PropTypes.oneOfType([ + AssessmentPeriodsConfigPropType, + PeriodsConfigPropType + ]) +} From ff7ebb5acbf66b0f54a6bc3b45c657e2aa4ff37d Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 14 May 2020 23:12:32 +0200 Subject: [PATCH 072/247] NCI-Agency/anet#2971: Update ReportStatistics This makes the ReportStatistics more genric, and prepared for also using more complex aggregations next to ListAggregations. Note: Started implementation of ReportsByTaskAggregation as an example, but the BarChart is ending in an endless loop somehow. --- client/src/components/ReportStatistics.js | 111 +++++++++--------- .../aggregations/ListAggregation.js | 29 +++++ .../aggregations/ReportsByTaskAggregation.js | 66 +++++++++++ 3 files changed, 148 insertions(+), 58 deletions(-) create mode 100644 client/src/components/aggregations/ListAggregation.js create mode 100644 client/src/components/aggregations/ReportsByTaskAggregation.js diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index e1bb452599..fa99320ea5 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -1,14 +1,16 @@ -import AggregationWidget from "components/AggregationWidget" +/* eslint-disable */ import API, { Settings } from "api" import { gql } from "apollo-boost" -import { getFieldPropsFromFieldConfig } from "components/CustomFields" import { PageDispatchersPropType, useBoilerplate } from "components/Page" +import ListAggregation from "components/aggregations/ListAggregation" +import ReportsByTaskAggregation from "components/aggregations/ReportsByTaskAggregation" import _get from "lodash/get" import { Report } from "models" +import pluralize from "pluralize" import { PeriodsConfigPropType, PeriodsPropType, - PeriodsTableHeader + PeriodsTableHeader, } from "periodUtils" import PropTypes from "prop-types" import React, { useEffect } from "react" @@ -17,12 +19,17 @@ import { Table } from "react-bootstrap" const REPORT_FIELDS_FOR_STATISTICS = { state: { aggregation: { widget: "default" }, - label: "State" + label: "State", }, atmosphere: { aggregation: { widget: "default" }, - label: Settings.fields.report.atmosphere - } + label: Settings.fields.report.atmosphere, + }, + // TODO: right not the bar chart ends in an endless loop + // tasks: { + // aggregation: { widget: "reportsByTask" }, + // label: pluralize(Settings.fields.task.subLevel.shortLabel) + // } } const GQL_GET_REPORT_LIST = gql` @@ -37,36 +44,44 @@ const GQL_GET_REPORT_LIST = gql` engagementDate atmosphere state + tasks { + uuid + shortName + } customFields } } } ` +// TODO: Move this in a more general aggregations related file +const AGGREGATIONS = { + likertScale: ListAggregation, + numberAggregation: ListAggregation, + reportsByTask: ReportsByTaskAggregation, + default: ListAggregation, +} + const FieldStatisticsRow = ({ fieldConfig, - fieldKey, + fieldName, periods, - periodsData + periodsData, }) => { if (!fieldConfig.aggregation) { return null } - const aggWidgetProps = { - widget: fieldConfig.aggregation.widget || fieldConfig.widget, - aggregationType: fieldConfig.aggregation.aggregationType, - vertical: true - } - const fieldProps = getFieldPropsFromFieldConfig(fieldConfig) + const AggregationComponent = + AGGREGATIONS[fieldConfig.aggregation.widget || fieldConfig.widget] return ( {periods.map((period, index) => ( ))} @@ -75,31 +90,31 @@ const FieldStatisticsRow = ({ } FieldStatisticsRow.propTypes = { fieldConfig: PropTypes.object, - fieldKey: PropTypes.string, + fieldName: PropTypes.string, periods: PeriodsPropType, - periodsData: PropTypes.array + periodsData: PropTypes.arrayOf(PropTypes.array), } const ReportStatistics = ({ pageDispatchers, periodsConfig, setTotalCount, - queryParams + queryParams, }) => { const reportQuery = Object.assign({}, queryParams, { pageSize: 0 }) const { loading, error, data } = API.useApiQuery(GQL_GET_REPORT_LIST, { - reportQuery + reportQuery, }) const { done, result } = useBoilerplate({ loading, error, - pageDispatchers + pageDispatchers, }) // Update the total count const totalCount = done ? null : data?.reportList?.totalCount useEffect(() => setTotalCount && setTotalCount(totalCount), [ setTotalCount, - totalCount + totalCount, ]) if (done) { return result @@ -109,46 +124,26 @@ const ReportStatistics = ({ if (_get(reports, "length", 0) === 0) { return No reports found } - - const customFieldsConfig = Settings.fields.report.customFields - - const getPeriodStatistics = (reports, dateRange) => { + 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.customFieldsJson = JSON.parse(report.customFields)) + report => (report[CUSTOM_FIELDS_KEY] = JSON.parse(report.customFields)) ) - const periodStatistics = {} - reportsForDateRange.forEach(report => { - const customFieldsValues = report.customFieldsJson - if (customFieldsValues && typeof customFieldsValues === "object") { - // TODO: make the key custom fields specific, to make sure we don't have both a normal as a custom field with the same name - Object.keys(customFieldsConfig).forEach(key => { - if (!Object.prototype.hasOwnProperty.call(periodStatistics, key)) { - periodStatistics[key] = [] - } - periodStatistics[key].push(Object.get(customFieldsValues, key)) - }) - } - // TODO: combine with above to reduce code duplication - Object.keys(REPORT_FIELDS_FOR_STATISTICS).forEach(key => { - if (!Object.prototype.hasOwnProperty.call(periodStatistics, key)) { - periodStatistics[key] = [] - } - periodStatistics[key].push(report[key]) - }) - }) - return periodStatistics + return reportsForDateRange } const { periods } = periodsConfig - const periodsStatistics = [] + const dataPerPeriod = [] periodsConfig.periods.forEach(period => - periodsStatistics.push(getPeriodStatistics(reports, period)) + dataPerPeriod.push(getPeriodData(reports, period)) ) + const customFieldsConfig = Settings.fields.report.customFields + return (
{periodToString(period)}
-
@@ -157,19 +152,19 @@ const ReportStatistics = ({ {Object.keys(REPORT_FIELDS_FOR_STATISTICS || {}).map(key => ( ))} {Object.keys(customFieldsConfig || {}).map(key => ( ))} @@ -182,7 +177,7 @@ ReportStatistics.propTypes = { pageDispatchers: PageDispatchersPropType, periodsConfig: PeriodsConfigPropType, setTotalCount: PropTypes.func, - queryParams: PropTypes.object + queryParams: PropTypes.object, } export default ReportStatistics diff --git a/client/src/components/aggregations/ListAggregation.js b/client/src/components/aggregations/ListAggregation.js new file mode 100644 index 0000000000..4b16452760 --- /dev/null +++ b/client/src/components/aggregations/ListAggregation.js @@ -0,0 +1,29 @@ +import AggregationWidget from "components/AggregationWidget" +import { getFieldPropsFromFieldConfig } from "components/CustomFields" +import PropTypes from "prop-types" +import React from "react" + +const ListAggregation = ({ fieldName, fieldConfig, data }) => { + const values = data.map(item => Object.get(item, fieldName)) + const aggWidgetProps = { + widget: fieldConfig.aggregation?.widget || fieldConfig.widget, + aggregationType: fieldConfig.aggregation?.aggregationType, + vertical: true + } + const fieldProps = getFieldPropsFromFieldConfig(fieldConfig) + return ( + + ) +} +ListAggregation.propTypes = { + data: PropTypes.array, + fieldName: PropTypes.string, + fieldConfig: PropTypes.object +} + +export default ListAggregation diff --git a/client/src/components/aggregations/ReportsByTaskAggregation.js b/client/src/components/aggregations/ReportsByTaskAggregation.js new file mode 100644 index 0000000000..974303213a --- /dev/null +++ b/client/src/components/aggregations/ReportsByTaskAggregation.js @@ -0,0 +1,66 @@ +import { Settings } from "api" +import AggregationWidget from "components/AggregationWidget" +import { getFieldPropsFromFieldConfig } from "components/CustomFields" +import PropTypes from "prop-types" +import React from "react" + +const noTaskMessage = `No ${Settings.fields.task.subLevel.shortLabel}` +const noTask = { + uuid: "-1", + shortName: noTaskMessage, + longName: noTaskMessage +} + +// TODO: use it also in components/ReportsByTasks +const getReportsByTasks = reportsList => { + 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 + }) +} + +const ReportsByTaskAggregation = ({ fieldName, fieldConfig, data }) => { + const values = getReportsByTasks(data) + const aggWidgetProps = { + widget: fieldConfig.aggregation?.widget || fieldConfig.widget, + aggregationType: fieldConfig.aggregation?.aggregationType, + vertical: true + } + const fieldProps = getFieldPropsFromFieldConfig(fieldConfig) + return ( + + ) +} +ReportsByTaskAggregation.propTypes = { + data: PropTypes.array, + fieldName: PropTypes.string, + fieldConfig: PropTypes.object +} + +export default ReportsByTaskAggregation From 4df9d811f4315f4a00bf307b5716f06f46081255 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Mon, 18 May 2020 15:58:57 +0200 Subject: [PATCH 073/247] NCI-Agency/anet#2971: Add CountPerValue type of aggregation This makes it possible to aggregate report fields data by doing a count per value and displaying this in a pie aggregation widget. --- anet.yml | 2 +- client/src/components/AggregationWidget.js | 79 ++++++++++++++++++- client/src/components/ReportStatistics.js | 67 ++++++++++------ .../advancedSearch/ReportStateFilter.js | 14 +--- .../aggregations/CountPerValueAggregation.js | 74 +++++++++++++++++ ...ggregation.js => ValuesListAggregation.js} | 6 +- client/src/components/aggregations/utils.js | 11 +++ client/src/models/Report.js | 9 +++ src/main/resources/anet-schema.yml | 4 +- 9 files changed, 220 insertions(+), 46 deletions(-) create mode 100644 client/src/components/aggregations/CountPerValueAggregation.js rename client/src/components/aggregations/{ListAggregation.js => ValuesListAggregation.js} (83%) create mode 100644 client/src/components/aggregations/utils.js diff --git a/anet.yml b/anet.yml index 69412edc1e..194479e27e 100644 --- a/anet.yml +++ b/anet.yml @@ -386,7 +386,7 @@ dictionary: other: label: Other aggregation: - widget: default + widget: countPerValue trainingEvent: type: enum label: Training event diff --git a/client/src/components/AggregationWidget.js b/client/src/components/AggregationWidget.js index bccb6732db..18b67ac6bf 100644 --- a/client/src/components/AggregationWidget.js +++ b/client/src/components/AggregationWidget.js @@ -1,12 +1,24 @@ +import BarChart from "components/BarChart" import LikertScale from "components/graphs/LikertScale" +import Pie from "components/graphs/Pie" +import _uniqueId from "lodash/uniqueId" import PropTypes from "prop-types" import React from "react" import { Col, ControlLabel, FormGroup } from "react-bootstrap" +import ContainerDimensions from "react-container-dimensions" const aggregationPropTypes = { - values: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.array]) - ), + values: PropTypes.oneOfType([ + PropTypes.object, + PropTypes.arrayOf( + PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number, + PropTypes.array, + PropTypes.object + ]) + ) + ]), aggregationType: PropTypes.string } @@ -26,6 +38,65 @@ const NumberAggWidget = ({ values, aggregationType, ...otherWidgetProps }) => ) : null NumberAggWidget.propTypes = aggregationPropTypes +const PieWidget = ({ + values, + aggregationType, + legend, + ...otherWidgetProps +}) => { + return ( + <> + acc + cur, 0)} + segmentFill={entity => legend[entity.data.key]?.color} + segmentLabel={d => d.data.value} + /> +
+ {Object.map(legend, (key, choice) => ( + + {choice.label} + + ))} + + ) +} +PieWidget.propTypes = { + legend: PropTypes.object, + ...aggregationPropTypes +} + +const ReportsByTaskWidget = ({ + values, + aggregationType, + ...otherWidgetProps +}) => { + return ( +
+ + {({ width, height }) => ( + ` +

${d.task.shortName}

+

${d.reportsCount}

+ `} + /> + )} +
+
+ ) +} +ReportsByTaskWidget.propTypes = aggregationPropTypes + const DefaultAggWidget = ({ values, ...otherWidgetProps }) => (
{`[${values}]`}
) @@ -34,6 +105,8 @@ DefaultAggWidget.propTypes = aggregationPropTypes const WIDGETS = { likertScale: LikertScale, numberAggregation: NumberAggWidget, + reportsByTask: ReportsByTaskWidget, + countPerValue: PieWidget, default: DefaultAggWidget } diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index fa99320ea5..9472d098a2 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -1,16 +1,13 @@ -/* eslint-disable */ import API, { Settings } from "api" import { gql } from "apollo-boost" +import { WIDGET_AGGREGATIONS } from "components/aggregations/utils" import { PageDispatchersPropType, useBoilerplate } from "components/Page" -import ListAggregation from "components/aggregations/ListAggregation" -import ReportsByTaskAggregation from "components/aggregations/ReportsByTaskAggregation" import _get from "lodash/get" import { Report } from "models" -import pluralize from "pluralize" import { PeriodsConfigPropType, PeriodsPropType, - PeriodsTableHeader, + PeriodsTableHeader } from "periodUtils" import PropTypes from "prop-types" import React, { useEffect } from "react" @@ -18,14 +15,40 @@ import { Table } from "react-bootstrap" const REPORT_FIELDS_FOR_STATISTICS = { state: { - aggregation: { widget: "default" }, + aggregation: { widget: "countPerValue" }, label: "State", + choices: { + [Report.STATE.DRAFT]: { + label: Report.STATE_LABELS[Report.STATE.DRAFT], + color: "#bdbdaf" + }, + [Report.STATE.PENDING_APPROVAL]: { + label: Report.STATE_LABELS[Report.STATE.PENDING_APPROVAL], + color: "#848478" + }, + [Report.STATE.APPROVED]: { + label: Report.STATE_LABELS[Report.STATE.APPROVED], + color: "#75eb75" + }, + [Report.STATE.PUBLISHED]: { + label: Report.STATE_LABELS[Report.STATE.PUBLISHED], + color: "#5cb85c" + }, + [Report.STATE.CANCELLED]: { + label: Report.STATE_LABELS[Report.STATE.CANCELLED], + color: "#ec971f" + }, + [Report.STATE.REJECTED]: { + label: Report.STATE_LABELS[Report.STATE.REJECTED], + color: "#c23030" + } + } }, atmosphere: { - aggregation: { widget: "default" }, - label: Settings.fields.report.atmosphere, - }, - // TODO: right not the bar chart ends in an endless loop + aggregation: { widget: "countPerValue" }, + label: Settings.fields.report.atmosphere + } + // FIXME: right not the bar chart ends in an endless loop // tasks: { // aggregation: { widget: "reportsByTask" }, // label: pluralize(Settings.fields.task.subLevel.shortLabel) @@ -54,25 +77,17 @@ const GQL_GET_REPORT_LIST = gql` } ` -// TODO: Move this in a more general aggregations related file -const AGGREGATIONS = { - likertScale: ListAggregation, - numberAggregation: ListAggregation, - reportsByTask: ReportsByTaskAggregation, - default: ListAggregation, -} - const FieldStatisticsRow = ({ fieldConfig, fieldName, periods, - periodsData, + periodsData }) => { if (!fieldConfig.aggregation) { return null } const AggregationComponent = - AGGREGATIONS[fieldConfig.aggregation.widget || fieldConfig.widget] + WIDGET_AGGREGATIONS[fieldConfig.aggregation.widget || fieldConfig.widget] return (
{periods.map((period, index) => ( @@ -92,29 +107,29 @@ FieldStatisticsRow.propTypes = { fieldConfig: PropTypes.object, fieldName: PropTypes.string, periods: PeriodsPropType, - periodsData: PropTypes.arrayOf(PropTypes.array), + periodsData: PropTypes.arrayOf(PropTypes.array) } const ReportStatistics = ({ pageDispatchers, periodsConfig, setTotalCount, - queryParams, + queryParams }) => { const reportQuery = Object.assign({}, queryParams, { pageSize: 0 }) const { loading, error, data } = API.useApiQuery(GQL_GET_REPORT_LIST, { - reportQuery, + reportQuery }) const { done, result } = useBoilerplate({ loading, error, - pageDispatchers, + pageDispatchers }) // Update the total count const totalCount = done ? null : data?.reportList?.totalCount useEffect(() => setTotalCount && setTotalCount(totalCount), [ setTotalCount, - totalCount, + totalCount ]) if (done) { return result @@ -177,7 +192,7 @@ ReportStatistics.propTypes = { pageDispatchers: PageDispatchersPropType, periodsConfig: PeriodsConfigPropType, setTotalCount: PropTypes.func, - queryParams: PropTypes.object, + queryParams: PropTypes.object } export default ReportStatistics 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/aggregations/CountPerValueAggregation.js b/client/src/components/aggregations/CountPerValueAggregation.js new file mode 100644 index 0000000000..d32d215d3c --- /dev/null +++ b/client/src/components/aggregations/CountPerValueAggregation.js @@ -0,0 +1,74 @@ +import AggregationWidget from "components/AggregationWidget" +import { getFieldPropsFromFieldConfig } from "components/CustomFields" +import _clone from "lodash/clone" +import _isEmpty from "lodash/isEmpty" +import PropTypes from "prop-types" +import React from "react" + +// TODO: maybe use a library for a list of colors +const CHART_COLORS = [ + "#3366CC", + "#DC3912", + "#FF9900", + "#109618", + "#990099", + "#3B3EAC", + "#0099C6", + "#DD4477", + "#66AA00", + "#B82E2E", + "#316395", + "#994499", + "#22AA99", + "#AAAA11", + "#6633CC", + "#E67300", + "#8B0707", + "#329262", + "#5574A6", + "#3B3EAC" +] +const CountPerValueAggregation = ({ fieldName, fieldConfig, data }) => { + const counters = data.reduce((counter, entity) => { + const value = Object.get(entity, fieldName) + counter[value] = ++counter[value] || 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.pop() + }) + ) + legend.null = { label: "Unspecified", color: "#bbbbbb" } + + const aggWidgetProps = { + widget: fieldConfig.aggregation?.widget || fieldConfig.widget, + aggregationType: fieldConfig.aggregation?.aggregationType, + vertical: true + } + const fieldProps = getFieldPropsFromFieldConfig(fieldConfig) + return ( + + ) +} +CountPerValueAggregation.propTypes = { + data: PropTypes.array, + fieldName: PropTypes.string, + fieldConfig: PropTypes.object +} + +export default CountPerValueAggregation diff --git a/client/src/components/aggregations/ListAggregation.js b/client/src/components/aggregations/ValuesListAggregation.js similarity index 83% rename from client/src/components/aggregations/ListAggregation.js rename to client/src/components/aggregations/ValuesListAggregation.js index 4b16452760..a3676d60da 100644 --- a/client/src/components/aggregations/ListAggregation.js +++ b/client/src/components/aggregations/ValuesListAggregation.js @@ -3,7 +3,7 @@ import { getFieldPropsFromFieldConfig } from "components/CustomFields" import PropTypes from "prop-types" import React from "react" -const ListAggregation = ({ fieldName, fieldConfig, data }) => { +const ValuesListAggregation = ({ fieldName, fieldConfig, data }) => { const values = data.map(item => Object.get(item, fieldName)) const aggWidgetProps = { widget: fieldConfig.aggregation?.widget || fieldConfig.widget, @@ -20,10 +20,10 @@ const ListAggregation = ({ fieldName, fieldConfig, data }) => { /> ) } -ListAggregation.propTypes = { +ValuesListAggregation.propTypes = { data: PropTypes.array, fieldName: PropTypes.string, fieldConfig: PropTypes.object } -export default ListAggregation +export default ValuesListAggregation diff --git a/client/src/components/aggregations/utils.js b/client/src/components/aggregations/utils.js new file mode 100644 index 0000000000..42938e92e3 --- /dev/null +++ b/client/src/components/aggregations/utils.js @@ -0,0 +1,11 @@ +import ValuesListAggregation from "components/aggregations/ValuesListAggregation" +import ReportsByTaskAggregation from "components/aggregations/ReportsByTaskAggregation" +import CountPerValueAggregation from "components/aggregations/CountPerValueAggregation" + +export const WIDGET_AGGREGATIONS = { + likertScale: ValuesListAggregation, + numberAggregation: ValuesListAggregation, + countPerValue: CountPerValueAggregation, + reportsByTask: ReportsByTaskAggregation, + default: ValuesListAggregation +} diff --git a/client/src/models/Report.js b/client/src/models/Report.js index f8d5ae3105..103115340d 100644 --- a/client/src/models/Report.js +++ b/client/src/models/Report.js @@ -26,6 +26,15 @@ 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 ENGAGEMENT_STATUS = { HAPPENED: "HAPPENED", FUTURE: "FUTURE", diff --git a/src/main/resources/anet-schema.yml b/src/main/resources/anet-schema.yml index 31c9d15aa3..e20a888f4b 100644 --- a/src/main/resources/anet-schema.yml +++ b/src/main/resources/anet-schema.yml @@ -99,13 +99,13 @@ definitions: properties: widget: type: string - enum: [likertScale, numberAggregation, default] + enum: [likertScale, numberAggregation, countPerValue, default] dependencies: widget: oneOf: - properties: widget: - enum: [likertScale, default] + enum: [likertScale, countPerValue, default] - properties: type: enum: [numberAggregation] From f631ee1e7bf6a41edbe51a2a75a0ae9844a6ed90 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Mon, 18 May 2020 17:48:01 +0200 Subject: [PATCH 074/247] NCI-Agency/anet#2971: Fix ReportsReportsByTaskWidget It was ending in an andless loop. --- client/src/components/AggregationWidget.js | 29 ++++++++-------------- client/src/components/ReportStatistics.js | 11 ++++---- 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/client/src/components/AggregationWidget.js b/client/src/components/AggregationWidget.js index 18b67ac6bf..24282d4118 100644 --- a/client/src/components/AggregationWidget.js +++ b/client/src/components/AggregationWidget.js @@ -5,7 +5,6 @@ import _uniqueId from "lodash/uniqueId" import PropTypes from "prop-types" import React from "react" import { Col, ControlLabel, FormGroup } from "react-bootstrap" -import ContainerDimensions from "react-container-dimensions" const aggregationPropTypes = { values: PropTypes.oneOfType([ @@ -75,23 +74,17 @@ const ReportsByTaskWidget = ({ }) => { return (
- - {({ width, height }) => ( - ` -

${d.task.shortName}

-

${d.reportsCount}

- `} - /> - )} -
+ ` +

${d.task.shortName}

+

${d.reportsCount}

+ `} + />
) } diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index 9472d098a2..7029a4e572 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -9,6 +9,7 @@ import { PeriodsPropType, PeriodsTableHeader } from "periodUtils" +import pluralize from "pluralize" import PropTypes from "prop-types" import React, { useEffect } from "react" import { Table } from "react-bootstrap" @@ -47,12 +48,12 @@ const REPORT_FIELDS_FOR_STATISTICS = { atmosphere: { aggregation: { widget: "countPerValue" }, label: Settings.fields.report.atmosphere - } + }, // FIXME: right not the bar chart ends in an endless loop - // tasks: { - // aggregation: { widget: "reportsByTask" }, - // label: pluralize(Settings.fields.task.subLevel.shortLabel) - // } + tasks: { + aggregation: { widget: "reportsByTask" }, + label: pluralize(Settings.fields.task.subLevel.shortLabel) + } } const GQL_GET_REPORT_LIST = gql` From 19ab0b7ebe4d7072662a779a30b9ed231e0e4013 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 19 May 2020 12:08:24 +0200 Subject: [PATCH 075/247] NCI-Agency/anet#2971: Code refactoring AggregationWidget Reduce code duplication and use beter naming of variables. --- client/src/components/AggregationWidget.js | 31 ++++++++++--------- .../aggregations/CountPerValueAggregation.js | 10 +----- .../aggregations/ReportsByTaskAggregation.js | 10 +----- .../aggregations/ValuesListAggregation.js | 10 +----- .../assessments/AssessmentResultsTable.js | 10 +----- 5 files changed, 20 insertions(+), 51 deletions(-) diff --git a/client/src/components/AggregationWidget.js b/client/src/components/AggregationWidget.js index 24282d4118..e4b8d58bb4 100644 --- a/client/src/components/AggregationWidget.js +++ b/client/src/components/AggregationWidget.js @@ -1,4 +1,5 @@ import BarChart from "components/BarChart" +import { getFieldPropsFromFieldConfig } from "components/CustomFields" import LikertScale from "components/graphs/LikertScale" import Pie from "components/graphs/Pie" import _uniqueId from "lodash/uniqueId" @@ -95,7 +96,7 @@ const DefaultAggWidget = ({ values, ...otherWidgetProps }) => ( ) DefaultAggWidget.propTypes = aggregationPropTypes -const WIDGETS = { +const WIDGET_COMPONENTS = { likertScale: LikertScale, numberAggregation: NumberAggWidget, reportsByTask: ReportsByTaskWidget, @@ -104,18 +105,23 @@ const WIDGETS = { } const AggregationWidget = ({ - label, - widget, + fieldConfig, values, - aggregationType, vertical, ...otherWidgetProps }) => { - const Widget = (widget && WIDGETS[widget]) || WIDGETS.default + const aggregationType = fieldConfig.aggregation?.aggregationType + const fieldProps = getFieldPropsFromFieldConfig(fieldConfig) + const label = fieldProps.label + const widget = fieldConfig.aggregation?.widget || fieldConfig.widget + const WidgetComponent = + (widget && WIDGET_COMPONENTS[widget]) || WIDGET_COMPONENTS.default const widgetElem = ( - ) @@ -142,17 +148,12 @@ const AggregationWidget = ({ ) } AggregationWidget.propTypes = { - label: PropTypes.string, - widget: PropTypes.string, - vertical: PropTypes.bool, - ...aggregationPropTypes + values: PropTypes.any, + fieldConfig: PropTypes.object, + vertical: PropTypes.bool } AggregationWidget.defaultProps = { - label: "", - widget: "", - values: [], - aggregationType: "", - vertical: false + vertical: true } export default AggregationWidget diff --git a/client/src/components/aggregations/CountPerValueAggregation.js b/client/src/components/aggregations/CountPerValueAggregation.js index d32d215d3c..5f7f2c68d6 100644 --- a/client/src/components/aggregations/CountPerValueAggregation.js +++ b/client/src/components/aggregations/CountPerValueAggregation.js @@ -1,5 +1,4 @@ import AggregationWidget from "components/AggregationWidget" -import { getFieldPropsFromFieldConfig } from "components/CustomFields" import _clone from "lodash/clone" import _isEmpty from "lodash/isEmpty" import PropTypes from "prop-types" @@ -49,19 +48,12 @@ const CountPerValueAggregation = ({ fieldName, fieldConfig, data }) => { ) legend.null = { label: "Unspecified", color: "#bbbbbb" } - const aggWidgetProps = { - widget: fieldConfig.aggregation?.widget || fieldConfig.widget, - aggregationType: fieldConfig.aggregation?.aggregationType, - vertical: true - } - const fieldProps = getFieldPropsFromFieldConfig(fieldConfig) return ( ) } diff --git a/client/src/components/aggregations/ReportsByTaskAggregation.js b/client/src/components/aggregations/ReportsByTaskAggregation.js index 974303213a..797df1d49a 100644 --- a/client/src/components/aggregations/ReportsByTaskAggregation.js +++ b/client/src/components/aggregations/ReportsByTaskAggregation.js @@ -1,6 +1,5 @@ import { Settings } from "api" import AggregationWidget from "components/AggregationWidget" -import { getFieldPropsFromFieldConfig } from "components/CustomFields" import PropTypes from "prop-types" import React from "react" @@ -42,18 +41,11 @@ const getReportsByTasks = reportsList => { const ReportsByTaskAggregation = ({ fieldName, fieldConfig, data }) => { const values = getReportsByTasks(data) - const aggWidgetProps = { - widget: fieldConfig.aggregation?.widget || fieldConfig.widget, - aggregationType: fieldConfig.aggregation?.aggregationType, - vertical: true - } - const fieldProps = getFieldPropsFromFieldConfig(fieldConfig) return ( ) } diff --git a/client/src/components/aggregations/ValuesListAggregation.js b/client/src/components/aggregations/ValuesListAggregation.js index a3676d60da..697e7036d7 100644 --- a/client/src/components/aggregations/ValuesListAggregation.js +++ b/client/src/components/aggregations/ValuesListAggregation.js @@ -1,22 +1,14 @@ import AggregationWidget from "components/AggregationWidget" -import { getFieldPropsFromFieldConfig } from "components/CustomFields" import PropTypes from "prop-types" import React from "react" const ValuesListAggregation = ({ fieldName, fieldConfig, data }) => { const values = data.map(item => Object.get(item, fieldName)) - const aggWidgetProps = { - widget: fieldConfig.aggregation?.widget || fieldConfig.widget, - aggregationType: fieldConfig.aggregation?.aggregationType, - vertical: true - } - const fieldProps = getFieldPropsFromFieldConfig(fieldConfig) return ( ) } diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index 10a1dc28e2..e5aa8ce068 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -2,7 +2,6 @@ import AggregationWidget from "components/AggregationWidget" import AppContext from "components/AppContext" import AssessmentModal from "components/assessments/AssessmentModal" import PeriodicAssessment from "components/assessments/PeriodicAssessment" -import { getFieldPropsFromFieldConfig } from "components/CustomFields" import Fieldset from "components/Fieldset" import LinkTo from "components/LinkTo" import { NOTE_TYPE } from "components/Model" @@ -44,12 +43,6 @@ const InstantAssessmentRow = ({ entity, periods }) => { - const aggWidgetProps = { - widget: questionConfig.aggregation?.widget || questionConfig.widget, - aggregationType: questionConfig.aggregation?.aggregationType, - vertical: true - } - const fieldProps = getFieldPropsFromFieldConfig(questionConfig) return (
{periods.map((period, index) => ( @@ -57,8 +50,7 @@ const InstantAssessmentRow = ({ ))} From f513ab1904ed98cd210c7b59a5c44bdf2bd2d18f Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 19 May 2020 16:22:05 +0200 Subject: [PATCH 076/247] NCI-Agency/anet#2971: Define default aggregation type and widget per field type We now make sure that we have default aggregation types and aggregation widgets per field type. When the aggregation type/widget is not being defined for a field, use the default one for the field type. --- anet.yml | 10 -- client/src/components/ReportStatistics.js | 25 +++-- .../AggregationWidgetContainer.js | 98 +++++++++++++++++++ .../AggregationWidgets.js} | 77 ++------------- .../aggregations/CountPerValueAggregation.js | 4 +- .../aggregations/ReportsByTaskAggregation.js | 4 +- .../aggregations/ValuesListAggregation.js | 4 +- client/src/components/aggregations/utils.js | 28 ++++-- .../assessments/AssessmentResultsTable.js | 4 +- 9 files changed, 154 insertions(+), 100 deletions(-) create mode 100644 client/src/components/aggregations/AggregationWidgetContainer.js rename client/src/components/{AggregationWidget.js => aggregations/AggregationWidgets.js} (54%) diff --git a/anet.yml b/anet.yml index 194479e27e..29f9d50f3e 100644 --- a/anet.yml +++ b/anet.yml @@ -385,8 +385,6 @@ dictionary: label: Assist other: label: Other - aggregation: - widget: countPerValue trainingEvent: type: enum label: Training event @@ -396,8 +394,6 @@ dictionary: label: "Yes" NO: label: "No" - aggregation: - widget: default numberTrained: type: number typeError: Number trained must be a number @@ -408,8 +404,6 @@ dictionary: - type: min params: [1] visibleWhen: $[?(@.multipleButtons && @.multipleButtons.indexOf('train') != -1)] - aggregation: - widget: default levelTrained: type: special_field widget: likertScale @@ -426,8 +420,6 @@ dictionary: - color: lightGray endValue: 10 label: advanced advanced advanced advanced - aggregation: - widget: likertScale systemProcess: type: enum label: System / process @@ -437,8 +429,6 @@ dictionary: label: System NO: label: Process - aggregation: - widget: default echelons: type: text label: Issue echelon to fix diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index 7029a4e572..1182da62c5 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -1,6 +1,9 @@ import API, { Settings } from "api" import { gql } from "apollo-boost" -import { WIDGET_AGGREGATIONS } from "components/aggregations/utils" +import { + AGGREGATION_TYPE_COMPONENTS, + DEFAULT_AGGREGATION_TYPE_PER_FIELD_TYPE +} from "components/aggregations/utils" import { PageDispatchersPropType, useBoilerplate } from "components/Page" import _get from "lodash/get" import { Report } from "models" @@ -16,7 +19,7 @@ import { Table } from "react-bootstrap" const REPORT_FIELDS_FOR_STATISTICS = { state: { - aggregation: { widget: "countPerValue" }, + aggregation: { aggregationType: "countPerValue", widget: "pie" }, label: "State", choices: { [Report.STATE.DRAFT]: { @@ -46,12 +49,14 @@ const REPORT_FIELDS_FOR_STATISTICS = { } }, atmosphere: { - aggregation: { widget: "countPerValue" }, + aggregation: { aggregationType: "countPerValue", widget: "pie" }, label: Settings.fields.report.atmosphere }, - // FIXME: right not the bar chart ends in an endless loop tasks: { - aggregation: { widget: "reportsByTask" }, + aggregation: { + aggregationType: "countReportsByTask", + widget: "reportsByTask" + }, label: pluralize(Settings.fields.task.subLevel.shortLabel) } } @@ -84,11 +89,17 @@ const FieldStatisticsRow = ({ periods, periodsData }) => { - if (!fieldConfig.aggregation) { + if ( + !fieldConfig.aggregation && + !DEFAULT_AGGREGATION_TYPE_PER_FIELD_TYPE[fieldConfig.type] + ) { return null } const AggregationComponent = - WIDGET_AGGREGATIONS[fieldConfig.aggregation.widget || fieldConfig.widget] + AGGREGATION_TYPE_COMPONENTS[ + fieldConfig.aggregation?.aggregationType || + DEFAULT_AGGREGATION_TYPE_PER_FIELD_TYPE[fieldConfig.type] + ] return ( {periods.map((period, index) => ( diff --git a/client/src/components/aggregations/AggregationWidgetContainer.js b/client/src/components/aggregations/AggregationWidgetContainer.js new file mode 100644 index 0000000000..c181d85b94 --- /dev/null +++ b/client/src/components/aggregations/AggregationWidgetContainer.js @@ -0,0 +1,98 @@ +import { + DefaultAggWidget, + NumberAggWidget, + PieWidget, + ReportsByTaskWidget +} from "components/aggregations/AggregationWidgets" +import { getFieldPropsFromFieldConfig } from "components/CustomFields" +import LikertScale from "components/graphs/LikertScale" +import { CUSTOM_FIELD_TYPE } from "components/Model" +import PropTypes from "prop-types" +import React from "react" +import { Col, ControlLabel, FormGroup } from "react-bootstrap" + +const AGGERGATION_WIDGET_TYPE = { + LIKERT_SCALE: "likertScale", + PIE: "pie", + REPORTS_BY_TASK: "reportsByTask", + NUMBER_AGGREGATION: "numberAggregation", + DEFAULT: "default" +} +export const DEFAULT_AGGREGATION_WIDGET_PER_FIELD_TYPE = { + [CUSTOM_FIELD_TYPE.TEXT]: AGGERGATION_WIDGET_TYPE.DEFAULT, + [CUSTOM_FIELD_TYPE.NUMBER]: AGGERGATION_WIDGET_TYPE.DEFAULT, + [CUSTOM_FIELD_TYPE.DATE]: AGGERGATION_WIDGET_TYPE.DEFAULT, + [CUSTOM_FIELD_TYPE.DATETIME]: AGGERGATION_WIDGET_TYPE.DEFAULT, + [CUSTOM_FIELD_TYPE.ENUM]: AGGERGATION_WIDGET_TYPE.PIE, + [CUSTOM_FIELD_TYPE.ENUMSET]: AGGERGATION_WIDGET_TYPE.PIE, + [CUSTOM_FIELD_TYPE.ARRAY_OF_OBJECTS]: AGGERGATION_WIDGET_TYPE.DEFAULT, + [CUSTOM_FIELD_TYPE.SPECIAL_FIELD]: AGGERGATION_WIDGET_TYPE.DEFAULT +} + +const WIDGET_COMPONENTS = { + [AGGERGATION_WIDGET_TYPE.LIKERT_SCALE]: LikertScale, + [AGGERGATION_WIDGET_TYPE.PIE]: PieWidget, + [AGGERGATION_WIDGET_TYPE.NUMBER_AGGREGATION]: NumberAggWidget, + [AGGERGATION_WIDGET_TYPE.REPORTS_BY_TASK]: ReportsByTaskWidget, + [AGGERGATION_WIDGET_TYPE.COUNT_PER_VALUE]: PieWidget, + default: DefaultAggWidget +} + +const AggregationWidgetContainer = ({ + fieldConfig, + values, + vertical, + ...otherWidgetProps +}) => { + const aggregationType = fieldConfig.aggregation?.aggregationType + const fieldProps = getFieldPropsFromFieldConfig(fieldConfig) + const label = fieldProps.label + const widget = + fieldConfig.aggregation?.widget || + (fieldConfig.widget && + WIDGET_COMPONENTS[fieldConfig.widget] && + fieldConfig.widget) || + DEFAULT_AGGREGATION_WIDGET_PER_FIELD_TYPE[fieldConfig.type] + const WidgetComponent = + (widget && WIDGET_COMPONENTS[widget]) || WIDGET_COMPONENTS.default + const widgetElem = ( + + ) + return ( + + {vertical ? ( + <> + {label !== null && {label}} + {widgetElem} + + ) : ( + <> + {label !== null && ( + + {label} + + )} + +
{widgetElem}
+ + + )} + + ) +} +AggregationWidgetContainer.propTypes = { + values: PropTypes.any, + fieldConfig: PropTypes.object, + vertical: PropTypes.bool +} +AggregationWidgetContainer.defaultProps = { + vertical: true +} + +export default AggregationWidgetContainer diff --git a/client/src/components/AggregationWidget.js b/client/src/components/aggregations/AggregationWidgets.js similarity index 54% rename from client/src/components/AggregationWidget.js rename to client/src/components/aggregations/AggregationWidgets.js index e4b8d58bb4..9375a07f53 100644 --- a/client/src/components/AggregationWidget.js +++ b/client/src/components/aggregations/AggregationWidgets.js @@ -1,11 +1,8 @@ import BarChart from "components/BarChart" -import { getFieldPropsFromFieldConfig } from "components/CustomFields" -import LikertScale from "components/graphs/LikertScale" import Pie from "components/graphs/Pie" import _uniqueId from "lodash/uniqueId" import PropTypes from "prop-types" import React from "react" -import { Col, ControlLabel, FormGroup } from "react-bootstrap" const aggregationPropTypes = { values: PropTypes.oneOfType([ @@ -32,13 +29,17 @@ const NUMBER_AGG = { max: arr => Math.max(...arr) } -const NumberAggWidget = ({ values, aggregationType, ...otherWidgetProps }) => +export const NumberAggWidget = ({ + values, + aggregationType, + ...otherWidgetProps +}) => values?.length ? (
{NUMBER_AGG[aggregationType](arrayOfNumbers(values))}
) : null NumberAggWidget.propTypes = aggregationPropTypes -const PieWidget = ({ +export const PieWidget = ({ values, aggregationType, legend, @@ -68,7 +69,7 @@ PieWidget.propTypes = { ...aggregationPropTypes } -const ReportsByTaskWidget = ({ +export const ReportsByTaskWidget = ({ values, aggregationType, ...otherWidgetProps @@ -91,69 +92,7 @@ const ReportsByTaskWidget = ({ } ReportsByTaskWidget.propTypes = aggregationPropTypes -const DefaultAggWidget = ({ values, ...otherWidgetProps }) => ( +export const DefaultAggWidget = ({ values, ...otherWidgetProps }) => (
{`[${values}]`}
) DefaultAggWidget.propTypes = aggregationPropTypes - -const WIDGET_COMPONENTS = { - likertScale: LikertScale, - numberAggregation: NumberAggWidget, - reportsByTask: ReportsByTaskWidget, - countPerValue: PieWidget, - default: DefaultAggWidget -} - -const AggregationWidget = ({ - fieldConfig, - values, - vertical, - ...otherWidgetProps -}) => { - const aggregationType = fieldConfig.aggregation?.aggregationType - const fieldProps = getFieldPropsFromFieldConfig(fieldConfig) - const label = fieldProps.label - const widget = fieldConfig.aggregation?.widget || fieldConfig.widget - const WidgetComponent = - (widget && WIDGET_COMPONENTS[widget]) || WIDGET_COMPONENTS.default - const widgetElem = ( - - ) - return ( - - {vertical ? ( - <> - {label !== null && {label}} - {widgetElem} - - ) : ( - <> - {label !== null && ( - - {label} - - )} - -
{widgetElem}
- - - )} - - ) -} -AggregationWidget.propTypes = { - values: PropTypes.any, - fieldConfig: PropTypes.object, - vertical: PropTypes.bool -} -AggregationWidget.defaultProps = { - vertical: true -} - -export default AggregationWidget diff --git a/client/src/components/aggregations/CountPerValueAggregation.js b/client/src/components/aggregations/CountPerValueAggregation.js index 5f7f2c68d6..8789568c0e 100644 --- a/client/src/components/aggregations/CountPerValueAggregation.js +++ b/client/src/components/aggregations/CountPerValueAggregation.js @@ -1,4 +1,4 @@ -import AggregationWidget from "components/AggregationWidget" +import AggregationWidgetContainer from "components/aggregations/AggregationWidgetContainer" import _clone from "lodash/clone" import _isEmpty from "lodash/isEmpty" import PropTypes from "prop-types" @@ -49,7 +49,7 @@ const CountPerValueAggregation = ({ fieldName, fieldConfig, data }) => { legend.null = { label: "Unspecified", color: "#bbbbbb" } return ( - { const ReportsByTaskAggregation = ({ fieldName, fieldConfig, data }) => { const values = getReportsByTasks(data) return ( - { const values = data.map(item => Object.get(item, fieldName)) return ( - {periods.map((period, index) => ( {periods.map((period, index) => ( diff --git a/client/src/components/aggregations/AggregationWidgetContainer.js b/client/src/components/aggregations/AggregationWidgetContainer.js index 0da8c2f7c2..305dfa184b 100644 --- a/client/src/components/aggregations/AggregationWidgetContainer.js +++ b/client/src/components/aggregations/AggregationWidgetContainer.js @@ -18,7 +18,8 @@ const AGGERGATION_WIDGET_TYPE = { IQR_BOX_PLOT: "iqrBoxPlot", DEFAULT: "default" } -export const DEFAULT_AGGREGATION_WIDGET_PER_FIELD_TYPE = { + +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.DEFAULT, diff --git a/client/src/components/aggregations/utils.js b/client/src/components/aggregations/utils.js index 1ec71a35dc..d3990c7f63 100644 --- a/client/src/components/aggregations/utils.js +++ b/client/src/components/aggregations/utils.js @@ -4,14 +4,14 @@ import ReportsByTaskAggregation from "components/aggregations/ReportsByTaskAggre import ValuesListAggregation from "components/aggregations/ValuesListAggregation" import { CUSTOM_FIELD_TYPE } from "components/Model" -export const AGGREGATION_TYPE = { +const AGGREGATION_TYPE = { REPORTS_BY_TASK: "countReportsByTask", COUNT_PER_VALUE: "countPerValue", NUMBERS_LIST: "numbersList", VALUES_LIST: "valuesList" } -export const DEFAULT_AGGREGATION_TYPE_PER_FIELD_TYPE = { +const DEFAULT_AGGREGATION_TYPE_PER_FIELD_TYPE = { [CUSTOM_FIELD_TYPE.TEXT]: AGGREGATION_TYPE.VALUES_LIST, [CUSTOM_FIELD_TYPE.NUMBER]: AGGREGATION_TYPE.NUMBERS_LIST, [CUSTOM_FIELD_TYPE.DATE]: AGGREGATION_TYPE.VALUES_LIST, @@ -22,9 +22,16 @@ export const DEFAULT_AGGREGATION_TYPE_PER_FIELD_TYPE = { [CUSTOM_FIELD_TYPE.SPECIAL_FIELD]: AGGREGATION_TYPE.VALUES_LIST } -export const AGGREGATION_TYPE_COMPONENTS = { +const AGGREGATION_TYPE_COMPONENTS = { [AGGREGATION_TYPE.REPORTS_BY_TASK]: ReportsByTaskAggregation, [AGGREGATION_TYPE.COUNT_PER_VALUE]: CountPerValueAggregation, [AGGREGATION_TYPE.NUMBERS_LIST]: NumbersListAggregation, [AGGREGATION_TYPE.VALUES_LIST]: ValuesListAggregation } + +export const getAggregationComponentForFieldConfig = fieldConfig => { + const aggregationType = + fieldConfig.aggregation?.aggregationType || + DEFAULT_AGGREGATION_TYPE_PER_FIELD_TYPE[fieldConfig.type] + return aggregationType ? AGGREGATION_TYPE_COMPONENTS[aggregationType] : null +} diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index ea26959dff..9de74bb82f 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -1,7 +1,8 @@ -import AggregationWidgetContainer from "components/aggregations/AggregationWidgetContainer" +import { getAggregationComponentForFieldConfig } from "components/aggregations/utils" import AppContext from "components/AppContext" import AssessmentModal from "components/assessments/AssessmentModal" import PeriodicAssessment from "components/assessments/PeriodicAssessment" + import Fieldset from "components/Fieldset" import LinkTo from "components/LinkTo" import { NOTE_TYPE } from "components/Model" @@ -43,14 +44,21 @@ const InstantAssessmentRow = ({ entity, periods }) => { + const AggregationComponent = getAggregationComponentForFieldConfig( + questionConfig + ) + if (!AggregationComponent) { + return null + } return ( {periods.map((period, index) => ( ))} From dab4e9575514a09fc8740e1064133c6d9695e7cf Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 19 May 2020 23:56:02 +0200 Subject: [PATCH 079/247] NCI-Agency/anet#2971: Fix CountPerValueAggregation when value undefined When the value for a field is undefined, treat it as null and display it as undefined in the aggregation widget. --- client/src/components/aggregations/CountPerValueAggregation.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/src/components/aggregations/CountPerValueAggregation.js b/client/src/components/aggregations/CountPerValueAggregation.js index 8789568c0e..0e2092d219 100644 --- a/client/src/components/aggregations/CountPerValueAggregation.js +++ b/client/src/components/aggregations/CountPerValueAggregation.js @@ -29,11 +29,10 @@ const CHART_COLORS = [ ] const CountPerValueAggregation = ({ fieldName, fieldConfig, data }) => { const counters = data.reduce((counter, entity) => { - const value = Object.get(entity, fieldName) + const value = Object.get(entity, fieldName) || null counter[value] = ++counter[value] || 1 return counter }, {}) - const legendColors = _clone(CHART_COLORS) const legend = fieldConfig?.choices || {} const legendKeys = !_isEmpty(legend) From 361712cfdc807a66da7f4e8e7ed03d874c01a670 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 20 May 2020 00:06:22 +0200 Subject: [PATCH 080/247] NCI-Agency/anet#2971: Removed not used aggregationType prop Aggregation widgets don't need the aggregation type property (this one is being used in one of the ancestor components to determine how to perform the aggregation of the data). --- .../AggregationWidgetContainer.js | 2 -- .../aggregations/AggregationWidgets.js | 24 ++++++------------- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/client/src/components/aggregations/AggregationWidgetContainer.js b/client/src/components/aggregations/AggregationWidgetContainer.js index 305dfa184b..9ea35402cb 100644 --- a/client/src/components/aggregations/AggregationWidgetContainer.js +++ b/client/src/components/aggregations/AggregationWidgetContainer.js @@ -45,7 +45,6 @@ const AggregationWidgetContainer = ({ vertical, ...otherWidgetProps }) => { - const aggregationType = fieldConfig.aggregation?.aggregationType const fieldProps = getFieldPropsFromFieldConfig(fieldConfig) const label = fieldProps.label const widget = @@ -59,7 +58,6 @@ const AggregationWidgetContainer = ({ const widgetElem = ( { +export const PieWidget = ({ values, legend, ...otherWidgetProps }) => { return ( <> { +export const ReportsByTaskWidget = ({ values, ...otherWidgetProps }) => { return (
) } -ReportsByTaskWidget.propTypes = aggregationPropTypes +ReportsByTaskWidget.propTypes = aggregationWidgetPropTypes export const DefaultAggWidget = ({ values, ...otherWidgetProps }) => (
{`[${values}]`}
) -DefaultAggWidget.propTypes = aggregationPropTypes +DefaultAggWidget.propTypes = aggregationWidgetPropTypes From 049e5ff2ce25f8a4a855ba3502352e6a92ea8cb0 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 20 May 2020 15:56:10 +0200 Subject: [PATCH 081/247] NCI-Agency/anet#2971: Add aggregation widget for date types of fields The widget is a month calendar displaying the number of events per day. --- anet.yml | 4 ++ .../AggregationWidgetContainer.js | 11 +++- .../aggregations/AggregationWidgets.js | 61 ++++++++++++++++++- .../aggregations/CountPerDateAggregation.js | 31 ++++++++++ .../aggregations/CountPerValueAggregation.js | 1 + .../aggregations/NumbersListAggregation.js | 1 + .../aggregations/ReportsByTaskAggregation.js | 1 + .../aggregations/ValuesListAggregation.js | 1 + client/src/components/aggregations/utils.js | 7 ++- 9 files changed, 112 insertions(+), 6 deletions(-) create mode 100644 client/src/components/aggregations/CountPerDateAggregation.js diff --git a/anet.yml b/anet.yml index 29f9d50f3e..338cab507c 100644 --- a/anet.yml +++ b/anet.yml @@ -420,6 +420,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 diff --git a/client/src/components/aggregations/AggregationWidgetContainer.js b/client/src/components/aggregations/AggregationWidgetContainer.js index 9ea35402cb..e86d5f92e9 100644 --- a/client/src/components/aggregations/AggregationWidgetContainer.js +++ b/client/src/components/aggregations/AggregationWidgetContainer.js @@ -1,4 +1,5 @@ import { + CalendarWidget, DefaultAggWidget, PieWidget, ReportsByTaskWidget @@ -16,14 +17,15 @@ const AGGERGATION_WIDGET_TYPE = { PIE: "pie", REPORTS_BY_TASK: "reportsByTask", IQR_BOX_PLOT: "iqrBoxPlot", + CALENDAR: "calendar", DEFAULT: "default" } 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.DEFAULT, - [CUSTOM_FIELD_TYPE.DATETIME]: AGGERGATION_WIDGET_TYPE.DEFAULT, + [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.ARRAY_OF_OBJECTS]: AGGERGATION_WIDGET_TYPE.DEFAULT, @@ -36,11 +38,13 @@ const WIDGET_COMPONENTS = { [AGGERGATION_WIDGET_TYPE.IQR_BOX_PLOT]: IqrBoxPlot, [AGGERGATION_WIDGET_TYPE.REPORTS_BY_TASK]: ReportsByTaskWidget, [AGGERGATION_WIDGET_TYPE.COUNT_PER_VALUE]: PieWidget, + [AGGERGATION_WIDGET_TYPE.CALENDAR]: CalendarWidget, default: DefaultAggWidget } const AggregationWidgetContainer = ({ fieldConfig, + fieldName, values, vertical, ...otherWidgetProps @@ -60,6 +64,8 @@ const AggregationWidgetContainer = ({ values={values} vertical={vertical} {...fieldProps} + fieldConfig={fieldConfig} + fieldName={fieldName} {...otherWidgetProps} /> ) @@ -88,6 +94,7 @@ const AggregationWidgetContainer = ({ AggregationWidgetContainer.propTypes = { values: PropTypes.any, fieldConfig: PropTypes.object, + fieldName: PropTypes.string, vertical: PropTypes.bool } AggregationWidgetContainer.defaultProps = { diff --git a/client/src/components/aggregations/AggregationWidgets.js b/client/src/components/aggregations/AggregationWidgets.js index 08d6759d96..a225d55935 100644 --- a/client/src/components/aggregations/AggregationWidgets.js +++ b/client/src/components/aggregations/AggregationWidgets.js @@ -1,8 +1,12 @@ +import "@fullcalendar/core/main.css" +import dayGridPlugin from "@fullcalendar/daygrid" +import "@fullcalendar/daygrid/main.css" +import FullCalendar from "@fullcalendar/react" import BarChart from "components/BarChart" import Pie from "components/graphs/Pie" import _uniqueId from "lodash/uniqueId" import PropTypes from "prop-types" -import React from "react" +import React, { useRef } from "react" const aggregationWidgetPropTypes = { values: PropTypes.oneOfType([ @@ -15,7 +19,10 @@ const aggregationWidgetPropTypes = { PropTypes.object ]) ) - ]) + ]), + fieldConfig: PropTypes.object, + fieldName: PropTypes.string, + vertical: PropTypes.bool } export const PieWidget = ({ values, legend, ...otherWidgetProps }) => { @@ -62,6 +69,56 @@ export const ReportsByTaskWidget = ({ values, ...otherWidgetProps }) => { } ReportsByTaskWidget.propTypes = aggregationWidgetPropTypes +export const CalendarWidget = ({ + values, + fieldConfig, + fieldName, + ...otherWidgetProps +}) => { + const calendarComponentRef = useRef(null) + const events = Object.entries(values).map(([key, value]) => { + return { + title: `${value} events`, + start: key, + end: key + } + }) + + return ( + + ) +} +CalendarWidget.propTypes = aggregationWidgetPropTypes + export const DefaultAggWidget = ({ values, ...otherWidgetProps }) => (
{`[${values}]`}
) diff --git a/client/src/components/aggregations/CountPerDateAggregation.js b/client/src/components/aggregations/CountPerDateAggregation.js new file mode 100644 index 0000000000..842defc78f --- /dev/null +++ b/client/src/components/aggregations/CountPerDateAggregation.js @@ -0,0 +1,31 @@ +import AggregationWidgetContainer from "components/aggregations/AggregationWidgetContainer" +import moment from "moment" +import PropTypes from "prop-types" +import React from "react" + +const CountPerDateAggregation = ({ fieldName, fieldConfig, data }) => { + const countPerDate = 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 ( + + ) +} +CountPerDateAggregation.propTypes = { + data: PropTypes.array, + fieldName: PropTypes.string, + fieldConfig: PropTypes.object +} + +export default CountPerDateAggregation diff --git a/client/src/components/aggregations/CountPerValueAggregation.js b/client/src/components/aggregations/CountPerValueAggregation.js index 0e2092d219..92336f5790 100644 --- a/client/src/components/aggregations/CountPerValueAggregation.js +++ b/client/src/components/aggregations/CountPerValueAggregation.js @@ -51,6 +51,7 @@ const CountPerValueAggregation = ({ fieldName, fieldConfig, data }) => { diff --git a/client/src/components/aggregations/NumbersListAggregation.js b/client/src/components/aggregations/NumbersListAggregation.js index 1a360bddbb..1d14bd81e2 100644 --- a/client/src/components/aggregations/NumbersListAggregation.js +++ b/client/src/components/aggregations/NumbersListAggregation.js @@ -12,6 +12,7 @@ const NumbersListAggregation = ({ fieldName, fieldConfig, data }) => { ) diff --git a/client/src/components/aggregations/ReportsByTaskAggregation.js b/client/src/components/aggregations/ReportsByTaskAggregation.js index 401b2725a7..26506dfa8e 100644 --- a/client/src/components/aggregations/ReportsByTaskAggregation.js +++ b/client/src/components/aggregations/ReportsByTaskAggregation.js @@ -45,6 +45,7 @@ const ReportsByTaskAggregation = ({ fieldName, fieldConfig, data }) => { ) diff --git a/client/src/components/aggregations/ValuesListAggregation.js b/client/src/components/aggregations/ValuesListAggregation.js index 8c873ace80..7f489dbffb 100644 --- a/client/src/components/aggregations/ValuesListAggregation.js +++ b/client/src/components/aggregations/ValuesListAggregation.js @@ -8,6 +8,7 @@ const ValuesListAggregation = ({ fieldName, fieldConfig, data }) => { ) diff --git a/client/src/components/aggregations/utils.js b/client/src/components/aggregations/utils.js index d3990c7f63..a0b8cea620 100644 --- a/client/src/components/aggregations/utils.js +++ b/client/src/components/aggregations/utils.js @@ -1,4 +1,5 @@ import CountPerValueAggregation from "components/aggregations/CountPerValueAggregation" +import CountPerDateAggregation from "components/aggregations/CountPerDateAggregation" import NumbersListAggregation from "components/aggregations/NumbersListAggregation" import ReportsByTaskAggregation from "components/aggregations/ReportsByTaskAggregation" import ValuesListAggregation from "components/aggregations/ValuesListAggregation" @@ -6,6 +7,7 @@ import { CUSTOM_FIELD_TYPE } from "components/Model" const AGGREGATION_TYPE = { REPORTS_BY_TASK: "countReportsByTask", + COUNT_PER_DATE: "countPerDate", COUNT_PER_VALUE: "countPerValue", NUMBERS_LIST: "numbersList", VALUES_LIST: "valuesList" @@ -14,8 +16,8 @@ const AGGREGATION_TYPE = { const DEFAULT_AGGREGATION_TYPE_PER_FIELD_TYPE = { [CUSTOM_FIELD_TYPE.TEXT]: AGGREGATION_TYPE.VALUES_LIST, [CUSTOM_FIELD_TYPE.NUMBER]: AGGREGATION_TYPE.NUMBERS_LIST, - [CUSTOM_FIELD_TYPE.DATE]: AGGREGATION_TYPE.VALUES_LIST, - [CUSTOM_FIELD_TYPE.DATETIME]: AGGREGATION_TYPE.VALUES_LIST, + [CUSTOM_FIELD_TYPE.DATE]: AGGREGATION_TYPE.COUNT_PER_DATE, + [CUSTOM_FIELD_TYPE.DATETIME]: AGGREGATION_TYPE.COUNT_PER_DATE, [CUSTOM_FIELD_TYPE.ENUM]: AGGREGATION_TYPE.COUNT_PER_VALUE, [CUSTOM_FIELD_TYPE.ENUMSET]: AGGREGATION_TYPE.COUNT_PER_VALUE, [CUSTOM_FIELD_TYPE.ARRAY_OF_OBJECTS]: AGGREGATION_TYPE.VALUES_LIST, @@ -25,6 +27,7 @@ const DEFAULT_AGGREGATION_TYPE_PER_FIELD_TYPE = { const AGGREGATION_TYPE_COMPONENTS = { [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 } From 98f581e7bd155301f0cfaf308114b9a502f4d949 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 20 May 2020 16:59:52 +0200 Subject: [PATCH 082/247] NCI-Agency/anet#2971: Remove aggregation type components Replace them by aggregation functions, used by the AggregationWidgetContainer. This way the components model is easier to understand and to maintain. --- client/src/components/ReportStatistics.js | 11 +- .../AggregationWidgetContainer.js | 16 ++- .../aggregations/CountPerDateAggregation.js | 31 ---- .../aggregations/CountPerValueAggregation.js | 66 --------- .../aggregations/NumbersListAggregation.js | 26 ---- .../aggregations/ReportsByTaskAggregation.js | 59 -------- .../aggregations/ValuesListAggregation.js | 22 --- client/src/components/aggregations/utils.js | 135 ++++++++++++++++-- .../assessments/AssessmentResultsTable.js | 11 +- 9 files changed, 146 insertions(+), 231 deletions(-) delete mode 100644 client/src/components/aggregations/CountPerDateAggregation.js delete mode 100644 client/src/components/aggregations/CountPerValueAggregation.js delete mode 100644 client/src/components/aggregations/NumbersListAggregation.js delete mode 100644 client/src/components/aggregations/ReportsByTaskAggregation.js delete mode 100644 client/src/components/aggregations/ValuesListAggregation.js diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index d2e411a325..3e9b22c8e1 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -1,6 +1,7 @@ import API, { Settings } from "api" import { gql } from "apollo-boost" -import { getAggregationComponentForFieldConfig } from "components/aggregations/utils" +import AggregationWidgetContainer from "components/aggregations/AggregationWidgetContainer" +import { getAggregationFunctionForFieldConfig } from "components/aggregations/utils" import { PageDispatchersPropType, useBoilerplate } from "components/Page" import _get from "lodash/get" import { Report } from "models" @@ -86,17 +87,15 @@ const FieldStatisticsRow = ({ periods, periodsData }) => { - const AggregationComponent = getAggregationComponentForFieldConfig( - fieldConfig - ) - if (!AggregationComponent) { + const aggregationFunction = getAggregationFunctionForFieldConfig(fieldConfig) + if (!aggregationFunction) { return null } return (
{periods.map((period, index) => ( {periods.map((period, index) => ( {periods.map((period, index) => ( - {periods.map((period, index) => ( - - ))} - - ) -} -InstantAssessmentRow.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 -} - -const BasePeriodicAssessmentRows = ({ - entity, - entityType, - periodsConfig, - canAddAssessment, - onUpdateAssessment, - currentUser -}) => { - 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 ( - - ) - })} - - )} - {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 ( - - ) - })} - - )} - - ) -} -BasePeriodicAssessmentRows.propTypes = { - entity: PropTypes.object.isRequired, - entityType: PropTypes.func.isRequired, - periodsConfig: AssessmentPeriodsConfigPropType.isRequired, - canAddAssessment: PropTypes.bool, - onUpdateAssessment: PropTypes.func.isRequired, - currentUser: PropTypes.instanceOf(Person) -} - -const PeriodicAssessmentRows = props => ( - - {context => ( - - )} - -) - const EntityAssessmentResults = ({ entity, entityType, @@ -252,7 +54,7 @@ const EntityAssessmentResults = ({ {Object.keys(instantAssessmentConfig || {}).map((key, index) => ( - ))} - 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) => ( + + ))} + + ) +} +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/PeriodicAssessment.js b/client/src/components/assessments/PeriodicAssessment.js deleted file mode 100644 index 4e1006d412..0000000000 --- a/client/src/components/assessments/PeriodicAssessment.js +++ /dev/null @@ -1,133 +0,0 @@ -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 from "components/Model" -import { Person } from "models" -import moment from "moment" -import { AssessmentPeriodPropType, periodToString } from "periodUtils" -import PropTypes from "prop-types" -import React, { useState } from "react" -import { Button, Panel } from "react-bootstrap" -import "components/assessments/AssessmentResultsTable.css" - -const BasePeriodicAssessment = ({ - assessment, - assessmentYupSchema, - assessmentConfig, - note, - entity, - period, - recurrence, - onUpdateAssessment, - currentUser -}) => { - 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 ( - - ) - }} - -
-
-
- ) -} -BasePeriodicAssessment.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, - currentUser: PropTypes.instanceOf(Person) -} - -const PeriodicAssessment = props => ( - - {context => ( - - )} - -) -export default PeriodicAssessment diff --git a/client/src/components/assessments/PeriodicAssessmentResults.js b/client/src/components/assessments/PeriodicAssessmentResults.js new file mode 100644 index 0000000000..584fe5d47e --- /dev/null +++ b/client/src/components/assessments/PeriodicAssessmentResults.js @@ -0,0 +1,281 @@ +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, { useState } from "react" +import { Button, Panel } from "react-bootstrap" + +const BasePeriodicAssessment = ({ + assessment, + assessmentYupSchema, + assessmentConfig, + note, + entity, + period, + recurrence, + onUpdateAssessment, + currentUser +}) => { + 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 ( + + ) + }} + +
+
+
+ ) +} +BasePeriodicAssessment.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, + currentUser: PropTypes.instanceOf(Person) +} + +const PeriodicAssessment = props => ( + + {context => ( + + )} + +) + +const BasePeriodicAssessmentsRows = ({ + entity, + entityType, + periodsConfig, + canAddAssessment, + onUpdateAssessment, + currentUser +}) => { + 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 ( + + ) + })} + + )} + {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 ( + + ) + })} + + )} + + ) +} +BasePeriodicAssessmentsRows.propTypes = { + entity: PropTypes.object.isRequired, + entityType: PropTypes.func.isRequired, + periodsConfig: AssessmentPeriodsConfigPropType.isRequired, + canAddAssessment: PropTypes.bool, + onUpdateAssessment: PropTypes.func.isRequired, + currentUser: PropTypes.instanceOf(Person) +} + +export const PeriodicAssessmentsRows = props => ( + + {context => ( + + )} + +) From b5076122013fa962aab00a4d3652e1802661e71e Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Thu, 9 Jul 2020 16:37:08 +0200 Subject: [PATCH 167/247] NCI-Agency/anet#2347: Make sure we keep our initial admin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sometimes the sim would assign 'arthur' to a newly created position, after which he was no longer admin and subsequent calls started failing. Fix this by: • making 'arthur' the special user • changing the ignored uuid's into a callback so the caller can more flexibly decide which random objects should not be returned --- client/tests/sim/simutils.js | 3 ++- client/tests/sim/stories/NoteStories.js | 4 ++-- client/tests/sim/stories/PositionStories.js | 4 +++- 3 files changed, 7 insertions(+), 4 deletions(-) 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 = { From 50833743e06dc0349bf993f64e5672461ba6542a Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 9 Jul 2020 15:24:53 +0200 Subject: [PATCH 168/247] NCI-Agency/anet#2954: Improve typechecking for InstantAssessmentsContainerField --- .../assessments/InstantAssessmentsContainerField.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/src/components/assessments/InstantAssessmentsContainerField.js b/client/src/components/assessments/InstantAssessmentsContainerField.js index 2ca4ba29da..0f6fdc20fe 100644 --- a/client/src/components/assessments/InstantAssessmentsContainerField.js +++ b/client/src/components/assessments/InstantAssessmentsContainerField.js @@ -3,6 +3,7 @@ import { 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" @@ -62,18 +63,19 @@ const InstantAssessmentsContainerField = ({ } InstantAssessmentsContainerField.propTypes = { entityType: PropTypes.func.isRequired, - entities: PropTypes.array, + 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, + values: PropTypes.object.isRequired, validateForm: PropTypes.func }), readonly: PropTypes.bool } InstantAssessmentsContainerField.defaultProps = { + entities: [], readonly: false } export default InstantAssessmentsContainerField From 5d08f87a8338e5b5d10b1e69eea5df950260373c Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 9 Jul 2020 15:38:32 +0200 Subject: [PATCH 169/247] NCI-Agency/anet#2954: Minor code style change --- client/src/components/graphs/IqrBoxPlot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/graphs/IqrBoxPlot.js b/client/src/components/graphs/IqrBoxPlot.js index 8102d6e554..b889971203 100644 --- a/client/src/components/graphs/IqrBoxPlot.js +++ b/client/src/components/graphs/IqrBoxPlot.js @@ -34,7 +34,7 @@ const IqrBoxPlot = ({ const index = quartileNumber * (sortedData.length / 4) const idx = Math.floor(index) return idx === index - ? (sortedData[index - 1] + sortedData[index]) / 2 + ? (sortedData[idx - 1] + sortedData[idx]) / 2 : sortedData[idx] } From d12ce5d980f56f9c21c523ec8fe5615e2c7754a7 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 9 Jul 2020 17:57:14 +0200 Subject: [PATCH 170/247] NCI-Agency/anet#2954: Only display delete button if onDelete is defined --- client/src/components/RelatedObjectNoteModal.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/src/components/RelatedObjectNoteModal.js b/client/src/components/RelatedObjectNoteModal.js index 194f16b38e..c8ab773bb1 100644 --- a/client/src/components/RelatedObjectNoteModal.js +++ b/client/src/components/RelatedObjectNoteModal.js @@ -128,7 +128,7 @@ const RelatedObjectNoteModal = ({ - {_isEmpty(relatedObjects) ? ( + {_isEmpty(relatedObjects) && onDelete && ( onDelete(note.uuid)} objectType="note" @@ -136,7 +136,8 @@ const RelatedObjectNoteModal = ({ bsStyle="warning" buttonLabel="Delete note" /> - ) : ( + )} + {!_isEmpty(relatedObjects) && ( + setIncludeChildrenOrgs(!includeChildrenOrgs)} > include reports from sub-orgs @@ -422,14 +424,6 @@ const BaseOrganizationShow = ({ pageDispatchers, currentUser }) => { }} ) - - function togglePendingApprovalFilter() { - setFilterPendingApproval(!filterPendingApproval) - } - - function toggleIncludeChildrenOrgs() { - setIncludeChildrenOrgs(!includeChildrenOrgs) - } } BaseOrganizationShow.propTypes = { From bbca430eedea70afeaf93c113781e65135191b1f Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 9 Jul 2020 21:41:08 +0200 Subject: [PATCH 175/247] NCI-Agency/anet#2954: Put each aggregation widget in its own file --- client/src/components/ReportMap.js | 2 +- .../AggregationWidgetContainer.js | 14 +- .../aggregations/AggregationWidgets.js | 293 ------------------ .../components/aggregations/CalendarWidget.js | 80 +++++ .../aggregations/DefaultAggWidget.js | 47 +++ .../aggregations/LikertScaleAndPieWidget.js | 46 +++ .../src/components/aggregations/PieWidget.js | 49 +++ .../aggregations/ReportsByTaskWidget.js | 27 ++ .../aggregations/ReportsMapWidget.js | 65 ++++ client/src/components/aggregations/utils.js | 24 ++ 10 files changed, 345 insertions(+), 302 deletions(-) delete mode 100644 client/src/components/aggregations/AggregationWidgets.js create mode 100644 client/src/components/aggregations/CalendarWidget.js create mode 100644 client/src/components/aggregations/DefaultAggWidget.js create mode 100644 client/src/components/aggregations/LikertScaleAndPieWidget.js create mode 100644 client/src/components/aggregations/PieWidget.js create mode 100644 client/src/components/aggregations/ReportsByTaskWidget.js create mode 100644 client/src/components/aggregations/ReportsMapWidget.js diff --git a/client/src/components/ReportMap.js b/client/src/components/ReportMap.js index 1d32f53010..a6bbe250a9 100644 --- a/client/src/components/ReportMap.js +++ b/client/src/components/ReportMap.js @@ -1,6 +1,6 @@ import API from "api" import { gql } from "apollo-boost" -import { ReportsMapWidget } from "components/aggregations/AggregationWidgets" +import ReportsMapWidget from "components/aggregations/ReportsMapWidget" import { PageDispatchersPropType, mapPageDispatchersToProps, diff --git a/client/src/components/aggregations/AggregationWidgetContainer.js b/client/src/components/aggregations/AggregationWidgetContainer.js index ab9b14a01b..a6408239ca 100644 --- a/client/src/components/aggregations/AggregationWidgetContainer.js +++ b/client/src/components/aggregations/AggregationWidgetContainer.js @@ -1,3 +1,9 @@ +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, @@ -7,14 +13,6 @@ import { reportsByTaskAggregation, valuesListAggregation } from "components/aggregations/utils" -import { - CalendarWidget, - DefaultAggWidget, - LikertScaleAndPieWidget, - PieWidget, - ReportsByTaskWidget, - ReportsMapWidget -} from "components/aggregations/AggregationWidgets" import { getFieldPropsFromFieldConfig, SPECIAL_WIDGET_TYPES diff --git a/client/src/components/aggregations/AggregationWidgets.js b/client/src/components/aggregations/AggregationWidgets.js deleted file mode 100644 index 669853bee0..0000000000 --- a/client/src/components/aggregations/AggregationWidgets.js +++ /dev/null @@ -1,293 +0,0 @@ -import "@fullcalendar/core/main.css" -import dayGridPlugin from "@fullcalendar/daygrid" -import "@fullcalendar/daygrid/main.css" -import FullCalendar from "@fullcalendar/react" -import BarChart from "components/BarChart" -import LikertScale from "components/graphs/LikertScale" -import Pie from "components/graphs/Pie" -import Leaflet from "components/Leaflet" -import _escape from "lodash/escape" -import _isEmpty from "lodash/isEmpty" -import _uniqueId from "lodash/uniqueId" -import { Location } from "models" -import { AssessmentPeriodPropType, PeriodPropType } from "periodUtils" -import PropTypes from "prop-types" -import React, { useMemo, useRef, useState } from "react" -import { Button, Collapse, Table } from "react-bootstrap" -import utils from "utils" - -const DATE_FORMAT = "YYYY-MM-DD" - -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]) -} -const aggregationWidgetDefaultProps = { - whenUnspecified: null -} - -export 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 const LikertScaleAndPieWidget = ({ values, ...otherWidgetProps }) => { - const { likertScaleValues, pieValues } = values - return ( -
-
- -
- {!_isEmpty(likertScaleValues) && ( -
- -
- )} -
- ) -} -LikertScaleAndPieWidget.propTypes = aggregationWidgetPropTypes -LikertScaleAndPieWidget.defaultProps = aggregationWidgetDefaultProps - -export const ReportsByTaskWidget = ({ values, ...otherWidgetProps }) => ( -
- ` -

${d.task.shortName}

-

${d.reportsCount}

- `} - /> -
-) -ReportsByTaskWidget.propTypes = aggregationWidgetPropTypes -ReportsByTaskWidget.defaultProps = aggregationWidgetDefaultProps - -export 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 const DefaultAggWidget = ({ - values, - whenUnspecified, - ...otherWidgetProps -}) => { - const [showValues, setShowValues] = useState(false) - const filteredValues = values.filter(value => !utils.isNullOrUndefined(value)) - if (_isEmpty(filteredValues)) { - return whenUnspecified - } - return ( -
- - -
- Date: Tue, 19 May 2020 20:26:17 +0200 Subject: [PATCH 077/247] NCI-Agency/anet#2971: Add IqrBoxPlot widget for number type of fields --- .../AggregationWidgetContainer.js | 8 +- .../aggregations/AggregationWidgets.js | 20 --- .../aggregations/NumbersListAggregation.js | 25 +++ client/src/components/aggregations/utils.js | 9 +- client/src/components/graphs/IqrBoxPlot.js | 164 ++++++++++++++++++ src/main/resources/anet-schema.yml | 7 +- 6 files changed, 204 insertions(+), 29 deletions(-) create mode 100644 client/src/components/aggregations/NumbersListAggregation.js create mode 100644 client/src/components/graphs/IqrBoxPlot.js diff --git a/client/src/components/aggregations/AggregationWidgetContainer.js b/client/src/components/aggregations/AggregationWidgetContainer.js index c181d85b94..0da8c2f7c2 100644 --- a/client/src/components/aggregations/AggregationWidgetContainer.js +++ b/client/src/components/aggregations/AggregationWidgetContainer.js @@ -1,10 +1,10 @@ import { DefaultAggWidget, - NumberAggWidget, PieWidget, ReportsByTaskWidget } from "components/aggregations/AggregationWidgets" import { getFieldPropsFromFieldConfig } from "components/CustomFields" +import IqrBoxPlot from "components/graphs/IqrBoxPlot" import LikertScale from "components/graphs/LikertScale" import { CUSTOM_FIELD_TYPE } from "components/Model" import PropTypes from "prop-types" @@ -15,12 +15,12 @@ const AGGERGATION_WIDGET_TYPE = { LIKERT_SCALE: "likertScale", PIE: "pie", REPORTS_BY_TASK: "reportsByTask", - NUMBER_AGGREGATION: "numberAggregation", + IQR_BOX_PLOT: "iqrBoxPlot", DEFAULT: "default" } export const DEFAULT_AGGREGATION_WIDGET_PER_FIELD_TYPE = { [CUSTOM_FIELD_TYPE.TEXT]: AGGERGATION_WIDGET_TYPE.DEFAULT, - [CUSTOM_FIELD_TYPE.NUMBER]: AGGERGATION_WIDGET_TYPE.DEFAULT, + [CUSTOM_FIELD_TYPE.NUMBER]: AGGERGATION_WIDGET_TYPE.IQR_BOX_PLOT, [CUSTOM_FIELD_TYPE.DATE]: AGGERGATION_WIDGET_TYPE.DEFAULT, [CUSTOM_FIELD_TYPE.DATETIME]: AGGERGATION_WIDGET_TYPE.DEFAULT, [CUSTOM_FIELD_TYPE.ENUM]: AGGERGATION_WIDGET_TYPE.PIE, @@ -32,7 +32,7 @@ export const DEFAULT_AGGREGATION_WIDGET_PER_FIELD_TYPE = { const WIDGET_COMPONENTS = { [AGGERGATION_WIDGET_TYPE.LIKERT_SCALE]: LikertScale, [AGGERGATION_WIDGET_TYPE.PIE]: PieWidget, - [AGGERGATION_WIDGET_TYPE.NUMBER_AGGREGATION]: NumberAggWidget, + [AGGERGATION_WIDGET_TYPE.IQR_BOX_PLOT]: IqrBoxPlot, [AGGERGATION_WIDGET_TYPE.REPORTS_BY_TASK]: ReportsByTaskWidget, [AGGERGATION_WIDGET_TYPE.COUNT_PER_VALUE]: PieWidget, default: DefaultAggWidget diff --git a/client/src/components/aggregations/AggregationWidgets.js b/client/src/components/aggregations/AggregationWidgets.js index 9375a07f53..8faceab62c 100644 --- a/client/src/components/aggregations/AggregationWidgets.js +++ b/client/src/components/aggregations/AggregationWidgets.js @@ -19,26 +19,6 @@ const aggregationPropTypes = { 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) -} - -export const NumberAggWidget = ({ - values, - aggregationType, - ...otherWidgetProps -}) => - values?.length ? ( -
{NUMBER_AGG[aggregationType](arrayOfNumbers(values))}
- ) : null -NumberAggWidget.propTypes = aggregationPropTypes - export const PieWidget = ({ values, aggregationType, diff --git a/client/src/components/aggregations/NumbersListAggregation.js b/client/src/components/aggregations/NumbersListAggregation.js new file mode 100644 index 0000000000..1a360bddbb --- /dev/null +++ b/client/src/components/aggregations/NumbersListAggregation.js @@ -0,0 +1,25 @@ +import AggregationWidgetContainer from "components/aggregations/AggregationWidgetContainer" +import PropTypes from "prop-types" +import React from "react" + +const arrayOfNumbers = arr => + arr.filter(n => !isNaN(parseFloat(n)) && isFinite(n)).map(n => Number(n)) + +const NumbersListAggregation = ({ fieldName, fieldConfig, data }) => { + const values = data.map(item => Object.get(item, fieldName)) + const numberValues = arrayOfNumbers(values) + return ( + + ) +} +NumbersListAggregation.propTypes = { + data: PropTypes.array, + fieldName: PropTypes.string, + fieldConfig: PropTypes.object +} + +export default NumbersListAggregation diff --git a/client/src/components/aggregations/utils.js b/client/src/components/aggregations/utils.js index fe5139cc1b..1ec71a35dc 100644 --- a/client/src/components/aggregations/utils.js +++ b/client/src/components/aggregations/utils.js @@ -1,17 +1,19 @@ -import ValuesListAggregation from "components/aggregations/ValuesListAggregation" -import ReportsByTaskAggregation from "components/aggregations/ReportsByTaskAggregation" import CountPerValueAggregation from "components/aggregations/CountPerValueAggregation" +import NumbersListAggregation from "components/aggregations/NumbersListAggregation" +import ReportsByTaskAggregation from "components/aggregations/ReportsByTaskAggregation" +import ValuesListAggregation from "components/aggregations/ValuesListAggregation" import { CUSTOM_FIELD_TYPE } from "components/Model" export const AGGREGATION_TYPE = { REPORTS_BY_TASK: "countReportsByTask", COUNT_PER_VALUE: "countPerValue", + NUMBERS_LIST: "numbersList", VALUES_LIST: "valuesList" } export const DEFAULT_AGGREGATION_TYPE_PER_FIELD_TYPE = { [CUSTOM_FIELD_TYPE.TEXT]: AGGREGATION_TYPE.VALUES_LIST, - [CUSTOM_FIELD_TYPE.NUMBER]: AGGREGATION_TYPE.VALUES_LIST, + [CUSTOM_FIELD_TYPE.NUMBER]: AGGREGATION_TYPE.NUMBERS_LIST, [CUSTOM_FIELD_TYPE.DATE]: AGGREGATION_TYPE.VALUES_LIST, [CUSTOM_FIELD_TYPE.DATETIME]: AGGREGATION_TYPE.VALUES_LIST, [CUSTOM_FIELD_TYPE.ENUM]: AGGREGATION_TYPE.COUNT_PER_VALUE, @@ -23,5 +25,6 @@ export const DEFAULT_AGGREGATION_TYPE_PER_FIELD_TYPE = { export const AGGREGATION_TYPE_COMPONENTS = { [AGGREGATION_TYPE.REPORTS_BY_TASK]: ReportsByTaskAggregation, [AGGREGATION_TYPE.COUNT_PER_VALUE]: CountPerValueAggregation, + [AGGREGATION_TYPE.NUMBERS_LIST]: NumbersListAggregation, [AGGREGATION_TYPE.VALUES_LIST]: ValuesListAggregation } diff --git a/client/src/components/graphs/IqrBoxPlot.js b/client/src/components/graphs/IqrBoxPlot.js new file mode 100644 index 0000000000..7d7916eaec --- /dev/null +++ b/client/src/components/graphs/IqrBoxPlot.js @@ -0,0 +1,164 @@ +import React, { useEffect, useRef } from "react" +import * as d3 from "d3" +import PropTypes from "prop-types" +import useDimensions from "react-use-dimensions" + +const IqrBoxPlot = ({ onChange, values, levels, width, height, readonly }) => { + 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[index - 1] + sortedData[index]) / 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 (values.length === 0) { + return null + } else { + return ( + + {values?.length > 1 && ( + + + + + + + + + )} + + + {onChange && ( + + + + )} + + ) + } +} + +IqrBoxPlot.propTypes = { + values: PropTypes.arrayOf(PropTypes.number), + onChange: PropTypes.func, + 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, + readonly: PropTypes.bool +} + +IqrBoxPlot.defaultProps = { + levels: [ + { + color: "red", + endValue: 3 + }, + { + color: "#FFBF00", + endValue: 7 + }, + { + color: "green", + endValue: 10 + } + ], + height: "65", + width: "100%" +} + +export default IqrBoxPlot diff --git a/src/main/resources/anet-schema.yml b/src/main/resources/anet-schema.yml index e20a888f4b..b2cb14d99c 100644 --- a/src/main/resources/anet-schema.yml +++ b/src/main/resources/anet-schema.yml @@ -97,9 +97,12 @@ definitions: aggregation: type: object properties: + aggregationType: + type: string + enum: [countPerValue, numbersList, valuesList] widget: type: string - enum: [likertScale, numberAggregation, countPerValue, default] + enum: [pie, iqrBoxPlot, likertScale, default] dependencies: widget: oneOf: @@ -108,7 +111,7 @@ definitions: enum: [likertScale, countPerValue, default] - properties: type: - enum: [numberAggregation] + enum: [iqrBoxPlot] aggregationType: type: string enum: [sum, avg, min, max] From 6b3b9fe694a00c744f7a85a3c47ad83141c7e034 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 19 May 2020 23:30:32 +0200 Subject: [PATCH 078/247] NCI-Agency/anet#2971: Fix assessment aggregation widgets They were no longer working for enum fields, as the values were not properly aggregated for a pie type of widget. We now also use the AggregationComponent for the aggregation of instant assessments results to make sure the data is being aggregated properly. --- client/src/components/Model.js | 19 ++++--------------- client/src/components/ReportStatistics.js | 18 +++++------------- .../AggregationWidgetContainer.js | 3 ++- client/src/components/aggregations/utils.js | 13 ++++++++++--- .../assessments/AssessmentResultsTable.js | 14 +++++++++++--- 5 files changed, 32 insertions(+), 35 deletions(-) diff --git a/client/src/components/Model.js b/client/src/components/Model.js index 9485b6d2a7..86317d5407 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -463,7 +463,7 @@ export default class Model { const publishedReportsUuids = publishedReports ? publishedReports.map(r => r.uuid) : undefined - const assessmentsNotes = this.notes + return this.notes .filter( n => n.type === NOTE_TYPE.ASSESSMENT && @@ -478,22 +478,11 @@ export default class Model { (!dateRange || (n.createdAt <= dateRange.end && n.createdAt >= dateRange.start)) ) - .map(note => ({ note: note, assessment: JSON.parse(note.text) })) + .map(note => JSON.parse(note.text)) .filter( obj => - obj.assessment.__recurrence === ASSESSMENTS_RECURRENCE_TYPE.ONCE && - obj.assessment.__relatedObjectType === relatedObjectType + obj.__recurrence === ASSESSMENTS_RECURRENCE_TYPE.ONCE && + obj.__relatedObjectType === relatedObjectType ) - const assessmentsResults = {} - assessmentsNotes.forEach(n => { - const a = n.assessment - Object.keys(a).forEach(k => { - if (!Object.prototype.hasOwnProperty.call(assessmentsResults, k)) { - assessmentsResults[k] = [] - } - assessmentsResults[k].push(a[k]) - }) - }) - return assessmentsResults } } diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index 1182da62c5..d2e411a325 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -1,9 +1,6 @@ import API, { Settings } from "api" import { gql } from "apollo-boost" -import { - AGGREGATION_TYPE_COMPONENTS, - DEFAULT_AGGREGATION_TYPE_PER_FIELD_TYPE -} from "components/aggregations/utils" +import { getAggregationComponentForFieldConfig } from "components/aggregations/utils" import { PageDispatchersPropType, useBoilerplate } from "components/Page" import _get from "lodash/get" import { Report } from "models" @@ -89,17 +86,12 @@ const FieldStatisticsRow = ({ periods, periodsData }) => { - if ( - !fieldConfig.aggregation && - !DEFAULT_AGGREGATION_TYPE_PER_FIELD_TYPE[fieldConfig.type] - ) { + const AggregationComponent = getAggregationComponentForFieldConfig( + fieldConfig + ) + if (!AggregationComponent) { return null } - const AggregationComponent = - AGGREGATION_TYPE_COMPONENTS[ - fieldConfig.aggregation?.aggregationType || - DEFAULT_AGGREGATION_TYPE_PER_FIELD_TYPE[fieldConfig.type] - ] return (
-
- { + const aggregationFunction = getAggregationFunctionForFieldConfig(fieldConfig) + const { values, ...otherAggregationDetails } = aggregationFunction( + fieldName, + fieldConfig, + data + ) + const fieldProps = getFieldPropsFromFieldConfig(fieldConfig) const label = fieldProps.label + const widget = fieldConfig.aggregation?.widget || (fieldConfig.widget && @@ -63,10 +72,11 @@ const AggregationWidgetContainer = ({ ) return ( @@ -92,7 +102,7 @@ const AggregationWidgetContainer = ({ ) } AggregationWidgetContainer.propTypes = { - values: PropTypes.any, + data: PropTypes.any, fieldConfig: PropTypes.object, fieldName: PropTypes.string, vertical: PropTypes.bool diff --git a/client/src/components/aggregations/CountPerDateAggregation.js b/client/src/components/aggregations/CountPerDateAggregation.js deleted file mode 100644 index 842defc78f..0000000000 --- a/client/src/components/aggregations/CountPerDateAggregation.js +++ /dev/null @@ -1,31 +0,0 @@ -import AggregationWidgetContainer from "components/aggregations/AggregationWidgetContainer" -import moment from "moment" -import PropTypes from "prop-types" -import React from "react" - -const CountPerDateAggregation = ({ fieldName, fieldConfig, data }) => { - const countPerDate = 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 ( - - ) -} -CountPerDateAggregation.propTypes = { - data: PropTypes.array, - fieldName: PropTypes.string, - fieldConfig: PropTypes.object -} - -export default CountPerDateAggregation diff --git a/client/src/components/aggregations/CountPerValueAggregation.js b/client/src/components/aggregations/CountPerValueAggregation.js deleted file mode 100644 index 92336f5790..0000000000 --- a/client/src/components/aggregations/CountPerValueAggregation.js +++ /dev/null @@ -1,66 +0,0 @@ -import AggregationWidgetContainer from "components/aggregations/AggregationWidgetContainer" -import _clone from "lodash/clone" -import _isEmpty from "lodash/isEmpty" -import PropTypes from "prop-types" -import React from "react" - -// TODO: maybe use a library for a list of colors -const CHART_COLORS = [ - "#3366CC", - "#DC3912", - "#FF9900", - "#109618", - "#990099", - "#3B3EAC", - "#0099C6", - "#DD4477", - "#66AA00", - "#B82E2E", - "#316395", - "#994499", - "#22AA99", - "#AAAA11", - "#6633CC", - "#E67300", - "#8B0707", - "#329262", - "#5574A6", - "#3B3EAC" -] -const CountPerValueAggregation = ({ fieldName, fieldConfig, data }) => { - const counters = data.reduce((counter, entity) => { - const value = Object.get(entity, fieldName) || null - counter[value] = ++counter[value] || 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.pop() - }) - ) - legend.null = { label: "Unspecified", color: "#bbbbbb" } - - return ( - - ) -} -CountPerValueAggregation.propTypes = { - data: PropTypes.array, - fieldName: PropTypes.string, - fieldConfig: PropTypes.object -} - -export default CountPerValueAggregation diff --git a/client/src/components/aggregations/NumbersListAggregation.js b/client/src/components/aggregations/NumbersListAggregation.js deleted file mode 100644 index 1d14bd81e2..0000000000 --- a/client/src/components/aggregations/NumbersListAggregation.js +++ /dev/null @@ -1,26 +0,0 @@ -import AggregationWidgetContainer from "components/aggregations/AggregationWidgetContainer" -import PropTypes from "prop-types" -import React from "react" - -const arrayOfNumbers = arr => - arr.filter(n => !isNaN(parseFloat(n)) && isFinite(n)).map(n => Number(n)) - -const NumbersListAggregation = ({ fieldName, fieldConfig, data }) => { - const values = data.map(item => Object.get(item, fieldName)) - const numberValues = arrayOfNumbers(values) - return ( - - ) -} -NumbersListAggregation.propTypes = { - data: PropTypes.array, - fieldName: PropTypes.string, - fieldConfig: PropTypes.object -} - -export default NumbersListAggregation diff --git a/client/src/components/aggregations/ReportsByTaskAggregation.js b/client/src/components/aggregations/ReportsByTaskAggregation.js deleted file mode 100644 index 26506dfa8e..0000000000 --- a/client/src/components/aggregations/ReportsByTaskAggregation.js +++ /dev/null @@ -1,59 +0,0 @@ -import { Settings } from "api" -import AggregationWidgetContainer from "components/aggregations/AggregationWidgetContainer" -import PropTypes from "prop-types" -import React from "react" - -const noTaskMessage = `No ${Settings.fields.task.subLevel.shortLabel}` -const noTask = { - uuid: "-1", - shortName: noTaskMessage, - longName: noTaskMessage -} - -// TODO: use it also in components/ReportsByTasks -const getReportsByTasks = reportsList => { - 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 - }) -} - -const ReportsByTaskAggregation = ({ fieldName, fieldConfig, data }) => { - const values = getReportsByTasks(data) - return ( - - ) -} -ReportsByTaskAggregation.propTypes = { - data: PropTypes.array, - fieldName: PropTypes.string, - fieldConfig: PropTypes.object -} - -export default ReportsByTaskAggregation diff --git a/client/src/components/aggregations/ValuesListAggregation.js b/client/src/components/aggregations/ValuesListAggregation.js deleted file mode 100644 index 7f489dbffb..0000000000 --- a/client/src/components/aggregations/ValuesListAggregation.js +++ /dev/null @@ -1,22 +0,0 @@ -import AggregationWidgetContainer from "components/aggregations/AggregationWidgetContainer" -import PropTypes from "prop-types" -import React from "react" - -const ValuesListAggregation = ({ fieldName, fieldConfig, data }) => { - const values = data.map(item => Object.get(item, fieldName)) - return ( - - ) -} -ValuesListAggregation.propTypes = { - data: PropTypes.array, - fieldName: PropTypes.string, - fieldConfig: PropTypes.object -} - -export default ValuesListAggregation diff --git a/client/src/components/aggregations/utils.js b/client/src/components/aggregations/utils.js index a0b8cea620..4c950ef859 100644 --- a/client/src/components/aggregations/utils.js +++ b/client/src/components/aggregations/utils.js @@ -1,9 +1,8 @@ -import CountPerValueAggregation from "components/aggregations/CountPerValueAggregation" -import CountPerDateAggregation from "components/aggregations/CountPerDateAggregation" -import NumbersListAggregation from "components/aggregations/NumbersListAggregation" -import ReportsByTaskAggregation from "components/aggregations/ReportsByTaskAggregation" -import ValuesListAggregation from "components/aggregations/ValuesListAggregation" +import { Settings } from "api" import { CUSTOM_FIELD_TYPE } from "components/Model" +import _clone from "lodash/clone" +import _isEmpty from "lodash/isEmpty" +import moment from "moment" const AGGREGATION_TYPE = { REPORTS_BY_TASK: "countReportsByTask", @@ -24,17 +23,127 @@ const DEFAULT_AGGREGATION_TYPE_PER_FIELD_TYPE = { [CUSTOM_FIELD_TYPE.SPECIAL_FIELD]: AGGREGATION_TYPE.VALUES_LIST } -const AGGREGATION_TYPE_COMPONENTS = { - [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 +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 } } -export const getAggregationComponentForFieldConfig = fieldConfig => { +// TODO: maybe use a library for a list of colors +const CHART_COLORS = [ + "#3366CC", + "#DC3912", + "#FF9900", + "#109618", + "#990099", + "#3B3EAC", + "#0099C6", + "#DD4477", + "#66AA00", + "#B82E2E", + "#316395", + "#994499", + "#22AA99", + "#AAAA11", + "#6633CC", + "#E67300", + "#8B0707", + "#329262", + "#5574A6", + "#3B3EAC" +] +const countPerValueAggregation = (fieldName, fieldConfig, data) => { + const counters = data.reduce((counter, entity) => { + const value = Object.get(entity, fieldName) || null + counter[value] = ++counter[value] || 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.pop() + }) + ) + legend.null = { label: "Unspecified", color: "#bbbbbb" } + return { values: counters, legend: legend } +} + +const arrayOfNumbers = arr => + arr.filter(n => !isNaN(parseFloat(n)) && isFinite(n)).map(n => Number(n)) + +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 +} + +// TODO: use it also in components/ReportsByTasks +const getReportsByTasks = reportsList => { + 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 + }) +} + +const reportsByTaskAggregation = (fieldName, fieldConfig, data) => ({ + values: getReportsByTasks(data) +}) + +const valuesListAggregation = (fieldName, fieldConfig, data) => ({ + values: data.map(item => Object.get(item, fieldName)) +}) + +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 +} + +export const getAggregationFunctionForFieldConfig = fieldConfig => { const aggregationType = fieldConfig.aggregation?.aggregationType || DEFAULT_AGGREGATION_TYPE_PER_FIELD_TYPE[fieldConfig.type] - return aggregationType ? AGGREGATION_TYPE_COMPONENTS[aggregationType] : null + return aggregationType ? AGGREGATION_TYPE_FUNCTION[aggregationType] : null } diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index 9de74bb82f..a6dbc4ac16 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -1,8 +1,8 @@ -import { getAggregationComponentForFieldConfig } from "components/aggregations/utils" +import AggregationWidgetContainer from "components/aggregations/AggregationWidgetContainer" +import { getAggregationFunctionForFieldConfig } from "components/aggregations/utils" import AppContext from "components/AppContext" import AssessmentModal from "components/assessments/AssessmentModal" import PeriodicAssessment from "components/assessments/PeriodicAssessment" - import Fieldset from "components/Fieldset" import LinkTo from "components/LinkTo" import { NOTE_TYPE } from "components/Model" @@ -44,17 +44,18 @@ const InstantAssessmentRow = ({ entity, periods }) => { - const AggregationComponent = getAggregationComponentForFieldConfig( + const aggregationFunction = getAggregationFunctionForFieldConfig( questionConfig ) - if (!AggregationComponent) { + if (!aggregationFunction) { return null } + return (
- Date: Wed, 20 May 2020 23:17:40 +0200 Subject: [PATCH 083/247] NCI-Agency/anet#2971: Add LikertScaleAndPieWidget for aggregations This widget is being used by default for special fields having a likertScale widget. --- client/src/components/CustomFields.js | 2 +- .../AggregationWidgetContainer.js | 19 ++++++-- .../aggregations/AggregationWidgets.js | 12 +++++ client/src/components/aggregations/utils.js | 47 +++++++++++++++++-- 4 files changed, 71 insertions(+), 9 deletions(-) diff --git a/client/src/components/CustomFields.js b/client/src/components/CustomFields.js index 62fda30b45..8dc0203015 100644 --- a/client/src/components/CustomFields.js +++ b/client/src/components/CustomFields.js @@ -26,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" } diff --git a/client/src/components/aggregations/AggregationWidgetContainer.js b/client/src/components/aggregations/AggregationWidgetContainer.js index 45c8d49d7c..04827597b0 100644 --- a/client/src/components/aggregations/AggregationWidgetContainer.js +++ b/client/src/components/aggregations/AggregationWidgetContainer.js @@ -1,11 +1,15 @@ import { CalendarWidget, DefaultAggWidget, + LikertScaleAndPieWidget, PieWidget, ReportsByTaskWidget } from "components/aggregations/AggregationWidgets" import { getAggregationFunctionForFieldConfig } from "components/aggregations/utils" -import { getFieldPropsFromFieldConfig } from "components/CustomFields" +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" @@ -16,6 +20,7 @@ import { Col, ControlLabel, FormGroup } from "react-bootstrap" const AGGERGATION_WIDGET_TYPE = { LIKERT_SCALE: "likertScale", PIE: "pie", + LIKERT_SCALE_AND_PIE: "likertScaleAndPie", REPORTS_BY_TASK: "reportsByTask", IQR_BOX_PLOT: "iqrBoxPlot", CALENDAR: "calendar", @@ -30,12 +35,16 @@ const DEFAULT_AGGREGATION_WIDGET_PER_FIELD_TYPE = { [CUSTOM_FIELD_TYPE.ENUM]: AGGERGATION_WIDGET_TYPE.PIE, [CUSTOM_FIELD_TYPE.ENUMSET]: AGGERGATION_WIDGET_TYPE.PIE, [CUSTOM_FIELD_TYPE.ARRAY_OF_OBJECTS]: AGGERGATION_WIDGET_TYPE.DEFAULT, - [CUSTOM_FIELD_TYPE.SPECIAL_FIELD]: AGGERGATION_WIDGET_TYPE.DEFAULT + [CUSTOM_FIELD_TYPE.SPECIAL_FIELD]: { + [SPECIAL_WIDGET_TYPES.LIKERT_SCALE]: + AGGERGATION_WIDGET_TYPE.LIKERT_SCALE_AND_PIE + } } const 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.COUNT_PER_VALUE]: PieWidget, @@ -62,9 +71,9 @@ const AggregationWidgetContainer = ({ const widget = fieldConfig.aggregation?.widget || - (fieldConfig.widget && - WIDGET_COMPONENTS[fieldConfig.widget] && - fieldConfig.widget) || + DEFAULT_AGGREGATION_WIDGET_PER_FIELD_TYPE[fieldConfig.type][ + fieldConfig.widget + ] || DEFAULT_AGGREGATION_WIDGET_PER_FIELD_TYPE[fieldConfig.type] const WidgetComponent = (widget && WIDGET_COMPONENTS[widget]) || WIDGET_COMPONENTS.default diff --git a/client/src/components/aggregations/AggregationWidgets.js b/client/src/components/aggregations/AggregationWidgets.js index a225d55935..5014dbefbd 100644 --- a/client/src/components/aggregations/AggregationWidgets.js +++ b/client/src/components/aggregations/AggregationWidgets.js @@ -3,6 +3,7 @@ import dayGridPlugin from "@fullcalendar/daygrid" import "@fullcalendar/daygrid/main.css" import FullCalendar from "@fullcalendar/react" import BarChart from "components/BarChart" +import LikertScale from "components/graphs/LikertScale" import Pie from "components/graphs/Pie" import _uniqueId from "lodash/uniqueId" import PropTypes from "prop-types" @@ -50,6 +51,17 @@ PieWidget.propTypes = { ...aggregationWidgetPropTypes } +export const LikertScaleAndPieWidget = ({ values, ...otherWidgetProps }) => { + const { likertScaleValues, pieValues } = values + return ( + <> + + + + ) +} +LikertScaleAndPieWidget.propTypes = aggregationWidgetPropTypes + export const ReportsByTaskWidget = ({ values, ...otherWidgetProps }) => { return (
diff --git a/client/src/components/aggregations/utils.js b/client/src/components/aggregations/utils.js index 4c950ef859..307ab54194 100644 --- a/client/src/components/aggregations/utils.js +++ b/client/src/components/aggregations/utils.js @@ -1,4 +1,5 @@ import { Settings } from "api" +import { SPECIAL_WIDGET_TYPES } from "components/CustomFields" import { CUSTOM_FIELD_TYPE } from "components/Model" import _clone from "lodash/clone" import _isEmpty from "lodash/isEmpty" @@ -9,7 +10,8 @@ const AGGREGATION_TYPE = { COUNT_PER_DATE: "countPerDate", COUNT_PER_VALUE: "countPerValue", NUMBERS_LIST: "numbersList", - VALUES_LIST: "valuesList" + VALUES_LIST: "valuesList", + LIKERT_SCALE_AND_PIE_AGG: "likertScaleAndPieAgg" } const DEFAULT_AGGREGATION_TYPE_PER_FIELD_TYPE = { @@ -20,7 +22,10 @@ const DEFAULT_AGGREGATION_TYPE_PER_FIELD_TYPE = { [CUSTOM_FIELD_TYPE.ENUM]: AGGREGATION_TYPE.COUNT_PER_VALUE, [CUSTOM_FIELD_TYPE.ENUMSET]: AGGREGATION_TYPE.COUNT_PER_VALUE, [CUSTOM_FIELD_TYPE.ARRAY_OF_OBJECTS]: AGGREGATION_TYPE.VALUES_LIST, - [CUSTOM_FIELD_TYPE.SPECIAL_FIELD]: AGGREGATION_TYPE.VALUES_LIST + [CUSTOM_FIELD_TYPE.SPECIAL_FIELD]: { + [SPECIAL_WIDGET_TYPES.LIKERT_SCALE]: + AGGREGATION_TYPE.LIKERT_SCALE_AND_PIE_AGG + } } const countPerDateAggregation = (fieldName, fieldConfig, data) => { @@ -133,17 +138,53 @@ const valuesListAggregation = (fieldName, fieldConfig, data) => ({ values: data.map(item => Object.get(item, fieldName)) }) +const countPerLevelAggregation = (fieldName, fieldConfig, data) => { + const levels = fieldConfig.levels + if (_isEmpty(levels)) { + return null + } + const levelsEndValues = levels + .map(level => level.endValue) + .sort((a, b) => a - b) + const counters = data.reduce((counter, entity) => { + const value = Object.get(entity, fieldName) || null + const levelEndValue = + value !== null ? levelsEndValues.filter(x => x >= 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, legend: legend } +} + +const likertScaleAndPieAggregation = (fieldName, fieldConfig, data) => { + return { + values: { + likertScaleValues: valuesListAggregation(fieldName, fieldConfig, data), + pieValues: countPerLevelAggregation(fieldName, fieldConfig, data) + } + } +} + 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.VALUES_LIST]: valuesListAggregation, + [AGGREGATION_TYPE.LIKERT_SCALE_AND_PIE_AGG]: likertScaleAndPieAggregation } export const getAggregationFunctionForFieldConfig = fieldConfig => { const aggregationType = fieldConfig.aggregation?.aggregationType || + DEFAULT_AGGREGATION_TYPE_PER_FIELD_TYPE[fieldConfig.type][ + fieldConfig.widget + ] || DEFAULT_AGGREGATION_TYPE_PER_FIELD_TYPE[fieldConfig.type] return aggregationType ? AGGREGATION_TYPE_FUNCTION[aggregationType] : null } From f190e6beaed618051148c9e824c0cae64824d37e Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 21 May 2020 00:24:14 +0200 Subject: [PATCH 084/247] NCI-Agency/anet#2971: Make default aggregation depend on the widget The default aggregation used to be determined based on the field type. The aggregation widget was also determined based on the field type. But that way, if a user configured the widget but didn't configure the aggregation the default aggregation for the field type would have been used and might have ended up in errors. --- client/src/components/ReportStatistics.js | 9 ++- .../AggregationWidgetContainer.js | 79 ++++++++++++++++--- client/src/components/aggregations/utils.js | 58 ++------------ .../assessments/AssessmentResultsTable.js | 11 ++- insertBaseData-mssql.sql | 4 +- 5 files changed, 85 insertions(+), 76 deletions(-) diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index 3e9b22c8e1..79e34ae290 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -1,7 +1,8 @@ import API, { Settings } from "api" import { gql } from "apollo-boost" -import AggregationWidgetContainer from "components/aggregations/AggregationWidgetContainer" -import { getAggregationFunctionForFieldConfig } from "components/aggregations/utils" +import AggregationWidgetContainer, { + getAggregationWidget +} from "components/aggregations/AggregationWidgetContainer" import { PageDispatchersPropType, useBoilerplate } from "components/Page" import _get from "lodash/get" import { Report } from "models" @@ -87,8 +88,8 @@ const FieldStatisticsRow = ({ periods, periodsData }) => { - const aggregationFunction = getAggregationFunctionForFieldConfig(fieldConfig) - if (!aggregationFunction) { + const aggregationWidget = getAggregationWidget(fieldConfig) + if (!aggregationWidget) { return null } return ( diff --git a/client/src/components/aggregations/AggregationWidgetContainer.js b/client/src/components/aggregations/AggregationWidgetContainer.js index 04827597b0..dd724c43ee 100644 --- a/client/src/components/aggregations/AggregationWidgetContainer.js +++ b/client/src/components/aggregations/AggregationWidgetContainer.js @@ -1,3 +1,11 @@ +import { + countPerDateAggregation, + countPerValueAggregation, + likertScaleAndPieAggregation, + numbersListAggregation, + reportsByTaskAggregation, + valuesListAggregation +} from "components/aggregations/utils" import { CalendarWidget, DefaultAggWidget, @@ -5,7 +13,6 @@ import { PieWidget, ReportsByTaskWidget } from "components/aggregations/AggregationWidgets" -import { getAggregationFunctionForFieldConfig } from "components/aggregations/utils" import { getFieldPropsFromFieldConfig, SPECIAL_WIDGET_TYPES @@ -41,7 +48,7 @@ const DEFAULT_AGGREGATION_WIDGET_PER_FIELD_TYPE = { } } -const WIDGET_COMPONENTS = { +const AGGREGATION_WIDGET_COMPONENTS = { [AGGERGATION_WIDGET_TYPE.LIKERT_SCALE]: LikertScale, [AGGERGATION_WIDGET_TYPE.PIE]: PieWidget, [AGGERGATION_WIDGET_TYPE.LIKERT_SCALE_AND_PIE]: LikertScaleAndPieWidget, @@ -49,7 +56,52 @@ const WIDGET_COMPONENTS = { [AGGERGATION_WIDGET_TYPE.REPORTS_BY_TASK]: ReportsByTaskWidget, [AGGERGATION_WIDGET_TYPE.COUNT_PER_VALUE]: PieWidget, [AGGERGATION_WIDGET_TYPE.CALENDAR]: CalendarWidget, - default: DefaultAggWidget + [AGGERGATION_WIDGET_TYPE.DEFAULT]: DefaultAggWidget +} + +const AGGREGATION_TYPE = { + REPORTS_BY_TASK: "countReportsByTask", + COUNT_PER_DATE: "countPerDate", + COUNT_PER_VALUE: "countPerValue", + NUMBERS_LIST: "numbersList", + VALUES_LIST: "valuesList", + 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.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.LIKERT_SCALE_AND_PIE_AGG]: likertScaleAndPieAggregation +} + +export const getAggregationWidget = fieldConfig => + fieldConfig.aggregation?.widget || + DEFAULT_AGGREGATION_WIDGET_PER_FIELD_TYPE[fieldConfig.type][ + fieldConfig.widget + ] || + DEFAULT_AGGREGATION_WIDGET_PER_FIELD_TYPE[fieldConfig.type] + +const getAggregationFunction = (fieldConfig, aggregationWidget) => { + const aggregationType = + fieldConfig.aggregation?.aggregationType || + DEFAULT_AGGREGATION_TYPE_PER_WIDGET_TYPE[aggregationWidget] + return aggregationType + ? AGGREGATION_TYPE_FUNCTION[aggregationType] || null + : null } const AggregationWidgetContainer = ({ @@ -59,24 +111,25 @@ const AggregationWidgetContainer = ({ vertical, ...otherWidgetProps }) => { - const aggregationFunction = getAggregationFunctionForFieldConfig(fieldConfig) + const aggregationWidget = getAggregationWidget(fieldConfig) + const aggregationFunction = getAggregationFunction( + fieldConfig, + aggregationWidget + ) + if (!aggregationFunction) { + return null + } + const { values, ...otherAggregationDetails } = aggregationFunction( fieldName, fieldConfig, data ) - const fieldProps = getFieldPropsFromFieldConfig(fieldConfig) const label = fieldProps.label - - const widget = - fieldConfig.aggregation?.widget || - DEFAULT_AGGREGATION_WIDGET_PER_FIELD_TYPE[fieldConfig.type][ - fieldConfig.widget - ] || - DEFAULT_AGGREGATION_WIDGET_PER_FIELD_TYPE[fieldConfig.type] const WidgetComponent = - (widget && WIDGET_COMPONENTS[widget]) || WIDGET_COMPONENTS.default + (aggregationWidget && AGGREGATION_WIDGET_COMPONENTS[aggregationWidget]) || + AGGREGATION_WIDGET_COMPONENTS.default const widgetElem = ( { +export const countPerDateAggregation = (fieldName, fieldConfig, data) => { const values = data.reduce((counter, entity) => { const dateFieldValue = Object.get(entity, fieldName) const value = dateFieldValue @@ -63,7 +38,7 @@ const CHART_COLORS = [ "#5574A6", "#3B3EAC" ] -const countPerValueAggregation = (fieldName, fieldConfig, data) => { +export const countPerValueAggregation = (fieldName, fieldConfig, data) => { const counters = data.reduce((counter, entity) => { const value = Object.get(entity, fieldName) || null counter[value] = ++counter[value] || 1 @@ -88,7 +63,7 @@ const countPerValueAggregation = (fieldName, fieldConfig, data) => { const arrayOfNumbers = arr => arr.filter(n => !isNaN(parseFloat(n)) && isFinite(n)).map(n => Number(n)) -const numbersListAggregation = (fieldName, fieldConfig, data) => { +export const numbersListAggregation = (fieldName, fieldConfig, data) => { const values = data.map(item => Object.get(item, fieldName)) const numberValues = arrayOfNumbers(values) return { values: numberValues } @@ -130,15 +105,15 @@ const getReportsByTasks = reportsList => { }) } -const reportsByTaskAggregation = (fieldName, fieldConfig, data) => ({ +export const reportsByTaskAggregation = (fieldName, fieldConfig, data) => ({ values: getReportsByTasks(data) }) -const valuesListAggregation = (fieldName, fieldConfig, data) => ({ +export const valuesListAggregation = (fieldName, fieldConfig, data) => ({ values: data.map(item => Object.get(item, fieldName)) }) -const countPerLevelAggregation = (fieldName, fieldConfig, data) => { +export const countPerLevelAggregation = (fieldName, fieldConfig, data) => { const levels = fieldConfig.levels if (_isEmpty(levels)) { return null @@ -161,7 +136,7 @@ const countPerLevelAggregation = (fieldName, fieldConfig, data) => { return { values: counters, legend: legend } } -const likertScaleAndPieAggregation = (fieldName, fieldConfig, data) => { +export const likertScaleAndPieAggregation = (fieldName, fieldConfig, data) => { return { values: { likertScaleValues: valuesListAggregation(fieldName, fieldConfig, data), @@ -169,22 +144,3 @@ const likertScaleAndPieAggregation = (fieldName, fieldConfig, data) => { } } } - -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.LIKERT_SCALE_AND_PIE_AGG]: likertScaleAndPieAggregation -} - -export const getAggregationFunctionForFieldConfig = fieldConfig => { - const aggregationType = - fieldConfig.aggregation?.aggregationType || - DEFAULT_AGGREGATION_TYPE_PER_FIELD_TYPE[fieldConfig.type][ - fieldConfig.widget - ] || - DEFAULT_AGGREGATION_TYPE_PER_FIELD_TYPE[fieldConfig.type] - return aggregationType ? AGGREGATION_TYPE_FUNCTION[aggregationType] : null -} diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index a6dbc4ac16..557cbb3165 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -1,5 +1,6 @@ -import AggregationWidgetContainer from "components/aggregations/AggregationWidgetContainer" -import { getAggregationFunctionForFieldConfig } from "components/aggregations/utils" +import AggregationWidgetContainer, { + getAggregationWidget +} from "components/aggregations/AggregationWidgetContainer" import AppContext from "components/AppContext" import AssessmentModal from "components/assessments/AssessmentModal" import PeriodicAssessment from "components/assessments/PeriodicAssessment" @@ -44,10 +45,8 @@ const InstantAssessmentRow = ({ entity, periods }) => { - const aggregationFunction = getAggregationFunctionForFieldConfig( - questionConfig - ) - if (!aggregationFunction) { + const aggregationWidget = getAggregationWidget(questionConfig) + if (!aggregationWidget) { return null } diff --git a/insertBaseData-mssql.sql b/insertBaseData-mssql.sql index 182af58d98..84d32d5502 100644 --- a/insertBaseData-mssql.sql +++ b/insertBaseData-mssql.sql @@ -319,9 +319,9 @@ 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', '{ "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\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Test Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }","relatedObjectType":"report"}] }'), + (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\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Monthly assessment Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }","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\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Weekly assessment Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }","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\", \"aggregationType\": \"avg\" } }, \"question3\": { \"type\": \"number\", \"label\": \"Instant assessment Question 3\", \"aggregation\": { \"widget\": \"numberAggregation\", \"aggregationType\": \"sum\" } } }","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 From 812f7d8ceaa85163ec0ac91a1e1e689ae9686818 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 21 May 2020 01:01:46 +0200 Subject: [PATCH 085/247] NCI-Agency/anet#2971: Fix legend for LikertScaleAndPie widget The legend was not displaying all possible levels. --- client/src/components/aggregations/utils.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/client/src/components/aggregations/utils.js b/client/src/components/aggregations/utils.js index c972335911..c25f1aa4e9 100644 --- a/client/src/components/aggregations/utils.js +++ b/client/src/components/aggregations/utils.js @@ -118,20 +118,21 @@ export const countPerLevelAggregation = (fieldName, fieldConfig, data) => { if (_isEmpty(levels)) { return null } - const levelsEndValues = levels - .map(level => level.endValue) - .sort((a, b) => a - b) + 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(x => x >= value)[0] : null + 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, legend: legend } } From 449924a55eafb4815e8bed9da120347df5b00814 Mon Sep 17 00:00:00 2001 From: vassil Date: Thu, 21 May 2020 11:46:46 +0200 Subject: [PATCH 086/247] nci-agency/anet#2954: Prevent bad json from stopping pages to render --- client/src/components/Model.js | 6 ++-- .../src/components/RelatedObjectNoteModal.js | 4 ++- client/src/components/RelatedObjectNotes.js | 5 +-- client/src/components/ReportStatistics.js | 4 ++- client/src/models/Report.js | 2 +- client/src/models/Task.js | 2 +- client/src/pages/people/Edit.js | 5 +-- client/src/pages/people/Show.js | 9 ++--- client/src/pages/reports/Edit.js | 5 +-- client/src/pages/reports/Show.js | 2 +- client/src/pages/tasks/Edit.js | 7 ++-- client/src/pages/tasks/Show.js | 33 +++++++------------ client/src/utils.js | 10 ++++++ 13 files changed, 53 insertions(+), 41 deletions(-) diff --git a/client/src/components/Model.js b/client/src/components/Model.js index 86317d5407..7efba31ad8 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -365,7 +365,7 @@ export default class Model { typeof questions === "object" ? questions : typeof questions === "string" - ? JSON.parse(questions) + ? utils.parseJsonSafe(questions) : {} ] }) @@ -416,7 +416,7 @@ export default class Model { ) }) .sort((a, b) => b.createdAt - a.createdAt) // desc sorted - .map(note => ({ note: note, assessment: JSON.parse(note.text) })) + .map(note => ({ note: note, assessment: utils.parseJsonSafe(note.text) })) .filter( obj => // FIXME: make a nicer implementation of the check on period start @@ -478,7 +478,7 @@ export default class Model { (!dateRange || (n.createdAt <= dateRange.end && n.createdAt >= dateRange.start)) ) - .map(note => JSON.parse(note.text)) + .map(note => utils.parseJsonSafe(note.text)) .filter( obj => obj.__recurrence === ASSESSMENTS_RECURRENCE_TYPE.ONCE && diff --git a/client/src/components/RelatedObjectNoteModal.js b/client/src/components/RelatedObjectNoteModal.js index 7684e6d8cc..32ebc9051d 100644 --- a/client/src/components/RelatedObjectNoteModal.js +++ b/client/src/components/RelatedObjectNoteModal.js @@ -11,6 +11,7 @@ import { Field, Form, Formik } from "formik" 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 = ({ @@ -44,7 +45,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 || diff --git a/client/src/components/RelatedObjectNotes.js b/client/src/components/RelatedObjectNotes.js index 54e8876a3c..46311c1789 100644 --- a/client/src/components/RelatedObjectNotes.js +++ b/client/src/components/RelatedObjectNotes.js @@ -97,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]) counters[question.id] = {} @@ -252,7 +252,8 @@ const BaseRelatedObjectNotes = ({ note.type !== NOTE_TYPE.ASSESSMENT && (byMe || currentUser.isAdmin()) 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 : parseHtmlWithLinkTo(note.text) diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index 79e34ae290..3461ec660d 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -15,6 +15,7 @@ import pluralize from "pluralize" import PropTypes from "prop-types" import React, { useEffect } from "react" import { Table } from "react-bootstrap" +import utils from "utils" const REPORT_FIELDS_FOR_STATISTICS = { state: { @@ -151,7 +152,8 @@ const ReportStatistics = ({ elem.engagementDate >= dateRange.start ) reportsForDateRange.map( - report => (report[CUSTOM_FIELDS_KEY] = JSON.parse(report.customFields)) + report => + (report[CUSTOM_FIELDS_KEY] = utils.parseJsonSafe(report.customFields)) ) return reportsForDateRange } diff --git a/client/src/models/Report.js b/client/src/models/Report.js index 103115340d..4a4ab76682 100644 --- a/client/src/models/Report.js +++ b/client/src/models/Report.js @@ -412,7 +412,7 @@ export default class Report extends Model { .map(ro => ro.relatedObjectUuid) ], assessmentUuid: n.uuid, - assessment: JSON.parse(n.text) + assessment: utils.parseJsonSafe(n.text) })) // When updating the instant assessments, we need for each entity the uuid of the // related instant assessment diff --git a/client/src/models/Task.js b/client/src/models/Task.js index 4c975ef515..771a307030 100644 --- a/client/src/models/Task.js +++ b/client/src/models/Task.js @@ -179,6 +179,6 @@ export default class Task extends Model { instanceAssessmentsConfig() { // The given task instance might have a specific assessments config - return JSON.parse(this.customFields || "{}").assessments || [] + return utils.parseJsonSafe(this.customFields || "{}").assessments || [] } } diff --git a/client/src/pages/people/Edit.js b/client/src/pages/people/Edit.js index db09cad104..e0a0c9bc5c 100644 --- a/client/src/pages/people/Edit.js +++ b/client/src/pages/people/Edit.js @@ -3,8 +3,8 @@ 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, { @@ -15,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` @@ -75,7 +76,7 @@ const PersonEdit = ({ pageDispatchers }) => { const parsedFullName = Person.parseFullName(data.person.name) data.person.firstName = parsedFullName.firstName data.person.lastName = parsedFullName.lastName - data.person[DEFAULT_CUSTOM_FIELDS_PARENT] = JSON.parse( + data.person[DEFAULT_CUSTOM_FIELDS_PARENT] = utils.parseJsonSafe( data.person.customFields ) } diff --git a/client/src/pages/people/Show.js b/client/src/pages/people/Show.js index 308b382039..509bb7637b 100644 --- a/client/src/pages/people/Show.js +++ b/client/src/pages/people/Show.js @@ -14,18 +14,18 @@ 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_CALENDAR, FORMAT_MAP, FORMAT_SUMMARY, - FORMAT_TABLE, - FORMAT_CALENDAR + FORMAT_TABLE } from "components/ReportCollection" import { Field, Form, Formik } from "formik" import _isEmpty from "lodash/isEmpty" @@ -37,6 +37,7 @@ import React, { 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 utils from "utils" import { parseHtmlWithLinkTo } from "utils_links" const GQL_GET_PERSON = gql` @@ -120,7 +121,7 @@ const BasePersonShow = ({ pageDispatchers, currentUser }) => { return result } if (data) { - data.person[DEFAULT_CUSTOM_FIELDS_PARENT] = JSON.parse( + data.person[DEFAULT_CUSTOM_FIELDS_PARENT] = utils.parseJsonSafe( data.person.customFields ) } diff --git a/client/src/pages/reports/Edit.js b/client/src/pages/reports/Edit.js index 2bb602d01a..cf3d75b775 100644 --- a/client/src/pages/reports/Edit.js +++ b/client/src/pages/reports/Edit.js @@ -3,8 +3,8 @@ 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 +14,7 @@ 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` @@ -120,7 +121,7 @@ const ReportEdit = ({ pageDispatchers }) => { id: tag.uuid.toString(), text: tag.name })) - data.report[DEFAULT_CUSTOM_FIELDS_PARENT] = JSON.parse( + data.report[DEFAULT_CUSTOM_FIELDS_PARENT] = utils.parseJsonSafe( data.report.customFields ) } diff --git a/client/src/pages/reports/Show.js b/client/src/pages/reports/Show.js index c66c1cd74c..5a481e8e3c 100644 --- a/client/src/pages/reports/Show.js +++ b/client/src/pages/reports/Show.js @@ -303,7 +303,7 @@ const BaseReportShow = ({ currentUser, setSearchQuery, pageDispatchers }) => { data.report.tasks = Task.fromArray(data.report.tasks) data.report.attendees = Person.fromArray(data.report.attendees) data.report.to = "" - data.report[DEFAULT_CUSTOM_FIELDS_PARENT] = JSON.parse( + data.report[DEFAULT_CUSTOM_FIELDS_PARENT] = utils.parseJsonSafe( data.report.customFields ) report = new Report(data.report) diff --git a/client/src/pages/tasks/Edit.js b/client/src/pages/tasks/Edit.js index ef76aea50b..7917892c56 100644 --- a/client/src/pages/tasks/Edit.js +++ b/client/src/pages/tasks/Edit.js @@ -3,8 +3,8 @@ import API, { Settings } 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 +14,7 @@ import { Task } from "models" import React from "react" import { connect } from "react-redux" import { useParams } from "react-router-dom" +import utils from "utils" import TaskForm from "./Form" const GQL_GET_TASK = gql` @@ -111,7 +112,9 @@ const TaskEdit = ({ pageDispatchers }) => { return result } if (data) { - data.task[DEFAULT_CUSTOM_FIELDS_PARENT] = JSON.parse(data.task.customFields) + data.task[DEFAULT_CUSTOM_FIELDS_PARENT] = utils.parseJsonSafe( + data.task.customFields + ) } const task = new Task(data ? data.task : {}) diff --git a/client/src/pages/tasks/Show.js b/client/src/pages/tasks/Show.js index ef96fbcdaa..c7e3adffe9 100644 --- a/client/src/pages/tasks/Show.js +++ b/client/src/pages/tasks/Show.js @@ -27,6 +27,7 @@ import PropTypes from "prop-types" import React from "react" import { connect } from "react-redux" import { useLocation, useParams } from "react-router-dom" +import utils from "utils" import DictionaryField from "../../HOC/DictionaryField" const GQL_GET_TASK = gql` @@ -157,33 +158,23 @@ const BaseTaskShow = ({ pageDispatchers, currentUser }) => { } if (data) { - data.task[DEFAULT_CUSTOM_FIELDS_PARENT] = 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() + // TODO: Maybe move this code to Task() + data.task[DEFAULT_CUSTOM_FIELDS_PARENT] = utils.parseJsonSafe( + data.task.customFields + ) + data.task.notes.forEach( + note => (note.customFields = utils.parseJsonSafe(note.text)) + ) } 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() + // TODO: Maybe move this code to Task() + subTask.notes.forEach( + note => (note.customFields = utils.parseJsonSafe(note.text)) + ) subTasks.push(new Task(subTask)) }) diff --git a/client/src/utils.js b/client/src/utils.js index 1c806150fa..9e9aabafaf 100644 --- a/client/src/utils.js +++ b/client/src/utils.js @@ -151,6 +151,16 @@ export default { } else { location.hash = hash } + }, + + parseJsonSafe: function(jsonString) { + // TODO: Improve error handling so that consuming widgets can display an error w/o crashing + try { + return JSON.parse(jsonString) + } catch (error) { + console.error(`unable to parse JSON: ${jsonString}`) + } + return null } } From 8efc300d12676d4bee9015fc2bcdc74984d3f75a Mon Sep 17 00:00:00 2001 From: vassil Date: Thu, 21 May 2020 12:54:51 +0200 Subject: [PATCH 087/247] nci-agency/anet#2954: Layout improvements Truncate labels in BarChart, fix svgRef missing prop warning --- client/src/components/BarChart.js | 5 +- .../aggregations/AggregationWidgets.js | 52 +++++++++++++++---- .../components/graphs/OrganizationalChart.js | 2 - client/src/components/graphs/SVGCanvas.js | 13 ++--- 4 files changed, 48 insertions(+), 24 deletions(-) diff --git a/client/src/components/BarChart.js b/client/src/components/BarChart.js index 4fad434951..36b83d5807 100644 --- a/client/src/components/BarChart.js +++ b/client/src/components/BarChart.js @@ -50,7 +50,10 @@ const BarChart = ({ const xScale = d3.scaleBand().domain( data.map(function(d) { - xLabels[getPropValue(d, xProp)] = getPropValue(d, label) + xLabels[getPropValue(d, xProp)] = getPropValue(d, label).substring( + 0, + 10 + ) // TODO: Make responsive return getPropValue(d, xProp) }) ) diff --git a/client/src/components/aggregations/AggregationWidgets.js b/client/src/components/aggregations/AggregationWidgets.js index 5014dbefbd..74dbf9afff 100644 --- a/client/src/components/aggregations/AggregationWidgets.js +++ b/client/src/components/aggregations/AggregationWidgets.js @@ -26,7 +26,12 @@ const aggregationWidgetPropTypes = { vertical: PropTypes.bool } -export const PieWidget = ({ values, legend, ...otherWidgetProps }) => { +export const PieWidget = ({ + values, + legend, + showLegend, + ...otherWidgetProps +}) => { return ( <> { segmentFill={entity => legend[entity.data.key]?.color} segmentLabel={d => d.data.value} /> -
- {Object.map(legend, (key, choice) => ( - - {choice.label} - - ))} + {showLegend && ( + <> +
+ {Object.map(legend, (key, choice) => ( + + + {choice.label}{" "} + + + ))} + + )} ) } PieWidget.propTypes = { legend: PropTypes.object, + showLegend: PropTypes.bool, ...aggregationWidgetPropTypes } export const LikertScaleAndPieWidget = ({ values, ...otherWidgetProps }) => { const { likertScaleValues, pieValues } = values return ( - <> - - - +
+
+ +
+
+ +
+
) } LikertScaleAndPieWidget.propTypes = aggregationWidgetPropTypes diff --git a/client/src/components/graphs/OrganizationalChart.js b/client/src/components/graphs/OrganizationalChart.js index 9b9955a2ea..25f761c786 100644 --- a/client/src/components/graphs/OrganizationalChart.js +++ b/client/src/components/graphs/OrganizationalChart.js @@ -90,7 +90,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()) @@ -382,7 +381,6 @@ const OrganizationalChart = ({ return ( { +const SVGCanvas = ({ width, height, exportTitle, zoomFn, children }) => { + const svgRef = useRef(null) const exportSvg = () => { var svgBlob = new Blob( ['', svgRef.current.outerHTML], @@ -79,7 +73,6 @@ SVGCanvas.propTypes = { height: PropTypes.number.isRequired, exportTitle: PropTypes.string, zoomFn: PropTypes.func, - svgRef: PropTypes.object.isRequired, children: PropTypes.node } From a914eab3dc28800aba3b5253a7efcc6b282fc36c Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Mon, 25 May 2020 12:34:49 +0200 Subject: [PATCH 088/247] NCI-Agency/anet#2971: Specify aggregation for richTextEditor special field --- .../src/components/aggregations/AggregationWidgetContainer.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/components/aggregations/AggregationWidgetContainer.js b/client/src/components/aggregations/AggregationWidgetContainer.js index dd724c43ee..443a260603 100644 --- a/client/src/components/aggregations/AggregationWidgetContainer.js +++ b/client/src/components/aggregations/AggregationWidgetContainer.js @@ -44,7 +44,8 @@ const DEFAULT_AGGREGATION_WIDGET_PER_FIELD_TYPE = { [CUSTOM_FIELD_TYPE.ARRAY_OF_OBJECTS]: AGGERGATION_WIDGET_TYPE.DEFAULT, [CUSTOM_FIELD_TYPE.SPECIAL_FIELD]: { [SPECIAL_WIDGET_TYPES.LIKERT_SCALE]: - AGGERGATION_WIDGET_TYPE.LIKERT_SCALE_AND_PIE + AGGERGATION_WIDGET_TYPE.LIKERT_SCALE_AND_PIE, + [SPECIAL_WIDGET_TYPES.RICH_TEXT_EDITOR]: AGGERGATION_WIDGET_TYPE.DEFAULT } } From c48e1acb0729ca0bc1829154e814edf137cec87c Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Mon, 25 May 2020 15:32:15 +0200 Subject: [PATCH 089/247] NCI-Agency/anet#2971: Filter reports in ReportStatistics This makes sure that the ReportStatistics only retrieves reports from the given period of time. --- client/src/components/ReportStatistics.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index 3461ec660d..8530086eb2 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -121,7 +121,26 @@ const ReportStatistics = ({ setTotalCount, queryParams }) => { + const dateSortAsc = datesArray => datesArray.sort((a, b) => a - b) + const statisticsStartDate = dateSortAsc( + periodsConfig.periods.map(p => p.start) + )[0] + const statisticsEndDate = dateSortAsc(periodsConfig.periods.map(p => p.end))[ + periodsConfig.periods.length - 1 + ] const reportQuery = Object.assign({}, queryParams, { pageSize: 0 }) + if ( + !queryParams.engagementDateStart || + queryParams.engagementDateStart < statisticsStartDate + ) { + reportQuery.engagementDateStart = statisticsStartDate + } + if ( + !queryParams.engagementDateEnd || + queryParams.engagementDateEnd > statisticsEndDate + ) { + reportQuery.engagementDateEnd = statisticsEndDate + } const { loading, error, data } = API.useApiQuery(GQL_GET_REPORT_LIST, { reportQuery }) From 36f05aa3385178e20e66b26a71599d9fda88dde3 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 27 May 2020 12:11:02 +0200 Subject: [PATCH 090/247] NCI-Agency/anet#2971: Add include children orgs filter for org reports This makes it possible to filter the report collection of an organization on the organization page to also contain reports from sub-organizations. --- client/src/pages/organizations/Show.js | 44 ++++++++++++++++++++------ 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/client/src/pages/organizations/Show.js b/client/src/pages/organizations/Show.js index 6e3c776444..6d4a37d2e6 100644 --- a/client/src/pages/organizations/Show.js +++ b/client/src/pages/organizations/Show.js @@ -24,6 +24,7 @@ import ReportCollection, { FORMAT_SUMMARY, FORMAT_TABLE } 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" @@ -31,7 +32,13 @@ 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 { + Checkbox, + ListGroup, + ListGroupItem, + Nav, + Button +} from "react-bootstrap" import { connect } from "react-redux" import { useLocation, useParams } from "react-router-dom" import DictionaryField from "../../HOC/DictionaryField" @@ -127,6 +134,7 @@ const GQL_GET_ORGANIZATION = gql` const BaseOrganizationShow = ({ pageDispatchers, currentUser }) => { 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 +200,10 @@ const BaseOrganizationShow = ({ pageDispatchers, currentUser }) => { if (filterPendingApproval) { reportQueryParams.state = Report.STATE.PENDING_APPROVAL } + if (includeChildrenOrgs) { + reportQueryParams.orgRecurseStrategy = RECURSE_STRATEGY.CHILDREN + } + return ( {({ values }) => { @@ -389,15 +401,23 @@ const BaseOrganizationShow = ({ pageDispatchers, currentUser }) => { ]} reportsFilter={ !isSuperUser ? null : ( - + <> + + + include reports from sub-orgs + + ) } /> @@ -412,6 +432,10 @@ const BaseOrganizationShow = ({ pageDispatchers, currentUser }) => { function togglePendingApprovalFilter() { setFilterPendingApproval(!filterPendingApproval) } + + function toggleIncludeChildrenOrgs() { + setIncludeChildrenOrgs(!includeChildrenOrgs) + } } BaseOrganizationShow.propTypes = { From 483e1fe1024fa1edaacd18ff8db820a5bdb745bc Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 27 May 2020 12:19:40 +0200 Subject: [PATCH 091/247] NCI-Agency/anet#2889: Add missing dependency in BoardDashboard effect --- client/src/pages/dashboards/BoardDashboard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/pages/dashboards/BoardDashboard.js b/client/src/pages/dashboards/BoardDashboard.js index a42459d8eb..30c0389e21 100644 --- a/client/src/pages/dashboards/BoardDashboard.js +++ b/client/src/pages/dashboards/BoardDashboard.js @@ -153,7 +153,7 @@ const BoardDashboard = () => { }) model.getNodes().forEach(node => node.registerListener(selectionListener)) } - }, [model]) + }, [editedNode, model]) useEffect(() => { model && model.setLocked(!edit) From c2550d5f92fcad3f268217bb45fe2cda36dfbe22 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 27 May 2020 12:25:34 +0200 Subject: [PATCH 092/247] NCI-Agency/anet#2971: No legend for LikertScaleAndPieWidget widget The pie legend is not needed when using a LikertScaleAndPieWidget widget. --- client/src/components/aggregations/AggregationWidgets.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/components/aggregations/AggregationWidgets.js b/client/src/components/aggregations/AggregationWidgets.js index 74dbf9afff..cdf211c0e9 100644 --- a/client/src/components/aggregations/AggregationWidgets.js +++ b/client/src/components/aggregations/AggregationWidgets.js @@ -29,7 +29,7 @@ const aggregationWidgetPropTypes = { export const PieWidget = ({ values, legend, - showLegend, + showLegend = true, ...otherWidgetProps }) => { return ( @@ -78,7 +78,7 @@ export const LikertScaleAndPieWidget = ({ values, ...otherWidgetProps }) => { flexGrow: "0" }} > - +
Date: Wed, 27 May 2020 16:14:29 +0200 Subject: [PATCH 093/247] Fix handleChange of CustomFields When the customField value is null, handleChange would have tried to retrieve value.target, because typeOf null === object. That was resulting in an error. --- client/src/components/CustomFields.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/src/components/CustomFields.js b/client/src/components/CustomFields.js index 8dc0203015..36aa64d71b 100644 --- a/client/src/components/CustomFields.js +++ b/client/src/components/CustomFields.js @@ -468,8 +468,7 @@ const CustomField = ({ const [validateFormDebounced] = useDebouncedCallback(validateForm, 400) // with validateField it somehow doesn't work const handleChange = useMemo( () => (value, shouldValidate: true) => { - const val = - typeof value === "object" && value.target ? value.target.value : value + const val = value?.target?.value || value const sv = shouldValidate === undefined ? true : shouldValidate setFieldTouched(fieldName, true, false) setFieldValue(fieldName, val, sv) From 7ac559f69a5a89143e31dcdef7fcc7ee696f40ef Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 27 May 2020 16:19:36 +0200 Subject: [PATCH 094/247] NCI-Agency/anet#2971: Make it possible to (not/re)-set LikertScale value When the LikertScale was being used in a form - If the value displayed by the LikertScale was null or undefined, the cursor was showing the value 0, which was misleading. - It was also not possible to set the value of the LikertScale to null. - It was possible to click/drag outside the LikertScale itself. The LikertScale has been changed as follows: - When the value to be displayed is null or undefined, an empty cursor is being displayed within the left margin outside the scale. This way the user knows the cursor needs to be moved to the scale in order to set a value. - A user can set the value to null by moving the cursor to the left margin outside the scale. - Clicking/dragging in/on the left margin of the scale now results in the cursor being displayed empty in the middle of the margin. - Clicking/dragging in/on the right margin of the scale now results in the cursor being displayed on the last scale position. - When displaying the LikertScale on a readonly mode for a value of null we don't display the cursor any more. --- client/src/components/graphs/LikertScale.js | 102 +++++++++++++------- 1 file changed, 68 insertions(+), 34 deletions(-) diff --git a/client/src/components/graphs/LikertScale.js b/client/src/components/graphs/LikertScale.js index 59f0cb3f1f..afb22307c0 100644 --- a/client/src/components/graphs/LikertScale.js +++ b/client/src/components/graphs/LikertScale.js @@ -1,4 +1,4 @@ -import React, { useEffect, useRef } from "react" +import React, { useCallback, useEffect, useRef } from "react" import * as d3 from "d3" import PropTypes from "prop-types" import Text from "react-svg-text" @@ -19,14 +19,36 @@ const LikertScale = ({ const containerHeight = containerBox.height || 0 const containerWidth = containerBox.width || 0 const containerX = containerBox.x || 0 - const MARGIN = 13 + const MARGIN_LEFT = readonly ? 13 : 25 + 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 = + value !== undefined && value !== null + ? scale(Number(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 => { + const a = newX >= scale.range()[0] ? scale.invert(newX) : null + return a + }, + [scale] + ) useEffect(() => { if (readonly) { @@ -34,15 +56,20 @@ const LikertScale = ({ } 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, + readonly, + MARGIN_LEFT, + calculateNewX, + xToValue + ]) useEffect(() => { d3.select(cursorRef.current).attr( @@ -75,8 +102,12 @@ const LikertScale = ({ width={width} xmlns="http://www.w3.org/2000/svg" ref={containerRef} - onClick={e => - !readonly && e.clientX && onChange(scale.invert(e.clientX - containerX))} + onClick={e => { + if (!readonly && 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) @@ -172,27 +203,30 @@ const LikertScale = ({ )} - {onChange && ( - - - - {Number(value).toFixed(value < scale.domain()[1] ? 1 : 0)} - - + {onChange && + (!readonly || (readonly && value && value >= scale.domain()[0])) && ( + + + + {value && value >= scale.domain()[0] + ? Number(value).toFixed(value < scale.domain()[1] ? 1 : 0) + : null} + + )} ) @@ -216,7 +250,7 @@ LikertScale.propTypes = { } LikertScale.defaultProps = { - value: 0, + value: null, levels: [ { color: "red", From 42f2463fae2bfb9efc1bde3fe4726c8e2d132131 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 27 May 2020 17:15:22 +0200 Subject: [PATCH 095/247] NCI-Agency/anet#2971: Fix isEmptyAssessment check It was not always seeing an assessment as being empty as it was not only checking the real assessment fields values but also some assessment configuration keys being also saved as part of the assessment. --- client/src/components/RelatedObjectNotes.js | 2 +- client/src/pages/reports/Form.js | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/client/src/components/RelatedObjectNotes.js b/client/src/components/RelatedObjectNotes.js index 77bd41be97..9d28bb3e68 100644 --- a/client/src/components/RelatedObjectNotes.js +++ b/client/src/components/RelatedObjectNotes.js @@ -36,7 +36,7 @@ const GQL_DELETE_NOTE = gql` export { GRAPHQL_NOTES_FIELDS } from "components/Model" -const EXCLUDED_ASSESSMENT_FIELDS = [ +export const EXCLUDED_ASSESSMENT_FIELDS = [ "__recurrence", "__periodStart", "__relatedObjectType", diff --git a/client/src/pages/reports/Form.js b/client/src/pages/reports/Form.js index 5d3b89a623..fcbd45f1f9 100644 --- a/client/src/pages/reports/Form.js +++ b/client/src/pages/reports/Form.js @@ -25,7 +25,6 @@ import { ASSESSMENTS_RECURRENCE_TYPE, ASSESSMENTS_RELATED_OBJECT_TYPE, DEFAULT_CUSTOM_FIELDS_PARENT, - INVISIBLE_CUSTOM_FIELDS_FIELD, NOTE_TYPE } from "components/Model" import NavigationWarning from "components/NavigationWarning" @@ -35,6 +34,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" @@ -1264,9 +1264,12 @@ const BaseReportForm = ({ function isEmptyAssessment(assessment) { return ( - (Object.keys(assessment).length === 1 && - Object.keys(assessment)[0] === INVISIBLE_CUSTOM_FIELDS_FIELD) || - _isEmpty(assessment) + Object.entries(assessment).filter( + ([key, value]) => + !EXCLUDED_ASSESSMENT_FIELDS.includes(key) && + value !== null && + value !== undefined + ).length < 1 ) } From 817fce3db1ceb05e39bb5f339e70e6d0f47d0dc5 Mon Sep 17 00:00:00 2001 From: vassil Date: Wed, 27 May 2020 17:54:52 +0200 Subject: [PATCH 096/247] nci-agency/anet#2954: Make table columns equal width for report statistics --- client/src/components/ReportStatistics.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index 8530086eb2..860caeb1cb 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -185,7 +185,12 @@ const ReportStatistics = ({ const customFieldsConfig = Settings.fields.report.customFields return ( - +
<> From 147b1c7d99c4ba683663a4f6dea2fa3a70a4db09 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 28 May 2020 10:34:59 +0200 Subject: [PATCH 097/247] NCI-Agency/anet#2971: Replace hardcoded recurrence value with constant We used to hardcode the monthly period in the ReportCollection, it is now replaced by an already existing constant. --- client/src/components/ReportCollection.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/components/ReportCollection.js b/client/src/components/ReportCollection.js index d074967f34..ca1959ee68 100644 --- a/client/src/components/ReportCollection.js +++ b/client/src/components/ReportCollection.js @@ -1,6 +1,7 @@ import { setPagination } from "actions" import { ASSESSMENT_PERIOD_FACTORIES } from "components/assessments/AssessmentResultsContainer" import ButtonToggleGroup from "components/ButtonToggleGroup" +import { ASSESSMENTS_RECURRENCE_TYPE } from "components/Model" import { PageDispatchersPropType, mapPageDispatchersToProps @@ -38,7 +39,7 @@ const ReportCollection = ({ }) => { const [viewFormat, setViewFormat] = useState(viewFormats[0]) const showHeader = viewFormats.length > 1 || reportsFilter - const statisticsRecurrence = ["monthly"] + const statisticsRecurrence = [ASSESSMENTS_RECURRENCE_TYPE.MONTHLY] const now = moment() return ( From c4337f6a68cd47c12d5c3e3dd34a3013a0297a31 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 28 May 2020 10:36:47 +0200 Subject: [PATCH 098/247] NCI-Agency/anet#2889: Add instant assessments to process board diagram This makes sure that for the object types having instant assessments defined we display the aggregation of the questions of type LikertScale. We display them using a Pie widget without legend. --- client/src/components/ReportStatistics.js | 1 + .../MultiTypeAdvancedSelectComponent.js | 4 +- .../AggregationWidgetContainer.js | 34 +++++++--- .../assessments/AssessmentResultsTable.js | 1 + client/src/models/Person.js | 8 ++- client/src/models/Task.js | 8 ++- client/src/pages/dashboards/DiagramNode.js | 66 ++++++++++++++++--- 7 files changed, 98 insertions(+), 24 deletions(-) diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index 8530086eb2..0df6e57434 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -102,6 +102,7 @@ const FieldStatisticsRow = ({ fieldConfig={fieldConfig} fieldName={fieldName} data={periodsData[index]} + widget={aggregationWidget} /> ))} diff --git a/client/src/components/advancedSelectWidget/MultiTypeAdvancedSelectComponent.js b/client/src/components/advancedSelectWidget/MultiTypeAdvancedSelectComponent.js index 3e1180ea65..d37aa32bb4 100644 --- a/client/src/components/advancedSelectWidget/MultiTypeAdvancedSelectComponent.js +++ b/client/src/components/advancedSelectWidget/MultiTypeAdvancedSelectComponent.js @@ -59,7 +59,7 @@ const widgetPropsPeople = { overlayColumns: ["Name", "Position", "Location", "Organization"], filterDefs: peopleFilters, queryParams: {}, - fields: Models.Person.autocompleteQuery, + fields: Models.Person.autocompleteQueryWithNotes, addon: PEOPLE_ICON } @@ -99,7 +99,7 @@ const widgetPropsTask = { overlayColumns: ["Name"], filterDefs: entityFilters, queryParams: { status: Models.Task.STATUS.ACTIVE }, - fields: Models.Task.autocompleteQuery, + fields: Models.Task.autocompleteQueryWithNotes, addon: TASKS_ICON } diff --git a/client/src/components/aggregations/AggregationWidgetContainer.js b/client/src/components/aggregations/AggregationWidgetContainer.js index 443a260603..f99ca4ca76 100644 --- a/client/src/components/aggregations/AggregationWidgetContainer.js +++ b/client/src/components/aggregations/AggregationWidgetContainer.js @@ -24,7 +24,7 @@ import PropTypes from "prop-types" import React from "react" import { Col, ControlLabel, FormGroup } from "react-bootstrap" -const AGGERGATION_WIDGET_TYPE = { +export const AGGERGATION_WIDGET_TYPE = { LIKERT_SCALE: "likertScale", PIE: "pie", LIKERT_SCALE_AND_PIE: "likertScaleAndPie", @@ -89,12 +89,23 @@ const AGGREGATION_TYPE_FUNCTION = { [AGGREGATION_TYPE.LIKERT_SCALE_AND_PIE_AGG]: likertScaleAndPieAggregation } -export const getAggregationWidget = fieldConfig => - fieldConfig.aggregation?.widget || - DEFAULT_AGGREGATION_WIDGET_PER_FIELD_TYPE[fieldConfig.type][ - fieldConfig.widget - ] || - DEFAULT_AGGREGATION_WIDGET_PER_FIELD_TYPE[fieldConfig.type] +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 = @@ -110,9 +121,10 @@ const AggregationWidgetContainer = ({ fieldConfig, fieldName, vertical, + widget, ...otherWidgetProps }) => { - const aggregationWidget = getAggregationWidget(fieldConfig) + const aggregationWidget = widget || getAggregationWidget(fieldConfig) const aggregationFunction = getAggregationFunction( fieldConfig, aggregationWidget @@ -168,10 +180,12 @@ AggregationWidgetContainer.propTypes = { data: PropTypes.any, fieldConfig: PropTypes.object, fieldName: PropTypes.string, - vertical: PropTypes.bool + vertical: PropTypes.bool, + widget: PropTypes.string } AggregationWidgetContainer.defaultProps = { - vertical: true + vertical: true, + widget: "" } export default AggregationWidgetContainer diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index 557cbb3165..3623d6e0bd 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -59,6 +59,7 @@ const InstantAssessmentRow = ({ fieldConfig={questionConfig} fieldName={questionKey} data={entity.getInstantAssessmentResults(period)} + widget={aggregationWidget} /> ))} diff --git a/client/src/models/Person.js b/client/src/models/Person.js index 23dae864d5..bdbe7e9ef5 100644 --- a/client/src/models/Person.js +++ b/client/src/models/Person.js @@ -1,5 +1,9 @@ import { Settings } from "api" -import Model, { createCustomFieldsSchema, 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" @@ -156,6 +160,8 @@ export default class Person extends Model { 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 diff --git a/client/src/models/Task.js b/client/src/models/Task.js index 771a307030..71fbe8350c 100644 --- a/client/src/models/Task.js +++ b/client/src/models/Task.js @@ -1,5 +1,9 @@ import { Settings } from "api" -import Model, { createCustomFieldsSchema, yupDate } from "components/Model" +import Model, { + createCustomFieldsSchema, + GRAPHQL_NOTES_FIELDS, + yupDate +} from "components/Model" import _isEmpty from "lodash/isEmpty" import TASKS_ICON from "resources/tasks.png" import utils from "utils" @@ -147,6 +151,8 @@ export default class Task extends Model { 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) } diff --git a/client/src/pages/dashboards/DiagramNode.js b/client/src/pages/dashboards/DiagramNode.js index 6d9e194013..6118b0a9ff 100644 --- a/client/src/pages/dashboards/DiagramNode.js +++ b/client/src/pages/dashboards/DiagramNode.js @@ -15,19 +15,37 @@ import { DefaultLinkModel, DefaultLinkWidget } from "@projectstorm/react-diagrams-defaults" +import AggregationWidgetContainer, { + AGGERGATION_WIDGET_TYPE, + getAggregationWidget +} from "components/aggregations/AggregationWidgetContainer" +import { ASSESSMENT_PERIOD_FACTORIES } from "components/assessments/AssessmentResultsContainer" +import AvatarDisplayComponent from "components/AvatarDisplayComponent" +import { SPECIAL_WIDGET_TYPES } from "components/CustomFields" import LinkTo from "components/LinkTo" +import { + ASSESSMENTS_RECURRENCE_TYPE, + CUSTOM_FIELD_TYPE +} from "components/Model" +import { GRAPHQL_NOTES_FIELDS } from "components/RelatedObjectNotes" import * as Models from "models" +import moment from "moment" import PropTypes from "prop-types" import * as React from "react" -import AvatarDisplayComponent from "components/AvatarDisplayComponent" const ENTITY_GQL_FIELDS = { Report: "uuid, intent", - Person: "uuid, name, role, avatar(size: 64)", + Person: `uuid, name, role, avatar(size: 64), ${GRAPHQL_NOTES_FIELDS}`, Organization: "uuid, shortName", Position: "uuid, name", Location: "uuid, name", - Task: "uuid, shortName, longName" + Task: `uuid, shortName, longName, ${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 { @@ -100,10 +118,17 @@ const Port = styled.div` ` export const DiagramNodeWidget = ({ size, node, engine }) => { - const ModelClass = - node.options.anetObjectType && Models[node.options.anetObjectType] - - const modelInstance = ModelClass && new ModelClass(node.options.anetObject) + const { anetObjectType, anetObject } = node.options + const ModelClass = anetObjectType && Models[anetObjectType] + const modelInstance = ModelClass && new ModelClass(anetObject) + const now = moment() + const period = ASSESSMENT_PERIOD_FACTORIES[ + ASSESSMENTS_RECURRENCE_TYPE.MONTHLY + ](now, 0) + const instantAssessmentConfig = + anetObject && anetObject.getInstantAssessmentConfig() + const instantAssessmentResults = + instantAssessmentConfig && anetObject.getInstantAssessmentResults(period) return (
{ style={{ marginLeft: 8, marginTop: 8, pointerEvents: "none" }} /> )} - {node.options.anetObjectType && node.options.anetObject && ( + {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 + })} +
)} Date: Thu, 28 May 2020 14:29:53 +0200 Subject: [PATCH 099/247] NCI-Agency/anet#2971: Fix LikertScale when some values are not numbers When the values property for a LikertScale was containign an undefined value we were getting errors of type NaN. Fixed this by first transforming the array of values to an array of numbers. --- client/src/components/graphs/LikertScale.js | 16 +++++++++------- client/src/utils.js | 6 ++++++ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/client/src/components/graphs/LikertScale.js b/client/src/components/graphs/LikertScale.js index afb22307c0..2d0c0e2eba 100644 --- a/client/src/components/graphs/LikertScale.js +++ b/client/src/components/graphs/LikertScale.js @@ -3,6 +3,7 @@ import * as d3 from "d3" import PropTypes from "prop-types" import Text from "react-svg-text" import useDimensions from "react-use-dimensions" +import utils from "utils" const LikertScale = ({ onChange, @@ -85,11 +86,12 @@ const LikertScale = ({ let activeColor = null let valuesStats = null - if (values?.length) { + const numberValues = utils.arrayOfNumbers(values) + 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 @@ -139,7 +141,7 @@ const LikertScale = ({ ) })} - {values?.map((xValue, index) => ( + {numberValues?.map((xValue, index) => ( ))} - {values?.length > 1 && ( + {numberValues?.length > 1 && ( )} - {values?.length > 0 && ( + {numberValues?.length > 0 && ( !isNaN(parseFloat(n)) && isFinite(n)) + .map(n => Number(n)) } } From 6f693ffa0aee23935e6dc0755195ad5f83de6e2c Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 3 Jun 2020 12:18:58 +0200 Subject: [PATCH 100/247] NCI-Agency/anet#2971: Fix arrayOfNumbers util It was giving an error when the provided value was undefined. --- client/src/utils.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/src/utils.js b/client/src/utils.js index b23d7469a2..b544e3cc5b 100644 --- a/client/src/utils.js +++ b/client/src/utils.js @@ -164,9 +164,10 @@ export default { }, arrayOfNumbers: function(arr) { - return arr - .filter(n => !isNaN(parseFloat(n)) && isFinite(n)) - .map(n => Number(n)) + return ( + arr && + arr.filter(n => !isNaN(parseFloat(n)) && isFinite(n)).map(n => Number(n)) + ) } } From 526f63c7deaf6dd00df267b12c298cff2baef992 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 3 Jun 2020 13:57:10 +0200 Subject: [PATCH 101/247] NCI-Agency/anet#2971: Filter engagement instant assessments When retrieving the engagement assessments for a given period, filter on the engagementDate of the engagement and only assessments belonging to published engagements. --- client/src/components/Model.js | 20 +++++++------------- client/src/pages/tasks/Show.js | 14 +------------- 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/client/src/components/Model.js b/client/src/components/Model.js index c53df6cf0e..2cad7a4481 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -47,6 +47,8 @@ export const GRAPHQL_NOTE_FIELDS = /* GraphQL */ ` } ... on Report { intent + engagementDate + state } ... on Task { shortName @@ -525,12 +527,6 @@ export default class Model { dateRange, relatedObjectType = ASSESSMENTS_RELATED_OBJECT_TYPE.REPORT ) { - // FIXME: don't retrieve the published reports but also return the note's - // relatedObject and filter on its status - const publishedReports = this.publishedReports - const publishedReportsUuids = publishedReports - ? publishedReports.map(r => r.uuid) - : undefined return this.notes .filter( n => @@ -538,13 +534,11 @@ export default class Model { n.noteRelatedObjects.filter( ro => ro.relatedObjectType === Models.Report.relatedObjectType && - (publishedReportsUuids !== undefined - ? publishedReportsUuids.includes(ro.relatedObjectUuid) - : true) - ).length && - // FIXME: make sure we actually filter on the report's engagementDate - (!dateRange || - (n.createdAt <= dateRange.end && n.createdAt >= dateRange.start)) + 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( diff --git a/client/src/pages/tasks/Show.js b/client/src/pages/tasks/Show.js index df6eefd4c1..ec1f21d0dd 100644 --- a/client/src/pages/tasks/Show.js +++ b/client/src/pages/tasks/Show.js @@ -21,7 +21,7 @@ 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 { Person, Task } from "models" import moment from "moment" import PropTypes from "prop-types" import React from "react" @@ -103,12 +103,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 @@ -125,12 +119,6 @@ const GQL_GET_TASK = gql` } customFields ${GRAPHQL_NOTES_FIELDS} - publishedReports: reports(query: { - pageSize: 0 - state: [${Report.STATE.PUBLISHED}] - }) { - uuid - } } } } From 8ba11fedb54290838ff0819a7a59ac6fcd2819fb Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 3 Jun 2020 14:13:07 +0200 Subject: [PATCH 102/247] NCI-Agency/anet#2971: Remove report statistics for array_of_objects field For now we won't show report statistics for fields of type array_of_objects. --- client/src/components/aggregations/AggregationWidgetContainer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/client/src/components/aggregations/AggregationWidgetContainer.js b/client/src/components/aggregations/AggregationWidgetContainer.js index f99ca4ca76..5eda5aeb30 100644 --- a/client/src/components/aggregations/AggregationWidgetContainer.js +++ b/client/src/components/aggregations/AggregationWidgetContainer.js @@ -41,7 +41,6 @@ const DEFAULT_AGGREGATION_WIDGET_PER_FIELD_TYPE = { [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.ARRAY_OF_OBJECTS]: AGGERGATION_WIDGET_TYPE.DEFAULT, [CUSTOM_FIELD_TYPE.SPECIAL_FIELD]: { [SPECIAL_WIDGET_TYPES.LIKERT_SCALE]: AGGERGATION_WIDGET_TYPE.LIKERT_SCALE_AND_PIE, From 078c6014c42ff9e1daa93d9f16c301753d21e1fa Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 3 Jun 2020 20:26:12 +0200 Subject: [PATCH 103/247] NCI-Agency/anet#2971: Sync calendar widget with displayed period This makes sure that when displaying a calendar widget in the report statistics view, the calendar displays the month corresponding to the displayed period instead of the current month. --- client/src/components/ReportStatistics.js | 1 + .../components/aggregations/AggregationWidgetContainer.js | 6 +++++- client/src/components/aggregations/AggregationWidgets.js | 8 +++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index 06d67e6b7d..845a967349 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -103,6 +103,7 @@ const FieldStatisticsRow = ({ fieldName={fieldName} data={periodsData[index]} widget={aggregationWidget} + period={period} /> ))} diff --git a/client/src/components/aggregations/AggregationWidgetContainer.js b/client/src/components/aggregations/AggregationWidgetContainer.js index 5eda5aeb30..cdeb0400fa 100644 --- a/client/src/components/aggregations/AggregationWidgetContainer.js +++ b/client/src/components/aggregations/AggregationWidgetContainer.js @@ -20,6 +20,7 @@ import { 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" @@ -121,6 +122,7 @@ const AggregationWidgetContainer = ({ fieldName, vertical, widget, + period, ...otherWidgetProps }) => { const aggregationWidget = widget || getAggregationWidget(fieldConfig) @@ -148,6 +150,7 @@ const AggregationWidgetContainer = ({ vertical={vertical} fieldConfig={fieldConfig} fieldName={fieldName} + period={period} {...fieldProps} {...otherWidgetProps} {...otherAggregationDetails} @@ -180,7 +183,8 @@ AggregationWidgetContainer.propTypes = { fieldConfig: PropTypes.object, fieldName: PropTypes.string, vertical: PropTypes.bool, - widget: PropTypes.string + widget: PropTypes.string, + period: PropTypes.oneOfType([AssessmentPeriodPropType, PeriodPropType]) } AggregationWidgetContainer.defaultProps = { vertical: true, diff --git a/client/src/components/aggregations/AggregationWidgets.js b/client/src/components/aggregations/AggregationWidgets.js index cdf211c0e9..ed0519e95f 100644 --- a/client/src/components/aggregations/AggregationWidgets.js +++ b/client/src/components/aggregations/AggregationWidgets.js @@ -6,9 +6,12 @@ import BarChart from "components/BarChart" import LikertScale from "components/graphs/LikertScale" import Pie from "components/graphs/Pie" import _uniqueId from "lodash/uniqueId" +import { AssessmentPeriodPropType, PeriodPropType } from "periodUtils" import PropTypes from "prop-types" import React, { useRef } from "react" +const DATE_FORMAT = "YYYY-MM-DD" + const aggregationWidgetPropTypes = { values: PropTypes.oneOfType([ PropTypes.object, @@ -23,7 +26,8 @@ const aggregationWidgetPropTypes = { ]), fieldConfig: PropTypes.object, fieldName: PropTypes.string, - vertical: PropTypes.bool + vertical: PropTypes.bool, + period: PropTypes.oneOfType([AssessmentPeriodPropType, PeriodPropType]) } export const PieWidget = ({ @@ -115,6 +119,7 @@ export const CalendarWidget = ({ values, fieldConfig, fieldName, + period, ...otherWidgetProps }) => { const calendarComponentRef = useRef(null) @@ -135,6 +140,7 @@ export const CalendarWidget = ({ right: "" }} defaultView="dayGridMonth" + defaultDate={period.start.format(DATE_FORMAT)} allDayDefault eventTimeFormat={{ hour: "2-digit", From 797b890aa9681dacbfbe6b83d5d56a2c6b7d30a1 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 3 Jun 2020 21:37:35 +0200 Subject: [PATCH 104/247] NCI-Agency/anet#2971: Fix layout of InstantAssessmentsContainerField The tasks/people engagement assessment fields were displayed without empty space among them, because of the unneeded use of the assessments-table class. Removed the class and now the fields are spaced properly. --- .../components/assessments/InstantAssessmentsContainerField.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/assessments/InstantAssessmentsContainerField.js b/client/src/components/assessments/InstantAssessmentsContainerField.js index ec38b2f8c9..2ca4ba29da 100644 --- a/client/src/components/assessments/InstantAssessmentsContainerField.js +++ b/client/src/components/assessments/InstantAssessmentsContainerField.js @@ -18,7 +18,7 @@ const InstantAssessmentsContainerField = ({ }) => { const { values } = formikProps return ( -
+
{entities.map(entity => { const entityInstantAssessmentConfig = !_isEmpty( From 9f1a4c19f435ceea07eeb428f4998a43076d9350 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 4 Jun 2020 10:56:33 +0200 Subject: [PATCH 105/247] Fix CustomFields enumHumanValue Make sure the function doesn't give an error when the fieldValue is not among the choices. Saw one context in which an enum value was suddenly the string null (can't reproduce it any more) and we were getting an error. Added the fix to make sure that if that happens again we don't get an error. --- client/src/components/CustomFields.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/CustomFields.js b/client/src/components/CustomFields.js index 36aa64d71b..a1ef0012ea 100644 --- a/client/src/components/CustomFields.js +++ b/client/src/components/CustomFields.js @@ -169,7 +169,7 @@ const enumHumanValue = (choices, fieldVal) => { if (Array.isArray(fieldVal)) { return fieldVal && fieldVal.map(k => choices[k].label).join(", ") } else { - return fieldVal && choices[fieldVal].label + return fieldVal && choices[fieldVal]?.label } } From bda43e1e5c0be65f41ce24069eb40b24e3d24110 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 4 Jun 2020 17:27:11 +0200 Subject: [PATCH 106/247] NCI-Agency/anet#2971: Improve pie aggregation widget Always display the number of entities in the middle and make a pie slice for each used value. For enumset types of fields we might have more selected values per entity so the number displayed in the middle of the pie no longer corresponds with the count of the different values. --- .../AggregationWidgetContainer.js | 21 +++++++++---------- .../aggregations/AggregationWidgets.js | 4 +++- client/src/components/aggregations/utils.js | 7 ++++--- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/client/src/components/aggregations/AggregationWidgetContainer.js b/client/src/components/aggregations/AggregationWidgetContainer.js index cdeb0400fa..4e1b265df6 100644 --- a/client/src/components/aggregations/AggregationWidgetContainer.js +++ b/client/src/components/aggregations/AggregationWidgetContainer.js @@ -35,6 +35,16 @@ export const AGGERGATION_WIDGET_TYPE = { 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.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, @@ -49,17 +59,6 @@ const DEFAULT_AGGREGATION_WIDGET_PER_FIELD_TYPE = { } } -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.COUNT_PER_VALUE]: PieWidget, - [AGGERGATION_WIDGET_TYPE.CALENDAR]: CalendarWidget, - [AGGERGATION_WIDGET_TYPE.DEFAULT]: DefaultAggWidget -} - const AGGREGATION_TYPE = { REPORTS_BY_TASK: "countReportsByTask", COUNT_PER_DATE: "countPerDate", diff --git a/client/src/components/aggregations/AggregationWidgets.js b/client/src/components/aggregations/AggregationWidgets.js index ed0519e95f..731c4eb07c 100644 --- a/client/src/components/aggregations/AggregationWidgets.js +++ b/client/src/components/aggregations/AggregationWidgets.js @@ -32,6 +32,7 @@ const aggregationWidgetPropTypes = { export const PieWidget = ({ values, + entitiesCount, legend, showLegend = true, ...otherWidgetProps @@ -42,7 +43,7 @@ export const PieWidget = ({ width={70} height={70} data={values} - label={Object.values(values).reduce((acc, cur) => acc + cur, 0)} + label={entitiesCount} segmentFill={entity => legend[entity.data.key]?.color} segmentLabel={d => d.data.value} /> @@ -62,6 +63,7 @@ export const PieWidget = ({ ) } PieWidget.propTypes = { + entitiesCount: PropTypes.number, legend: PropTypes.object, showLegend: PropTypes.bool, ...aggregationWidgetPropTypes diff --git a/client/src/components/aggregations/utils.js b/client/src/components/aggregations/utils.js index c25f1aa4e9..af25dfe24e 100644 --- a/client/src/components/aggregations/utils.js +++ b/client/src/components/aggregations/utils.js @@ -41,7 +41,8 @@ const CHART_COLORS = [ export const countPerValueAggregation = (fieldName, fieldConfig, data) => { const counters = data.reduce((counter, entity) => { const value = Object.get(entity, fieldName) || null - counter[value] = ++counter[value] || 1 + const values = Array.isArray(value) ? value : [value] + values.forEach(choice => (counter[choice] = ++counter[choice] || 1)) return counter }, {}) const legendColors = _clone(CHART_COLORS) @@ -57,7 +58,7 @@ export const countPerValueAggregation = (fieldName, fieldConfig, data) => { }) ) legend.null = { label: "Unspecified", color: "#bbbbbb" } - return { values: counters, legend: legend } + return { values: counters, entitiesCount: data.length, legend: legend } } const arrayOfNumbers = arr => @@ -134,7 +135,7 @@ export const countPerLevelAggregation = (fieldName, fieldConfig, data) => { return res }, {}) legend.null = { label: "Unspecified", color: "#bbbbbb" } - return { values: counters, legend: legend } + return { values: counters, entitiesCount: data.length, legend: legend } } export const likertScaleAndPieAggregation = (fieldName, fieldConfig, data) => { From 247cbc75ed4f69356f3ce1d40bf7cb9feaffac2c Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 4 Jun 2020 22:48:05 +0200 Subject: [PATCH 107/247] NCI-Agency/anet#2971: Change default aggregation widget layout The default aggregation widget is being used for text type of fields. It now no longer displays a list of values directly but uses a show/hide button to do that. --- .../aggregations/AggregationWidgets.js | 42 +++++++++++++++++-- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/client/src/components/aggregations/AggregationWidgets.js b/client/src/components/aggregations/AggregationWidgets.js index 731c4eb07c..9fcdb01adc 100644 --- a/client/src/components/aggregations/AggregationWidgets.js +++ b/client/src/components/aggregations/AggregationWidgets.js @@ -5,10 +5,12 @@ import FullCalendar from "@fullcalendar/react" import BarChart from "components/BarChart" import LikertScale from "components/graphs/LikertScale" import Pie from "components/graphs/Pie" +import _isEmpty from "lodash/isEmpty" import _uniqueId from "lodash/uniqueId" import { AssessmentPeriodPropType, PeriodPropType } from "periodUtils" import PropTypes from "prop-types" -import React, { useRef } from "react" +import React, { useRef, useState } from "react" +import { Button, Collapse, Table } from "react-bootstrap" const DATE_FORMAT = "YYYY-MM-DD" @@ -169,7 +171,39 @@ export const CalendarWidget = ({ } CalendarWidget.propTypes = aggregationWidgetPropTypes -export const DefaultAggWidget = ({ values, ...otherWidgetProps }) => ( -
{`[${values}]`}
-) +export const DefaultAggWidget = ({ values, ...otherWidgetProps }) => { + const [showValues, setShowValues] = useState(false) + if (_isEmpty(values)) { + return null + } + return ( +
+ + +
+ + {values.map(val => { + const keyValue = _uniqueId("value_") + return ( + + + + ) + })} + +
val
+ +
+ ) + function toggleShowValues() { + setShowValues(!showValues) + } +} DefaultAggWidget.propTypes = aggregationWidgetPropTypes From fb8db34edb0d95ce8e729f16b1955729b5dc8dd9 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Fri, 5 Jun 2020 20:58:22 +0200 Subject: [PATCH 108/247] NCI-Agency/anet#2954: Make table columns equal width for assessment results --- .../src/components/assessments/AssessmentResultsTable.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index 3623d6e0bd..8b7b1ce089 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -292,7 +292,12 @@ const AssessmentResultsTable = ({ title={`Assessment results - ${recurrence}`} id={`"entity-assessments-results-${recurrence}`} > - +
{!_isEmpty(subEntities) && ( From 9a2045248ffd828e9d0bf65802542caf6b5043bd Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Mon, 8 Jun 2020 16:32:23 +0200 Subject: [PATCH 109/247] NCI-Agency/anet#3052: Fix emptying a number type of custom field Emptying a number type of custom field resulted in displaying [object Object] in the input field and a strange validation error. This was happening because when the value was emptied we were setting the value to the original syntentic event. --- client/src/components/CustomFields.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/components/CustomFields.js b/client/src/components/CustomFields.js index a1ef0012ea..3ad3908028 100644 --- a/client/src/components/CustomFields.js +++ b/client/src/components/CustomFields.js @@ -468,7 +468,8 @@ const CustomField = ({ const [validateFormDebounced] = useDebouncedCallback(validateForm, 400) // with validateField it somehow doesn't work const handleChange = useMemo( () => (value, shouldValidate: true) => { - const val = value?.target?.value || value + const val = + value?.target?.value !== undefined ? value.target.value : value const sv = shouldValidate === undefined ? true : shouldValidate setFieldTouched(fieldName, true, false) setFieldValue(fieldName, val, sv) From 5ddbce5c301d805d4a8938cf7f0d2a07ca995d95 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Mon, 8 Jun 2020 23:31:47 +0200 Subject: [PATCH 110/247] NCI-Agency/anet#3052: Change default validation message for number The default validation message for a number type of custom field is not really clear to the user. We therefore simplified the default validation message for number type of custom fields. --- client/src/components/Model.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/src/components/Model.js b/client/src/components/Model.js index 2cad7a4481..1379abbd20 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -137,7 +137,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(""), From ec3f60319b2e05939513f4062851a130db2d7ee0 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 9 Jun 2020 13:49:20 +0200 Subject: [PATCH 111/247] NCI-Agency/anet#3051: Fix assign principal position to advisor position This makes sure we no longer get the error "Internal Server Error: The variables input contains a filed name 'relatedObject' that is not defined for input object type 'NoteRelatedObjectInput'" when assigning a principal position to an advisor position. --- client/src/components/EditAssociatedPositionsModal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/EditAssociatedPositionsModal.js b/client/src/components/EditAssociatedPositionsModal.js index 74deeca5b4..5d7b991395 100644 --- a/client/src/components/EditAssociatedPositionsModal.js +++ b/client/src/components/EditAssociatedPositionsModal.js @@ -182,7 +182,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. From 02185e32e8930e3cbfd8daa06a45d088e29671b5 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 9 Jun 2020 14:53:16 +0200 Subject: [PATCH 112/247] NCI-Agency/anet#2571: Change default views for report collection The default view of the ReportCollection is now most of the times statistics, except when used for saved searches, report search resullts, my reports and authorization groups reports. In these 4 situations the default view is summary. --- .../components/CancelledEngagementReports.js | 12 +++++++--- .../components/FutureEngagementsByLocation.js | 12 +++++++--- .../src/components/PendingApprovalReports.js | 12 +++++++--- client/src/components/ReportCollection.js | 8 ++++++- client/src/components/ReportsByDayOfWeek.js | 12 +++++++--- client/src/components/ReportsByTask.js | 12 +++++++--- client/src/components/SavedSearchTable.js | 22 +++++++++++++++++-- client/src/pages/Search.js | 15 ++++++++++++- .../pages/admin/authorizationgroup/Show.js | 15 ++++++++++++- client/src/pages/locations/Show.js | 13 +---------- client/src/pages/organizations/Show.js | 15 +------------ client/src/pages/people/Show.js | 13 +---------- client/src/pages/reports/MyReports.js | 15 ++++++++++++- client/src/pages/rollup/Show.js | 8 ++++++- 14 files changed, 124 insertions(+), 60 deletions(-) diff --git a/client/src/components/CancelledEngagementReports.js b/client/src/components/CancelledEngagementReports.js index 249abcead8..e266e7d849 100644 --- a/client/src/components/CancelledEngagementReports.js +++ b/client/src/components/CancelledEngagementReports.js @@ -5,10 +5,11 @@ 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" @@ -255,7 +256,12 @@ const Collection = ({ id, queryParams }) => ( ) diff --git a/client/src/components/FutureEngagementsByLocation.js b/client/src/components/FutureEngagementsByLocation.js index 875ac3b198..4727a8ac1d 100644 --- a/client/src/components/FutureEngagementsByLocation.js +++ b/client/src/components/FutureEngagementsByLocation.js @@ -5,10 +5,11 @@ import HorizontalBarChart from "components/HorizontalBarChart" 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" @@ -169,7 +170,12 @@ const Collection = ({ id, queryParams }) => ( ) diff --git a/client/src/components/PendingApprovalReports.js b/client/src/components/PendingApprovalReports.js index b16df6735b..e20428009d 100644 --- a/client/src/components/PendingApprovalReports.js +++ b/client/src/components/PendingApprovalReports.js @@ -5,10 +5,11 @@ 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" @@ -136,7 +137,12 @@ const Collection = ({ id, queryParams }) => ( ) diff --git a/client/src/components/ReportCollection.js b/client/src/components/ReportCollection.js index ca1959ee68..aad45f5a10 100644 --- a/client/src/components/ReportCollection.js +++ b/client/src/components/ReportCollection.js @@ -168,7 +168,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/ReportsByDayOfWeek.js b/client/src/components/ReportsByDayOfWeek.js index 3aeb6d6b05..552e027b7f 100644 --- a/client/src/components/ReportsByDayOfWeek.js +++ b/client/src/components/ReportsByDayOfWeek.js @@ -5,10 +5,11 @@ 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 bdfe701bac..3172d9cb68 100644 --- a/client/src/components/ReportsByTask.js +++ b/client/src/components/ReportsByTask.js @@ -5,10 +5,11 @@ 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/SavedSearchTable.js b/client/src/components/SavedSearchTable.js index 6b8a76360c..7861e77aec 100644 --- a/client/src/components/SavedSearchTable.js +++ b/client/src/components/SavedSearchTable.js @@ -1,5 +1,11 @@ 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" @@ -18,7 +24,19 @@ const SavedSearchTable = props => { query.pageNum = query.pageNum || 0 query.pageSize = query.pageSize || 10 - return + return ( + + ) } SavedSearchTable.propTypes = { diff --git a/client/src/pages/Search.js b/client/src/pages/Search.js index 151917cf27..d90f78ae1f 100644 --- a/client/src/pages/Search.js +++ b/client/src/pages/Search.js @@ -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, @@ -892,6 +898,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/authorizationgroup/Show.js b/client/src/pages/admin/authorizationgroup/Show.js index 3b5184a907..c2dcd2f283 100644 --- a/client/src/pages/admin/authorizationgroup/Show.js +++ b/client/src/pages/admin/authorizationgroup/Show.js @@ -15,7 +15,13 @@ 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" @@ -137,6 +143,13 @@ const BaseAuthorizationGroupShow = ({ pageDispatchers, currentUser }) => { authorizationGroupUuid: uuid }} mapId="reports" + viewFormats={[ + FORMAT_SUMMARY, + FORMAT_TABLE, + FORMAT_CALENDAR, + FORMAT_MAP, + FORMAT_STATISTICS + ]} /> diff --git a/client/src/pages/locations/Show.js b/client/src/pages/locations/Show.js index ef4770e26a..8b93c4a806 100644 --- a/client/src/pages/locations/Show.js +++ b/client/src/pages/locations/Show.js @@ -16,12 +16,7 @@ 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" @@ -163,12 +158,6 @@ const BaseLocationShow = ({ pageDispatchers, currentUser }) => { paginationKey={`r_${uuid}`} queryParams={{ locationUuid: uuid }} mapId="reports" - viewFormats={[ - FORMAT_CALENDAR, - FORMAT_SUMMARY, - FORMAT_TABLE, - FORMAT_MAP - ]} /> diff --git a/client/src/pages/organizations/Show.js b/client/src/pages/organizations/Show.js index a8834a3464..b76cb1c96c 100644 --- a/client/src/pages/organizations/Show.js +++ b/client/src/pages/organizations/Show.js @@ -17,13 +17,7 @@ import { import RelatedObjectNotes, { GRAPHQL_NOTES_FIELDS } from "components/RelatedObjectNotes" -import ReportCollection, { - FORMAT_CALENDAR, - FORMAT_MAP, - FORMAT_STATISTICS, - FORMAT_SUMMARY, - FORMAT_TABLE -} 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" @@ -398,13 +392,6 @@ const BaseOrganizationShow = ({ pageDispatchers, currentUser }) => { diff --git a/client/src/pages/people/Show.js b/client/src/pages/people/Show.js index d8b81d06c5..0101e679d6 100644 --- a/client/src/pages/people/Show.js +++ b/client/src/pages/people/Show.js @@ -21,12 +21,7 @@ import { import RelatedObjectNotes, { GRAPHQL_NOTES_FIELDS } from "components/RelatedObjectNotes" -import ReportCollection, { - FORMAT_CALENDAR, - FORMAT_MAP, - FORMAT_SUMMARY, - FORMAT_TABLE -} from "components/ReportCollection" +import ReportCollection from "components/ReportCollection" import { Field, Form, Formik } from "formik" import _isEmpty from "lodash/isEmpty" import { Person, Position } from "models" @@ -355,12 +350,6 @@ const BasePersonShow = ({ pageDispatchers, currentUser }) => { queryParams={{ authorUuid: uuid }} - viewFormats={[ - FORMAT_CALENDAR, - FORMAT_SUMMARY, - FORMAT_TABLE, - FORMAT_MAP - ]} mapId="reports-authored" /> diff --git a/client/src/pages/reports/MyReports.js b/client/src/pages/reports/MyReports.js index 2bf5bb3be4..dd8e6f3e69 100644 --- a/client/src/pages/reports/MyReports.js +++ b/client/src/pages/reports/MyReports.js @@ -5,7 +5,13 @@ 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" @@ -83,6 +89,13 @@ const BaseMyReports = ({ paginationKey={`r_${id}_${uuid}`} queryParams={queryParams} mapId={id} + viewFormats={[ + FORMAT_SUMMARY, + FORMAT_TABLE, + FORMAT_CALENDAR, + FORMAT_MAP, + FORMAT_STATISTICS + ]} /> ) diff --git a/client/src/pages/rollup/Show.js b/client/src/pages/rollup/Show.js index 090d36e40a..d2b63ad6b6 100644 --- a/client/src/pages/rollup/Show.js +++ b/client/src/pages/rollup/Show.js @@ -21,6 +21,7 @@ import { import ReportCollection, { FORMAT_CALENDAR, FORMAT_MAP, + FORMAT_STATISTICS, FORMAT_SUMMARY, FORMAT_TABLE } from "components/ReportCollection" @@ -222,7 +223,12 @@ const Collection = ({ queryParams }) => ( ) From 70fe0ad590b3518ecf4097acc6364631835a6bcb Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 9 Jun 2020 16:45:36 +0200 Subject: [PATCH 113/247] NCI-Agency/anet#2971: Add engagementDate to report statistics Also changed the order of the report fields in the report statistics. --- client/src/components/ReportStatistics.js | 12 ++++++++---- .../aggregations/AggregationWidgetContainer.js | 14 +++++++++----- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index 845a967349..d70cdce456 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -3,6 +3,7 @@ import { gql } from "apollo-boost" import AggregationWidgetContainer, { getAggregationWidget } from "components/aggregations/AggregationWidgetContainer" +import { CUSTOM_FIELD_TYPE } from "components/Model" import { PageDispatchersPropType, useBoilerplate } from "components/Page" import _get from "lodash/get" import { Report } from "models" @@ -18,6 +19,9 @@ import { Table } from "react-bootstrap" import utils from "utils" const REPORT_FIELDS_FOR_STATISTICS = { + engagementDate: { + type: CUSTOM_FIELD_TYPE.DATE + }, state: { aggregation: { aggregationType: "countPerValue", widget: "pie" }, label: "State", @@ -48,16 +52,16 @@ const REPORT_FIELDS_FOR_STATISTICS = { } } }, - atmosphere: { - aggregation: { aggregationType: "countPerValue", widget: "pie" }, - label: Settings.fields.report.atmosphere - }, tasks: { aggregation: { aggregationType: "countReportsByTask", widget: "reportsByTask" }, label: pluralize(Settings.fields.task.subLevel.shortLabel) + }, + atmosphere: { + aggregation: { aggregationType: "countPerValue", widget: "pie" }, + label: Settings.fields.report.atmosphere } } diff --git a/client/src/components/aggregations/AggregationWidgetContainer.js b/client/src/components/aggregations/AggregationWidgetContainer.js index 4e1b265df6..8fb28f7e01 100644 --- a/client/src/components/aggregations/AggregationWidgetContainer.js +++ b/client/src/components/aggregations/AggregationWidgetContainer.js @@ -24,6 +24,7 @@ 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", @@ -139,7 +140,10 @@ const AggregationWidgetContainer = ({ data ) const fieldProps = getFieldPropsFromFieldConfig(fieldConfig) - const label = fieldProps.label + let label = fieldProps.label + if (label === undefined) { + label = utils.sentenceCase(fieldName) // name is a required prop of field + } const WidgetComponent = (aggregationWidget && AGGREGATION_WIDGET_COMPONENTS[aggregationWidget]) || AGGREGATION_WIDGET_COMPONENTS.default @@ -179,11 +183,11 @@ const AggregationWidgetContainer = ({ } AggregationWidgetContainer.propTypes = { data: PropTypes.any, - fieldConfig: PropTypes.object, - fieldName: PropTypes.string, + fieldConfig: PropTypes.object.isRequired, + fieldName: PropTypes.string.isRequired, + period: PropTypes.oneOfType([AssessmentPeriodPropType, PeriodPropType]), vertical: PropTypes.bool, - widget: PropTypes.string, - period: PropTypes.oneOfType([AssessmentPeriodPropType, PeriodPropType]) + widget: PropTypes.string } AggregationWidgetContainer.defaultProps = { vertical: true, From a43197fd2695903435c7c18616932e59992dadfc Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 9 Jun 2020 17:11:15 +0200 Subject: [PATCH 114/247] NCI-Agency/anet#2971: Refactor configuration of report statistics Refactored the configuration of the state and atmosphere report statistics: - no need for label when that one is the same as the name - use type enum for state and atmosphere, it is better than defining the aggregation details, as if the default widget for that type would change, it would also be used for these fields automatically - add choices definition for atmosphere, to make sure we show all options in the legend of the field --- client/src/components/ReportStatistics.js | 16 +++++++++++++--- client/src/components/SearchFilters.js | 6 +++++- client/src/models/Report.js | 6 ++++++ client/src/pages/reports/Form.js | 10 ++++++---- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index d70cdce456..4de1d3f204 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -23,8 +23,7 @@ const REPORT_FIELDS_FOR_STATISTICS = { type: CUSTOM_FIELD_TYPE.DATE }, state: { - aggregation: { aggregationType: "countPerValue", widget: "pie" }, - label: "State", + type: CUSTOM_FIELD_TYPE.ENUM, choices: { [Report.STATE.DRAFT]: { label: Report.STATE_LABELS[Report.STATE.DRAFT], @@ -61,7 +60,18 @@ const REPORT_FIELDS_FOR_STATISTICS = { }, atmosphere: { aggregation: { aggregationType: "countPerValue", widget: "pie" }, - label: Settings.fields.report.atmosphere + label: Settings.fields.report.atmosphere, + choices: { + [Report.ATMOSPHERE.POSITIVE]: { + label: Report.ATMOSPHERE_LABELS[Report.ATMOSPHERE.POSITIVE] + }, + [Report.ATMOSPHERE.NEGATIVE]: { + label: Report.ATMOSPHERE_LABELS[Report.ATMOSPHERE.NEGATIVE] + }, + [Report.ATMOSPHERE.NEUTRAL]: { + label: Report.ATMOSPHERE_LABELS[Report.ATMOSPHERE.NEUTRAL] + } + } } } diff --git a/client/src/components/SearchFilters.js b/client/src/components/SearchFilters.js index cd625a1cc5..8b4a05fac8 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/models/Report.js b/client/src/models/Report.js index 4a4ab76682..c60ffe7191 100644 --- a/client/src/models/Report.js +++ b/client/src/models/Report.js @@ -58,6 +58,12 @@ 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" diff --git a/client/src/pages/reports/Form.js b/client/src/pages/reports/Form.js index fcbd45f1f9..3fab6a47e2 100644 --- a/client/src/pages/reports/Form.js +++ b/client/src/pages/reports/Form.js @@ -241,17 +241,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 = [ @@ -692,7 +692,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" /> From b404ad3d83ecff71790ea52b4f1a5d6b19e54168 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 9 Jun 2020 17:15:22 +0200 Subject: [PATCH 115/247] NCI-Agency/anet#2971: WIP: Add ReportsMapWidget aggregation widget --- .../aggregations/AggregationWidgets.js | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/client/src/components/aggregations/AggregationWidgets.js b/client/src/components/aggregations/AggregationWidgets.js index 9fcdb01adc..5aa7bdaea0 100644 --- a/client/src/components/aggregations/AggregationWidgets.js +++ b/client/src/components/aggregations/AggregationWidgets.js @@ -207,3 +207,42 @@ export const DefaultAggWidget = ({ values, ...otherWidgetProps }) => { } } DefaultAggWidget.propTypes = aggregationWidgetPropTypes + +export const ReportsMapWidget = ({ + 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}{" "} + + + ))} + + )} + + ) +} +ReportsMapWidget.propTypes = { + entitiesCount: PropTypes.number, + legend: PropTypes.object, + showLegend: PropTypes.bool, + ...aggregationWidgetPropTypes +} From 68ffb2fef1e7d2b9e2ef6608cb1501b6245bc7b8 Mon Sep 17 00:00:00 2001 From: Vassil Iordanov Date: Tue, 9 Jun 2020 18:15:48 +0200 Subject: [PATCH 116/247] nci-agency/anet#2954: Prevent NPEs --- client/src/components/CustomFields.js | 2 +- client/src/components/Model.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/components/CustomFields.js b/client/src/components/CustomFields.js index 3ad3908028..b31bc882d7 100644 --- a/client/src/components/CustomFields.js +++ b/client/src/components/CustomFields.js @@ -167,7 +167,7 @@ const EnumField = fieldProps => { 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 } diff --git a/client/src/components/Model.js b/client/src/components/Model.js index 1379abbd20..519a92c761 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -536,6 +536,7 @@ export default class Model { n.type === NOTE_TYPE.ASSESSMENT && n.noteRelatedObjects.filter( ro => + ro.relatedObject && ro.relatedObjectType === Models.Report.relatedObjectType && ro.relatedObject.state === Models.Report.STATE.PUBLISHED && (!dateRange || From e2efd4ca5e1ec69bfd9bc6bfdba55250f406c6d0 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 10 Jun 2020 23:42:52 +0200 Subject: [PATCH 117/247] NCI-Agency/anet#2971: Add ReportsMapWidget The new widget is being used by the ReportStatistics component to display aggregations for the location field and in the ReportMap component to display the reports on the map. --- client/src/components/ReportMap.js | 32 ++------- client/src/components/ReportStatistics.js | 19 ++++- .../AggregationWidgetContainer.js | 11 ++- .../aggregations/AggregationWidgets.js | 71 +++++++++++-------- client/src/components/aggregations/utils.js | 4 ++ 5 files changed, 76 insertions(+), 61 deletions(-) diff --git a/client/src/components/ReportMap.js b/client/src/components/ReportMap.js index c0ae8170b1..1d32f53010 100644 --- a/client/src/components/ReportMap.js +++ b/client/src/components/ReportMap.js @@ -1,15 +1,13 @@ import API from "api" import { gql } from "apollo-boost" -import Leaflet from "components/Leaflet" +import { ReportsMapWidget } from "components/aggregations/AggregationWidgets" 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 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]) return ( - <> - legend[entity.data.key]?.color} - segmentLabel={d => d.data.value} +
+ - {showLegend && ( - <> -
- {Object.map(legend, (key, choice) => ( - - - {choice.label}{" "} - - - ))} - - )} - +
) } ReportsMapWidget.propTypes = { - entitiesCount: PropTypes.number, - legend: PropTypes.object, - showLegend: PropTypes.bool, - ...aggregationWidgetPropTypes + ...aggregationWidgetPropTypes, + values: PropTypes.arrayOf(PropTypes.instanceOf(Report)).isRequired, + mapId: PropTypes.string, + width: PropTypes.number, + height: PropTypes.number +} +ReportsMapWidget.defaultProps = { + values: [] } diff --git a/client/src/components/aggregations/utils.js b/client/src/components/aggregations/utils.js index af25dfe24e..69fed58911 100644 --- a/client/src/components/aggregations/utils.js +++ b/client/src/components/aggregations/utils.js @@ -114,6 +114,10 @@ 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)) { From c7d7df8d91c6c750541bf535f16d58ff047321bc Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 11 Jun 2020 11:02:54 +0200 Subject: [PATCH 118/247] NCI-Agency/anet#2971: Fix ReportMapWidget error When being on the rollup page and clicking on the email rollup button we were getting an error that the map was already initialized. This was because of the way we were determining the mapId. A page contains several map widgets whe used for the report statistics. We therefore had to make sure each map on a mage has a unique id. --- client/src/components/ReportStatistics.js | 2 ++ .../aggregations/AggregationWidgetContainer.js | 11 ++++++++--- .../src/components/aggregations/AggregationWidgets.js | 5 ++--- .../components/assessments/AssessmentResultsTable.js | 2 ++ client/src/pages/dashboards/DiagramNode.js | 2 ++ 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index 04f454261e..4e843dae87 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -8,6 +8,7 @@ import AggregationWidgetContainer, { import { CUSTOM_FIELD_TYPE } from "components/Model" import { PageDispatchersPropType, useBoilerplate } from "components/Page" import _get from "lodash/get" +import _uniqueId from "lodash/uniqueId" import { Report } from "models" import { PeriodsConfigPropType, @@ -131,6 +132,7 @@ const FieldStatisticsRow = ({ data={periodsData[index]} widget={aggregationWidget} period={period} + widgetId={`${fieldName}-${_uniqueId("statistics")}`} /> ))} diff --git a/client/src/components/aggregations/AggregationWidgetContainer.js b/client/src/components/aggregations/AggregationWidgetContainer.js index fb6781ebd9..1ad8cdc76f 100644 --- a/client/src/components/aggregations/AggregationWidgetContainer.js +++ b/client/src/components/aggregations/AggregationWidgetContainer.js @@ -127,9 +127,10 @@ const AggregationWidgetContainer = ({ data, fieldConfig, fieldName, + period, vertical, widget, - period, + widgetId, ...otherWidgetProps }) => { const aggregationWidget = widget || getAggregationWidget(fieldConfig) @@ -149,11 +150,14 @@ const AggregationWidgetContainer = ({ const fieldProps = getFieldPropsFromFieldConfig(fieldConfig) let label = fieldProps.label if (label === undefined) { - label = utils.sentenceCase(fieldName) // name is a required prop of field + label = utils.sentenceCase(fieldName) // name is a required prop } const WidgetComponent = (aggregationWidget && AGGREGATION_WIDGET_COMPONENTS[aggregationWidget]) || AGGREGATION_WIDGET_COMPONENTS.default + if (WidgetComponent === ReportsMapWidget) { + otherWidgetProps.mapId = `map-${widgetId}` + } const widgetElem = ( @@ -251,7 +251,6 @@ export const ReportsMapWidget = ({ } ReportsMapWidget.propTypes = { ...aggregationWidgetPropTypes, - values: PropTypes.arrayOf(PropTypes.instanceOf(Report)).isRequired, mapId: PropTypes.string, width: PropTypes.number, height: PropTypes.number diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index 8b7b1ce089..85a425a933 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -9,6 +9,7 @@ import LinkTo from "components/LinkTo" import { NOTE_TYPE } from "components/Model" import { Person } from "models" import _isEmpty from "lodash/isEmpty" +import _uniqueId from "lodash/uniqueId" import { AssessmentPeriodPropType, PeriodsTableHeader, @@ -60,6 +61,7 @@ const InstantAssessmentRow = ({ fieldName={questionKey} data={entity.getInstantAssessmentResults(period)} widget={aggregationWidget} + widgetId={`${questionKey}-${_uniqueId("assessment")}`} /> ))} diff --git a/client/src/pages/dashboards/DiagramNode.js b/client/src/pages/dashboards/DiagramNode.js index 6118b0a9ff..18c7934af1 100644 --- a/client/src/pages/dashboards/DiagramNode.js +++ b/client/src/pages/dashboards/DiagramNode.js @@ -28,6 +28,7 @@ import { CUSTOM_FIELD_TYPE } 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 PropTypes from "prop-types" @@ -181,6 +182,7 @@ export const DiagramNodeWidget = ({ size, node, engine }) => { fieldName={questionKey} data={instantAssessmentResults} widget={aggregationWidget} + widgetId={`${questionKey}-${_uniqueId("assessment")}`} /> ) : null })} From 040f4e537541959c56bf2d2227d3950d1e9260db Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 11 Jun 2020 12:39:10 +0200 Subject: [PATCH 119/247] NCI-Agency/anet#2971: Add a factory for fields choices in ReportStatistics --- client/src/components/ReportStatistics.js | 54 +++++++---------------- client/src/models/Report.js | 15 +++++++ 2 files changed, 32 insertions(+), 37 deletions(-) diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index 4e843dae87..2eb9544857 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -21,6 +21,17 @@ import React, { useEffect } from "react" import { Table } from "react-bootstrap" import utils from "utils" +const choicesFactory = (values, labels, colors) => { + 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 @@ -32,32 +43,11 @@ const REPORT_FIELDS_FOR_STATISTICS = { }, state: { type: CUSTOM_FIELD_TYPE.ENUM, - choices: { - [Report.STATE.DRAFT]: { - label: Report.STATE_LABELS[Report.STATE.DRAFT], - color: "#bdbdaf" - }, - [Report.STATE.PENDING_APPROVAL]: { - label: Report.STATE_LABELS[Report.STATE.PENDING_APPROVAL], - color: "#848478" - }, - [Report.STATE.APPROVED]: { - label: Report.STATE_LABELS[Report.STATE.APPROVED], - color: "#75eb75" - }, - [Report.STATE.PUBLISHED]: { - label: Report.STATE_LABELS[Report.STATE.PUBLISHED], - color: "#5cb85c" - }, - [Report.STATE.CANCELLED]: { - label: Report.STATE_LABELS[Report.STATE.CANCELLED], - color: "#ec971f" - }, - [Report.STATE.REJECTED]: { - label: Report.STATE_LABELS[Report.STATE.REJECTED], - color: "#c23030" - } - } + choices: choicesFactory( + Report.STATE, + Report.STATE_LABELS, + Report.STATE_COLORS + ) }, tasks: { aggregation: { @@ -69,17 +59,7 @@ const REPORT_FIELDS_FOR_STATISTICS = { atmosphere: { type: CUSTOM_FIELD_TYPE.ENUM, label: Settings.fields.report.atmosphere, - choices: { - [Report.ATMOSPHERE.POSITIVE]: { - label: Report.ATMOSPHERE_LABELS[Report.ATMOSPHERE.POSITIVE] - }, - [Report.ATMOSPHERE.NEGATIVE]: { - label: Report.ATMOSPHERE_LABELS[Report.ATMOSPHERE.NEGATIVE] - }, - [Report.ATMOSPHERE.NEUTRAL]: { - label: Report.ATMOSPHERE_LABELS[Report.ATMOSPHERE.NEUTRAL] - } - } + choices: choicesFactory(Report.ATMOSPHERE, Report.ATMOSPHERE_LABELS) } } diff --git a/client/src/models/Report.js b/client/src/models/Report.js index c60ffe7191..30f5177015 100644 --- a/client/src/models/Report.js +++ b/client/src/models/Report.js @@ -35,12 +35,27 @@ export default class Report extends Model { [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", From c29ec3a05425b4b5bcb79d97f0fb089f62db6dfe Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 11 Jun 2020 14:46:01 +0200 Subject: [PATCH 120/247] NCI-Agency/anet#2971: Add engagementStatus to the ReportStatistics --- client/src/components/ReportStatistics.js | 8 +++++ src/main/java/mil/dds/anet/beans/Report.java | 15 ++++++++ .../java/mil/dds/anet/database/ReportDao.java | 36 +++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index 2eb9544857..52e793bf2d 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -49,6 +49,13 @@ const REPORT_FIELDS_FOR_STATISTICS = { 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, @@ -81,6 +88,7 @@ const GQL_GET_REPORT_LIST = gql` } atmosphere state + engagementStatus tasks { uuid shortName diff --git a/src/main/java/mil/dds/anet/beans/Report.java b/src/main/java/mil/dds/anet/beans/Report.java index 0cffa63f4a..68428d51dc 100644 --- a/src/main/java/mil/dds/anet/beans/Report.java +++ b/src/main/java/mil/dds/anet/beans/Report.java @@ -32,6 +32,10 @@ public enum ReportState { APPROVED } + public enum EngagementStatus { + HAPPENED, FUTURE, CANCELLED + } + public enum Atmosphere { POSITIVE, NEUTRAL, NEGATIVE } @@ -109,6 +113,8 @@ public enum ReportCancelledReason { private List authorizationGroups; // annotated below private List workflow; + // annotated below + private List engagementStatus; @GraphQLQuery(name = "approvalStep") public CompletableFuture loadApprovalStep( @@ -786,6 +792,15 @@ public boolean isFutureEngagement() { return engagementDate != null && engagementDate.isAfter(Utils.endOfToday()); } + @GraphQLQuery(name = "engagementStatus") + public synchronized List loadEngagementStatus() { + if (this.engagementStatus == null) { + this.engagementStatus = + AnetObjectEngine.getInstance().getReportDao().getEngagementStatus(uuid); + } + return engagementStatus; + } + @Override public boolean equals(Object o) { if (!(o instanceof Report)) { diff --git a/src/main/java/mil/dds/anet/database/ReportDao.java b/src/main/java/mil/dds/anet/database/ReportDao.java index 6628d24a48..dfff04cef6 100644 --- a/src/main/java/mil/dds/anet/database/ReportDao.java +++ b/src/main/java/mil/dds/anet/database/ReportDao.java @@ -27,6 +27,7 @@ import mil.dds.anet.beans.Person; import mil.dds.anet.beans.Position; import mil.dds.anet.beans.Report; +import mil.dds.anet.beans.Report.EngagementStatus; import mil.dds.anet.beans.Report.ReportState; import mil.dds.anet.beans.ReportAction; import mil.dds.anet.beans.ReportAction.ActionType; @@ -358,6 +359,41 @@ public CompletableFuture> getTagsForReport( return new ForeignKeyFetcher().load(context, FkDataLoaderKey.REPORT_TAGS, reportUuid); } + @InTransaction + public List getEngagementStatus(String reportUuid) { + final List engagementStatus = new ArrayList<>(); + Number happenedCount = (Number) getDbHandle() + .createQuery( + "/* getHappened */ SELECT count(*) as ct from reports where uuid = :reportUuid " + + "AND reports.\"engagementDate\" <= :endOfHappened") + .bind("reportUuid", reportUuid) + .bind("endOfHappened", DaoUtils.asLocalDateTime(Utils.endOfToday())) + .map(new MapMapper(false)).one().get("ct"); + if (happenedCount.longValue() > 0) { + engagementStatus.add(EngagementStatus.HAPPENED); + } + Number futureCount = (Number) getDbHandle() + .createQuery("/* getFuture */ SELECT count(*) as ct from reports where uuid = :reportUuid " + + "AND reports.\"engagementDate\" > :startOfFuture") + .bind("reportUuid", reportUuid) + .bind("startOfFuture", DaoUtils.asLocalDateTime(Utils.endOfToday())) + .map(new MapMapper(false)).one().get("ct"); + if (futureCount.longValue() > 0) { + engagementStatus.add(EngagementStatus.FUTURE); + } + Number cancelledCount = (Number) getDbHandle() + .createQuery( + "/* getCancelled */ SELECT count(*) as ct from reports where uuid = :reportUuid " + + "AND reports.state = :cancelledState") + .bind("reportUuid", reportUuid) + .bind("cancelledState", DaoUtils.getEnumId(ReportState.CANCELLED)).map(new MapMapper(false)) + .one().get("ct"); + if (cancelledCount.longValue() > 0) { + engagementStatus.add(EngagementStatus.CANCELLED); + } + return engagementStatus; + } + @Override public AnetBeanList search(ReportSearchQuery query) { return search(AnetObjectEngine.getInstance().getContext(), query).join(); From b9a9398887ab791232cd3675857905e75a1291f9 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Fri, 12 Jun 2020 15:37:54 +0200 Subject: [PATCH 121/247] NCI-Agency/anet#2971: Prevent error on report statistics map Prevent error "map container is already initialized" when mapId changed for the current map (which was already initialized). Context in whicbh the error was occuring: - go to My report page - go to the statistics view of a section with reports - click on My reports navigation item - now we were getting the error 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) --- client/src/components/Leaflet.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/client/src/components/Leaflet.js b/client/src/components/Leaflet.js index 85bf25ec61..d8918d9ab1 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 { @@ -154,6 +154,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 From 354982bad938bc0b714a47477b65b7cef7864612 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Fri, 12 Jun 2020 22:13:30 +0200 Subject: [PATCH 122/247] NCI-Agency/anet#2971: Update check for empty assessment The check for empty assessment now also checks if the value is an empty HTML value. This was needed as before if we had an assessment with a richt text editor field, the assessment was being saved even if we didn't fill the field. --- client/src/components/CustomFields.js | 2 +- client/src/pages/reports/Form.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/client/src/components/CustomFields.js b/client/src/components/CustomFields.js index 066e72e142..a8b6438069 100644 --- a/client/src/components/CustomFields.js +++ b/client/src/components/CustomFields.js @@ -65,7 +65,7 @@ SpecialField.propTypes = { const ReadonlySpecialField = ({ name, widget, values, ...otherFieldProps }) => { 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 ( !EXCLUDED_ASSESSMENT_FIELDS.includes(key) && value !== null && - value !== undefined + value !== undefined && + !utils.isEmptyHtml(value) ).length < 1 ) } From ec4f04cbc2803da242027e85d765c144445f6250 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 18 Jun 2020 17:09:50 +0200 Subject: [PATCH 123/247] NCI-Agency/anet#2954: Fix error on save task periodic assessment When editing a periodic assessment of a task and saving it, we were getting the error "Internal Server Error: The variables input contains a field name 'relatedObject' that is not defined for input object type 'NoteRelatedObjectInput'". Fixed it. Also fixed LGTM warning in the AssessmentModal, when calculating the intialValues. --- client/src/components/assessments/AssessmentModal.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/client/src/components/assessments/AssessmentModal.js b/client/src/components/assessments/AssessmentModal.js index 37ffc0a778..2c37b1c216 100644 --- a/client/src/components/assessments/AssessmentModal.js +++ b/client/src/components/assessments/AssessmentModal.js @@ -11,6 +11,7 @@ import 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" @@ -31,8 +32,9 @@ const AssessmentModal = ({ const edit = !!note.uuid const initialValues = useMemo( () => - ({ [ENTITY_ASSESSMENT_PARENT_FIELD]: assessment } || - Model.fillObject({}, assessmentYupSchema)), + _isEmpty(assessment) + ? Model.fillObject({}, assessmentYupSchema) + : { [ENTITY_ASSESSMENT_PARENT_FIELD]: assessment }, [assessment, assessmentYupSchema] ) return ( @@ -121,11 +123,15 @@ const AssessmentModal = ({ } 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: note.noteRelatedObjects + noteRelatedObjects } // values contains the assessment fields const clonedValues = _cloneDeep(values) From 14abdf5d57903463ea006be46be040794299a197 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 18 Jun 2020 17:19:25 +0200 Subject: [PATCH 124/247] NCI-Agency/anet#2954: Fix anet.yml indentation --- anet.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/anet.yml b/anet.yml index 189bf182c7..eb327fedc5 100644 --- a/anet.yml +++ b/anet.yml @@ -332,7 +332,7 @@ dictionary: once: label: once daily: - label: daily + label: daily weekly: label: weekly biweekly: From 4178f5a37f0c7ea0f8cc26522420822fc6213e1f Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 18 Jun 2020 17:27:33 +0200 Subject: [PATCH 125/247] NCI-Agency/anet#2954: Fix typo in anet.yml --- anet.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/anet.yml b/anet.yml index eb327fedc5..5c438eae54 100644 --- a/anet.yml +++ b/anet.yml @@ -267,7 +267,7 @@ dictionary: status: type: enum label: Project status - helpText: Select an assessement status for objective + helpText: Select an assessment status for objective choices: GREEN: label: Green From 34d7ecbad597fddca6ee0ca7d5aa96977ab2548c Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 18 Jun 2020 17:28:36 +0200 Subject: [PATCH 126/247] NCI-Agency/anet#2954: Simplify expression in LikertScale Followed the remark from the code review. --- client/src/components/graphs/LikertScale.js | 47 ++++++++++----------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/client/src/components/graphs/LikertScale.js b/client/src/components/graphs/LikertScale.js index 2d0c0e2eba..177f0c5a86 100644 --- a/client/src/components/graphs/LikertScale.js +++ b/client/src/components/graphs/LikertScale.js @@ -205,30 +205,29 @@ const LikertScale = ({ )} - {onChange && - (!readonly || (readonly && value && value >= scale.domain()[0])) && ( - - - - {value && value >= scale.domain()[0] - ? Number(value).toFixed(value < scale.domain()[1] ? 1 : 0) - : null} - - + {onChange && (!readonly || (value && value >= scale.domain()[0])) && ( + + + + {value && value >= scale.domain()[0] + ? Number(value).toFixed(value < scale.domain()[1] ? 1 : 0) + : null} + + )} ) From 38b8921daf4db0c7c54d8499ca2a807fba70fa71 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Fri, 19 Jun 2020 16:29:32 +0200 Subject: [PATCH 127/247] NCI-Agency/anet#2954: Add isNumeric util function --- client/src/components/BarChart.js | 9 +++------ client/src/components/DailyRollupChart.js | 7 ++----- client/src/components/HorizontalBarChart.js | 7 ++----- client/src/utils.js | 4 ++++ 4 files changed, 11 insertions(+), 16 deletions(-) diff --git a/client/src/components/BarChart.js b/client/src/components/BarChart.js index 36b83d5807..f833cb045b 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" /* @@ -111,8 +112,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 @@ -200,10 +201,6 @@ const BarChart = ({ )) || ) - - function isNumeric(value) { - return typeof value === "number" - } } BarChart.propTypes = { 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/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/utils.js b/client/src/utils.js index 1d6603c33f..e35f7fb2f5 100644 --- a/client/src/utils.js +++ b/client/src/utils.js @@ -138,6 +138,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) : "" From 778373814f263f1bc481a5ef7e04db757ab8a01a Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Fri, 19 Jun 2020 16:30:39 +0200 Subject: [PATCH 128/247] NCI-Agency/anet#2954: Show zero value in LikertScale when in domain This makes sure that if the value is zero and this one also fits within the domain ranges, it is being displayed on the scale. Also simplified the LikertScale code a bit. --- client/src/components/graphs/LikertScale.js | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/client/src/components/graphs/LikertScale.js b/client/src/components/graphs/LikertScale.js index 177f0c5a86..8104c1135e 100644 --- a/client/src/components/graphs/LikertScale.js +++ b/client/src/components/graphs/LikertScale.js @@ -23,15 +23,11 @@ const LikertScale = ({ const MARGIN_LEFT = readonly ? 13 : 25 const MARGIN_RIGHT = 13 const scaleYPosition = containerHeight - 30 - const scale = d3 .scaleLinear() .domain([0, 10]) .range([MARGIN_LEFT, containerWidth - MARGIN_RIGHT]) - const x = - value !== undefined && value !== null - ? scale(Number(value)) - : MARGIN_LEFT / 2 + const x = utils.isNumeric(value) ? scale(value) : MARGIN_LEFT / 2 const calculateNewX = useCallback( eventX => { @@ -198,8 +194,7 @@ const LikertScale = ({ y={25} style={{ pointerEvents: "none" }} > - avg:{" "} - {Number(valuesStats.avg).toFixed(value < scale.domain()[1] ? 1 : 0)} + avg: {valuesStats.avg.toFixed(value < scale.domain()[1] ? 1 : 0)} )} @@ -223,8 +218,8 @@ const LikertScale = ({ y={25} style={{ pointerEvents: "none" }} > - {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} From 2400630d06ec2d5144283ccc50c74c773022b460 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Fri, 19 Jun 2020 16:34:33 +0200 Subject: [PATCH 129/247] NCI-Agency/anet#2954: Code refactoring conform review comments --- client/src/components/Model.js | 24 +++++++++++-------- .../src/components/editor/LinkAnetEntity.js | 12 +++++----- src/main/java/mil/dds/anet/beans/Report.java | 4 ++-- .../java/mil/dds/anet/database/ReportDao.java | 6 ++--- 4 files changed, 25 insertions(+), 21 deletions(-) diff --git a/client/src/components/Model.js b/client/src/components/Model.js index b1e60f36dc..fdff119658 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -367,8 +367,8 @@ export default class Model { return a && b && a.uuid === b.uuid } - static fetchByUuid(uuid, ENTITY_GQL_FIELDS) { - const fields = ENTITY_GQL_FIELDS[this.resourceName] + static fetchByUuid(uuid, entityGqlFields) { + const fields = entityGqlFields[this.resourceName] if (!fields) { return null } @@ -429,6 +429,17 @@ export default class Model { 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 => { @@ -437,14 +448,7 @@ export default class Model { ? `${a.relatedObjectType}_${recurrence}` : recurrence const questions = a.questions || {} - return [ - assessmentKey, - typeof questions === "object" - ? questions - : typeof questions === "string" - ? utils.parseJsonSafe(questions) - : {} - ] + return [assessmentKey, Model.toConfigObject(questions)] }) ) } diff --git a/client/src/components/editor/LinkAnetEntity.js b/client/src/components/editor/LinkAnetEntity.js index cd5c442cde..fa04cb3b6b 100644 --- a/client/src/components/editor/LinkAnetEntity.js +++ b/client/src/components/editor/LinkAnetEntity.js @@ -5,12 +5,12 @@ import React, { useEffect, useState } from "react" // Entity type --> GQL query const ENTITY_GQL_FIELDS = { - Report: "uuid, intent", - Person: "uuid, name, role, avatar(size: 32)", - Organization: "uuid, shortName", - Position: "uuid, name", - Location: "uuid, name", - Task: "uuid, shortName, longName" + Report: "uuid intent", + Person: "uuid name role avatar(size: 32)", + Organization: "uuid shortName", + Position: "uuid name", + Location: "uuid name", + Task: "uuid shortName longName" } const LinkAnetEntity = ({ type, uuid, children }) => { diff --git a/src/main/java/mil/dds/anet/beans/Report.java b/src/main/java/mil/dds/anet/beans/Report.java index 68428d51dc..735350ffc0 100644 --- a/src/main/java/mil/dds/anet/beans/Report.java +++ b/src/main/java/mil/dds/anet/beans/Report.java @@ -794,8 +794,8 @@ public boolean isFutureEngagement() { @GraphQLQuery(name = "engagementStatus") public synchronized List loadEngagementStatus() { - if (this.engagementStatus == null) { - this.engagementStatus = + if (engagementStatus == null) { + engagementStatus = AnetObjectEngine.getInstance().getReportDao().getEngagementStatus(uuid); } return engagementStatus; diff --git a/src/main/java/mil/dds/anet/database/ReportDao.java b/src/main/java/mil/dds/anet/database/ReportDao.java index dfff04cef6..9ce6445258 100644 --- a/src/main/java/mil/dds/anet/database/ReportDao.java +++ b/src/main/java/mil/dds/anet/database/ReportDao.java @@ -362,7 +362,7 @@ public CompletableFuture> getTagsForReport( @InTransaction public List getEngagementStatus(String reportUuid) { final List engagementStatus = new ArrayList<>(); - Number happenedCount = (Number) getDbHandle() + final Number happenedCount = (Number) getDbHandle() .createQuery( "/* getHappened */ SELECT count(*) as ct from reports where uuid = :reportUuid " + "AND reports.\"engagementDate\" <= :endOfHappened") @@ -372,7 +372,7 @@ public List getEngagementStatus(String reportUuid) { if (happenedCount.longValue() > 0) { engagementStatus.add(EngagementStatus.HAPPENED); } - Number futureCount = (Number) getDbHandle() + final Number futureCount = (Number) getDbHandle() .createQuery("/* getFuture */ SELECT count(*) as ct from reports where uuid = :reportUuid " + "AND reports.\"engagementDate\" > :startOfFuture") .bind("reportUuid", reportUuid) @@ -381,7 +381,7 @@ public List getEngagementStatus(String reportUuid) { if (futureCount.longValue() > 0) { engagementStatus.add(EngagementStatus.FUTURE); } - Number cancelledCount = (Number) getDbHandle() + final Number cancelledCount = (Number) getDbHandle() .createQuery( "/* getCancelled */ SELECT count(*) as ct from reports where uuid = :reportUuid " + "AND reports.state = :cancelledState") From fe52e24f0c67a79e801252ac1e1bd33a79462307 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Fri, 19 Jun 2020 16:51:18 +0200 Subject: [PATCH 130/247] NCI-Agency/anet#2971: Make calendar default for insights ReportCollection This sets the default view for the ReportCollection displayed on insights pages back to calendar. The same goes for the daily rollup page. The users would be more interested in this view on this page which already contains a type of statistics. --- client/src/components/CancelledEngagementReports.js | 4 ++-- client/src/components/FutureEngagementsByLocation.js | 4 ++-- client/src/components/PendingApprovalReports.js | 4 ++-- client/src/components/ReportsByDayOfWeek.js | 4 ++-- client/src/components/ReportsByTask.js | 4 ++-- client/src/pages/rollup/Show.js | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/client/src/components/CancelledEngagementReports.js b/client/src/components/CancelledEngagementReports.js index 727ff24d37..b5a25aa98c 100644 --- a/client/src/components/CancelledEngagementReports.js +++ b/client/src/components/CancelledEngagementReports.js @@ -264,10 +264,10 @@ const Collection = ({ id, queryParams }) => ( paginationKey={`r_${id}`} queryParams={queryParams} viewFormats={[ - FORMAT_STATISTICS, FORMAT_CALENDAR, FORMAT_TABLE, - FORMAT_SUMMARY + FORMAT_SUMMARY, + FORMAT_STATISTICS ]} /> diff --git a/client/src/components/FutureEngagementsByLocation.js b/client/src/components/FutureEngagementsByLocation.js index 68b9ccacf4..077c81c735 100644 --- a/client/src/components/FutureEngagementsByLocation.js +++ b/client/src/components/FutureEngagementsByLocation.js @@ -172,10 +172,10 @@ const Collection = ({ id, queryParams }) => ( paginationKey={`r_${id}`} queryParams={queryParams} viewFormats={[ - FORMAT_STATISTICS, FORMAT_CALENDAR, FORMAT_TABLE, - FORMAT_SUMMARY + FORMAT_SUMMARY, + FORMAT_STATISTICS ]} /> diff --git a/client/src/components/PendingApprovalReports.js b/client/src/components/PendingApprovalReports.js index 98cc86b4b9..a2fd5aef6c 100644 --- a/client/src/components/PendingApprovalReports.js +++ b/client/src/components/PendingApprovalReports.js @@ -141,10 +141,10 @@ const Collection = ({ id, queryParams }) => ( paginationKey={`r_${id}`} queryParams={queryParams} viewFormats={[ - FORMAT_STATISTICS, FORMAT_CALENDAR, FORMAT_TABLE, - FORMAT_SUMMARY + FORMAT_SUMMARY, + FORMAT_STATISTICS ]} /> diff --git a/client/src/components/ReportsByDayOfWeek.js b/client/src/components/ReportsByDayOfWeek.js index 552e027b7f..7bccaca8e2 100644 --- a/client/src/components/ReportsByDayOfWeek.js +++ b/client/src/components/ReportsByDayOfWeek.js @@ -136,10 +136,10 @@ const Collection = ({ id, queryParams }) => ( paginationKey={`r_${id}`} queryParams={queryParams} viewFormats={[ - FORMAT_STATISTICS, FORMAT_CALENDAR, FORMAT_TABLE, - FORMAT_SUMMARY + FORMAT_SUMMARY, + FORMAT_STATISTICS ]} /> diff --git a/client/src/components/ReportsByTask.js b/client/src/components/ReportsByTask.js index 0ded89bfff..26ecaf80ab 100644 --- a/client/src/components/ReportsByTask.js +++ b/client/src/components/ReportsByTask.js @@ -137,10 +137,10 @@ const Collection = ({ id, queryParams }) => ( paginationKey={`r_${id}`} queryParams={queryParams} viewFormats={[ - FORMAT_STATISTICS, FORMAT_CALENDAR, FORMAT_TABLE, - FORMAT_SUMMARY + FORMAT_SUMMARY, + FORMAT_STATISTICS ]} /> diff --git a/client/src/pages/rollup/Show.js b/client/src/pages/rollup/Show.js index 916d823b5e..e413e0d6e5 100644 --- a/client/src/pages/rollup/Show.js +++ b/client/src/pages/rollup/Show.js @@ -225,10 +225,10 @@ const Collection = ({ queryParams }) => ( paginationKey="r_rollup" queryParams={queryParams} viewFormats={[ - FORMAT_STATISTICS, FORMAT_CALENDAR, FORMAT_TABLE, - FORMAT_SUMMARY + FORMAT_SUMMARY, + FORMAT_STATISTICS ]} /> From cf3cd42978edd1ea35f7c87edfd5bdf8f485d91c Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Fri, 19 Jun 2020 17:35:23 +0200 Subject: [PATCH 131/247] NCI-Agency/anet#2954: Remove code duplication Remove code duplication by reusing the getReportsByTask method in the ReportsByTask insight. --- client/src/components/ReportsByTask.js | 33 ++------------------- client/src/components/aggregations/utils.js | 3 +- 2 files changed, 3 insertions(+), 33 deletions(-) diff --git a/client/src/components/ReportsByTask.js b/client/src/components/ReportsByTask.js index 26ecaf80ab..a2f5ca9a67 100644 --- a/client/src/components/ReportsByTask.js +++ b/client/src/components/ReportsByTask.js @@ -1,6 +1,7 @@ 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" @@ -54,41 +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(reportsList) }, [data]) if (done) { return result diff --git a/client/src/components/aggregations/utils.js b/client/src/components/aggregations/utils.js index 15b832ce31..84018d581b 100644 --- a/client/src/components/aggregations/utils.js +++ b/client/src/components/aggregations/utils.js @@ -77,8 +77,7 @@ const noTask = { longName: noTaskMessage } -// TODO: use it also in components/ReportsByTasks -const getReportsByTasks = reportsList => { +export const getReportsByTasks = reportsList => { const simplifiedValues = reportsList.map(d => { return { reportUuid: d.uuid, tasks: d.tasks.map(p => p.uuid) } }) From cbb9b3eb5dfd007ed98bc9c4ea02dd1793b63776 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Fri, 19 Jun 2020 19:50:06 +0200 Subject: [PATCH 132/247] NCI-Agency/anet#2954: Run spotlessJavaApply --- src/main/java/mil/dds/anet/beans/Report.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/mil/dds/anet/beans/Report.java b/src/main/java/mil/dds/anet/beans/Report.java index 735350ffc0..991abeb523 100644 --- a/src/main/java/mil/dds/anet/beans/Report.java +++ b/src/main/java/mil/dds/anet/beans/Report.java @@ -795,8 +795,7 @@ public boolean isFutureEngagement() { @GraphQLQuery(name = "engagementStatus") public synchronized List loadEngagementStatus() { if (engagementStatus == null) { - engagementStatus = - AnetObjectEngine.getInstance().getReportDao().getEngagementStatus(uuid); + engagementStatus = AnetObjectEngine.getInstance().getReportDao().getEngagementStatus(uuid); } return engagementStatus; } From a74379df3c2c0259c07245189d798d6acc244025 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Mon, 22 Jun 2020 11:36:34 +0200 Subject: [PATCH 133/247] NCI-Agency/anet#2971: Change no reports message in ReportStatistics The message "no reports found" was not always clear enough for ReportStatistics. In the following context it needed extra details: - I create a report without an engagement date (a draft report) - I go to My Reports, draft reports - I see in the summary view a report (the draft I've just created) - I switch to the statistics tab - I see now "no reports found" This would be strange to the users, why are there reports in the summary tab but not in the statistics tab? This happens because for the statistics we only retrieve the reports for the past 3 months, so in this context no reports are retrieved for statistics. In order to make it clear to the user what happens, we made the no reports found message more specific for ReportStatistics. --- client/src/components/ReportStatistics.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index 371c6ad65c..8fe00778cf 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -7,13 +7,15 @@ import AggregationWidgetContainer, { } from "components/aggregations/AggregationWidgetContainer" import { CUSTOM_FIELD_TYPE } from "components/Model" import { PageDispatchersPropType, useBoilerplate } from "components/Page" + import _get from "lodash/get" import _uniqueId from "lodash/uniqueId" import { Report } from "models" import { PeriodsConfigPropType, PeriodsPropType, - PeriodsTableHeader + PeriodsTableHeader, + periodToString } from "periodUtils" import pluralize from "pluralize" import PropTypes from "prop-types" @@ -161,6 +163,10 @@ const ReportStatistics = ({ ) { reportQuery.engagementDateEnd = statisticsEndDate } + const totalPeriod = { + start: reportQuery.engagementDateStart, + end: reportQuery.engagementDateEnd + } const { loading, error, data } = API.useApiQuery(GQL_GET_REPORT_LIST, { reportQuery }) @@ -181,7 +187,7 @@ const ReportStatistics = ({ const reports = data ? Report.fromArray(data.reportList.list) : [] if (_get(reports, "length", 0) === 0) { - return No reports found + return {`No reports found for ${periodToString(totalPeriod)}`} } const CUSTOM_FIELDS_KEY = "customFieldsJson" const getPeriodData = (reports, dateRange) => { From e171c5d683e2bacf1d5c2b0ec15434c391c98b1c Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Mon, 22 Jun 2020 12:11:53 +0200 Subject: [PATCH 134/247] NCI-Agency/anet#2971: Improve ReportsByTask aggregation widget This makes sure that the ReportsByTask aggregation widget no longer displays a chart with a bar for no effort when there are no reports to aggregate the data of. Instead it just displays the "no data" message, as the reports by task insights also do. Also did a small code style refactoring in the ReportsByTasksWidget. --- client/src/components/ReportsByTask.js | 7 +--- .../aggregations/AggregationWidgets.js | 32 +++++++++---------- client/src/components/aggregations/utils.js | 3 ++ 3 files changed, 19 insertions(+), 23 deletions(-) diff --git a/client/src/components/ReportsByTask.js b/client/src/components/ReportsByTask.js index a2f5ca9a67..e5863ed83d 100644 --- a/client/src/components/ReportsByTask.js +++ b/client/src/components/ReportsByTask.js @@ -55,16 +55,11 @@ const Chart = ({ if (!data) { return [] } - const reportsList = data.reportList.list || [] - if (!reportsList.length) { - return [] - } - return getReportsByTasks(reportsList) + return getReportsByTasks(data.reportList.list || []) }, [data]) if (done) { return result } - return (
diff --git a/client/src/components/aggregations/AggregationWidgets.js b/client/src/components/aggregations/AggregationWidgets.js index 4f4e94be88..75e95d9f66 100644 --- a/client/src/components/aggregations/AggregationWidgets.js +++ b/client/src/components/aggregations/AggregationWidgets.js @@ -103,23 +103,21 @@ export const LikertScaleAndPieWidget = ({ values, ...otherWidgetProps }) => { } LikertScaleAndPieWidget.propTypes = aggregationWidgetPropTypes -export const ReportsByTaskWidget = ({ values, ...otherWidgetProps }) => { - return ( -
- ` -

${d.task.shortName}

-

${d.reportsCount}

- `} - /> -
- ) -} +export const ReportsByTaskWidget = ({ values, ...otherWidgetProps }) => ( +
+ ` +

${d.task.shortName}

+

${d.reportsCount}

+ `} + /> +
+) ReportsByTaskWidget.propTypes = aggregationWidgetPropTypes export const CalendarWidget = ({ diff --git a/client/src/components/aggregations/utils.js b/client/src/components/aggregations/utils.js index 84018d581b..3bd8f76c0f 100644 --- a/client/src/components/aggregations/utils.js +++ b/client/src/components/aggregations/utils.js @@ -78,6 +78,9 @@ const noTask = { } export const getReportsByTasks = reportsList => { + if (!reportsList.length) { + return [] + } const simplifiedValues = reportsList.map(d => { return { reportUuid: d.uuid, tasks: d.tasks.map(p => p.uuid) } }) From cc3b15f85b87c8f2255634b261a31dc86e3bd950 Mon Sep 17 00:00:00 2001 From: Vassil Iordanov Date: Wed, 24 Jun 2020 16:35:21 +0200 Subject: [PATCH 135/247] nci-agency/anet#2954: Simplify engagementStatus calculation --- src/main/java/mil/dds/anet/beans/Report.java | 13 +++---- .../java/mil/dds/anet/database/ReportDao.java | 35 ------------------- 2 files changed, 7 insertions(+), 41 deletions(-) diff --git a/src/main/java/mil/dds/anet/beans/Report.java b/src/main/java/mil/dds/anet/beans/Report.java index 991abeb523..dc3e6d4ded 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; @@ -113,8 +114,6 @@ public enum ReportCancelledReason { private List authorizationGroups; // annotated below private List workflow; - // annotated below - private List engagementStatus; @GraphQLQuery(name = "approvalStep") public CompletableFuture loadApprovalStep( @@ -793,11 +792,13 @@ public boolean isFutureEngagement() { } @GraphQLQuery(name = "engagementStatus") - public synchronized List loadEngagementStatus() { - if (engagementStatus == null) { - engagementStatus = AnetObjectEngine.getInstance().getReportDao().getEngagementStatus(uuid); + public List getEngagementStatus() { + LinkedList statuses = new LinkedList(); + if (ReportState.CANCELLED.equals(getState())) { + statuses.add(EngagementStatus.CANCELLED); } - return engagementStatus; + statuses.add(isFutureEngagement() ? EngagementStatus.FUTURE : EngagementStatus.HAPPENED); + return statuses; } @Override diff --git a/src/main/java/mil/dds/anet/database/ReportDao.java b/src/main/java/mil/dds/anet/database/ReportDao.java index 9ce6445258..06638437f4 100644 --- a/src/main/java/mil/dds/anet/database/ReportDao.java +++ b/src/main/java/mil/dds/anet/database/ReportDao.java @@ -359,41 +359,6 @@ public CompletableFuture> getTagsForReport( return new ForeignKeyFetcher().load(context, FkDataLoaderKey.REPORT_TAGS, reportUuid); } - @InTransaction - public List getEngagementStatus(String reportUuid) { - final List engagementStatus = new ArrayList<>(); - final Number happenedCount = (Number) getDbHandle() - .createQuery( - "/* getHappened */ SELECT count(*) as ct from reports where uuid = :reportUuid " - + "AND reports.\"engagementDate\" <= :endOfHappened") - .bind("reportUuid", reportUuid) - .bind("endOfHappened", DaoUtils.asLocalDateTime(Utils.endOfToday())) - .map(new MapMapper(false)).one().get("ct"); - if (happenedCount.longValue() > 0) { - engagementStatus.add(EngagementStatus.HAPPENED); - } - final Number futureCount = (Number) getDbHandle() - .createQuery("/* getFuture */ SELECT count(*) as ct from reports where uuid = :reportUuid " - + "AND reports.\"engagementDate\" > :startOfFuture") - .bind("reportUuid", reportUuid) - .bind("startOfFuture", DaoUtils.asLocalDateTime(Utils.endOfToday())) - .map(new MapMapper(false)).one().get("ct"); - if (futureCount.longValue() > 0) { - engagementStatus.add(EngagementStatus.FUTURE); - } - final Number cancelledCount = (Number) getDbHandle() - .createQuery( - "/* getCancelled */ SELECT count(*) as ct from reports where uuid = :reportUuid " - + "AND reports.state = :cancelledState") - .bind("reportUuid", reportUuid) - .bind("cancelledState", DaoUtils.getEnumId(ReportState.CANCELLED)).map(new MapMapper(false)) - .one().get("ct"); - if (cancelledCount.longValue() > 0) { - engagementStatus.add(EngagementStatus.CANCELLED); - } - return engagementStatus; - } - @Override public AnetBeanList search(ReportSearchQuery query) { return search(AnetObjectEngine.getInstance().getContext(), query).join(); From 3ff917212c82b5a51dc909cf4dfa09b1bb38c34d Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 2 Jul 2020 16:39:21 +0200 Subject: [PATCH 136/247] NCI-Agency/anet#2954: Display no assessment when no period assessment When for a period there are no assessments available, we display the text no assessments and no longer display the possible question labels. --- .../assessments/AssessmentResultsTable.js | 38 +++++++++++++------ 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index 85a425a933..e8e9ed9c41 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -44,7 +44,9 @@ const InstantAssessmentRow = ({ questionKey, questionConfig, entity, - periods + periods, + periodsData, + rowIndex }) => { const aggregationWidget = getAggregationWidget(questionConfig) if (!aggregationWidget) { @@ -55,14 +57,20 @@ const InstantAssessmentRow = ({
{periods.map((period, index) => ( ))} @@ -71,8 +79,10 @@ const InstantAssessmentRow = ({ InstantAssessmentRow.propTypes = { entity: PropTypes.object, periods: PeriodsPropType, + periodsData: PropTypes.arrayOf(PropTypes.array), questionKey: PropTypes.string, - questionConfig: PropTypes.object + questionConfig: PropTypes.object, + rowIndex: PropTypes.number } const BasePeriodicAssessmentRows = ({ @@ -229,6 +239,10 @@ const EntityAssessmentResults = ({ } const instantAssessmentConfig = entity.getInstantAssessmentConfig() const { periods } = periodsConfig + const dataPerPeriod = [] + periodsConfig.periods.forEach(period => + dataPerPeriod.push(entity.getInstantAssessmentResults(period)) + ) return ( <> @@ -236,13 +250,15 @@ const EntityAssessmentResults = ({ - {Object.keys(instantAssessmentConfig || {}).map(key => ( + {Object.keys(instantAssessmentConfig || {}).map((key, index) => ( ))} Date: Thu, 2 Jul 2020 16:45:25 +0200 Subject: [PATCH 137/247] NCI-Agency/anet#2954: Distinguish case when no reports for report period This makes sure that if there are no reports for one of the ReportStatistics periods, we display a message instead of not filled widgets. --- client/src/components/ReportStatistics.js | 35 ++++++++++++++--------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index 8fe00778cf..2fee81950e 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -7,8 +7,8 @@ import AggregationWidgetContainer, { } from "components/aggregations/AggregationWidgetContainer" import { CUSTOM_FIELD_TYPE } from "components/Model" import { PageDispatchersPropType, useBoilerplate } from "components/Page" - import _get from "lodash/get" +import _isEmpty from "lodash/isEmpty" import _uniqueId from "lodash/uniqueId" import { Report } from "models" import { @@ -106,7 +106,8 @@ const FieldStatisticsRow = ({ fieldConfig, fieldName, periods, - periodsData + periodsData, + rowIndex }) => { const aggregationWidget = getAggregationWidget(fieldConfig) if (!aggregationWidget) { @@ -116,15 +117,21 @@ const FieldStatisticsRow = ({ {periods.map((period, index) => ( ))} @@ -134,7 +141,8 @@ FieldStatisticsRow.propTypes = { fieldConfig: PropTypes.object, fieldName: PropTypes.string, periods: PeriodsPropType, - periodsData: PropTypes.arrayOf(PropTypes.array) + periodsData: PropTypes.arrayOf(PropTypes.array), + rowIndex: PropTypes.number } const ReportStatistics = ({ @@ -220,13 +228,14 @@ const ReportStatistics = ({ <> - {Object.keys(REPORT_FIELDS_FOR_STATISTICS || {}).map(key => ( + {Object.keys(REPORT_FIELDS_FOR_STATISTICS || {}).map((key, index) => ( ))} {Object.keys(customFieldsConfig || {}).map(key => ( From f16f68ee2ac5098cdfdba7700c6853042f93db22 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 2 Jul 2020 17:23:41 +0200 Subject: [PATCH 138/247] NCI-Agency/anet#2954: Update aggregation widgets when no value This makes sure that if there are no values available for a field, but there is data to be aggregated, we no longer display an empty widget but display the message "no specified" instead. This makes it more clear to hte users what happens. --- .../AggregationWidgetContainer.js | 6 + .../aggregations/AggregationWidgets.js | 65 ++++--- client/src/components/graphs/IqrBoxPlot.js | 159 +++++++++--------- client/src/components/graphs/LikertScale.js | 11 +- 4 files changed, 142 insertions(+), 99 deletions(-) diff --git a/client/src/components/aggregations/AggregationWidgetContainer.js b/client/src/components/aggregations/AggregationWidgetContainer.js index 1ad8cdc76f..c57168d067 100644 --- a/client/src/components/aggregations/AggregationWidgetContainer.js +++ b/client/src/components/aggregations/AggregationWidgetContainer.js @@ -133,6 +133,11 @@ const AggregationWidgetContainer = ({ widgetId, ...otherWidgetProps }) => { + const WHEN_UNSPECIFIED = ( +
+ Not specified +
+ ) const aggregationWidget = widget || getAggregationWidget(fieldConfig) const aggregationFunction = getAggregationFunction( fieldConfig, @@ -165,6 +170,7 @@ const AggregationWidgetContainer = ({ fieldConfig={fieldConfig} fieldName={fieldName} period={period} + whenUnspecified={WHEN_UNSPECIFIED} {...fieldProps} {...otherWidgetProps} {...otherAggregationDetails} diff --git a/client/src/components/aggregations/AggregationWidgets.js b/client/src/components/aggregations/AggregationWidgets.js index 75e95d9f66..719a2ccb50 100644 --- a/client/src/components/aggregations/AggregationWidgets.js +++ b/client/src/components/aggregations/AggregationWidgets.js @@ -32,7 +32,8 @@ const aggregationWidgetPropTypes = { fieldConfig: PropTypes.object, fieldName: PropTypes.string, vertical: PropTypes.bool, - period: PropTypes.oneOfType([AssessmentPeriodPropType, PeriodPropType]) + period: PropTypes.oneOfType([AssessmentPeriodPropType, PeriodPropType]), + whenUnspecified: PropTypes.oneOfType([PropTypes.string, PropTypes.object]) } export const PieWidget = ({ @@ -91,13 +92,19 @@ export const LikertScaleAndPieWidget = ({ values, ...otherWidgetProps }) => { > -
- -
+ {!_isEmpty(likertScaleValues) && ( +
+ +
+ )} ) } @@ -125,17 +132,22 @@ export const CalendarWidget = ({ fieldConfig, fieldName, period, + whenUnspecified, ...otherWidgetProps }) => { const calendarComponentRef = useRef(null) - const events = Object.entries(values).map(([key, value]) => { - return { - title: `${value} events`, - start: key, - end: key + 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 ( { +export const DefaultAggWidget = ({ + values, + whenUnspecified, + ...otherWidgetProps +}) => { const [showValues, setShowValues] = useState(false) - if (_isEmpty(values)) { - return null + const filteredValues = values.filter( + value => !(value === null || value === undefined) + ) + if (_isEmpty(filteredValues)) { + return whenUnspecified } return (
@@ -185,16 +204,16 @@ export const DefaultAggWidget = ({ values, ...otherWidgetProps }) => { onClick={toggleShowValues} id="toggleShowValues" > - {showValues ? "Hide" : "Show"} {values.length} values + {showValues ? "Hide" : "Show"} {filteredValues.length} values
- + {_isEmpty(periodsData[index]) ? ( + rowIndex === 0 ? ( + No assessments + ) : null + ) : ( + + )}
- + {_isEmpty(periodsData[index]) ? ( + rowIndex === 0 ? ( + No reports found + ) : null + ) : ( + + )}
- {values.map(val => { + {filteredValues.map(val => { const keyValue = _uniqueId("value_") return ( - + ) })} @@ -214,6 +233,7 @@ export const ReportsMapWidget = ({ mapId, width, height, + whenUnspecified, ...otherWidgetProps }) => { const markers = useMemo(() => { @@ -235,6 +255,9 @@ export const ReportsMapWidget = ({ }) return markerArray }, [values]) + if (_isEmpty(markers)) { + return whenUnspecified + } return (
{ +const IqrBoxPlot = ({ + onChange, + values, + levels, + width, + height, + readonly, + whenUnspecified +}) => { const cursorRef = useRef(null) const axisRef = useRef(null) const [containerRef, containerBox] = useDimensions() @@ -50,80 +59,79 @@ const IqrBoxPlot = ({ onChange, values, levels, width, height, readonly }) => { const fillColor = d3.color("lightGray") fillColor.opacity = 0.4 - if (values.length === 0) { - return null - } else { - return ( - - {values?.length > 1 && ( - - - - - - - - - )} - - - {onChange && ( - - - - )} - - ) + if (_isEmpty(values)) { + return whenUnspecified } + return ( + + {values?.length > 1 && ( + + + + + + + + + )} + + + {onChange && ( + + + + )} + + ) } IqrBoxPlot.propTypes = { @@ -139,7 +147,8 @@ IqrBoxPlot.propTypes = { ).isRequired, width: PropTypes.string.isRequired, height: PropTypes.string.isRequired, - readonly: PropTypes.bool + readonly: PropTypes.bool, + whenUnspecified: PropTypes.oneOfType([PropTypes.string, PropTypes.object]) } IqrBoxPlot.defaultProps = { diff --git a/client/src/components/graphs/LikertScale.js b/client/src/components/graphs/LikertScale.js index 8104c1135e..3235186cf0 100644 --- a/client/src/components/graphs/LikertScale.js +++ b/client/src/components/graphs/LikertScale.js @@ -1,5 +1,6 @@ import React, { useCallback, useEffect, useRef } from "react" import * as d3 from "d3" +import _isEmpty from "lodash/isEmpty" import PropTypes from "prop-types" import Text from "react-svg-text" import useDimensions from "react-use-dimensions" @@ -12,7 +13,8 @@ const LikertScale = ({ levels, width, height, - readonly + readonly, + whenUnspecified }) => { const cursorRef = useRef(null) const axisRef = useRef(null) @@ -83,6 +85,9 @@ const LikertScale = ({ let activeColor = null let valuesStats = null const numberValues = utils.arrayOfNumbers(values) + if (numberValues !== undefined && _isEmpty(numberValues)) { + return whenUnspecified + } if (numberValues?.length) { valuesStats = { min: Math.min(...numberValues), @@ -93,7 +98,6 @@ const LikertScale = ({ level => level.endValue > valuesStats.avg )?.color } - return ( Date: Thu, 2 Jul 2020 17:48:25 +0200 Subject: [PATCH 139/247] NCI-Agency/anet#2954: Introduce isNullOrUndefined util In order to reduce code duplication. --- client/src/components/FieldHelper.js | 8 ++------ client/src/components/Model.js | 3 +-- client/src/components/aggregations/AggregationWidgets.js | 5 ++--- client/src/utils.js | 7 ++++++- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/client/src/components/FieldHelper.js b/client/src/components/FieldHelper.js index 425d657edf..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 = ({ () => ( ), diff --git a/client/src/components/Model.js b/client/src/components/Model.js index fdff119658..ddc9ac4756 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -252,8 +252,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() } diff --git a/client/src/components/aggregations/AggregationWidgets.js b/client/src/components/aggregations/AggregationWidgets.js index 719a2ccb50..ac8462d1ab 100644 --- a/client/src/components/aggregations/AggregationWidgets.js +++ b/client/src/components/aggregations/AggregationWidgets.js @@ -14,6 +14,7 @@ import { AssessmentPeriodPropType, PeriodPropType } from "periodUtils" import PropTypes from "prop-types" import React, { useMemo, useRef, useState } from "react" import { Button, Collapse, Table } from "react-bootstrap" +import utils from "utils" const DATE_FORMAT = "YYYY-MM-DD" @@ -190,9 +191,7 @@ export const DefaultAggWidget = ({ ...otherWidgetProps }) => { const [showValues, setShowValues] = useState(false) - const filteredValues = values.filter( - value => !(value === null || value === undefined) - ) + const filteredValues = values.filter(value => !utils.isNullOrUndefined(value)) if (_isEmpty(filteredValues)) { return whenUnspecified } diff --git a/client/src/utils.js b/client/src/utils.js index e35f7fb2f5..c5144dbe30 100644 --- a/client/src/utils.js +++ b/client/src/utils.js @@ -22,9 +22,14 @@ Object.keys(changeCase) !input ? "" : changeCase[c](input, options) }) +const isNullOrUndefined = value => { + return value === null || value === undefined +} + export default { ...wrappedChangeCase, pluralize, + isNullOrUndefined, resourceize: function(string) { return pluralize(wrappedChangeCase.camelCase(string)) }, @@ -193,7 +198,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 } } From 95b0c2338f0772a304a1f8c1539701a44864459e Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 2 Jul 2020 18:00:27 +0200 Subject: [PATCH 140/247] NCI-Agency/anet#2954: Remove prev/next from aggregation calendar widget Per default the calendar aggregation widget will not display a prev/next navigation. --- client/src/components/aggregations/AggregationWidgets.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/client/src/components/aggregations/AggregationWidgets.js b/client/src/components/aggregations/AggregationWidgets.js index ac8462d1ab..c010cdc75e 100644 --- a/client/src/components/aggregations/AggregationWidgets.js +++ b/client/src/components/aggregations/AggregationWidgets.js @@ -134,6 +134,7 @@ export const CalendarWidget = ({ fieldName, period, whenUnspecified, + hasPrevNext = false, ...otherWidgetProps }) => { const calendarComponentRef = useRef(null) @@ -153,7 +154,7 @@ export const CalendarWidget = ({ ) } -CalendarWidget.propTypes = aggregationWidgetPropTypes +CalendarWidget.propTypes = { + hasPrevNext: PropTypes.bool, + ...aggregationWidgetPropTypes +} export const DefaultAggWidget = ({ values, From 2e2f4cc754ef9aba77899d6322745458b099b662 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 2 Jul 2020 18:20:46 +0200 Subject: [PATCH 141/247] NCI-Agency/anet#2954: Set default prop value for whenUnspecified --- .../aggregations/AggregationWidgets.js | 16 ++++++++++++++-- client/src/components/graphs/IqrBoxPlot.js | 3 ++- client/src/components/graphs/LikertScale.js | 3 ++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/client/src/components/aggregations/AggregationWidgets.js b/client/src/components/aggregations/AggregationWidgets.js index c010cdc75e..e1630b1ef5 100644 --- a/client/src/components/aggregations/AggregationWidgets.js +++ b/client/src/components/aggregations/AggregationWidgets.js @@ -36,6 +36,9 @@ const aggregationWidgetPropTypes = { period: PropTypes.oneOfType([AssessmentPeriodPropType, PeriodPropType]), whenUnspecified: PropTypes.oneOfType([PropTypes.string, PropTypes.object]) } +const aggregationWidgetDefaultProps = { + whenUnspecified: null +} export const PieWidget = ({ values, @@ -75,6 +78,7 @@ PieWidget.propTypes = { showLegend: PropTypes.bool, ...aggregationWidgetPropTypes } +PieWidget.defaultProps = aggregationWidgetDefaultProps export const LikertScaleAndPieWidget = ({ values, ...otherWidgetProps }) => { const { likertScaleValues, pieValues } = values @@ -110,6 +114,7 @@ export const LikertScaleAndPieWidget = ({ values, ...otherWidgetProps }) => { ) } LikertScaleAndPieWidget.propTypes = aggregationWidgetPropTypes +LikertScaleAndPieWidget.defaultProps = aggregationWidgetDefaultProps export const ReportsByTaskWidget = ({ values, ...otherWidgetProps }) => (
@@ -127,6 +132,7 @@ export const ReportsByTaskWidget = ({ values, ...otherWidgetProps }) => (
) ReportsByTaskWidget.propTypes = aggregationWidgetPropTypes +ReportsByTaskWidget.defaultProps = aggregationWidgetDefaultProps export const CalendarWidget = ({ values, @@ -134,7 +140,7 @@ export const CalendarWidget = ({ fieldName, period, whenUnspecified, - hasPrevNext = false, + hasPrevNext, ...otherWidgetProps }) => { const calendarComponentRef = useRef(null) @@ -188,6 +194,10 @@ CalendarWidget.propTypes = { hasPrevNext: PropTypes.bool, ...aggregationWidgetPropTypes } +CalendarWidget.defaultProps = { + hasPrevNext: false, + ...aggregationWidgetDefaultProps +} export const DefaultAggWidget = ({ values, @@ -230,6 +240,7 @@ export const DefaultAggWidget = ({ } } DefaultAggWidget.propTypes = aggregationWidgetPropTypes +DefaultAggWidget.defaultProps = aggregationWidgetDefaultProps export const ReportsMapWidget = ({ values, @@ -280,5 +291,6 @@ ReportsMapWidget.propTypes = { height: PropTypes.number } ReportsMapWidget.defaultProps = { - values: [] + values: [], + ...aggregationWidgetDefaultProps } diff --git a/client/src/components/graphs/IqrBoxPlot.js b/client/src/components/graphs/IqrBoxPlot.js index c21ba61d5e..8102d6e554 100644 --- a/client/src/components/graphs/IqrBoxPlot.js +++ b/client/src/components/graphs/IqrBoxPlot.js @@ -167,7 +167,8 @@ IqrBoxPlot.defaultProps = { } ], height: "65", - width: "100%" + width: "100%", + whenUnspecified: null } export default IqrBoxPlot diff --git a/client/src/components/graphs/LikertScale.js b/client/src/components/graphs/LikertScale.js index 3235186cf0..81305c549d 100644 --- a/client/src/components/graphs/LikertScale.js +++ b/client/src/components/graphs/LikertScale.js @@ -267,7 +267,8 @@ LikertScale.defaultProps = { } ], height: "65", - width: "100%" + width: "100%", + whenUnspecified: null } export default LikertScale From af58902d312d052ec88c6978a0e97fefeacb20d8 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Thu, 2 Jul 2020 17:48:12 +0000 Subject: [PATCH 142/247] Update most non-major dependencies --- build.gradle | 6 +- client/package.json | 58 +- client/yarn.lock | 845 ++++++++++++++--------- gradle/wrapper/gradle-wrapper.properties | 2 +- 4 files changed, 566 insertions(+), 345 deletions(-) diff --git a/build.gradle b/build.gradle index a4eed07f7f..a1941b7c39 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ plugins { id "org.kordamp.markdown.convert" version "1.2.0" id "com.bmuschko.docker-remote-api" version "6.4.0" id "com.github.node-gradle.node" version "2.2.4" - id "com.diffplug.gradle.spotless" version "4.4.0" + id "com.diffplug.gradle.spotless" version "4.5.0" } apply plugin: 'java' @@ -74,7 +74,7 @@ dependencies { // Supported databases: implementation 'com.microsoft.sqlserver:mssql-jdbc:8.2.2.jre8' implementation 'org.postgresql:postgresql:42.2.14' // If using postgresql - implementation 'org.liquibase:liquibase-core:3.10.0' + implementation 'org.liquibase:liquibase-core:3.10.1' // For caching domain users (used in every request in the AuthenticationFilter) implementation 'org.ehcache:ehcache:3.8.1' @@ -93,7 +93,7 @@ dependencies { // 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' diff --git a/client/package.json b/client/package.json index 44c33a7454..a28981d823 100644 --- a/client/package.json +++ b/client/package.json @@ -4,33 +4,33 @@ "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.10.4", + "@babel/plugin-proposal-class-properties": "7.10.4", + "@babel/plugin-proposal-decorators": "7.10.4", + "@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.10.4", + "@babel/plugin-proposal-nullish-coalescing-operator": "7.10.4", + "@babel/plugin-proposal-numeric-separator": "7.10.4", + "@babel/plugin-proposal-optional-chaining": "7.10.4", + "@babel/plugin-proposal-pipeline-operator": "7.10.4", + "@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.4", + "@babel/preset-react": "7.10.4", + "@babel/register": "7.10.4", + "@babel/runtime": "7.10.4", "@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/cli": "6.1.24", + "@wdio/local-runner": "6.1.24", "@wdio/mocha-framework": "6.1.19", - "@wdio/spec-reporter": "6.1.14", + "@wdio/spec-reporter": "6.1.23", "@wdio/sync": "6.1.14", "aigle": "1.14.1", "autoprefixer": "9.8.4", @@ -46,7 +46,7 @@ "clean-webpack-plugin": "3.0.0", "colors": "1.4.0", "config": "3.3.1", - "copy-webpack-plugin": "6.0.2", + "copy-webpack-plugin": "6.0.3", "countries-list": "2.5.4", "cross-fetch": "3.0.5", "cross-spawn": "7.0.3", @@ -57,13 +57,13 @@ "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.3", + "eslint-plugin-react-hooks": "4.0.5", "eslint-plugin-standard": "4.0.1", "faker": "https://github.com/Marak/faker.js.git", "file-loader": "6.0.0", @@ -86,7 +86,7 @@ "style-loader": "1.2.1", "thread-loader": "2.1.3", "wdio-chromedriver-service": "6.0.3", - "webdriverio": "6.1.22", + "webdriverio": "6.1.24", "webpack": "4.43.0", "webpack-cli": "3.3.12", "webpack-dev-server": "3.11.0", @@ -118,7 +118,7 @@ "file-saver": "2.0.2", "formik": "2.1.4", "graphiql": "1.0.3", - "graphql": "15.1.0", + "graphql": "15.2.0", "hopscotch": "0.3.1", "html-react-parser": "0.13.0", "jsonpath-plus": "4.0.0", @@ -148,7 +148,7 @@ "react-scroll": "1.7.16", "react-svg-text": "0.1.2", "react-tag-input": "6.4.3", - "react-toastify": "6.0.6", + "react-toastify": "6.0.8", "react-tooltip": "4.2.7", "react-ultimate-pagination": "1.2.0", "react-use-dimensions": "1.2.1", diff --git a/client/yarn.lock b/client/yarn.lock index 476782c5d8..32ca6a1c18 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -34,12 +34,12 @@ dependencies: "@babel/highlight" "^7.10.1" -"@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== +"@babel/code-frame@^7.10.4": + 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.3" + "@babel/highlight" "^7.10.4" "@babel/compat-data@^7.10.1", "@babel/compat-data@^7.9.0": version "7.10.1" @@ -50,19 +50,19 @@ 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.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.4.tgz#780e8b83e496152f8dd7df63892b2e052bf1d51d" + integrity sha512-3A0tS0HWpy4XujGc7QtOIHTeNwUgWaZc/WuS5YQrfhU67jnVmsD6OGPc1AKHH0LJHQICGncy3+YUjIhVlfDdcA== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.10.4" + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helpers" "^7.10.4" + "@babel/parser" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" @@ -126,12 +126,12 @@ lodash "^4.17.13" source-map "^0.5.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.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.4.tgz#e49eeed9fe114b62fa5b181856a43a5e32f5f243" + integrity sha512-toLIHUIAgcQygFZRAQcsLQV3CBuX6yOIru1kJk/qqqvcRmZrYe6WavZTSG+bB8MxhnL9YPf+pKQfuiP161q7ng== dependencies: - "@babel/types" "^7.10.3" + "@babel/types" "^7.10.4" jsesc "^2.5.1" lodash "^4.17.13" source-map "^0.5.0" @@ -143,6 +143,13 @@ dependencies: "@babel/types" "^7.10.1" +"@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.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" @@ -160,6 +167,15 @@ "@babel/helper-module-imports" "^7.10.1" "@babel/types" "^7.10.1" +"@babel/helper-builder-react-jsx-experimental@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.10.4.tgz#d0ffb875184d749c63ffe1f4f65be15143ec322d" + integrity sha512-LyacH/kgQPgLAuaWrvvq1+E7f5bLyT8jXCh7nM67sRsy2cpIGfgWJ+FCnAKQXfY+F0tXUaN6FqLkp4JiCzdK8Q== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-module-imports" "^7.10.4" + "@babel/types" "^7.10.4" + "@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" @@ -168,6 +184,14 @@ "@babel/helper-annotate-as-pure" "^7.10.1" "@babel/types" "^7.10.1" +"@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.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" @@ -191,17 +215,17 @@ "@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== +"@babel/helper-create-class-features-plugin@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.4.tgz#2d4015d0136bd314103a70d84a7183e4b344a355" + integrity sha512-9raUiOsXPxzzLjCXeosApJItoMnX3uyT4QdM2UldffuGApNrF8e938MwNpDCK9CPoyxrEoCgT+hObJc3mZa6lQ== 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-function-name" "^7.10.4" + "@babel/helper-member-expression-to-functions" "^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" "@babel/helper-create-regexp-features-plugin@^7.10.1", "@babel/helper-create-regexp-features-plugin@^7.8.3": version "7.10.1" @@ -238,14 +262,14 @@ "@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== +"@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: - "@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.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/helper-get-function-arity@^7.10.1": version "7.10.1" @@ -254,12 +278,12 @@ 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== +"@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.3" + "@babel/types" "^7.10.4" "@babel/helper-hoist-variables@^7.10.1": version "7.10.1" @@ -275,12 +299,12 @@ 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== +"@babel/helper-member-expression-to-functions@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.4.tgz#7cd04b57dfcf82fce9aeae7d4e4452fa31b8c7c4" + integrity sha512-m5j85pK/KZhuSdM/8cHUABQTAslV47OjfIB9Cc7P+PvlAoBzdb79BGNfw8RhT5Mq3p+xGd0ZfAKixbrUZx0C7A== dependencies: - "@babel/types" "^7.10.3" + "@babel/types" "^7.10.4" "@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" @@ -289,6 +313,13 @@ dependencies: "@babel/types" "^7.10.1" +"@babel/helper-module-imports@^7.10.4": + 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.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" @@ -302,6 +333,19 @@ "@babel/types" "^7.10.1" lodash "^4.17.13" +"@babel/helper-module-transforms@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.10.4.tgz#ca1f01fdb84e48c24d7506bb818c961f1da8805d" + integrity sha512-Er2FQX0oa3nV7eM1o0tNCTx7izmQtwAQsIiaLRWtavAAEcskb0XJ5OjJbVrYXWOTr8om921Scabn4/tzlx7j1Q== + 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.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" + 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" @@ -309,22 +353,22 @@ 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== +"@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.3" + "@babel/types" "^7.10.4" "@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-plugin-utils@^7.10.4": + 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.1": version "7.10.1" @@ -354,6 +398,16 @@ "@babel/traverse" "^7.10.1" "@babel/types" "^7.10.1" +"@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.1": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz#08fb7e22ace9eb8326f7e3920a1c2052f13d851e" @@ -362,6 +416,14 @@ "@babel/template" "^7.10.1" "@babel/types" "^7.10.1" +"@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-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" @@ -369,15 +431,22 @@ dependencies: "@babel/types" "^7.10.1" +"@babel/helper-split-export-declaration@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz#2c70576eaa3b5609b24cb99db2888cc3fc4251d1" + integrity sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg== + dependencies: + "@babel/types" "^7.10.4" + "@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-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.1": version "7.10.1" @@ -389,6 +458,16 @@ "@babel/traverse" "^7.10.1" "@babel/types" "^7.10.1" +"@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.1", "@babel/helpers@^7.9.0": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.1.tgz#a6827b7cb975c9d9cef5fd61d919f60d8844a973" @@ -398,6 +477,15 @@ "@babel/traverse" "^7.10.1" "@babel/types" "^7.10.1" +"@babel/helpers@^7.10.4": + 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.1": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.1.tgz#841d098ba613ba1a427a2b383d79e35552c38ae0" @@ -407,12 +495,12 @@ 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== +"@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.3" + "@babel/helper-validator-identifier" "^7.10.4" chalk "^2.0.0" js-tokens "^4.0.0" @@ -421,10 +509,10 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.2.tgz#871807f10442b92ff97e4783b9b54f6a0ca812d0" integrity sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ== -"@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.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.4.tgz#9eedf27e1998d87739fb5028a5120557c06a1a64" + integrity sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA== "@babel/plugin-proposal-async-generator-functions@^7.10.1", "@babel/plugin-proposal-async-generator-functions@^7.8.3": version "7.10.1" @@ -435,13 +523,13 @@ "@babel/helper-remap-async-to-generator" "^7.10.1" "@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": + 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 +539,22 @@ "@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-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== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.1" + +"@babel/plugin-proposal-decorators@7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.10.4.tgz#fe20ef10cc73f386f70910fca48798041cd357c7" + integrity sha512-JHTWjQngOPv+ZQQqOGv2x6sCCr4IYWy7S1/VH6BE9ZfkoLrdQ2GpEP3tfb5M++G9PwvqjhY8VC/C3tXm+/eHvA== 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.4" + "@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,13 +565,13 @@ "@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" @@ -485,32 +581,40 @@ "@babel/helper-plugin-utils" "^7.10.1" "@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": + 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.4": + 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.4" + "@babel/plugin-syntax-json-strings" "^7.8.0" -"@babel/plugin-proposal-json-strings@7.10.1", "@babel/plugin-proposal-json-strings@^7.10.1", "@babel/plugin-proposal-json-strings@^7.8.3": +"@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== @@ -518,20 +622,20 @@ "@babel/helper-plugin-utils" "^7.10.1" "@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.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.10.4.tgz#e62b5cf38e494d6cc24683e2a26cba4a28f7ea44" + integrity sha512-gyZd+5BZdK3rTpLCw0cTXUESWywH4wvugdzuUYkDKhtP0Obkp2ebZZzVE24UhVOb47vTDNwbUzQpei9psxYj6A== 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": + 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 +646,21 @@ "@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": +"@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-numeric-separator/-/plugin-proposal-numeric-separator-7.10.1.tgz#a9a38bc34f78bdfd981e791c27c6fdcec478c123" - integrity sha512-jjfym4N9HtCiNfyyLAVD8WqPYeHUrw4ihxuAynWj6zzp2gf9Ey2f7ImhFm6ikB3CLf5Z/zmcJDri6B4+9j9RsA== + 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== dependencies: "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-numeric-separator" "^7.10.1" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + +"@babel/plugin-proposal-numeric-separator@7.10.4": + 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.4" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@babel/plugin-proposal-numeric-separator@7.8.3": version "7.8.3" @@ -558,6 +670,14 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-numeric-separator" "^7.8.3" +"@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== + dependencies: + "@babel/helper-plugin-utils" "^7.10.1" + "@babel/plugin-syntax-numeric-separator" "^7.10.1" + "@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" @@ -575,12 +695,12 @@ "@babel/helper-plugin-utils" "^7.10.1" "@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.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.4.tgz#750f1255e930a1f82d8cdde45031f81a0d0adff7" + integrity sha512-ZIhQIEeavTgouyMSdZRap4VPPHqJJ3NEs2cuHs5p0erH+iz6khB0qfgU8g7UuJkG88+fBMy23ZiU+nuHvekJeQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.3" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-optional-chaining" "^7.8.0" "@babel/plugin-proposal-optional-chaining@7.9.0": @@ -599,13 +719,13 @@ "@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== +"@babel/plugin-proposal-pipeline-operator@7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-pipeline-operator/-/plugin-proposal-pipeline-operator-7.10.4.tgz#14d76c110409416f84c520d8a617bbe7f6a754dc" + integrity sha512-NL4M3pQrvBZKrudP2WybWIHWgLR4ZwWiIYPk1T0jbXl665Ao7ODn+OLksv2+1bMGwOIE49vNcmhaAMA0uqRgGA== 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" @@ -615,13 +735,13 @@ "@babel/helper-create-class-features-plugin" "^7.10.1" "@babel/helper-plugin-utils" "^7.10.1" -"@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" @@ -652,19 +772,26 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.1" -"@babel/plugin-syntax-decorators@^7.10.1", "@babel/plugin-syntax-decorators@^7.8.3": +"@babel/plugin-syntax-decorators@^7.10.4": + 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.4" + +"@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== dependencies: "@babel/helper-plugin-utils" "^7.10.1" -"@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 +800,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" @@ -694,19 +821,19 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.1" -"@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": + 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" @@ -722,7 +849,21 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.1" -"@babel/plugin-syntax-logical-assignment-operators@^7.10.1", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": +"@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.4" + +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": + 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.4" + +"@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== @@ -743,6 +884,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.1" +"@babel/plugin-syntax-numeric-separator@^7.10.4": + 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.4" + "@babel/plugin-syntax-object-rest-spread@^7.8.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" @@ -764,19 +912,19 @@ 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" @@ -993,12 +1141,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.1" -"@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.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-proto-to-assign/-/plugin-transform-proto-to-assign-7.10.4.tgz#d2a5802a506955618805684a4699e4ee62fb4d6a" + integrity sha512-cu1HAWSPYPzL/ra4FodvPXycLCodjoOY3B3gi8Hz50HEaKJ1YZ/nDeCnCkQEQMVneImA6+B63UyTdmn02YngLA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" lodash "^4.17.13" "@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": @@ -1022,6 +1170,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.1" +"@babel/plugin-transform-react-display-name@^7.10.4": + 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.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" @@ -1031,6 +1186,15 @@ "@babel/helper-plugin-utils" "^7.10.1" "@babel/plugin-syntax-jsx" "^7.10.1" +"@babel/plugin-transform-react-jsx-development@^7.10.4": + 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.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" @@ -1039,6 +1203,14 @@ "@babel/helper-plugin-utils" "^7.10.1" "@babel/plugin-syntax-jsx" "^7.10.1" +"@babel/plugin-transform-react-jsx-self@^7.10.4": + 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.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" @@ -1047,6 +1219,14 @@ "@babel/helper-plugin-utils" "^7.10.1" "@babel/plugin-syntax-jsx" "^7.10.1" +"@babel/plugin-transform-react-jsx-source@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.10.4.tgz#86baf0fcccfe58084e06446a80858e1deae8f291" + integrity sha512-FTK3eQFrPv2aveerUSazFmGygqIdTtvskG50SnGnbEUnRPcGx2ylBhdFIzoVS1ty44hEgcPoCAyw5r3VDEq+Ug== + dependencies: + "@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" @@ -1057,6 +1237,16 @@ "@babel/helper-plugin-utils" "^7.10.1" "@babel/plugin-syntax-jsx" "^7.10.1" +"@babel/plugin-transform-react-jsx@^7.10.4": + 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.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" @@ -1065,6 +1255,14 @@ "@babel/helper-annotate-as-pure" "^7.10.1" "@babel/helper-plugin-utils" "^7.10.1" +"@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.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" @@ -1305,18 +1503,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": + 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" @@ -1330,6 +1528,19 @@ "@babel/plugin-transform-react-jsx-self" "^7.9.0" "@babel/plugin-transform-react-jsx-source" "^7.9.0" +"@babel/preset-react@^7.0.0": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.10.1.tgz#e2ab8ae9a363ec307b936589f07ed753192de041" + integrity sha512-Rw0SxQ7VKhObmFjD/cUcKhPTtzpeviEFX1E6PgP+cYOhQ98icNqtINNFANlsdbQHrmeWnqdxA4Tmnl1jy5tp3Q== + 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/preset-typescript@7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.9.0.tgz#87705a72b1f0d59df21c179f7c3d2ef4b16ce192" @@ -1338,10 +1549,10 @@ "@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.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.10.4.tgz#53004ba8b04c4af3cbd84508e03ad150669746e4" + integrity sha512-whHmgGiWNVyTVnYTSawtDWhaeYsc+noeU8Rmi+MPnbGhDYmr5QpEDMrQcIA07D2RUv0BlThPcN89XcHCqq/O4g== dependencies: find-cache-dir "^2.0.0" lodash "^4.17.13" @@ -1365,18 +1576,10 @@ 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== - 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.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.4.tgz#a6724f1a6b8d2f6ea5236dbfe58c7d7ea9c5eb99" + integrity sha512-UpTN5yUJr9b4EX2CnGNWIvER7Ab83ibv0pcvvHc4UOdrBI5jb8bj+32cCwPX6xu0mt2daFNjYhoi+X7beH0RSw== dependencies: regenerator-runtime "^0.13.4" @@ -1394,6 +1597,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@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== + 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" @@ -1403,14 +1613,14 @@ "@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== +"@babel/template@^7.10.4": + 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.3" - "@babel/parser" "^7.10.3" - "@babel/types" "^7.10.3" + "@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.1", "@babel/traverse@^7.7.0", "@babel/traverse@^7.9.0": version "7.10.1" @@ -1427,17 +1637,17 @@ 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/traverse@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.4.tgz#e642e5395a3b09cc95c8e74a27432b484b697818" + integrity sha512-aSy7p5THgSYm4YyxNGz6jZpXf+Ok40QF3aA2LyIONkDHpAcJzDUqlCKXv6peqYUs2gmic849C/t2HKw2a2K20Q== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.10.4" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" + "@babel/parser" "^7.10.4" + "@babel/types" "^7.10.4" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.13" @@ -1451,12 +1661,12 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" -"@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.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.4.tgz#369517188352e18219981efd156bfdb199fff1ee" + integrity sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg== dependencies: - "@babel/helper-validator-identifier" "^7.10.3" + "@babel/helper-validator-identifier" "^7.10.4" lodash "^4.17.13" to-fast-properties "^2.0.0" @@ -2868,10 +3078,10 @@ 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.1.24": + version "6.1.24" + resolved "https://registry.yarnpkg.com/@wdio/cli/-/cli-6.1.24.tgz#b0ec7714aacf585cd24bcfc7f4c7e0bf2c9a5f22" + integrity sha512-a0gX4vK7yzXSKtF+9ya0M+hc8ZKPXvJ/LhFaDgnv8n5NNRYO1ghRzRE0O3KSh1kiHp42Z6GAuzpwkpyft3RAKQ== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" @@ -2887,7 +3097,7 @@ lodash.pickby "^4.6.0" lodash.union "^4.6.0" log-update "^4.0.0" - webdriverio "6.1.22" + webdriverio "6.1.24" yargs "^15.0.1" yarn-install "^1.0.0" @@ -2900,14 +3110,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.1.24": + version "6.1.24" + resolved "https://registry.yarnpkg.com/@wdio/local-runner/-/local-runner-6.1.24.tgz#c72c8e7ab5548522618c736de81b37e2ec0d6f96" + integrity sha512-SU2IO0axEQSfdImxeB4lJjh/UXcklZm80hi7BxKFqK76311+sw7QyOlBMIPMOeDcToZkdI2J1RiKoImdzMMO+Q== dependencies: "@wdio/logger" "6.0.16" "@wdio/repl" "6.1.17" - "@wdio/runner" "6.1.22" + "@wdio/runner" "6.1.24" async-exit-hook "^2.0.1" stream-buffers "^3.0.2" @@ -2943,17 +3153,17 @@ dependencies: "@wdio/utils" "6.1.17" -"@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.1.23": + version "6.1.23" + resolved "https://registry.yarnpkg.com/@wdio/reporter/-/reporter-6.1.23.tgz#d4781cbf4ede1dfded91053dcafd8777a1d4bf6b" + integrity sha512-9OmAd6X/g6lpjNkA/sEPc28prCUCZKxbmoapzgaMrp7mNsb0Wmi2UDCWKvTVwldloQON7A98qQTrHr+k9GcL1w== 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.1.24": + version "6.1.24" + resolved "https://registry.yarnpkg.com/@wdio/runner/-/runner-6.1.24.tgz#072981706741af305bb740b1981f236b43e3dff9" + integrity sha512-aV8fhz5FYb5NroXH3V3BNQ11WMDDxV2748th2Ea0QHtxcFPZ4QYN5HJ7qWOoqNKSm/AYEKn1XuTat+6N55rmrQ== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" @@ -2961,14 +3171,14 @@ deepmerge "^4.0.0" gaze "^1.1.2" webdriver "6.1.17" - webdriverio "6.1.22" + webdriverio "6.1.24" -"@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.1.23": + version "6.1.23" + resolved "https://registry.yarnpkg.com/@wdio/spec-reporter/-/spec-reporter-6.1.23.tgz#e95c081a5711412afbd41388a85f7a263520f8a7" + integrity sha512-QA6gbrmnV0xWXB5mp86XXSKVgoR75M/euloVxJsIgFAXCfDdh1txUfmzW2wbjRrkv+XSSFKUFBAaHNwcvuWiFQ== dependencies: - "@wdio/reporter" "6.1.14" + "@wdio/reporter" "6.1.23" chalk "^4.0.0" easy-table "^1.1.1" pretty-ms "^7.0.0" @@ -3600,7 +3810,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== @@ -5478,21 +5688,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: @@ -6352,10 +6562,10 @@ 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@6.1.23: + version "6.1.23" + resolved "https://registry.yarnpkg.com/devtools/-/devtools-6.1.23.tgz#637ffefc48e8de6ce0d90ab0840880ae9ad7f5b2" + integrity sha512-+9b3bURLZED3sPVPQluGQFTuv/evRfQugM8dr+eybhOIfkSTGIlyks82QlaxMjHEBiaRXk3AFSl1f110T2tTKA== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" @@ -7021,10 +7231,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,27 +7292,27 @@ 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.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.0.5.tgz#4879003aa38e5d05d0312175beb6e4a1f617bfcf" + integrity sha512-3YLSjoArsE2rUwL8li4Yxx1SUg3DQWp+78N3bcJQGWVZckcp+yeQGsap/MSq05+thJk57o+Ww4PtZukXGL02TQ== -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.3: + version "7.20.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.3.tgz#0590525e7eb83890ce71f73c2cf836284ad8c2f1" + integrity sha512-txbo090buDeyV0ugF3YMWrzLIUqpYTsWSDZV9xLSmExE1P/Kmgg9++PD931r+KEWS66O1c9R4srLVVHmeHpoAg== 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" @@ -7486,7 +7696,7 @@ 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: +fast-glob@^3.0.3, fast-glob@^3.1.1: version "3.2.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.2.tgz#ade1a9d91148965d4bf7c51f72e1ca662d32e63d" integrity sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A== @@ -7498,6 +7708,18 @@ fast-glob@^3.0.3, fast-glob@^3.1.1, fast-glob@^3.2.2: micromatch "^4.0.2" picomatch "^2.2.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" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" + fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -8352,10 +8574,10 @@ graphql-tag@^2.4.2: resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.10.3.tgz#ea1baba5eb8fc6339e4c4cf049dabe522b0edf03" integrity sha512-4FOv3ZKfA4WdOKJeHdz6B3F/vxBLSgmBcGeAFPf4n1F64ltJUvOOerNj0rsJxONQGdhUMynQIvd6LzB+1J5oKA== -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.2.0: + version "15.2.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.2.0.tgz#d9c655a523a3196d4b23657ec6ec5963b3bd4970" + integrity sha512-tsceRyHfgzZo+ee0YK3o8f0CR0cXAXxRlxoORWFo/CoM1bVy3UXGWeyzBcf+Y6oqPvO27BDmOEVATcunOO/MrQ== growl@1.10.5: version "1.10.5" @@ -10187,14 +10409,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" @@ -11491,7 +11705,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== @@ -11696,6 +11910,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.1" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.0.1.tgz#584784ac0722d1aed09f19f90ed2999af6ce2839" + integrity sha512-mw/p92EyOzl2MhauKodw54Rx5ZK4624rNfgNaBguFZkHzyUG9WsDzFF5/yQVEJinbJDdP4jEfMN+uBquiGnaLg== + 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" @@ -13006,10 +13227,10 @@ 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" @@ -13454,7 +13675,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== @@ -13781,6 +14002,13 @@ serialize-javascript@^3.1.0: dependencies: randombytes "^2.1.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" + serve-favicon@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/serve-favicon/-/serve-favicon-2.5.0.tgz#935d240cdfe0f5805307fdfe967d88942a2cbcf0" @@ -15535,10 +15763,10 @@ webdriver@6.1.17: 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.1.24: + version "6.1.24" + resolved "https://registry.yarnpkg.com/webdriverio/-/webdriverio-6.1.24.tgz#2e71c89050db47d592420ff285a4c7fc9e3e32ea" + integrity sha512-VvB4davXI2w3V63Oy6tcmAlXIWXrRP4F8IaQVU1bTMwhMKkJZ82yGaP8BgE07P8e66+0O/ZpPnHNYaaJ6Zkzcg== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" @@ -15546,7 +15774,7 @@ webdriverio@6.1.22: "@wdio/utils" "6.1.17" archiver "^4.0.1" css-value "^0.0.1" - devtools "6.1.22" + devtools "6.1.23" grapheme-splitter "^1.0.2" lodash.clonedeep "^4.5.0" lodash.isobject "^3.0.2" @@ -15889,13 +16117,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" 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 From d7c6ff562de003848f0f82685bc8252aeae0b0a9 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Fri, 3 Jul 2020 00:08:33 +0200 Subject: [PATCH 143/247] NCI-Agency/anet#2954: Add periods navigation This makes it possible to shift the periods in the ReportStatistics and the AssessmentResultsTable to the left or to the right. --- client/src/components/Model.js | 21 +---- client/src/components/PeriodsNavigation.js | 30 ++++++ client/src/components/ReportCollection.js | 25 +---- client/src/components/ReportStatistics.js | 91 ++++++++++--------- .../assessments/AssessmentResultsContainer.js | 77 +--------------- .../assessments/AssessmentResultsTable.js | 30 +++--- client/src/pages/dashboards/DiagramNode.js | 11 +-- client/src/pages/reports/Form.js | 4 +- client/src/periodUtils.js | 88 ++++++++++++++++++ 9 files changed, 200 insertions(+), 177 deletions(-) create mode 100644 client/src/components/PeriodsNavigation.js diff --git a/client/src/components/Model.js b/client/src/components/Model.js index ddc9ac4756..c05e5eaba2 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -5,6 +5,7 @@ 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 utils from "utils" import * as yup from "yup" @@ -102,16 +103,6 @@ export const NOTE_TYPE = { export const DEFAULT_CUSTOM_FIELDS_PARENT = "formCustomFields" export const INVISIBLE_CUSTOM_FIELDS_FIELD = "invisibleCustomFields" -export const ASSESSMENTS_RECURRENCE_TYPE = { - ONCE: "once", - DAILY: "daily", - WEEKLY: "weekly", - BIWEEKLY: "biweekly", - SEMIMONTHLY: "semimonthly", - MONTHLY: "monthly", - QUARTERLY: "quarterly", - SEMIANNUALY: "semiannualy" -} export const ASSESSMENTS_RELATED_OBJECT_TYPE = { REPORT: "report" } @@ -442,7 +433,7 @@ export default class Model { static parseAssessmentsConfig(assessmentsConfig) { return Object.fromEntries( assessmentsConfig.map(a => { - const recurrence = a.recurrence || ASSESSMENTS_RECURRENCE_TYPE.ONCE + const recurrence = a.recurrence || RECURRENCE_TYPE.ONCE const assessmentKey = a.relatedObjectType ? `${a.relatedObjectType}_${recurrence}` : recurrence @@ -473,13 +464,11 @@ export default class Model { relatedObjectType = ASSESSMENTS_RELATED_OBJECT_TYPE.REPORT ) { return this.getAssessmentsConfig()[ - `${relatedObjectType}_${ASSESSMENTS_RECURRENCE_TYPE.ONCE}` + `${relatedObjectType}_${RECURRENCE_TYPE.ONCE}` ] } - getPeriodicAssessmentDetails( - recurrence = ASSESSMENTS_RECURRENCE_TYPE.MONTHLY - ) { + getPeriodicAssessmentDetails(recurrence = RECURRENCE_TYPE.MONTHLY) { const assessmentConfig = this.getAssessmentsConfig()[recurrence] return { assessmentConfig: assessmentConfig, @@ -554,7 +543,7 @@ export default class Model { .map(note => utils.parseJsonSafe(note.text)) .filter( obj => - obj.__recurrence === ASSESSMENTS_RECURRENCE_TYPE.ONCE && + obj.__recurrence === RECURRENCE_TYPE.ONCE && obj.__relatedObjectType === relatedObjectType ) } diff --git a/client/src/components/PeriodsNavigation.js b/client/src/components/PeriodsNavigation.js new file mode 100644 index 0000000000..7289c2524d --- /dev/null +++ b/client/src/components/PeriodsNavigation.js @@ -0,0 +1,30 @@ +import React from "react" +import { Button } from "react-bootstrap" +import PropTypes from "prop-types" + +const PeriodsNavigation = ({ offset, onChange }) => ( + <> + + {offset - 1 >= 0 && ( + + )} + +) +PeriodsNavigation.propTypes = { + offset: PropTypes.number, + onChange: PropTypes.func +} + +export default PeriodsNavigation diff --git a/client/src/components/ReportCollection.js b/client/src/components/ReportCollection.js index aad45f5a10..d587812c21 100644 --- a/client/src/components/ReportCollection.js +++ b/client/src/components/ReportCollection.js @@ -1,7 +1,5 @@ import { setPagination } from "actions" -import { ASSESSMENT_PERIOD_FACTORIES } from "components/assessments/AssessmentResultsContainer" import ButtonToggleGroup from "components/ButtonToggleGroup" -import { ASSESSMENTS_RECURRENCE_TYPE } from "components/Model" import { PageDispatchersPropType, mapPageDispatchersToProps @@ -11,7 +9,7 @@ import ReportMap from "components/ReportMap" import ReportStatistics from "components/ReportStatistics" import ReportSummary from "components/ReportSummary" import ReportTable from "components/ReportTable" -import moment from "moment" +import { RECURRENCE_TYPE } from "periodUtils" import PropTypes from "prop-types" import React, { useState } from "react" import { Button } from "react-bootstrap" @@ -39,9 +37,7 @@ const ReportCollection = ({ }) => { const [viewFormat, setViewFormat] = useState(viewFormats[0]) const showHeader = viewFormats.length > 1 || reportsFilter - const statisticsRecurrence = [ASSESSMENTS_RECURRENCE_TYPE.MONTHLY] - const now = moment() - + const statisticsRecurrence = [RECURRENCE_TYPE.MONTHLY] return (
@@ -125,22 +121,9 @@ const ReportCollection = ({ pageDispatchers={pageDispatchers} queryParams={queryParams} setTotalCount={setTotalCount} - periodsConfig={{ + periodsDetails={{ recurrence: recurrence, - periods: [ - { - // Second Most recent completed period - ...ASSESSMENT_PERIOD_FACTORIES[recurrence](now, 2) - }, - { - // Most recent completed period - ...ASSESSMENT_PERIOD_FACTORIES[recurrence](now, 1) - }, - { - // Ongoing period - ...ASSESSMENT_PERIOD_FACTORIES[recurrence](now, 0) - } - ] + numberOfPeriods: 3 }} /> ))} diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index 2fee81950e..c5c909791c 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -7,19 +7,19 @@ import AggregationWidgetContainer, { } from "components/aggregations/AggregationWidgetContainer" import { CUSTOM_FIELD_TYPE } from "components/Model" import { PageDispatchersPropType, useBoilerplate } from "components/Page" -import _get from "lodash/get" +import PeriodsNavigation from "components/PeriodsNavigation" import _isEmpty from "lodash/isEmpty" import _uniqueId from "lodash/uniqueId" import { Report } from "models" import { - PeriodsConfigPropType, + getPeriodsConfig, + PeriodsDetailsPropType, PeriodsPropType, - PeriodsTableHeader, - periodToString + PeriodsTableHeader } from "periodUtils" import pluralize from "pluralize" import PropTypes from "prop-types" -import React, { useEffect } from "react" +import React, { useEffect, useState } from "react" import { Table } from "react-bootstrap" import Settings from "settings" import utils from "utils" @@ -147,10 +147,13 @@ FieldStatisticsRow.propTypes = { const ReportStatistics = ({ pageDispatchers, - periodsConfig, + periodsDetails, setTotalCount, queryParams }) => { + const [offset, setOffset] = useState(0) + const { recurrence, numberOfPeriods } = periodsDetails + const periodsConfig = getPeriodsConfig(recurrence, numberOfPeriods, offset) const dateSortAsc = datesArray => datesArray.sort((a, b) => a - b) const statisticsStartDate = dateSortAsc( periodsConfig.periods.map(p => p.start) @@ -171,10 +174,6 @@ const ReportStatistics = ({ ) { reportQuery.engagementDateEnd = statisticsEndDate } - const totalPeriod = { - start: reportQuery.engagementDateStart, - end: reportQuery.engagementDateEnd - } const { loading, error, data } = API.useApiQuery(GQL_GET_REPORT_LIST, { reportQuery }) @@ -194,9 +193,6 @@ const ReportStatistics = ({ } const reports = data ? Report.fromArray(data.reportList.list) : [] - if (_get(reports, "length", 0) === 0) { - return {`No reports found for ${periodToString(totalPeriod)}`} - } const CUSTOM_FIELDS_KEY = "customFieldsJson" const getPeriodData = (reports, dateRange) => { const reportsForDateRange = reports.filter( @@ -219,43 +215,48 @@ const ReportStatistics = ({ const customFieldsConfig = Settings.fields.report.customFields return ( -
val{val}
- - - <> - {Object.keys(REPORT_FIELDS_FOR_STATISTICS || {}).map((key, index) => ( - - ))} - {Object.keys(customFieldsConfig || {}).map(key => ( - - ))} - - -
+ <> + + + + + <> + {Object.keys(REPORT_FIELDS_FOR_STATISTICS || {}).map( + (key, index) => ( + + ) + )} + {Object.keys(customFieldsConfig || {}).map(key => ( + + ))} + + +
+ ) } ReportStatistics.propTypes = { pageDispatchers: PageDispatchersPropType, - periodsConfig: PeriodsConfigPropType, + periodsDetails: PeriodsDetailsPropType, setTotalCount: PropTypes.func, queryParams: PropTypes.object } diff --git a/client/src/components/assessments/AssessmentResultsContainer.js b/client/src/components/assessments/AssessmentResultsContainer.js index b2a5beb701..794df37e42 100644 --- a/client/src/components/assessments/AssessmentResultsContainer.js +++ b/client/src/components/assessments/AssessmentResultsContainer.js @@ -1,61 +1,8 @@ import AssessmentResultsTable from "components/assessments/AssessmentResultsTable" -import { ASSESSMENTS_RECURRENCE_TYPE } from "components/Model" -import moment from "moment" +import { PERIOD_FACTORIES } from "periodUtils" import PropTypes from "prop-types" import React from "react" -const now = moment() - -export const ASSESSMENT_PERIOD_FACTORIES = { - [ASSESSMENTS_RECURRENCE_TYPE.DAILY]: (date, offset) => ({ - start: date.clone().subtract(offset, "days").startOf("day"), - end: date.clone().subtract(offset, "days").endOf("day") - }), - [ASSESSMENTS_RECURRENCE_TYPE.WEEKLY]: (date, offset) => ({ - start: date.clone().subtract(offset, "weeks").startOf("week"), - end: date.clone().subtract(offset, "weeks").endOf("week") - }), - // FIXME: biweekly should be each 2 weeks from the beginning of the year - [ASSESSMENTS_RECURRENCE_TYPE.BIWEEKLY]: (date, offset) => ({ - start: date - .clone() - .subtract(2 * offset, "weeks") - .startOf("week"), - end: date - .clone() - .subtract(2 * offset, "weeks") - .endOf("week") - }), - [ASSESSMENTS_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") - }), - [ASSESSMENTS_RECURRENCE_TYPE.MONTHLY]: (date, offset) => ({ - start: date.clone().subtract(offset, "months").startOf("month"), - end: date.clone().subtract(offset, "months").endOf("month") - }), - [ASSESSMENTS_RECURRENCE_TYPE.QUARTERLY]: (date, offset) => ({ - start: date.clone().subtract(offset, "quarters").startOf("quarter"), - end: date.clone().subtract(offset, "quarters").endOf("quarter") - }), - [ASSESSMENTS_RECURRENCE_TYPE.SEMIANNUALY]: (date, offset) => ({ - start: date - .clone() - .subtract(2 * offset, "quarters") - .startOf("quarter"), - end: date - .clone() - .subtract(2 * offset, "quarters") - .endOf("quarter") - }) -} - const AssessmentResultsContainer = ({ entity, entityType, @@ -71,32 +18,16 @@ const AssessmentResultsContainer = ({ <> {assessmentsTypes.map( assessmentsType => - ASSESSMENT_PERIOD_FACTORIES[assessmentsType] && ( + PERIOD_FACTORIES[assessmentsType] && ( { + const [offset, setOffset] = useState(0) if (!entity) { return null } - const { recurrence } = periodsConfig + const { recurrence, numberOfPeriods } = periodsDetails + const periodsConfig = getPeriodsConfig( + recurrence, + numberOfPeriods, + offset, + true + ) const entityInstantAssessmentConfig = entity.getInstantAssessmentConfig() const subentitiesInstantAssessmentConfig = subEntities ?.map(s => s.getInstantAssessmentConfig()) @@ -310,6 +315,7 @@ const AssessmentResultsTable = ({ title={`Assessment results - ${recurrence}`} id={`"entity-assessments-results-${recurrence}`} > + { const ModelClass = anetObjectType && Models[anetObjectType] const modelInstance = ModelClass && new ModelClass(anetObject) const now = moment() - const period = ASSESSMENT_PERIOD_FACTORIES[ - ASSESSMENTS_RECURRENCE_TYPE.MONTHLY - ](now, 0) + const period = PERIOD_FACTORIES[RECURRENCE_TYPE.MONTHLY](now, 0) const instantAssessmentConfig = anetObject && anetObject.getInstantAssessmentConfig() const instantAssessmentResults = diff --git a/client/src/pages/reports/Form.js b/client/src/pages/reports/Form.js index 6a904b801f..42d2743dfd 100644 --- a/client/src/pages/reports/Form.js +++ b/client/src/pages/reports/Form.js @@ -22,7 +22,6 @@ import * as FieldHelper from "components/FieldHelper" import Fieldset from "components/Fieldset" import Messages from "components/Messages" import { - ASSESSMENTS_RECURRENCE_TYPE, ASSESSMENTS_RELATED_OBJECT_TYPE, DEFAULT_CUSTOM_FIELDS_PARENT, NOTE_TYPE @@ -46,6 +45,7 @@ import _isEmpty from "lodash/isEmpty" import _upperFirst from "lodash/upperFirst" 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" @@ -1297,7 +1297,7 @@ const BaseReportForm = ({ !isEmptyAssessment(entitiesAssessments[key]) ) .map(key => { - entitiesAssessments[key].__recurrence = ASSESSMENTS_RECURRENCE_TYPE.ONCE + entitiesAssessments[key].__recurrence = RECURRENCE_TYPE.ONCE entitiesAssessments[key].__relatedObjectType = ASSESSMENTS_RELATED_OBJECT_TYPE.REPORT const noteObj = { diff --git a/client/src/periodUtils.js b/client/src/periodUtils.js index c9ccecc3fb..82b5bca7f0 100644 --- a/client/src/periodUtils.js +++ b/client/src/periodUtils.js @@ -1,6 +1,90 @@ +import moment from "moment" import PropTypes from "prop-types" import React from "react" +const now = moment() + +export const RECURRENCE_TYPE = { + ONCE: "once", + DAILY: "daily", + WEEKLY: "weekly", + BIWEEKLY: "biweekly", + SEMIMONTHLY: "semimonthly", + MONTHLY: "monthly", + QUARTERLY: "quarterly", + SEMIANNUALY: "semiannualy" +} + +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 should be each 2 weeks from the beginning of the year + [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 PeriodPropType = PropTypes.shape({ start: PropTypes.object, end: PropTypes.object @@ -16,6 +100,10 @@ export const PeriodsConfigPropType = PropTypes.shape({ recurrence: PropTypes.string, periods: PeriodsPropType }) +export const PeriodsDetailsPropType = PropTypes.shape({ + recurrence: PropTypes.string, + numberOfPeriods: PropTypes.number +}) export const AssessmentPeriodsPropType = PropTypes.arrayOf( AssessmentPeriodPropType ) From b0a0140bdc5bfc0f9b71b7d7d1347d498a0762bf Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Fri, 3 Jul 2020 15:13:40 +0200 Subject: [PATCH 144/247] NCI-Agency/anet#2954: Fix server side tests The server side tests related to reports were failing because of the Report's class getEngagementStatus method name (while the report bean doesn't have an engagementStatus property). Changed the method name to loadEngagementStatus. --- src/main/java/mil/dds/anet/beans/Report.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/mil/dds/anet/beans/Report.java b/src/main/java/mil/dds/anet/beans/Report.java index dc3e6d4ded..a04a45de25 100644 --- a/src/main/java/mil/dds/anet/beans/Report.java +++ b/src/main/java/mil/dds/anet/beans/Report.java @@ -792,7 +792,7 @@ public boolean isFutureEngagement() { } @GraphQLQuery(name = "engagementStatus") - public List getEngagementStatus() { + public List loadEngagementStatus() { LinkedList statuses = new LinkedList(); if (ReportState.CANCELLED.equals(getState())) { statuses.add(EngagementStatus.CANCELLED); From 67f94a184df2e666f20e5fa7e41590aced8db767 Mon Sep 17 00:00:00 2001 From: Vassil Date: Sat, 4 Jul 2020 12:00:13 +0200 Subject: [PATCH 145/247] nci-agency/anet#2954: Add icons and alignment to period navigation buttons --- client/src/components/PeriodsNavigation.js | 26 +++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/client/src/components/PeriodsNavigation.js b/client/src/components/PeriodsNavigation.js index 7289c2524d..c86b210c00 100644 --- a/client/src/components/PeriodsNavigation.js +++ b/client/src/components/PeriodsNavigation.js @@ -1,26 +1,26 @@ +import { Icon } from "@blueprintjs/core" +import { IconNames } from "@blueprintjs/icons" +import PropTypes from "prop-types" import React from "react" import { Button } from "react-bootstrap" -import PropTypes from "prop-types" const PeriodsNavigation = ({ offset, onChange }) => ( - <> +
+ - {offset - 1 >= 0 && ( - - )} - +
) PeriodsNavigation.propTypes = { offset: PropTypes.number, From 1802090b7c99865d1f896e0c15293bb885e55915 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Mon, 6 Jul 2020 12:29:52 +0200 Subject: [PATCH 146/247] NCI-Agency/anet#2954: Add primary advisor rank to ReportStatistics --- client/src/components/ReportStatistics.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index c5c909791c..99b2417226 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -70,6 +70,9 @@ const REPORT_FIELDS_FOR_STATISTICS = { type: CUSTOM_FIELD_TYPE.ENUM, label: Settings.fields.report.atmosphere, choices: choicesFactory(Report.ATMOSPHERE, Report.ATMOSPHERE_LABELS) + }, + "primaryAdvisor.rank": { + type: CUSTOM_FIELD_TYPE.ENUM } } @@ -92,6 +95,10 @@ const GQL_GET_REPORT_LIST = gql` atmosphere state engagementStatus + primaryAdvisor { + uuid + rank + } tasks { uuid shortName From 415aa3499daf2898147aca1f60db7a567968b3bf Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Tue, 7 Jul 2020 08:44:57 +0000 Subject: [PATCH 147/247] Update most non-major dependencies --- build.gradle | 18 ++-- client/package.json | 16 ++-- client/yarn.lock | 219 ++++++++++++++++++++++++++++++-------------- 3 files changed, 165 insertions(+), 88 deletions(-) diff --git a/build.gradle b/build.gradle index a1941b7c39..818e28e466 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.5.0" id "com.github.node-gradle.node" version "2.2.4" - id "com.diffplug.gradle.spotless" version "4.5.0" + id "com.diffplug.gradle.spotless" version "4.5.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.11' + implementation 'io.dropwizard:dropwizard-jdbi3:2.0.11' + implementation 'io.dropwizard:dropwizard-migrations:2.0.11' + implementation 'io.dropwizard:dropwizard-auth:2.0.11' + implementation 'io.dropwizard:dropwizard-views-freemarker:2.0.11' implementation 'io.dropwizard-bundles:dropwizard-configurable-assets-bundle:1.3.5' implementation 'ru.vyarus.guicey:guicey-jdbi3:5.1.0-2' @@ -105,8 +105,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.11' + testImplementation 'io.dropwizard:dropwizard-client:2.0.11' testImplementation 'org.apache.commons:commons-io:1.3.2' testImplementation 'org.assertj:assertj-core:3.16.1' diff --git a/client/package.json b/client/package.json index a28981d823..923c65f539 100644 --- a/client/package.json +++ b/client/package.json @@ -27,14 +27,14 @@ "@storybook/addon-actions": "5.3.19", "@storybook/react": "5.3.19", "@wdio/browserstack-service": "6.1.15", - "@wdio/cli": "6.1.24", - "@wdio/local-runner": "6.1.24", + "@wdio/cli": "6.1.25", + "@wdio/local-runner": "6.1.25", "@wdio/mocha-framework": "6.1.19", "@wdio/spec-reporter": "6.1.23", "@wdio/sync": "6.1.14", "aigle": "1.14.1", "autoprefixer": "9.8.4", - "ava": "3.9.0", + "ava": "3.10.0", "babel-eslint": "10.1.0", "babel-jest": "26.1.0", "babel-loader": "8.1.0", @@ -42,7 +42,7 @@ "cache-loader": "4.1.0", "chai": "4.2.0", "chalk": "4.1.0", - "chromedriver": "83.0.0", + "chromedriver": "83.0.1", "clean-webpack-plugin": "3.0.0", "colors": "1.4.0", "config": "3.3.1", @@ -52,7 +52,7 @@ "cross-spawn": "7.0.3", "css-loader": "3.6.0", "dotenv": "8.2.0", - "eslint": "7.3.1", + "eslint": "7.4.0", "eslint-config-react-app": "5.2.1", "eslint-config-standard": "14.1.1", "eslint-config-standard-react": "9.2.0", @@ -86,7 +86,7 @@ "style-loader": "1.2.1", "thread-loader": "2.1.3", "wdio-chromedriver-service": "6.0.3", - "webdriverio": "6.1.24", + "webdriverio": "6.1.25", "webpack": "4.43.0", "webpack-cli": "3.3.12", "webpack-dev-server": "3.11.0", @@ -118,7 +118,7 @@ "file-saver": "2.0.2", "formik": "2.1.4", "graphiql": "1.0.3", - "graphql": "15.2.0", + "graphql": "15.3.0", "hopscotch": "0.3.1", "html-react-parser": "0.13.0", "jsonpath-plus": "4.0.0", @@ -154,7 +154,7 @@ "react-use-dimensions": "1.2.1", "redux": "4.0.5", "redux-persist": "6.0.0", - "use-debounce": "3.4.2", + "use-debounce": "3.4.3", "yup": "0.29.1" }, "scripts": { diff --git a/client/yarn.lock b/client/yarn.lock index 32ca6a1c18..d1cc40c08b 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -1576,6 +1576,14 @@ core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" +"@babel/runtime-corejs3@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.10.4.tgz#f29fc1990307c4c57b10dbd6ce667b27159d9e0d" + integrity sha512-BFlgP2SoLO9HJX9WBwN67gHWMBhDX/eDz64Jajd6mR/UAUzqrNMm99d4qHnVaKscAElZoFiPv+JpR/Siud5lXw== + dependencies: + core-js-pure "^3.0.0" + regenerator-runtime "^0.13.4" + "@babel/runtime@7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.4.tgz#a6724f1a6b8d2f6ea5236dbfe58c7d7ea9c5eb99" @@ -3078,10 +3086,10 @@ browserstack-local "^1.4.5" got "^11.0.2" -"@wdio/cli@6.1.24": - version "6.1.24" - resolved "https://registry.yarnpkg.com/@wdio/cli/-/cli-6.1.24.tgz#b0ec7714aacf585cd24bcfc7f4c7e0bf2c9a5f22" - integrity sha512-a0gX4vK7yzXSKtF+9ya0M+hc8ZKPXvJ/LhFaDgnv8n5NNRYO1ghRzRE0O3KSh1kiHp42Z6GAuzpwkpyft3RAKQ== +"@wdio/cli@6.1.25": + version "6.1.25" + resolved "https://registry.yarnpkg.com/@wdio/cli/-/cli-6.1.25.tgz#f57177653fb66c97451e81ac9e96d64f25f3a812" + integrity sha512-9tOgqIOQgg5cWrqn46iln01/jp2keXWDT9KhNG49+1QJe1fRJ3FKGFfIWAfIwoXVhEOHKX8INv0AgzF7yqX1vg== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" @@ -3097,7 +3105,7 @@ lodash.pickby "^4.6.0" lodash.union "^4.6.0" log-update "^4.0.0" - webdriverio "6.1.24" + webdriverio "6.1.25" yargs "^15.0.1" yarn-install "^1.0.0" @@ -3110,14 +3118,14 @@ deepmerge "^4.0.0" glob "^7.1.2" -"@wdio/local-runner@6.1.24": - version "6.1.24" - resolved "https://registry.yarnpkg.com/@wdio/local-runner/-/local-runner-6.1.24.tgz#c72c8e7ab5548522618c736de81b37e2ec0d6f96" - integrity sha512-SU2IO0axEQSfdImxeB4lJjh/UXcklZm80hi7BxKFqK76311+sw7QyOlBMIPMOeDcToZkdI2J1RiKoImdzMMO+Q== +"@wdio/local-runner@6.1.25": + version "6.1.25" + resolved "https://registry.yarnpkg.com/@wdio/local-runner/-/local-runner-6.1.25.tgz#6f6490654b625c81a5b0bd65e60d6ccad05a171b" + integrity sha512-h/+NNI2L8vJv4ZfeYoReDDSyeL06rb72uoqPKuXdXWFa95DkcWX7CfafhEvjLPb/AI93/3f5MGXITtelOOPpiA== dependencies: "@wdio/logger" "6.0.16" "@wdio/repl" "6.1.17" - "@wdio/runner" "6.1.24" + "@wdio/runner" "6.1.25" async-exit-hook "^2.0.1" stream-buffers "^3.0.2" @@ -3141,10 +3149,10 @@ 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.1.25": + version "6.1.25" + resolved "https://registry.yarnpkg.com/@wdio/protocols/-/protocols-6.1.25.tgz#a5059fce8eb070610792708b228b5e53831d1f33" + integrity sha512-C84qqh5J6nE1zTjwF3svDUah3FvoUzMUGeRe8w//QPBcJIGNRgmVLgeFV7Cp2EwI5ag+BUfXExQ0bFtcZYHIVA== "@wdio/repl@6.1.17": version "6.1.17" @@ -3160,18 +3168,18 @@ dependencies: fs-extra "^9.0.0" -"@wdio/runner@6.1.24": - version "6.1.24" - resolved "https://registry.yarnpkg.com/@wdio/runner/-/runner-6.1.24.tgz#072981706741af305bb740b1981f236b43e3dff9" - integrity sha512-aV8fhz5FYb5NroXH3V3BNQ11WMDDxV2748th2Ea0QHtxcFPZ4QYN5HJ7qWOoqNKSm/AYEKn1XuTat+6N55rmrQ== +"@wdio/runner@6.1.25": + version "6.1.25" + resolved "https://registry.yarnpkg.com/@wdio/runner/-/runner-6.1.25.tgz#4aebfb4ebe2a30836d36e32582b5839cc5672578" + integrity sha512-sTAHhISiZhr0Km5Bbx0qaXaHoyxx4Nuq/CxwNrwbtepJUxUzjvmyZkvC1g1rC7Mm/0EJ4YBJjDssch3F+26/Xg== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" "@wdio/utils" "6.1.17" deepmerge "^4.0.0" gaze "^1.1.2" - webdriver "6.1.17" - webdriverio "6.1.24" + webdriver "6.1.25" + webdriverio "6.1.25" "@wdio/spec-reporter@6.1.23": version "6.1.23" @@ -3399,6 +3407,11 @@ acorn-walk@^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.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" @@ -3424,6 +3437,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@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" + integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== + dependencies: + es6-promisify "^5.0.0" + aggregate-error@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" @@ -3986,14 +4006,14 @@ autoprefixer@^9.7.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.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/ava/-/ava-3.10.0.tgz#ed1a53986435fc1cd8c15978cd8ff81217c34831" + integrity sha512-CxcYQYeE39pcLWrN2/TASMpnqH/SoaX+W61+4m3saETU041PIDcoP9LLNWPAE/yJZXjp0M1RWTohSkmGqJZKww== 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" @@ -4002,11 +4022,11 @@ ava@3.9.0: chokidar "^3.4.0" 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" @@ -4021,7 +4041,7 @@ 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 "^3.0.1" is-promise "^4.0.0" lodash "^4.17.15" matcher "^3.0.0" @@ -4045,7 +4065,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.0" aws-sign2@~0.7.0: version "0.7.0" @@ -5213,15 +5233,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@83.0.1: + version "83.0.1" + resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-83.0.1.tgz#c4cf9b3f7076fea5e9ef787e65907cd035ffbd10" + integrity sha512-51/YsLIMRF+L0ooMlM4aZjyoOpDs0gDXGlT6+/CwWEnvK53PUyef9FkotKbzknCaUeL/qUw3ic3IMmsNc+SUxg== dependencies: "@testim/chrome-version" "^1.0.7" axios "^0.19.2" del "^5.1.0" extract-zip "^2.0.0" + https-proxy-agent "^2.2.4" mkdirp "^1.0.4" tcp-port-used "^1.0.1" @@ -5235,10 +5256,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" @@ -5404,10 +5425,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" @@ -6306,7 +6327,7 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6. dependencies: ms "2.0.0" -debug@3.2.6, debug@^3.0.0, debug@^3.1.1, debug@^3.2.5: +debug@3.2.6, debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== @@ -6339,6 +6360,13 @@ decamelize@^1.2.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= +decamelize@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-3.2.0.tgz#84b8e8f4f8c579f938e35e2cc7024907e0090851" + integrity sha512-4TgkVUsmmu7oCSyGBm5FvfMoACuoh9EOidm7V5/J2X2djAwwt57qb3F2KMP2ITqODTCSwb+YRV+0Zqrv18k/hw== + dependencies: + xregexp "^4.2.4" + decimal.js@^10.2.0: version "10.2.0" resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.0.tgz#39466113a9e036111d02f82489b5fd6b0b5ed231" @@ -6562,14 +6590,14 @@ detect-port@^1.3.0: address "^1.0.1" debug "^2.6.0" -devtools@6.1.23: - version "6.1.23" - resolved "https://registry.yarnpkg.com/devtools/-/devtools-6.1.23.tgz#637ffefc48e8de6ce0d90ab0840880ae9ad7f5b2" - integrity sha512-+9b3bURLZED3sPVPQluGQFTuv/evRfQugM8dr+eybhOIfkSTGIlyks82QlaxMjHEBiaRXk3AFSl1f110T2tTKA== +devtools@6.1.25: + version "6.1.25" + resolved "https://registry.yarnpkg.com/devtools/-/devtools-6.1.25.tgz#beed5f5c7791985856c4279415a879f094fee8d0" + integrity sha512-t2tOW3aKlTwYR+t8RBxbHV6+260ZMFAKbiG/Vc9k2/w4s25azti/QxeA97jknFiNJ9f8AnnSVz+4skEiwd2BiQ== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" - "@wdio/protocols" "6.1.14" + "@wdio/protocols" "6.1.25" "@wdio/utils" "6.1.17" chrome-launcher "^0.13.1" puppeteer-core "^4.0.0" @@ -7130,6 +7158,18 @@ es5-shim@^4.5.13: resolved "https://registry.yarnpkg.com/es5-shim/-/es5-shim-4.5.14.tgz#90009e1019d0ea327447cb523deaff8fe45697ef" integrity sha512-7SwlpL+2JpymWTt8sNLuC2zdhhc+wrfe5cMPI2j0o6WsPdfAiPwmFy2f0AocPB4RQVBOZ9kNTgi5YF7TdhkvEg== +es6-promise@^4.0.3: + version "4.2.8" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== + +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= + dependencies: + es6-promise "^4.0.3" + es6-shim@^0.35.5: version "0.35.5" resolved "https://registry.yarnpkg.com/es6-shim/-/es6-shim-0.35.5.tgz#46f59dc0a84a1c5029e8ff1166ca0a902077a9ab" @@ -7347,10 +7387,10 @@ eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.2 resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.2.0.tgz#74415ac884874495f78ec2a97349525344c981fa" integrity sha512-WFb4ihckKil6hu3Dp798xdzSfddwKKU3+nGniKF6HfeW6OLd2OUDEPP7TcHtB5+QXOKg2s6B2DaMPE1Nn/kxKQ== -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.4.0: + version "7.4.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.4.0.tgz#4e35a2697e6c1972f9d6ef2b690ad319f80f206f" + integrity sha512-gU+lxhlPHu45H3JkEGgYhWhkR9wLHHEXC9FbWFnTlEkbKyZKWgWRLgf61E8zWmBuI6g5xKBph9ltg3NtZMVF8g== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.10.0" @@ -8574,10 +8614,10 @@ graphql-tag@^2.4.2: resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.10.3.tgz#ea1baba5eb8fc6339e4c4cf049dabe522b0edf03" integrity sha512-4FOv3ZKfA4WdOKJeHdz6B3F/vxBLSgmBcGeAFPf4n1F64ltJUvOOerNj0rsJxONQGdhUMynQIvd6LzB+1J5oKA== -graphql@15.2.0: - version "15.2.0" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.2.0.tgz#d9c655a523a3196d4b23657ec6ec5963b3bd4970" - integrity sha512-tsceRyHfgzZo+ee0YK3o8f0CR0cXAXxRlxoORWFo/CoM1bVy3UXGWeyzBcf+Y6oqPvO27BDmOEVATcunOO/MrQ== +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" @@ -9002,6 +9042,14 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= +https-proxy-agent@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" + integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg== + dependencies: + agent-base "^4.3.0" + debug "^3.1.0" + https-proxy-agent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz#702b71fb5520a132a66de1f67541d9e62154d82b" @@ -9598,6 +9646,11 @@ is-plain-object@^3.0.0: dependencies: isobject "^4.0.0" +is-plain-object@^3.0.1: + 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-potential-custom-element-name@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397" @@ -15546,10 +15599,10 @@ 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" @@ -15751,22 +15804,22 @@ 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.1.25: + version "6.1.25" + resolved "https://registry.yarnpkg.com/webdriver/-/webdriver-6.1.25.tgz#001fb82fb7162abfb9bd799b8c8eee79f0a2e030" + integrity sha512-JXXcZ8VwRTDJLHpEcWt7uy4524T21zxseumihwMcCNiDUmbsSDaxZ0iKA2j4m9NbCzu7dqJJs8/ma7qc+mhxUQ== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" - "@wdio/protocols" "6.1.14" + "@wdio/protocols" "6.1.25" "@wdio/utils" "6.1.17" got "^11.0.2" lodash.merge "^4.6.1" -webdriverio@6.1.24: - version "6.1.24" - resolved "https://registry.yarnpkg.com/webdriverio/-/webdriverio-6.1.24.tgz#2e71c89050db47d592420ff285a4c7fc9e3e32ea" - integrity sha512-VvB4davXI2w3V63Oy6tcmAlXIWXrRP4F8IaQVU1bTMwhMKkJZ82yGaP8BgE07P8e66+0O/ZpPnHNYaaJ6Zkzcg== +webdriverio@6.1.25: + version "6.1.25" + resolved "https://registry.yarnpkg.com/webdriverio/-/webdriverio-6.1.25.tgz#84e26907c386f1f58c3b150e08bb595efb9350bb" + integrity sha512-eD4ig9YFsawqVGeCU/zaA4CdZvxmi27Ejm21pL17hDMz/smdjd4TzFhskN1eXaikC+vfotHs56jB19ewJspLmQ== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" @@ -15774,7 +15827,7 @@ webdriverio@6.1.24: "@wdio/utils" "6.1.17" archiver "^4.0.1" css-value "^0.0.1" - devtools "6.1.23" + devtools "6.1.25" grapheme-splitter "^1.0.2" lodash.clonedeep "^4.5.0" lodash.isobject "^3.0.2" @@ -15783,7 +15836,7 @@ webdriverio@6.1.24: resq "^1.6.0" rgb2hex "^0.2.0" serialize-error "^7.0.0" - webdriver "6.1.17" + webdriver "6.1.25" webidl-conversions@^5.0.0: version "5.0.0" @@ -16117,6 +16170,13 @@ xmlchars@^2.2.0: resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== +xregexp@^4.2.4: + 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" @@ -16155,7 +16215,7 @@ 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@^18.1.1, 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== @@ -16205,6 +16265,23 @@ yargs@^15.0.1, yargs@^15.3.1: y18n "^4.0.0" yargs-parser "^18.1.1" +yargs@^15.4.0: + version "15.4.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.0.tgz#53949fb768309bac1843de9b17b80051e9805ec2" + integrity sha512-D3fRFnZwLWp8jVAAhPZBsmeIHY8tTsb8ItV9KaAaopmC6wde2u6Yw29JBIZHXw14kgkRnYmDgmQU4FVMDlIsWw== + dependencies: + cliui "^6.0.0" + decamelize "^3.2.0" + find-up "^4.1.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 "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + yarn-install@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/yarn-install/-/yarn-install-1.0.0.tgz#57f45050b82efd57182b3973c54aa05cb5d25230" From 628a7a1e890029c3554ef1e3057199d21f4c860c Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 8 Jul 2020 12:26:14 +0200 Subject: [PATCH 148/247] NCI-Agency/anet#2954: Move report state to ReportDao::minimalFields Move state from ReportDao::additionalFields to ReportDao::minimalFields (else a GraphQL search that requests engagementStatus but not state will give wrong results; note that engagementDate [used in isFutureEngagement()] is already part of the minimalFields). --- src/main/java/mil/dds/anet/database/ReportDao.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/mil/dds/anet/database/ReportDao.java b/src/main/java/mil/dds/anet/database/ReportDao.java index 06638437f4..1f481241db 100644 --- a/src/main/java/mil/dds/anet/database/ReportDao.java +++ b/src/main/java/mil/dds/anet/database/ReportDao.java @@ -67,9 +67,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); From a13c45de520e4d998abefd8224464c1ff49458dd Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 8 Jul 2020 12:28:56 +0200 Subject: [PATCH 149/247] NCI-Agency/anet#2954: Java code style change ReportState.CANCELLED.equals(getState()) is better expressed as state == ReportState.CANCELLED (it's an enum). --- src/main/java/mil/dds/anet/beans/Report.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/mil/dds/anet/beans/Report.java b/src/main/java/mil/dds/anet/beans/Report.java index a04a45de25..38115d0838 100644 --- a/src/main/java/mil/dds/anet/beans/Report.java +++ b/src/main/java/mil/dds/anet/beans/Report.java @@ -794,7 +794,7 @@ public boolean isFutureEngagement() { @GraphQLQuery(name = "engagementStatus") public List loadEngagementStatus() { LinkedList statuses = new LinkedList(); - if (ReportState.CANCELLED.equals(getState())) { + if (state == ReportState.CANCELLED) { statuses.add(EngagementStatus.CANCELLED); } statuses.add(isFutureEngagement() ? EngagementStatus.FUTURE : EngagementStatus.HAPPENED); From e005598a50104e151e36b6b09ba62943d8197d75 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 8 Jul 2020 12:41:20 +0200 Subject: [PATCH 150/247] NCI-Agency/anet#2954: Remove unused import --- src/main/java/mil/dds/anet/database/ReportDao.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/mil/dds/anet/database/ReportDao.java b/src/main/java/mil/dds/anet/database/ReportDao.java index 1f481241db..d9310cda07 100644 --- a/src/main/java/mil/dds/anet/database/ReportDao.java +++ b/src/main/java/mil/dds/anet/database/ReportDao.java @@ -27,7 +27,6 @@ import mil.dds.anet.beans.Person; import mil.dds.anet.beans.Position; import mil.dds.anet.beans.Report; -import mil.dds.anet.beans.Report.EngagementStatus; import mil.dds.anet.beans.Report.ReportState; import mil.dds.anet.beans.ReportAction; import mil.dds.anet.beans.ReportAction.ActionType; From ae3e3c306fbbe8e0159b4875ac5807e505f08a69 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 8 Jul 2020 22:00:11 +0200 Subject: [PATCH 151/247] NCI-Agency/anet#2954: Code refactoring ReportStatistics Improved ReportStatitsics typechecking and made sure that if there are no statistics available we don't display an empty row for the statistics related fields. --- client/src/components/ReportStatistics.js | 89 ++++++++++++++--------- 1 file changed, 54 insertions(+), 35 deletions(-) diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index 99b2417226..8a44eb38a6 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -114,7 +114,7 @@ const FieldStatisticsRow = ({ fieldName, periods, periodsData, - rowIndex + isFirstRow }) => { const aggregationWidget = getAggregationWidget(fieldConfig) if (!aggregationWidget) { @@ -125,7 +125,7 @@ const FieldStatisticsRow = ({ {periods.map((period, index) => (
+ {periods.map((period, index) => ( + + ))} + +) +NoStatisticsRow.propTypes = { + periods: PeriodsPropType.isRequired } const ReportStatistics = ({ @@ -161,23 +174,25 @@ const ReportStatistics = ({ 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 = dateSortAsc( - periodsConfig.periods.map(p => p.start) - )[0] - const statisticsEndDate = dateSortAsc(periodsConfig.periods.map(p => p.end))[ - periodsConfig.periods.length - 1 - ] + 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 ( - !queryParams.engagementDateStart || - queryParams.engagementDateStart < statisticsStartDate + statisticsStartDate && + (!queryParams.engagementDateStart || + queryParams.engagementDateStart < statisticsStartDate) ) { reportQuery.engagementDateStart = statisticsStartDate } if ( - !queryParams.engagementDateEnd || - queryParams.engagementDateEnd > statisticsEndDate + statisticsEndDate && + (!queryParams.engagementDateEnd || + queryParams.engagementDateEnd > statisticsEndDate) ) { reportQuery.engagementDateEnd = statisticsEndDate } @@ -198,6 +213,9 @@ const ReportStatistics = ({ if (done) { return result } + if (_isEmpty(periods)) { + return null + } const reports = data ? Report.fromArray(data.reportList.list) : [] const CUSTOM_FIELDS_KEY = "customFieldsJson" @@ -213,12 +231,9 @@ const ReportStatistics = ({ ) return reportsForDateRange } - const { periods } = periodsConfig const dataPerPeriod = [] - periodsConfig.periods.forEach(period => - dataPerPeriod.push(getPeriodData(reports, period)) - ) - + periods.forEach(period => dataPerPeriod.push(getPeriodData(reports, period))) + const hasStatistics = !_isEmpty(dataPerPeriod.filter(data => !_isEmpty(data))) const customFieldsConfig = Settings.fields.report.customFields return ( @@ -233,27 +248,31 @@ const ReportStatistics = ({ <> - {Object.keys(REPORT_FIELDS_FOR_STATISTICS || {}).map( - (key, index) => ( + {!hasStatistics && } + {hasStatistics && + Object.keys(REPORT_FIELDS_FOR_STATISTICS).map((key, index) => ( + ))} + {hasStatistics && + Object.keys(customFieldsConfig || {}).map((key, index) => ( + - ) - )} - {Object.keys(customFieldsConfig || {}).map(key => ( - - ))} + ))}
{_isEmpty(periodsData[index]) ? ( - rowIndex === 0 ? ( + isFirstRow ? ( No reports found ) : null ) : ( @@ -147,9 +147,22 @@ const FieldStatisticsRow = ({ FieldStatisticsRow.propTypes = { fieldConfig: PropTypes.object, fieldName: PropTypes.string, - periods: PeriodsPropType, - periodsData: PropTypes.arrayOf(PropTypes.array), - rowIndex: PropTypes.number + periods: PeriodsPropType.isRequired, + periodsData: PropTypes.arrayOf(PropTypes.array).isRequired, + isFirstRow: PropTypes.bool +} + +const NoStatisticsRow = ({ periods }) => ( +
+ No reports found +
@@ -263,7 +282,7 @@ const ReportStatistics = ({ ReportStatistics.propTypes = { pageDispatchers: PageDispatchersPropType, - periodsDetails: PeriodsDetailsPropType, + periodsDetails: PeriodsDetailsPropType.isRequired, setTotalCount: PropTypes.func, queryParams: PropTypes.object } From 6bb01f23d378260063fc5251035b0a7c0847fc5a Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 8 Jul 2020 22:05:33 +0200 Subject: [PATCH 152/247] NCI-Agency/anet#2954: Simplify use of Object.assign --- client/src/pages/reports/Edit.js | 7 ++----- client/src/pages/reports/New.js | 7 ++----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/client/src/pages/reports/Edit.js b/client/src/pages/reports/Edit.js index 89c38df1f1..ddc1dfc117 100644 --- a/client/src/pages/reports/Edit.js +++ b/client/src/pages/reports/Edit.js @@ -126,12 +126,9 @@ const ReportEdit = ({ pageDispatchers }) => { ) } const report = new Report(data ? data.report : {}) - let reportInitialValues = Object.assign( + const reportInitialValues = Object.assign( report, - report.getTasksEngagementAssessments() - ) - reportInitialValues = Object.assign( - reportInitialValues, + report.getTasksEngagementAssessments(), report.getAttendeesEngagementAssessments() ) reportInitialValues.tasks = Task.fromArray(reportInitialValues.tasks) diff --git a/client/src/pages/reports/New.js b/client/src/pages/reports/New.js index 2e03b48483..2300a7008d 100644 --- a/client/src/pages/reports/New.js +++ b/client/src/pages/reports/New.js @@ -26,12 +26,9 @@ const BaseReportNew = ({ pageDispatchers, currentUser }) => { person.primary = true report.attendees.push(person) } - let reportInitialValues = Object.assign( + const reportInitialValues = Object.assign( report, - report.getTasksEngagementAssessments() - ) - reportInitialValues = Object.assign( - reportInitialValues, + report.getTasksEngagementAssessments(), report.getAttendeesEngagementAssessments() ) From 31b95297dba835e9c57b0369d505b7e0fd1bf8b4 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 8 Jul 2020 22:06:47 +0200 Subject: [PATCH 153/247] NCI-Agency/anet#2954: Improve css formatting --- client/src/pages/dashboards/BoardDashboard.css | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/client/src/pages/dashboards/BoardDashboard.css b/client/src/pages/dashboards/BoardDashboard.css index 85fbff78ef..e4c4dc52a2 100644 --- a/client/src/pages/dashboards/BoardDashboard.css +++ b/client/src/pages/dashboards/BoardDashboard.css @@ -1,11 +1,10 @@ - -.diagram-container{ - width: 100%; +.diagram-container { + width: 100%; height: 100%; background: white; } -.custom-node{ +.custom-node { border: solid 2px gray; border-radius: 5px; width: 50px; @@ -16,7 +15,7 @@ position: relative; } -.custom-node-color{ +.custom-node-color { position: absolute; top: 50%; left: 50%; @@ -26,7 +25,7 @@ border-radius: 10px; } -.circle-port{ +.circle-port { width: 12px; height: 12px; margin: 2px; @@ -35,6 +34,6 @@ cursor: pointer; } -.circle-port:hover{ +.circle-port:hover { background: mediumpurple; } From bfee735758dacd4cdd1ef44a3c9d542a790a93ce Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 8 Jul 2020 22:07:28 +0200 Subject: [PATCH 154/247] NCI-Agency/anet#2954: Improve Dashboard DiagramNode Consider also the case that the anetObject might be null. --- client/src/components/Model.js | 2 +- client/src/pages/dashboards/DiagramNode.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/components/Model.js b/client/src/components/Model.js index c05e5eaba2..1e996a6353 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -360,7 +360,7 @@ export default class Model { static fetchByUuid(uuid, entityGqlFields) { const fields = entityGqlFields[this.resourceName] if (!fields) { - return null + return Promise.resolve(null) } return API.query( diff --git a/client/src/pages/dashboards/DiagramNode.js b/client/src/pages/dashboards/DiagramNode.js index 054333f9bd..805c7a9e87 100644 --- a/client/src/pages/dashboards/DiagramNode.js +++ b/client/src/pages/dashboards/DiagramNode.js @@ -118,7 +118,7 @@ const Port = styled.div` export const DiagramNodeWidget = ({ size, node, engine }) => { const { anetObjectType, anetObject } = node.options const ModelClass = anetObjectType && Models[anetObjectType] - const modelInstance = ModelClass && new ModelClass(anetObject) + const modelInstance = anetObject && ModelClass && new ModelClass(anetObject) const now = moment() const period = PERIOD_FACTORIES[RECURRENCE_TYPE.MONTHLY](now, 0) const instantAssessmentConfig = From fb02c930cb848f7237f0b8953044b7e5c5bc9689 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 8 Jul 2020 22:13:32 +0200 Subject: [PATCH 155/247] NCI-Agency/anet#2954: Remove useless check in ReportCollection --- client/src/components/ReportCollection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/ReportCollection.js b/client/src/components/ReportCollection.js index d587812c21..088bd6795b 100644 --- a/client/src/components/ReportCollection.js +++ b/client/src/components/ReportCollection.js @@ -113,7 +113,7 @@ const ReportCollection = ({ marginBottom={marginBottom} /> )} - {viewFormat === FORMAT_STATISTICS && statisticsRecurrence.length && ( + {viewFormat === FORMAT_STATISTICS && ( <> {statisticsRecurrence.map(recurrence => ( Date: Wed, 8 Jul 2020 22:14:15 +0200 Subject: [PATCH 156/247] NCI-Agency/anet#2954: Improve PeriodsNavigation typechecking --- client/src/components/PeriodsNavigation.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/src/components/PeriodsNavigation.js b/client/src/components/PeriodsNavigation.js index c86b210c00..c81fa0dac8 100644 --- a/client/src/components/PeriodsNavigation.js +++ b/client/src/components/PeriodsNavigation.js @@ -24,7 +24,10 @@ const PeriodsNavigation = ({ offset, onChange }) => ( ) PeriodsNavigation.propTypes = { offset: PropTypes.number, - onChange: PropTypes.func + onChange: PropTypes.func.isRequired +} +PeriodsNavigation.defaultProps = { + offset: 0 } export default PeriodsNavigation From 2c10bce6f1ef9a9fcaeede3eab41c3b25366836d Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 8 Jul 2020 23:27:50 +0200 Subject: [PATCH 157/247] NCI-Agency/anet#2954: Code refactoring MultiTypeAdvancedSelectComponent This makes sure that the MultiTypeAdvancedSelectComponent component displays the proper label for tasks. Simplify code by adding default value for the objectType property of the component. Also renamed some variables in order to make the code easier to understand. --- .../MultiTypeAdvancedSelectComponent.js | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/client/src/components/advancedSelectWidget/MultiTypeAdvancedSelectComponent.js b/client/src/components/advancedSelectWidget/MultiTypeAdvancedSelectComponent.js index d37aa32bb4..fab4cf08ad 100644 --- a/client/src/components/advancedSelectWidget/MultiTypeAdvancedSelectComponent.js +++ b/client/src/components/advancedSelectWidget/MultiTypeAdvancedSelectComponent.js @@ -1,4 +1,4 @@ -import { SEARCH_OBJECT_LABELS } from "actions" +import { SEARCH_OBJECT_LABELS, SEARCH_OBJECT_TYPES } from "actions" import { LocationOverlayRow, OrganizationOverlayRow, @@ -114,26 +114,26 @@ const widgetTypeMapping = { const MultiTypeAdvancedSelectComponent = ({ onConfirm, - objectType: objectTypeArg + objectType: entityTypeArg }) => { - const [objectType, setObjectType] = useState( - objectTypeArg || ENTITY_TYPES.REPORTS - ) + const [entityType, setEntityType] = useState(entityTypeArg) const [advancedSelectProps, setAdvancedSelectProps] = useState( - widgetTypeMapping[objectType] + widgetTypeMapping[entityType] ) - - function changeObjectType(newObjectType) { - setObjectType(newObjectType) - setAdvancedSelectProps(widgetTypeMapping[newObjectType]) + 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[key[0]] + const entityLabel = SEARCH_OBJECT_LABELS[SEARCH_OBJECT_TYPES[key[0]]] + if (entityName === entityType) { + searchPlaceholder = "Find " + entityLabel.toLowerCase() + } return (
{_isEmpty(periodsData[index]) ? ( - rowIndex === 0 ? ( + isFirstRow ? ( No assessments ) : null ) : ( @@ -75,12 +74,12 @@ const InstantAssessmentRow = ({ ) } InstantAssessmentRow.propTypes = { - entity: PropTypes.object, - periods: PeriodsPropType, - periodsData: PropTypes.arrayOf(PropTypes.array), - questionKey: PropTypes.string, - questionConfig: PropTypes.object, - rowIndex: PropTypes.number + entity: PropTypes.object.isRequired, + periods: PeriodsPropType.isRequired, + periodsData: PropTypes.arrayOf(PropTypes.array).isRequired, + questionKey: PropTypes.string.isRequired, + questionConfig: PropTypes.object.isRequired, + isFirstRow: PropTypes.bool } const BasePeriodicAssessmentRows = ({ @@ -93,6 +92,10 @@ const BasePeriodicAssessmentRows = ({ }) => { const [showAssessmentModalKey, setShowAssessmentModalKey] = useState(null) const { recurrence, periods } = periodsConfig + if (_isEmpty(periods)) { + return null + } + const { assessmentConfig, assessmentYupSchema @@ -205,11 +208,11 @@ const BasePeriodicAssessmentRows = ({ ) } BasePeriodicAssessmentRows.propTypes = { - entity: PropTypes.object, + entity: PropTypes.object.isRequired, entityType: PropTypes.func.isRequired, - periodsConfig: AssessmentPeriodsConfigPropType, + periodsConfig: AssessmentPeriodsConfigPropType.isRequired, canAddAssessment: PropTypes.bool, - onUpdateAssessment: PropTypes.func, + onUpdateAssessment: PropTypes.func.isRequired, currentUser: PropTypes.instanceOf(Person) } @@ -238,7 +241,7 @@ const EntityAssessmentResults = ({ const instantAssessmentConfig = entity.getInstantAssessmentConfig() const { periods } = periodsConfig const dataPerPeriod = [] - periodsConfig.periods.forEach(period => + periods.forEach(period => dataPerPeriod.push(entity.getInstantAssessmentResults(period)) ) return ( @@ -256,7 +259,7 @@ const EntityAssessmentResults = ({ periods={periods} periodsData={dataPerPeriod} entity={entity} - rowIndex={index} + isFirstRow={index === 0} /> ))} s.getInstantAssessmentConfig()) @@ -354,11 +360,11 @@ const AssessmentResultsTable = ({ } AssessmentResultsTable.propTypes = { style: PropTypes.object, - entity: PropTypes.object, + entity: PropTypes.object.isRequired, entityType: PropTypes.func.isRequired, subEntities: PropTypes.array, - periodsDetails: PeriodsDetailsPropType, - onUpdateAssessment: PropTypes.func, + periodsDetails: PeriodsDetailsPropType.isRequired, + onUpdateAssessment: PropTypes.func.isRequired, canAddAssessment: PropTypes.bool } From 70aafe40ae473730384a5e24533668a20c2bf08a Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Thu, 9 Jul 2020 15:06:57 +0200 Subject: [PATCH 166/247] NCI-Agency/anet#2954: Split AssessmentResultsTable.js into several files --- .../assessments/AssessmentResultsTable.js | 210 +------------ .../assessments/InstantAssessmentResults.js | 61 ++++ .../assessments/PeriodicAssessment.js | 133 --------- .../assessments/PeriodicAssessmentResults.js | 281 ++++++++++++++++++ 4 files changed, 348 insertions(+), 337 deletions(-) create mode 100644 client/src/components/assessments/InstantAssessmentResults.js delete mode 100644 client/src/components/assessments/PeriodicAssessment.js create mode 100644 client/src/components/assessments/PeriodicAssessmentResults.js diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index 856fab7a1b..301420b0b0 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -1,27 +1,18 @@ -import AggregationWidgetContainer, { - getAggregationWidget -} from "components/aggregations/AggregationWidgetContainer" -import AppContext from "components/AppContext" -import AssessmentModal from "components/assessments/AssessmentModal" -import PeriodicAssessment from "components/assessments/PeriodicAssessment" +import { PeriodicAssessmentsRows } from "components/assessments/PeriodicAssessmentResults" +import { InstantAssessmentsRow } from "components/assessments/InstantAssessmentResults" import Fieldset from "components/Fieldset" import LinkTo from "components/LinkTo" -import { NOTE_TYPE } from "components/Model" import PeriodsNavigation from "components/PeriodsNavigation" -import { Person } from "models" import _isEmpty from "lodash/isEmpty" -import _uniqueId from "lodash/uniqueId" import { AssessmentPeriodsConfigPropType, getPeriodsConfig, PeriodsDetailsPropType, - PeriodsPropType, - PeriodsTableHeader, - periodToString + 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 @@ -38,195 +29,6 @@ import "components/assessments/AssessmentResultsTable.css" * entity.getPeriodicAssessmentDetails(recurrence) */ -const InstantAssessmentRow = ({ - questionKey, - questionConfig, - entity, - periods, - periodsData, - isFirstRow -}) => { - const aggregationWidget = getAggregationWidget(questionConfig) - if (_isEmpty(periods) || !aggregationWidget) { - return null - } - return ( -
- {_isEmpty(periodsData[index]) ? ( - isFirstRow ? ( - No assessments - ) : null - ) : ( - - )} -
- {periodAssessments && - periodAssessments.map(({ note, assessment }, i) => ( -
- -
- ))} -
- {periodsAllowNewAssessment[index] && ( - <> - - { - setShowAssessmentModalKey(null) - onUpdateAssessment() - }} - onCancel={() => setShowAssessmentModalKey(null)} - /> - - )} -
+ {_isEmpty(periodsData[index]) ? ( + isFirstRow ? ( + No assessments + ) : null + ) : ( + + )} +
+ {periodAssessments && + periodAssessments.map(({ note, assessment }, i) => ( +
+ +
+ ))} +
+ {periodsAllowNewAssessment[index] && ( + <> + + { + setShowAssessmentModalKey(null) + onUpdateAssessment() + }} + onCancel={() => setShowAssessmentModalKey(null)} + /> + + )} +
- - {filteredValues.map(val => { - const keyValue = _uniqueId("value_") - return ( - - - - ) - })} - -
{val}
- - - ) -} -DefaultAggWidget.propTypes = aggregationWidgetPropTypes -DefaultAggWidget.defaultProps = aggregationWidgetDefaultProps - -export 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 -} 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..73a7cc913c --- /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 ( + + + + ) + })} + +
{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..8ef45ffbf2 --- /dev/null +++ b/client/src/components/aggregations/PieWidget.js @@ -0,0 +1,49 @@ +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 index 0c4f658740..a8190f8861 100644 --- a/client/src/components/aggregations/utils.js +++ b/client/src/components/aggregations/utils.js @@ -1,8 +1,32 @@ 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) From 289fad2759119aa1082031a7a53259d475140c23 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sun, 12 Jul 2020 22:25:13 +0000 Subject: [PATCH 176/247] Update dependency com.diffplug.gradle.spotless:com.diffplug.gradle.spotless.gradle.plugin to v5 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 818e28e466..c27aab87d2 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ plugins { id "org.kordamp.markdown.convert" version "1.2.0" id "com.bmuschko.docker-remote-api" version "6.5.0" id "com.github.node-gradle.node" version "2.2.4" - id "com.diffplug.gradle.spotless" version "4.5.1" + id "com.diffplug.gradle.spotless" version "5.0.0" } apply plugin: 'java' From f35234c1353ed3634adebbfcb145bf3e1767146b Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Mon, 13 Jul 2020 13:36:45 +0200 Subject: [PATCH 177/247] Change to new plugin id See https://github.com/diffplug/spotless/blob/main/plugin-gradle/CHANGES.md --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c27aab87d2..ad9834834b 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ plugins { id "org.kordamp.markdown.convert" version "1.2.0" id "com.bmuschko.docker-remote-api" version "6.5.0" id "com.github.node-gradle.node" version "2.2.4" - id "com.diffplug.gradle.spotless" version "5.0.0" + id "com.diffplug.spotless" version "5.0.0" } apply plugin: 'java' From abb54448dedd0ab9b2984a51762de33e27258e47 Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Mon, 13 Jul 2020 14:25:53 +0200 Subject: [PATCH 178/247] Improve layout/scrolling of NATO Member Reports insight if there are many organizations --- client/src/pages/insights/Show.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/pages/insights/Show.js b/client/src/pages/insights/Show.js index 57cc9e6e1e..6a20753d7a 100644 --- a/client/src/pages/insights/Show.js +++ b/client/src/pages/insights/Show.js @@ -101,7 +101,8 @@ const BaseInsightsShow = ({ display: "flex", flexDirection: "column", flex: "1 1 auto", - height: "100%" + height: "100%", + overflow: "auto" } const mosaicLayoutStyle = { display: "flex", From 770efe68868d512e503822625d6ca2c65c32b6e7 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Mon, 13 Jul 2020 17:18:01 +0200 Subject: [PATCH 179/247] NCI-Agency/anet#2954: Add wdio tests for report statistics --- .../AggregationWidgetContainer.js | 34 +++++++------ .../src/components/aggregations/PieWidget.js | 5 +- client/tests/webdriver/pages/home.page.js | 4 ++ client/tests/webdriver/pages/myOrg.page.js | 29 +++++++++++ client/tests/webdriver/pages/page.js | 6 ++- client/tests/webdriver/specs/myOrg.spec.js | 50 +++++++++++++++++++ 6 files changed, 108 insertions(+), 20 deletions(-) create mode 100644 client/tests/webdriver/pages/myOrg.page.js create mode 100644 client/tests/webdriver/specs/myOrg.spec.js diff --git a/client/src/components/aggregations/AggregationWidgetContainer.js b/client/src/components/aggregations/AggregationWidgetContainer.js index a6408239ca..e745e11d89 100644 --- a/client/src/components/aggregations/AggregationWidgetContainer.js +++ b/client/src/components/aggregations/AggregationWidgetContainer.js @@ -176,23 +176,25 @@ const AggregationWidgetContainer = ({ ) return ( - {vertical ? ( - <> - {label !== null && {label}} - {widgetElem} - - ) : ( - <> - {label !== null && ( - - {label} +
+ {vertical ? ( + <> + {label !== null && {label}} + {widgetElem} + + ) : ( + <> + {label !== null && ( + + {label} + + )} + +
{widgetElem}
- )} - -
{widgetElem}
- - - )} + + )} +
) } diff --git a/client/src/components/aggregations/PieWidget.js b/client/src/components/aggregations/PieWidget.js index 8ef45ffbf2..3a72f6f166 100644 --- a/client/src/components/aggregations/PieWidget.js +++ b/client/src/components/aggregations/PieWidget.js @@ -24,8 +24,7 @@ const PieWidget = ({ segmentLabel={d => d.data.value} /> {showLegend && ( - <> -
+
{Object.map(legend, (key, choice) => ( @@ -33,7 +32,7 @@ const PieWidget = ({ ))} - +
)} ) 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/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/specs/myOrg.spec.js b/client/tests/webdriver/specs/myOrg.spec.js new file mode 100644 index 0000000000..e934857d30 --- /dev/null +++ b/client/tests/webdriver/specs/myOrg.spec.js @@ -0,0 +1,50 @@ +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", () => { + MyOrg.engagementDateStatistics.waitForDisplayed() + const daysWithEvent = MyOrg.engagementDateStatistics.$$( + ".fc-event-container" + ) + expect(daysWithEvent.length).to.equal(1) + + MyOrg.locationStatistics.waitForDisplayed() + + MyOrg.engagementStatus.waitForDisplayed() + const engagementStatusLegend = MyOrg.engagementStatus + .$(".pieLegend") + .$$("span") + expect(engagementStatusLegend.length).to.equal(4) + + MyOrg.tasks.waitForDisplayed() + const tasksBars = MyOrg.tasks.$("svg g").$$(".bars-group") + expect(tasksBars.length).to.equal(4) + let countTasksBars = 0 + tasksBars.forEach(bar => { + if (bar.$("rect").getAttribute("data-tip").includes("

1

")) { + countTasksBars++ + } + }) + expect(countTasksBars).to.equal(3) + + MyOrg.trainingEvent.waitForDisplayed() + const trainingEventLegend = MyOrg.trainingEvent.$(".pieLegend").$$("span") + expect(trainingEventLegend.length).to.equal(3) + const trainignEventTotal = MyOrg.trainingEvent.$("svg g text") + expect(trainignEventTotal.getText()).to.equal("1") + + MyOrg.numberTrained.waitForDisplayed() + const numberTrained = MyOrg.numberTrained.$("div em") + expect(numberTrained.getText()).to.equal("Not specified") + }) + }) +}) From 8459327bc59e66dfa112ec81abac996a6ba1835b Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 13 Jul 2020 15:57:39 +0000 Subject: [PATCH 180/247] Update dependency com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer to v20200713 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 818e28e466..b219a7a6a1 100644 --- a/build.gradle +++ b/build.gradle @@ -88,7 +88,7 @@ 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' // Used for converting GraphQL request output to XML: implementation 'com.github.javadev:underscore-lodash:1.26' From 459d2cdb64cc355cc28f35bdb55878c1a10ad22e Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 13 Jul 2020 17:14:43 +0000 Subject: [PATCH 181/247] Update most non-major dependencies --- client/package.json | 20 ++--- client/yarn.lock | 187 +++++++++++++++++++++----------------------- 2 files changed, 97 insertions(+), 110 deletions(-) diff --git a/client/package.json b/client/package.json index 923c65f539..255d9b3c01 100644 --- a/client/package.json +++ b/client/package.json @@ -27,14 +27,14 @@ "@storybook/addon-actions": "5.3.19", "@storybook/react": "5.3.19", "@wdio/browserstack-service": "6.1.15", - "@wdio/cli": "6.1.25", - "@wdio/local-runner": "6.1.25", - "@wdio/mocha-framework": "6.1.19", + "@wdio/cli": "6.2.0", + "@wdio/local-runner": "6.2.0", + "@wdio/mocha-framework": "6.2.0", "@wdio/spec-reporter": "6.1.23", - "@wdio/sync": "6.1.14", + "@wdio/sync": "6.2.0", "aigle": "1.14.1", - "autoprefixer": "9.8.4", - "ava": "3.10.0", + "autoprefixer": "9.8.5", + "ava": "3.10.1", "babel-eslint": "10.1.0", "babel-jest": "26.1.0", "babel-loader": "8.1.0", @@ -63,7 +63,7 @@ "eslint-plugin-node": "11.1.0", "eslint-plugin-promise": "4.2.1", "eslint-plugin-react": "7.20.3", - "eslint-plugin-react-hooks": "4.0.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", @@ -86,7 +86,7 @@ "style-loader": "1.2.1", "thread-loader": "2.1.3", "wdio-chromedriver-service": "6.0.3", - "webdriverio": "6.1.25", + "webdriverio": "6.2.0", "webpack": "4.43.0", "webpack-cli": "3.3.12", "webpack-dev-server": "3.11.0", @@ -128,7 +128,7 @@ "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", "milsymbol": "2.0.0", "moment": "2.27.0", "pluralize": "8.0.0", @@ -145,7 +145,7 @@ "react-redux-loading-bar": "4.6.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.8", diff --git a/client/yarn.lock b/client/yarn.lock index d1cc40c08b..fd54791822 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -3086,14 +3086,14 @@ browserstack-local "^1.4.5" got "^11.0.2" -"@wdio/cli@6.1.25": - version "6.1.25" - resolved "https://registry.yarnpkg.com/@wdio/cli/-/cli-6.1.25.tgz#f57177653fb66c97451e81ac9e96d64f25f3a812" - integrity sha512-9tOgqIOQgg5cWrqn46iln01/jp2keXWDT9KhNG49+1QJe1fRJ3FKGFfIWAfIwoXVhEOHKX8INv0AgzF7yqX1vg== +"@wdio/cli@6.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@wdio/cli/-/cli-6.2.0.tgz#2913ad646c921a06cda916f98870ce74c9af9b76" + integrity sha512-5d0efFQBdGLNQR4R/dBxpPzSXCY68T9dDw1FcdltTb/kn9CW27/YzaPUBY60d4qIXTQufmUFBaJmkiRnJGtjZw== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" - "@wdio/utils" "6.1.17" + "@wdio/utils" "6.2.0" async-exit-hook "^2.0.1" chalk "^4.0.0" chokidar "^3.0.0" @@ -3104,8 +3104,9 @@ lodash.flattendeep "^4.4.0" lodash.pickby "^4.6.0" lodash.union "^4.6.0" - log-update "^4.0.0" - webdriverio "6.1.25" + mkdirp "^1.0.4" + recursive-readdir "^2.2.2" + webdriverio "6.2.0" yargs "^15.0.1" yarn-install "^1.0.0" @@ -3118,14 +3119,14 @@ deepmerge "^4.0.0" glob "^7.1.2" -"@wdio/local-runner@6.1.25": - version "6.1.25" - resolved "https://registry.yarnpkg.com/@wdio/local-runner/-/local-runner-6.1.25.tgz#6f6490654b625c81a5b0bd65e60d6ccad05a171b" - integrity sha512-h/+NNI2L8vJv4ZfeYoReDDSyeL06rb72uoqPKuXdXWFa95DkcWX7CfafhEvjLPb/AI93/3f5MGXITtelOOPpiA== +"@wdio/local-runner@6.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@wdio/local-runner/-/local-runner-6.2.0.tgz#3057165c819e6fcbaa4b81b38a495c6f8ae75a38" + integrity sha512-fbki4EbwAKAnMrTWYzPHnPDPBVLZQlbNfJdC7iOtlcpLktDe29e9ARnfv8R4EkCjGqeenFAtgRwYSvBXucehrw== dependencies: "@wdio/logger" "6.0.16" - "@wdio/repl" "6.1.17" - "@wdio/runner" "6.1.25" + "@wdio/repl" "6.2.0" + "@wdio/runner" "6.2.0" async-exit-hook "^2.0.1" stream-buffers "^3.0.2" @@ -3139,13 +3140,13 @@ 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.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@wdio/mocha-framework/-/mocha-framework-6.2.0.tgz#c4f2b34b32e8a47ca5fb7bee3cacb9ccceebdc92" + integrity sha512-QbSav4vn2zQcKTkTr0LXhsQP7uWbt45r81KGHIDUdXy1Q3i0loz9E3OJQreZqfGtz1nYwjdxs4C5jJCBuShJSw== dependencies: "@wdio/logger" "6.0.16" - "@wdio/utils" "6.1.17" + "@wdio/utils" "6.2.0" expect-webdriverio "^1.1.5" mocha "^8.0.1" @@ -3154,12 +3155,12 @@ resolved "https://registry.yarnpkg.com/@wdio/protocols/-/protocols-6.1.25.tgz#a5059fce8eb070610792708b228b5e53831d1f33" integrity sha512-C84qqh5J6nE1zTjwF3svDUah3FvoUzMUGeRe8w//QPBcJIGNRgmVLgeFV7Cp2EwI5ag+BUfXExQ0bFtcZYHIVA== -"@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.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@wdio/repl/-/repl-6.2.0.tgz#3edb83f9b310e007c87cddb31b265ec4404d48a7" + integrity sha512-63yuCBCLrTC1D5uk6wJ6D3lyhi5i3Dvj8sQuqSma66c+xYPQRNA/Jp6V+43CsnOzUDLvhliSjCanrl3/i2sOcg== dependencies: - "@wdio/utils" "6.1.17" + "@wdio/utils" "6.2.0" "@wdio/reporter@6.1.23": version "6.1.23" @@ -3168,18 +3169,18 @@ dependencies: fs-extra "^9.0.0" -"@wdio/runner@6.1.25": - version "6.1.25" - resolved "https://registry.yarnpkg.com/@wdio/runner/-/runner-6.1.25.tgz#4aebfb4ebe2a30836d36e32582b5839cc5672578" - integrity sha512-sTAHhISiZhr0Km5Bbx0qaXaHoyxx4Nuq/CxwNrwbtepJUxUzjvmyZkvC1g1rC7Mm/0EJ4YBJjDssch3F+26/Xg== +"@wdio/runner@6.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@wdio/runner/-/runner-6.2.0.tgz#394a145499b8d671febeafe42f1c6d3abdd26ba5" + integrity sha512-LqPJca5bfrhHPfMIDFxAepfCEMzLTW0NjUHqTgSHDZGq3HVhe9TC/NyBNcNak2qsAr25gdcOi4KG2oZN+hCZHw== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" - "@wdio/utils" "6.1.17" + "@wdio/utils" "6.2.0" deepmerge "^4.0.0" gaze "^1.1.2" - webdriver "6.1.25" - webdriverio "6.1.25" + webdriver "6.2.0" + webdriverio "6.2.0" "@wdio/spec-reporter@6.1.23": version "6.1.23" @@ -3191,18 +3192,18 @@ 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.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@wdio/sync/-/sync-6.2.0.tgz#c1b390d552f15f47df1ff3d20bc6628da00856b4" + integrity sha512-b3iMiNrY0vkpyPZ81UFDX/QqH5OPzvETHUdYhj9st1/3OkAeLd07jjTEqD68RheUp6PxxXE8Gpnm8n4ywRKGhg== dependencies: "@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.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@wdio/utils/-/utils-6.2.0.tgz#8aa23ecbab9374aa6c80d54c37f6d88caa25d613" + integrity sha512-nPx430WPtZts09pcFwkTMO3zm6F7qvPuOcbvCschSW6ay8ebBvS6lkKnAHxCjrslsIF8+lOESuF0QrWycoouRA== dependencies: "@wdio/logger" "6.0.16" @@ -3529,7 +3530,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== @@ -3980,13 +3981,13 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -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.5: + version "9.8.5" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.5.tgz#2c225de229ddafe1d1424c02791d0c3e10ccccaa" + integrity sha512-C2p5KkumJlsTHoNv9w31NrBRgXhf6eCMteJuHZi2xhkgC+5Vm40MEtCKPhc0qdgAOhox0YPy1SQHTAky05UoKg== dependencies: browserslist "^4.12.0" - caniuse-lite "^1.0.30001087" + caniuse-lite "^1.0.30001097" colorette "^1.2.0" normalize-range "^0.1.2" num2fraction "^1.2.2" @@ -4006,10 +4007,10 @@ autoprefixer@^9.7.2: postcss "^7.0.30" postcss-value-parser "^4.1.0" -ava@3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/ava/-/ava-3.10.0.tgz#ed1a53986435fc1cd8c15978cd8ff81217c34831" - integrity sha512-CxcYQYeE39pcLWrN2/TASMpnqH/SoaX+W61+4m3saETU041PIDcoP9LLNWPAE/yJZXjp0M1RWTohSkmGqJZKww== +ava@3.10.1: + version "3.10.1" + resolved "https://registry.yarnpkg.com/ava/-/ava-3.10.1.tgz#a4e68b1a2bb248fa0d96529d23dd83f57082e944" + integrity sha512-+w86ZHyFHIGCABi7NUrn/WJMyC+fDj0BSIlFNVS45WDKAD5vxbIiDWeclctxOOc2KDPfQD7tFOURSBz0FBLD0A== dependencies: "@concordance/react" "^2.0.0" acorn "^7.3.1" @@ -5028,10 +5029,10 @@ caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001043, caniuse-lite@^1.0.300010 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.30001097: + version "1.0.30001099" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001099.tgz#540118fcc6842d1fde62f4ee5521d1ec6afdb40e" + integrity sha512-sdS9A+sQTk7wKoeuZBN/YMAHVztUfVnjDi4/UV3sDE8xoh7YR12hKW+pIdB3oqKGwr9XaFL2ovfzt9w8eUI5CA== capital-case@^1.0.3: version "1.0.3" @@ -6590,15 +6591,15 @@ detect-port@^1.3.0: address "^1.0.1" debug "^2.6.0" -devtools@6.1.25: - version "6.1.25" - resolved "https://registry.yarnpkg.com/devtools/-/devtools-6.1.25.tgz#beed5f5c7791985856c4279415a879f094fee8d0" - integrity sha512-t2tOW3aKlTwYR+t8RBxbHV6+260ZMFAKbiG/Vc9k2/w4s25azti/QxeA97jknFiNJ9f8AnnSVz+4skEiwd2BiQ== +devtools@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/devtools/-/devtools-6.2.0.tgz#c373c0970857ed675efe4ac8c918264bd73ca085" + integrity sha512-PmDKnIlDdP5+b6VurEnrIiLdzpSuWeWfge8tXJWjvFPhoqvwzdw4j5YSFo/QRWusS37Mk/j/rNUUawYP0u/ZKg== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" "@wdio/protocols" "6.1.25" - "@wdio/utils" "6.1.17" + "@wdio/utils" "6.2.0" chrome-launcher "^0.13.1" puppeteer-core "^4.0.0" ua-parser-js "^0.7.21" @@ -7332,10 +7333,10 @@ 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.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.0.5.tgz#4879003aa38e5d05d0312175beb6e4a1f617bfcf" - integrity sha512-3YLSjoArsE2rUwL8li4Yxx1SUg3DQWp+78N3bcJQGWVZckcp+yeQGsap/MSq05+thJk57o+Ww4PtZukXGL02TQ== +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.3: version "7.20.3" @@ -10862,7 +10863,12 @@ 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: +lodash@4.17.19: + version "4.17.19" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" + integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== + +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== @@ -10874,16 +10880,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" @@ -13214,13 +13210,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" @@ -13454,7 +13450,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== @@ -14268,15 +14264,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" @@ -15804,30 +15791,30 @@ wdio-chromedriver-service@6.0.3: dependencies: fs-extra "^9.0.0" -webdriver@6.1.25: - version "6.1.25" - resolved "https://registry.yarnpkg.com/webdriver/-/webdriver-6.1.25.tgz#001fb82fb7162abfb9bd799b8c8eee79f0a2e030" - integrity sha512-JXXcZ8VwRTDJLHpEcWt7uy4524T21zxseumihwMcCNiDUmbsSDaxZ0iKA2j4m9NbCzu7dqJJs8/ma7qc+mhxUQ== +webdriver@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/webdriver/-/webdriver-6.2.0.tgz#333983ae0b5aee4c39bcf6202b8b60a92edace0b" + integrity sha512-8jcuMK0ygfVT0ySImE89TD79rmYzvKS3ImG/+xvS9CUzrlYJpXTos8OTM962YaqkX/nEiGlT4HdV+4SH1J27WQ== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" "@wdio/protocols" "6.1.25" - "@wdio/utils" "6.1.17" + "@wdio/utils" "6.2.0" got "^11.0.2" lodash.merge "^4.6.1" -webdriverio@6.1.25: - version "6.1.25" - resolved "https://registry.yarnpkg.com/webdriverio/-/webdriverio-6.1.25.tgz#84e26907c386f1f58c3b150e08bb595efb9350bb" - integrity sha512-eD4ig9YFsawqVGeCU/zaA4CdZvxmi27Ejm21pL17hDMz/smdjd4TzFhskN1eXaikC+vfotHs56jB19ewJspLmQ== +webdriverio@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/webdriverio/-/webdriverio-6.2.0.tgz#85c9ba83b0ab61e4b056cefe07a65b3be5f1463a" + integrity sha512-TpikNm7Glm9qqWfvVbO5u9BbmDpPULI1PsJG9eDgL8eP7QoDsJs3gYwAizoBZlcRB9u/m8PESN/+B5H14NCvkA== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" - "@wdio/repl" "6.1.17" - "@wdio/utils" "6.1.17" + "@wdio/repl" "6.2.0" + "@wdio/utils" "6.2.0" archiver "^4.0.1" css-value "^0.0.1" - devtools "6.1.25" + devtools "6.2.0" grapheme-splitter "^1.0.2" lodash.clonedeep "^4.5.0" lodash.isobject "^3.0.2" @@ -15836,7 +15823,7 @@ webdriverio@6.1.25: resq "^1.6.0" rgb2hex "^0.2.0" serialize-error "^7.0.0" - webdriver "6.1.25" + webdriver "6.2.0" webidl-conversions@^5.0.0: version "5.0.0" From 67427bc0b7527e057621813a784d30d383cfdb6a Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 13 Jul 2020 20:51:18 +0000 Subject: [PATCH 182/247] Lock file maintenance --- client/yarn.lock | 1949 ++++++++++++++++------------------------------ 1 file changed, 682 insertions(+), 1267 deletions(-) diff --git a/client/yarn.lock b/client/yarn.lock index fd54791822..07ea8a7437 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -27,30 +27,23 @@ 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== - dependencies: - "@babel/highlight" "^7.10.1" - -"@babel/code-frame@^7.10.4": +"@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.4" -"@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.9.0": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.10.4.tgz#706a6484ee6f910b719b696a9194f8da7d7ac241" + integrity sha512-t+rjExOrSVvjQQXNp5zAIYDp00KjdvGl/TpDX5REPr0S9IAIPQMTilcfG6q8c0QFmj9lSTVySV2VTsyggvtNIw== dependencies: browserslist "^4.12.0" invariant "^2.2.4" semver "^5.5.0" -"@babel/core@7.10.4": +"@babel/core@7.10.4", "@babel/core@^7.1.0", "@babel/core@^7.4.5", "@babel/core@^7.7.5": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.4.tgz#780e8b83e496152f8dd7df63892b2e052bf1d51d" integrity sha512-3A0tS0HWpy4XujGc7QtOIHTeNwUgWaZc/WuS5YQrfhU67jnVmsD6OGPc1AKHH0LJHQICGncy3+YUjIhVlfDdcA== @@ -94,39 +87,7 @@ semver "^5.4.1" 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" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.1" - json5 "^2.1.2" - lodash "^4.17.13" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" - -"@babel/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== - dependencies: - "@babel/types" "^7.10.2" - jsesc "^2.5.1" - lodash "^4.17.13" - source-map "^0.5.0" - -"@babel/generator@^7.10.4": +"@babel/generator@^7.10.4", "@babel/generator@^7.9.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.4.tgz#e49eeed9fe114b62fa5b181856a43a5e32f5f243" integrity sha512-toLIHUIAgcQygFZRAQcsLQV3CBuX6yOIru1kJk/qqqvcRmZrYe6WavZTSG+bB8MxhnL9YPf+pKQfuiP161q7ng== @@ -136,13 +97,6 @@ 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== - dependencies: - "@babel/types" "^7.10.1" - "@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" @@ -150,22 +104,13 @@ dependencies: "@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== - dependencies: - "@babel/helper-explode-assignable-expression" "^7.10.1" - "@babel/types" "^7.10.1" - -"@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-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-annotate-as-pure" "^7.10.1" - "@babel/helper-module-imports" "^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.4": version "7.10.4" @@ -176,14 +121,6 @@ "@babel/helper-module-imports" "^7.10.4" "@babel/types" "^7.10.4" -"@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== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.1" - "@babel/types" "^7.10.1" - "@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" @@ -192,30 +129,18 @@ "@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.4": +"@babel/helper-create-class-features-plugin@^7.10.4", "@babel/helper-create-class-features-plugin@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.4.tgz#2d4015d0136bd314103a70d84a7183e4b344a355" integrity sha512-9raUiOsXPxzzLjCXeosApJItoMnX3uyT4QdM2UldffuGApNrF8e938MwNpDCK9CPoyxrEoCgT+hObJc3mZa6lQ== @@ -227,40 +152,31 @@ "@babel/helper-replace-supers" "^7.10.4" "@babel/helper-split-export-declaration" "^7.10.4" -"@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== +"@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.1" - "@babel/helper-regex" "^7.10.1" + "@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== +"@babel/helper-define-map@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.4.tgz#f037ad794264f729eda1889f4ee210b870999092" + integrity sha512-nIij0oKErfCnLUCWaCaHW0Bmtl2RO9cN7+u2QT8yqTywgALKlyUVOvHDElh+b5DwVC6YB1FOYFOTWcN/+41EDA== dependencies: - "@babel/helper-function-name" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/helper-function-name" "^7.10.4" + "@babel/types" "^7.10.4" 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== +"@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/helper-get-function-arity" "^7.10.1" - "@babel/template" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/helper-function-name@^7.10.4": version "7.10.4" @@ -271,13 +187,6 @@ "@babel/template" "^7.10.4" "@babel/types" "^7.10.4" -"@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.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" @@ -285,19 +194,12 @@ dependencies: "@babel/types" "^7.10.4" -"@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== +"@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.1" + "@babel/types" "^7.10.4" "@babel/helper-member-expression-to-functions@^7.10.4": version "7.10.4" @@ -306,34 +208,14 @@ dependencies: "@babel/types" "^7.10.4" -"@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-imports@^7.10.4": +"@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.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-module-transforms@^7.10.4": +"@babel/helper-module-transforms@^7.10.4", "@babel/helper-module-transforms@^7.9.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.10.4.tgz#ca1f01fdb84e48c24d7506bb818c961f1da8805d" integrity sha512-Er2FQX0oa3nV7eM1o0tNCTx7izmQtwAQsIiaLRWtavAAEcskb0XJ5OjJbVrYXWOTr8om921Scabn4/tzlx7j1Q== @@ -346,13 +228,6 @@ "@babel/types" "^7.10.4" 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.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" @@ -360,43 +235,28 @@ dependencies: "@babel/types" "^7.10.4" -"@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.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.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-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.4.tgz#59b373daaf3458e5747dece71bbaf45f9676af6d" + integrity sha512-inWpnHGgtg5NOF0eyHlC0/74/VkdRITY9dtTpB2PrxKKn+AkVMRiZz/Adrx+Ssg+MLDesi2zohBW6MVq6b4pOQ== 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== +"@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-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-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" @@ -408,14 +268,6 @@ "@babel/traverse" "^7.10.4" "@babel/types" "^7.10.4" -"@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-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" @@ -424,13 +276,6 @@ "@babel/template" "^7.10.4" "@babel/types" "^7.10.4" -"@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-split-export-declaration@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz#2c70576eaa3b5609b24cb99db2888cc3fc4251d1" @@ -438,26 +283,11 @@ dependencies: "@babel/types" "^7.10.4" -"@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.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.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/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" @@ -468,16 +298,7 @@ "@babel/traverse" "^7.10.4" "@babel/types" "^7.10.4" -"@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/helpers@^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== @@ -486,16 +307,7 @@ "@babel/traverse" "^7.10.4" "@babel/types" "^7.10.4" -"@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.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== @@ -504,26 +316,21 @@ 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.10.4": +"@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.7.0", "@babel/parser@^7.9.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.4.tgz#9eedf27e1998d87739fb5028a5120557c06a1a64" integrity sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA== -"@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.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.4.tgz#4b65abb3d9bacc6c657aaa413e56696f9f170fc6" + integrity sha512-MJbxGSmejEFVOANAezdO39SObkURO5o/8b6fSH6D1pi9RZQt+ldppKPXfqgUWpSQ9asM6xaSaSJIaeWMDRP0Zg== 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.4": +"@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== @@ -539,14 +346,6 @@ "@babel/helper-create-class-features-plugin" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@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== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-proposal-decorators@7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.10.4.tgz#fe20ef10cc73f386f70910fca48798041cd357c7" @@ -573,12 +372,12 @@ "@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.4": @@ -606,7 +405,7 @@ "@babel/helper-wrap-function" "^7.10.4" "@babel/plugin-syntax-function-sent" "^7.10.4" -"@babel/plugin-proposal-json-strings@7.10.4": +"@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== @@ -614,14 +413,6 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.0" -"@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== - dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-json-strings" "^7.8.0" - "@babel/plugin-proposal-logical-assignment-operators@7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.10.4.tgz#e62b5cf38e494d6cc24683e2a26cba4a28f7ea44" @@ -630,7 +421,7 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@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.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== @@ -646,15 +437,7 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" -"@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== - dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - -"@babel/plugin-proposal-numeric-separator@7.10.4": +"@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== @@ -670,32 +453,24 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-numeric-separator" "^7.8.3" -"@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== - dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-numeric-separator" "^7.10.1" - -"@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.10.4", "@babel/plugin-proposal-object-rest-spread@^7.6.2", "@babel/plugin-proposal-object-rest-spread@^7.9.0": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.10.4.tgz#50129ac216b9a6a55b3853fdd923e74bf553a4c0" + integrity sha512-6vh4SqRuLLarjgeOf4EaROJAHjvu9Gl+/346PbDH9yWbJyfnJ/ah3jmYKYtswEyCoWZiidvVHjHshd4WgjB9BA== 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.4": +"@babel/plugin-proposal-optional-chaining@7.10.4", "@babel/plugin-proposal-optional-chaining@^7.10.4", "@babel/plugin-proposal-optional-chaining@^7.9.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.4.tgz#750f1255e930a1f82d8cdde45031f81a0d0adff7" integrity sha512-ZIhQIEeavTgouyMSdZRap4VPPHqJJ3NEs2cuHs5p0erH+iz6khB0qfgU8g7UuJkG88+fBMy23ZiU+nuHvekJeQ== @@ -711,14 +486,6 @@ "@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== - dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - "@babel/plugin-proposal-pipeline-operator@7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-pipeline-operator/-/plugin-proposal-pipeline-operator-7.10.4.tgz#14d76c110409416f84c520d8a617bbe7f6a754dc" @@ -727,13 +494,13 @@ "@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.4": version "7.10.4" @@ -743,13 +510,13 @@ "@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" @@ -765,27 +532,20 @@ 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.4": +"@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.4" -"@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== - dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@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" @@ -814,12 +574,12 @@ 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.4": version "7.10.4" @@ -828,7 +588,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-import-meta@7.10.4": +"@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== @@ -842,13 +602,6 @@ 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== - dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@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" @@ -856,20 +609,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": +"@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.4" -"@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== - dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0", "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" @@ -877,14 +623,7 @@ 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== - dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - -"@babel/plugin-syntax-numeric-separator@^7.10.4": +"@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== @@ -926,101 +665,101 @@ dependencies: "@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.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.4.tgz#a670d1364bb5019a621b9ea2001482876d734787" + integrity sha512-J3b5CluMg3hPUii2onJDRiaVbPtKFPLEaV5dOPY5OeAbDi1iU/UbbFFTgwb7WnanaDy7bjU35kc26W3eM5Qa0A== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" lodash "^4.17.13" -"@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" @@ -1030,116 +769,116 @@ "@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.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.4.tgz#cb407c68b862e4c1d13a2fc738c7ec5ed75fc520" + integrity sha512-3Fw+H3WLUrTlzi3zMiZWp3AR4xadAEMv6XRCYnd5jAlLM61Rn+CRJaZMaNvIpcJpQ3vs1kyifYvEVPFfoSkKOA== 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-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.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.4.tgz#8f576afd943ac2f789b35ded0a6312f929c633f9" + integrity sha512-Tb28LlfxrTiOTGtZFsvkjpyjCl9IoaRI52AEU/VIwOwvDQWtbNJsAqTXzh+5R7i74e/OZHH2c2w2fsOqAfnQYQ== 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.4" + "@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.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.4.tgz#7b4d137c87ea7adc2a0f3ebf53266871daa6fced" + integrity sha512-RurVtZ/D5nYfEg0iVERXYKEgDFeesHrHfx8RT05Sq57ucj2eOYAP6eu5fynL4Adju4I/mP/I6SO0DqNWAXjfLQ== 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.4": version "7.10.4" @@ -1150,11 +889,11 @@ lodash "^4.17.13" "@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" @@ -1163,30 +902,14 @@ 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== - dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - -"@babel/plugin-transform-react-display-name@^7.10.4": +"@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.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== - 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/plugin-transform-react-jsx-development@^7.10.4": +"@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== @@ -1195,15 +918,7 @@ "@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== - dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-jsx" "^7.10.1" - -"@babel/plugin-transform-react-jsx-self@^7.10.4": +"@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== @@ -1211,15 +926,7 @@ "@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== - dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-jsx" "^7.10.1" - -"@babel/plugin-transform-react-jsx-source@^7.10.4": +"@babel/plugin-transform-react-jsx-source@^7.10.4", "@babel/plugin-transform-react-jsx-source@^7.9.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.10.4.tgz#86baf0fcccfe58084e06446a80858e1deae8f291" integrity sha512-FTK3eQFrPv2aveerUSazFmGygqIdTtvskG50SnGnbEUnRPcGx2ylBhdFIzoVS1ty44hEgcPoCAyw5r3VDEq+Ug== @@ -1227,17 +934,7 @@ "@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== - 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/plugin-transform-react-jsx@^7.10.4": +"@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== @@ -1247,14 +944,6 @@ "@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== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" - "@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" @@ -1263,19 +952,19 @@ "@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" @@ -1287,66 +976,66 @@ 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.10.4", "@babel/plugin-transform-spread@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.10.4.tgz#4e2c85ea0d6abaee1b24dcfbbae426fe8d674cff" + integrity sha512-1e/51G/Ni+7uH5gktbWv+eCED9pP8ZpRhZB3jOaI3mmzfvJTWHkuyYTv0Z5PYtyM+Tr2Ccr9kUdQxn60fI5WuQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@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.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.4.tgz#e6375407b30fcb7fcfdbba3bb98ef3e9d36df7bc" + integrity sha512-4NErciJkAYe+xI5cqfS8pV/0ntlY5N5Ske/4ImxAVX7mk9Rxt2bwDTGv1Msc2BRJvWQcmYEC+yoMLdX22aE4VQ== 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.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.10.4.tgz#8b01cb8d77f795422277cc3fcf45af72bc68ba78" + integrity sha512-3WpXIKDJl/MHoAN0fNkSr7iHdUMHZoppXjf2HJ9/ed5Xht5wNIsXllJXdityKOxeA3Z8heYRb1D3p2H5rfCdPw== 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.4" + "@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" @@ -1415,69 +1104,69 @@ 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.10.4" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.10.4.tgz#fbf57f9a803afd97f4f32e4f798bb62e4b2bef5f" + integrity sha512-tcmuQ6vupfMZPrLrc38d0sF2OjLT3/bZ0dry5HchNCQbrokoQi4reXqclvkkAT5b+gWc23meVWpve5P/7+w/zw== + dependencies: + "@babel/compat-data" "^7.10.4" + "@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-json-strings" "^7.10.4" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.10.4" + "@babel/plugin-proposal-numeric-separator" "^7.10.4" + "@babel/plugin-proposal-object-rest-spread" "^7.10.4" + "@babel/plugin-proposal-optional-catch-binding" "^7.10.4" + "@babel/plugin-proposal-optional-chaining" "^7.10.4" + "@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-json-strings" "^7.8.0" "@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.10.4" + "@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.10.4" browserslist "^4.12.0" core-js-compat "^3.6.2" invariant "^2.2.2" @@ -1485,12 +1174,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" @@ -1503,7 +1192,7 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/preset-react@7.10.4": +"@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== @@ -1528,19 +1217,6 @@ "@babel/plugin-transform-react-jsx-self" "^7.9.0" "@babel/plugin-transform-react-jsx-source" "^7.9.0" -"@babel/preset-react@^7.0.0": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.10.1.tgz#e2ab8ae9a363ec307b936589f07ed753192de041" - integrity sha512-Rw0SxQ7VKhObmFjD/cUcKhPTtzpeviEFX1E6PgP+cYOhQ98icNqtINNFANlsdbQHrmeWnqdxA4Tmnl1jy5tp3Q== - 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/preset-typescript@7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.9.0.tgz#87705a72b1f0d59df21c179f7c3d2ef4b16ce192" @@ -1561,22 +1237,14 @@ 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.10.4" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs2/-/runtime-corejs2-7.10.4.tgz#5d48ee239624d511c88208da86c27a161ee01cf7" + integrity sha512-9sArmpZDQsnR1yyAcU51DxQrntWxt0LUKjPp3pIyo7kVLfaqKt8muppcT87QmFkXV5H50qXAF8JWOjk0jaXRYA== 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.4" resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.10.4.tgz#f29fc1990307c4c57b10dbd6ce667b27159d9e0d" integrity sha512-BFlgP2SoLO9HJX9WBwN67gHWMBhDX/eDz64Jajd6mR/UAUzqrNMm99d4qHnVaKscAElZoFiPv+JpR/Siud5lXw== @@ -1584,7 +1252,7 @@ core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" -"@babel/runtime@7.10.4": +"@babel/runtime@7.10.4", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.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.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.4.tgz#a6724f1a6b8d2f6ea5236dbfe58c7d7ea9c5eb99" integrity sha512-UpTN5yUJr9b4EX2CnGNWIvER7Ab83ibv0pcvvHc4UOdrBI5jb8bj+32cCwPX6xu0mt2daFNjYhoi+X7beH0RSw== @@ -1598,30 +1266,7 @@ 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== - dependencies: - regenerator-runtime "^0.13.4" - -"@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== - 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.4": +"@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== @@ -1630,22 +1275,7 @@ "@babel/parser" "^7.10.4" "@babel/types" "^7.10.4" -"@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.4": +"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.7.0", "@babel/traverse@^7.9.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.4.tgz#e642e5395a3b09cc95c8e74a27432b484b697818" integrity sha512-aSy7p5THgSYm4YyxNGz6jZpXf+Ok40QF3aA2LyIONkDHpAcJzDUqlCKXv6peqYUs2gmic849C/t2HKw2a2K20Q== @@ -1660,16 +1290,7 @@ 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" - -"@babel/types@^7.10.4": +"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@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.4" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.4.tgz#369517188352e18219981efd156bfdb199fff1ee" integrity sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg== @@ -2043,16 +1664,6 @@ 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" @@ -2064,9 +1675,9 @@ 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.6" + resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-1.6.6.tgz#71ece2a24261eed0e184c0ef9814fcb77b1a4aee" + integrity sha512-zOOdNreHUNSFQ0dg3wYYg9sOGg2csf7Sk8JGBigeBq+4Xk4LO0QdycGAmgKNfeme+SyBV5LBIPjt1NNsScyWEQ== "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" @@ -2110,9 +1721,9 @@ mkdirp "^1.0.4" "@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" @@ -2124,10 +1735,10 @@ 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.0.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-3.0.0.tgz#78fabc5e295adb6e1ef57eaafe4cc5d7aa35b183" + integrity sha512-kqA5I6Yun7PBHk8WN9BBP1c7FfN2SrD05GuVSEYPqDb4nerv7HqYfgBfMIKmT/EuejURkJKLZuLyGKGs6WEG9w== "@sinonjs/commons@^1.7.0": version "1.8.0" @@ -2763,7 +2374,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== @@ -2774,17 +2385,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" @@ -2801,9 +2401,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" @@ -2840,9 +2440,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" "*" @@ -2892,9 +2492,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" @@ -2912,9 +2512,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" @@ -2934,9 +2534,9 @@ 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== + version "14.0.23" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.23.tgz#676fa0883450ed9da0bb24156213636290892806" + integrity sha512-Z4U8yDAl5TFkmYsZdFPdjeMa57NOvnaf1tljHzhouaPEp7LCj2JKkejpI1ODviIAQuW4CcQmxkQ77rnLsOOoKw== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -2954,9 +2554,9 @@ 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" @@ -2991,9 +2591,9 @@ "@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.43" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.43.tgz#c287f23f6189666ee3bebc2eb8d0f84bcb6cdb6b" + integrity sha512-PxshAFcnJqIWYpJbLPriClH53Z2WlJcVZE+NP2etUtWQs2s7yIMj3/LDKZT/5CHJ/F62iyjVCDu2H3jHEXIxSg== dependencies: "@types/prop-types" "*" csstype "^2.2.0" @@ -3016,14 +2616,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" @@ -3042,9 +2642,9 @@ 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" "*" @@ -3403,12 +3003,7 @@ 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.2.0: +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== @@ -3418,12 +3013,7 @@ acorn@^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: +acorn@^7.1.1, acorn@^7.2.0, acorn@^7.3.1: version "7.3.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd" integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA== @@ -3494,14 +3084,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.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.1.tgz#b83ca89c5d42d69031f424cad49aada0236c6957" + integrity sha512-KWcq3xN8fDjSB+IMoh2VaXVhRI0BBGxoYp3rx7Pkb6z0cFjYR9Q9l4yZqqals0/zsioCmocC5H6UvsGD4MoIBA== 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== + 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" @@ -3515,12 +3105,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== @@ -3727,12 +3317,12 @@ archiver-utils@^2.1.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== + version "4.0.2" + resolved "https://registry.yarnpkg.com/archiver/-/archiver-4.0.2.tgz#43c72865eadb4ddaaa2fb74852527b6a450d927c" + integrity sha512-B9IZjlGwaxF33UN4oPbfBkyA4V1SxNLeIhR1qY8sRXSsbdUkEHrrOvwlYFPx+8uQeCe9M+FG6KgO+imDmQ79CQ== 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" @@ -3954,13 +3544,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" @@ -3981,7 +3576,7 @@ 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.5: +autoprefixer@9.8.5, autoprefixer@^9.7.2: version "9.8.5" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.5.tgz#2c225de229ddafe1d1424c02791d0c3e10ccccaa" integrity sha512-C2p5KkumJlsTHoNv9w31NrBRgXhf6eCMteJuHZi2xhkgC+5Vm40MEtCKPhc0qdgAOhox0YPy1SQHTAky05UoKg== @@ -3994,19 +3589,6 @@ autoprefixer@9.8.5: 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.10.1: version "3.10.1" resolved "https://registry.yarnpkg.com/ava/-/ava-3.10.1.tgz#a4e68b1a2bb248fa0d96529d23dd83f57082e944" @@ -4091,9 +3673,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" @@ -4394,13 +3976,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" @@ -4528,9 +4111,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" @@ -4737,14 +4320,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" @@ -4879,16 +4462,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" @@ -5024,12 +4607,7 @@ 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.30001097: +caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001093, caniuse-lite@^1.0.30001097: version "1.0.30001099" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001099.tgz#540118fcc6842d1fde62f4ee5521d1ec6afdb40e" integrity sha512-sdS9A+sQTk7wKoeuZBN/YMAHVztUfVnjDi4/UV3sDE8xoh7YR12hKW+pIdB3oqKGwr9XaFL2ovfzt9w8eUI5CA== @@ -5216,9 +4794,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" @@ -5357,6 +4935,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" @@ -5447,9 +5030,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.55.0" + resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.55.0.tgz#23731f641288f202a6858fdc878f3149e0e04363" + integrity sha512-TumikSANlwiGkdF/Blnu/rqovZ0Y3Jh8yy9TqrPbSM0xxSucq3RgnpVDQ+mD9q6JERJEIT2FMuF/fBGfkhIR/g== collect-v8-coverage@^1.0.0: version "1.0.1" @@ -5489,9 +5072,9 @@ color-name@~1.1.4: 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== + 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" @@ -5510,7 +5093,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== @@ -5905,7 +5488,7 @@ 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: +css-loader@3.6.0, css-loader@^3.0.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== @@ -5924,25 +5507,6 @@ css-loader@3.6.0: schema-utils "^2.7.0" semver "^6.3.0" -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== - 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-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" - semver "^6.3.0" - css-select-base-adapter@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" @@ -6029,9 +5593,9 @@ cssstyle@^2.2.0: 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== + version "2.6.11" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.11.tgz#452f4d024149ecf260a852b025e36562a253ffc5" + integrity sha512-l8YyEC9NBkSm783PFTvh0FmJy7s5pFKrDp49ZL7zBGX3fWkO+N4EEyan1qqp8cwPLDcD0OSdyY6hAMoxp34JFw== currently-unhandled@^0.4.1: version "0.4.1" @@ -6361,13 +5925,6 @@ decamelize@^1.2.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= -decamelize@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-3.2.0.tgz#84b8e8f4f8c579f938e35e2cc7024907e0090851" - integrity sha512-4TgkVUsmmu7oCSyGBm5FvfMoACuoh9EOidm7V5/J2X2djAwwt57qb3F2KMP2ITqODTCSwb+YRV+0Zqrv18k/hw== - dependencies: - xregexp "^4.2.4" - decimal.js@^10.2.0: version "10.2.0" resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.0.tgz#39466113a9e036111d02f82489b5fd6b0b5ed231" @@ -6610,11 +6167,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" @@ -6968,10 +6520,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.496" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.496.tgz#3f43d32930481d82ad3663d79658e7c59a58af0b" + integrity sha512-TXY4mwoyowwi4Lsrq9vcTUYBThyc1b2hXaTZI13p8/FRhY2CTaq5lK+DVjhYkKiTLsKt569Xes+0J5JsVXFurQ== element-resize-detector@^1.1.10, element-resize-detector@^1.2.1: version "1.2.1" @@ -6981,9 +6533,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" @@ -6999,9 +6551,9 @@ email-addresses@3.1.0: 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== + 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" @@ -7043,11 +6595,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" @@ -7056,16 +6608,7 @@ 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: +enhanced-resolve@^4.1.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== @@ -7075,11 +6618,11 @@ enhanced-resolve@^4.1.1: 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" @@ -7111,21 +6654,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" @@ -7176,6 +6719,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.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.0.1.tgz#52568a77443f6927cd0ab9c73129137533c965ed" + integrity sha512-DR6NO3h9niOT+MZs7bjxlj2a1k+POu5RN8CLTPX2+i78bRi9eLe7+0zXgUHMnGXWybYcL61E9hGhPKqedy8tQA== + escape-goat@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" @@ -7202,9 +6750,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" @@ -7238,9 +6786,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" @@ -7377,16 +6925,16 @@ eslint-scope@^5.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== + 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== + 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.4.0: version "7.4.0" @@ -7535,9 +7083,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" @@ -7575,26 +7123,14 @@ 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: +expect@^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== @@ -7686,9 +7222,9 @@ extglob@^2.0.4: 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== + 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" @@ -7708,7 +7244,8 @@ 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" + uid bfe2c9906abd29b7d3d925e6d7cc41530c3a42b8 + resolved "https://github.com/Marak/faker.js.git#bfe2c9906abd29b7d3d925e6d7cc41530c3a42b8" fast-deep-equal@^2.0.1: version "2.0.1" @@ -7737,19 +7274,7 @@ fast-glob@^2.0.2: merge2 "^1.2.3" micromatch "^3.1.10" -fast-glob@^3.0.3, fast-glob@^3.1.1: - version "3.2.2" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.2.tgz#ade1a9d91148965d4bf7c51f72e1ca662d32e63d" - integrity sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.0" - merge2 "^1.3.0" - micromatch "^4.0.2" - picomatch "^2.2.1" - -fast-glob@^3.2.4: +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== @@ -8043,10 +7568,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" @@ -8056,11 +7581,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" @@ -8515,19 +8038,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.0" + resolved "https://registry.yarnpkg.com/got/-/got-11.5.0.tgz#55dd61050f666679f46c49c877e1b2e064a7a523" + integrity sha512-vOZEcEaK0b6x11uniY0HcblZObKPRO75Jvz53VKuqGSaKCM/zEt0sj2LGYVdqDYJzO3wYdG+FPQQ1hsgoXy7vQ== 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.4.8" lowercase-keys "^2.0.0" p-cancelable "^2.0.0" responselike "^2.0.0" @@ -8611,9 +8133,9 @@ graphql-language-service@^3.0.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== + version "2.10.4" + resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.10.4.tgz#2f301a98219be8b178a6453bb7e33b79b66d8f83" + integrity sha512-O7vG5BT3w6Sotc26ybcvLKNTdfr4GfsIVMD+LdYqXCeJIYPRyp8BIsDOUtxw7S1PYvRw5vH3278J2EDezR6mfA== graphql@15.3.0: version "15.3.0" @@ -9030,12 +8552,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.4.8: + 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: @@ -9071,13 +8593,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" @@ -9269,20 +8798,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.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.2.tgz#25245d2e32dc9f33dbe26eeaada231daa66e9c7c" + integrity sha512-DF4osh1FM6l0RJc5YWYhSDB6TawiBRlbV9Cox8MWlidU218Tb7fm3lQTULyUJDfJ0tjbzl0W4q651mrCCEM55w== 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.16" 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" @@ -9407,7 +8936,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== @@ -9640,14 +9169,7 @@ 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.1: +is-plain-object@^3.0.0, is-plain-object@^3.0.1: 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== @@ -9662,7 +9184,7 @@ 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: +is-regex@^1.0.4, is-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.0.tgz#ece38e389e490df0dc21caea2bd596f987f767ff" integrity sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw== @@ -9923,16 +9445,6 @@ jest-config@^26.1.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" - jest-diff@^26.1.0: version "26.1.0" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.1.0.tgz#00a549bdc936c9691eb4dc25d1fbd78bf456abb2" @@ -9984,11 +9496,6 @@ jest-environment-node@^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-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" @@ -10045,17 +9552,7 @@ jest-leak-detector@^26.1.0: 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" - -jest-matcher-utils@^26.1.0: +jest-matcher-utils@^26.0.1, 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== @@ -10065,20 +9562,6 @@ jest-matcher-utils@^26.1.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" - 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" @@ -10101,14 +9584,9 @@ jest-mock@^26.1.0: "@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-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== + 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" @@ -10320,9 +9798,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" @@ -10344,7 +9822,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" @@ -10472,9 +9950,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" @@ -10863,16 +10341,11 @@ 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.19: +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.16, 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== -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== - log-symbols@3.0.0, log-symbols@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" @@ -10937,6 +10410,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" @@ -11397,16 +10877,11 @@ moment-timezone@0.5.31: dependencies: moment ">= 2.9.0" -moment@2.27.0: +moment@2.27.0, "moment@>= 2.9.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" @@ -11504,9 +10979,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" @@ -11597,10 +11072,10 @@ node-notifier@^7.0.0: uuid "^7.0.3" 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.59" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.59.tgz#4d648330641cec704bff10f8e4fe28e453ab8e8e" + integrity sha512-H3JrdUczbdiwxN5FuJPyCHnGHIFqQ0wWxo+9j1kAXAzqNMAHlo+4I/sYYxpyK0irQ73HgdiyzD32oqQDcU2Osw== normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" @@ -11720,9 +11195,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" @@ -11960,9 +11435,9 @@ p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.3.0: p-try "^2.0.0" p-limit@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.0.1.tgz#584784ac0722d1aed09f19f90ed2999af6ce2839" - integrity sha512-mw/p92EyOzl2MhauKodw54Rx5ZK4624rNfgNaBguFZkHzyUG9WsDzFF5/yQVEJinbJDdP4jEfMN+uBquiGnaLg== + 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" @@ -12350,7 +11825,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= @@ -12377,9 +11852,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" @@ -12469,12 +11944,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.0.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.16, 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== @@ -12516,16 +11991,6 @@ 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" @@ -12562,7 +12027,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== @@ -12746,9 +12211,9 @@ pupa@^2.0.1: 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== + version "4.0.1" + resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-4.0.1.tgz#d6026add5fe058de22cd80879967eaa5e9be4cfb" + integrity sha512-8OfHmUkEXU/k7Bmcdm6KRWhIIfmayv/ce1AUDkP0nTLK2IpjulFggxq1dZhWgWHXebeLILbieMvAor7tSf3EqQ== dependencies: debug "^4.1.0" extract-zip "^2.0.0" @@ -12805,7 +12270,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== @@ -13040,12 +12505,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.0" + resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.4.0.tgz#11235eff41f47567288d7ef574e5b006527739d5" + integrity sha512-mue/boxdfNhfxnQcZtEBvqwZ5XQxk0uRoAMwLGl8j6XolFV3UIlt6iGFBGqRdJsvVHhtyKC5i8fkLnBidxCTbA== 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" @@ -13513,12 +12978,11 @@ regenerator-runtime@^0.13.2, regenerator-runtime@^0.13.3, regenerator-runtime@^0 integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== 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" @@ -13554,9 +13018,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" @@ -13851,10 +13315,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.0" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.0.tgz#af2901eedf02e3a83ffa7f886240ff9018bbec84" + integrity sha512-3HMA8z/Oz61DUHe+SdOiQyzIf4tOx5oQHmMir7IZEu6TMqCLHT4LRcmNaUS0NwOz8VLvmmBduMsoaUvMaIiqzg== dependencies: tslib "^1.9.0" @@ -13880,7 +13344,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== @@ -14489,11 +13953,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" @@ -14649,7 +14108,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== @@ -14657,25 +14116,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== @@ -14765,9 +14206,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" @@ -14931,9 +14372,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" @@ -15031,9 +14472,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" @@ -15373,11 +14814,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.0" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.10.0.tgz#397a7e6e31ce820bfd1cb55b804ee140c587a9e7" + integrity sha512-Esj5HG5WAyrLIdYU74Z3JdG2PxdIusvj6IWHMtlyESxc7kcDz7zYlYjpnSokn1UbpV0d/QX9fan7gkCNd/9BQA== ultimate-pagination@1.0.0: version "1.0.0" @@ -15662,9 +15101,9 @@ uuid@^7.0.3: 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== + version "8.2.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.2.0.tgz#cb10dd6b118e2dada7d0cd9730ba7417c93d920e" + integrity sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q== v8-compile-cache@^2.0.3, v8-compile-cache@^2.1.1: version "2.1.1" @@ -15830,7 +15269,7 @@ webidl-conversions@^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== @@ -16005,9 +15444,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" @@ -16133,9 +15572,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" @@ -16157,13 +15596,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.2.4: - 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" @@ -16202,7 +15634,7 @@ 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@^18.1.2: +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== @@ -16235,10 +15667,10 @@ 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@^15.0.1, yargs@^15.3.1, yargs@^15.4.0: + 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" @@ -16250,23 +15682,6 @@ 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@^15.4.0: - version "15.4.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.0.tgz#53949fb768309bac1843de9b17b80051e9805ec2" - integrity sha512-D3fRFnZwLWp8jVAAhPZBsmeIHY8tTsb8ItV9KaAaopmC6wde2u6Yw29JBIZHXw14kgkRnYmDgmQU4FVMDlIsWw== - dependencies: - cliui "^6.0.0" - decamelize "^3.2.0" - find-up "^4.1.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 "^4.2.0" - which-module "^2.0.0" - y18n "^4.0.0" yargs-parser "^18.1.2" yarn-install@^1.0.0: From a7e78d0baf6b9b58f0e3fb97d46c31523de30e64 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 13 Jul 2020 21:47:54 +0000 Subject: [PATCH 183/247] Update dependency com.diffplug.spotless:com.diffplug.spotless.gradle.plugin to v5.1.0 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ad86d9a09a..cf7a99c7c9 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ plugins { id "org.kordamp.markdown.convert" version "1.2.0" id "com.bmuschko.docker-remote-api" version "6.5.0" id "com.github.node-gradle.node" version "2.2.4" - id "com.diffplug.spotless" version "5.0.0" + id "com.diffplug.spotless" version "5.1.0" } apply plugin: 'java' From f9cecda208098df903193d165bdf98ca83879fcd Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 13 Jul 2020 22:24:18 +0000 Subject: [PATCH 184/247] Update dependency org.liquibase:liquibase-core to v4 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ad86d9a09a..5400d8ab50 100644 --- a/build.gradle +++ b/build.gradle @@ -74,7 +74,7 @@ dependencies { // Supported databases: implementation 'com.microsoft.sqlserver:mssql-jdbc:8.2.2.jre8' implementation 'org.postgresql:postgresql:42.2.14' // If using postgresql - implementation 'org.liquibase:liquibase-core:3.10.1' + 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' From 351e865ef6acefdb363536d810e69c995f550543 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 14 Jul 2020 10:42:07 +0200 Subject: [PATCH 185/247] NCI-Agency/anet#2954: Make LikertScale onChange required when editable This makes sure we no longer get the error "Uncaught TypeError: onChange is not a function" when clicking on the LikertScale while it is not editable (like on the task show page, or in the ReportStatistics). --- client/src/components/CustomFields.js | 4 ++++ client/src/components/graphs/LikertScale.js | 19 ++++++++++--------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/client/src/components/CustomFields.js b/client/src/components/CustomFields.js index a8b6438069..59e44f1bd4 100644 --- a/client/src/components/CustomFields.js +++ b/client/src/components/CustomFields.js @@ -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 ( { const cursorRef = useRef(null) @@ -22,7 +22,7 @@ const LikertScale = ({ const containerHeight = containerBox.height || 0 const containerWidth = containerBox.width || 0 const containerX = containerBox.x || 0 - const MARGIN_LEFT = readonly ? 13 : 25 + const MARGIN_LEFT = editable ? 25 : 13 const MARGIN_RIGHT = 13 const scaleYPosition = containerHeight - 30 const scale = d3 @@ -50,7 +50,7 @@ const LikertScale = ({ ) useEffect(() => { - if (readonly) { + if (!editable) { return } const handleDrag = d3.drag().on("drag", function() { @@ -64,7 +64,7 @@ const LikertScale = ({ onChange, scale, scaleYPosition, - readonly, + editable, MARGIN_LEFT, calculateNewX, xToValue @@ -105,7 +105,7 @@ const LikertScale = ({ xmlns="http://www.w3.org/2000/svg" ref={containerRef} onClick={e => { - if (!readonly && e.clientX) { + if (editable && e.clientX) { const newX = calculateNewX(e.clientX - containerX) onChange(xToValue(newX)) } @@ -204,7 +204,7 @@ const LikertScale = ({ )} - {onChange && (!readonly || (value && value >= scale.domain()[0])) && ( + {onChange && (editable || (value && value >= scale.domain()[0])) && ( Date: Mon, 6 Jul 2020 13:34:02 +0000 Subject: [PATCH 186/247] Update dependency webpack-merge to v5 --- client/package.json | 2 +- client/yarn.lock | 32 +++++++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/client/package.json b/client/package.json index 255d9b3c01..e3e915aefa 100644 --- a/client/package.json +++ b/client/package.json @@ -90,7 +90,7 @@ "webpack": "4.43.0", "webpack-cli": "3.3.12", "webpack-dev-server": "3.11.0", - "webpack-merge": "4.2.2", + "webpack-merge": "5.0.3", "xhr2": "0.2.0" }, "dependencies": { diff --git a/client/yarn.lock b/client/yarn.lock index 07ea8a7437..8332415cf5 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -4978,6 +4978,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" @@ -13609,6 +13618,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" @@ -15359,12 +15375,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.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.0.3.tgz#d3bba03cc11bf43719bd058342842b16528f6779" + integrity sha512-DDbqWyHYBUxoxjysYRnfP30puLciPTZ0BQ3v3/l2OrafinwKurCQhzKUa3L7u8w469tcVWDxAbqQM13KXeij8g== 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" @@ -15495,6 +15512,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" From 41cc6631f39a9546e4413c374aa32490e7d77aca Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Mon, 6 Jul 2020 16:14:50 +0200 Subject: [PATCH 187/247] Update call to merge (breaking change in webpack-merge) --- client/config/webpack.client.dev.js | 2 +- client/config/webpack.client.prod.js | 2 +- client/config/webpack.common.js | 4 ++-- client/config/webpack.sim.dev.js | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) 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, From 2a2eff379d22abd285741fe94fcd6f3227e7a9ef Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Tue, 14 Jul 2020 12:06:27 +0200 Subject: [PATCH 188/247] Update to latest webpack-merge --- client/package.json | 2 +- client/yarn.lock | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/client/package.json b/client/package.json index e3e915aefa..56b7c890fa 100644 --- a/client/package.json +++ b/client/package.json @@ -90,7 +90,7 @@ "webpack": "4.43.0", "webpack-cli": "3.3.12", "webpack-dev-server": "3.11.0", - "webpack-merge": "5.0.3", + "webpack-merge": "^5.0.9", "xhr2": "0.2.0" }, "dependencies": { diff --git a/client/yarn.lock b/client/yarn.lock index 8332415cf5..d25c2af5e2 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -7253,7 +7253,6 @@ extsprintf@^1.2.0: "faker@https://github.com/Marak/faker.js.git": version "4.1.0" - uid bfe2c9906abd29b7d3d925e6d7cc41530c3a42b8 resolved "https://github.com/Marak/faker.js.git#bfe2c9906abd29b7d3d925e6d7cc41530c3a42b8" fast-deep-equal@^2.0.1: @@ -15375,10 +15374,10 @@ webpack-log@^2.0.0: ansi-colors "^3.0.0" uuid "^3.3.2" -webpack-merge@5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.0.3.tgz#d3bba03cc11bf43719bd058342842b16528f6779" - integrity sha512-DDbqWyHYBUxoxjysYRnfP30puLciPTZ0BQ3v3/l2OrafinwKurCQhzKUa3L7u8w469tcVWDxAbqQM13KXeij8g== +webpack-merge@^5.0.9: + version "5.0.9" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.0.9.tgz#d5e0e0ae564ae704836d747893bdd2741544bf31" + integrity sha512-P4teh6O26xIDPugOGX61wPxaeP918QOMjmzhu54zTVcLtOS28ffPWtnv+ilt3wscwBUCL2WNMnh97XkrKqt9Fw== dependencies: clone-deep "^4.0.1" wildcard "^2.0.0" From afa639bc3b70c3bd7fb0cde65f7de38e03c5f137 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 14 Jul 2020 12:50:28 +0200 Subject: [PATCH 189/247] NCI-Agency/anet#2954: Fix myOrg wdio tests This makes sure that the wdio tests also succeed if the jacocoTestReport have run before and did database changes. Did this by making the content checks less specific. --- client/tests/webdriver/specs/myOrg.spec.js | 28 +++++++++++++++------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/client/tests/webdriver/specs/myOrg.spec.js b/client/tests/webdriver/specs/myOrg.spec.js index e934857d30..a28f659006 100644 --- a/client/tests/webdriver/specs/myOrg.spec.js +++ b/client/tests/webdriver/specs/myOrg.spec.js @@ -11,36 +11,46 @@ describe("My organization page", () => { 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" ) - expect(daysWithEvent.length).to.equal(1) + // 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.length).to.equal(4) + expect(engagementStatusLegend).to.have.length(4) MyOrg.tasks.waitForDisplayed() - const tasksBars = MyOrg.tasks.$("svg g").$$(".bars-group") - expect(tasksBars.length).to.equal(4) + // 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 - tasksBars.forEach(bar => { - if (bar.$("rect").getAttribute("data-tip").includes("

1

")) { + tasks.forEach(bar => { + if (+bar.$("rect").getAttribute("height") > 0) { countTasksBars++ } }) - expect(countTasksBars).to.equal(3) + // 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.length).to.equal(3) + 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.equal("1") + expect(+trainignEventTotal.getText()).to.be.above(0) MyOrg.numberTrained.waitForDisplayed() const numberTrained = MyOrg.numberTrained.$("div em") From a609279391e0e25582d9c4223a3b4ec81f5f9633 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 14 Jul 2020 17:00:47 +0200 Subject: [PATCH 190/247] NCI-Agency/anet#2954: Fix typo in is name --- client/src/components/assessments/AssessmentResultsTable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/assessments/AssessmentResultsTable.js b/client/src/components/assessments/AssessmentResultsTable.js index 301420b0b0..37e27a7aff 100644 --- a/client/src/components/assessments/AssessmentResultsTable.js +++ b/client/src/components/assessments/AssessmentResultsTable.js @@ -121,7 +121,7 @@ const AssessmentResultsTable = ({
Date: Tue, 14 Jul 2020 17:01:27 +0200 Subject: [PATCH 191/247] NCI-Agency/anet#2954: Add wdio tests for assessments --- .../tests/webdriver/pages/myReports.page.js | 19 +++++++++++++ .../tests/webdriver/pages/showReport.page.js | 13 +++++++++ client/tests/webdriver/pages/showTask.page.js | 13 +++++++++ .../tests/webdriver/specs/showReport.spec.js | 27 ++++++++++++++++++ client/tests/webdriver/specs/showTask.spec.js | 28 +++++++++++++++++++ 5 files changed, 100 insertions(+) create mode 100644 client/tests/webdriver/pages/myReports.page.js create mode 100644 client/tests/webdriver/pages/showReport.page.js create mode 100644 client/tests/webdriver/pages/showTask.page.js create mode 100644 client/tests/webdriver/specs/showReport.spec.js create mode 100644 client/tests/webdriver/specs/showTask.spec.js 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/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/showReport.spec.js b/client/tests/webdriver/specs/showReport.spec.js new file mode 100644 index 0000000000..5580718a06 --- /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 assessmnets", () => { + 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 svgAssessmnets = ShowReport.tasksEngagementAssessments.$$("svg") + expect(svgAssessmnets).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..d5fb94c3c7 --- /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 assessmnets", () => { + 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()) + }) + }) +}) From 4db10f6ea6b9162df5e2fdd2a724626e5a6c6359 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Tue, 14 Jul 2020 18:31:55 +0000 Subject: [PATCH 192/247] Update most non-major dependencies --- client/package.json | 14 ++-- client/yarn.lock | 175 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 144 insertions(+), 45 deletions(-) diff --git a/client/package.json b/client/package.json index 255d9b3c01..fb202dd4f9 100644 --- a/client/package.json +++ b/client/package.json @@ -4,9 +4,9 @@ "private": true, "homepage": "/assets/client", "devDependencies": { - "@babel/core": "7.10.4", + "@babel/core": "7.10.5", "@babel/plugin-proposal-class-properties": "7.10.4", - "@babel/plugin-proposal-decorators": "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", @@ -16,14 +16,14 @@ "@babel/plugin-proposal-nullish-coalescing-operator": "7.10.4", "@babel/plugin-proposal-numeric-separator": "7.10.4", "@babel/plugin-proposal-optional-chaining": "7.10.4", - "@babel/plugin-proposal-pipeline-operator": "7.10.4", + "@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.4", - "@babel/plugin-transform-proto-to-assign": "7.10.4", + "@babel/plugin-transform-proto-to-assign": "7.10.5", "@babel/preset-react": "7.10.4", - "@babel/register": "7.10.4", - "@babel/runtime": "7.10.4", + "@babel/register": "7.10.5", + "@babel/runtime": "7.10.5", "@storybook/addon-actions": "5.3.19", "@storybook/react": "5.3.19", "@wdio/browserstack-service": "6.1.15", @@ -116,7 +116,7 @@ "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.3.0", "hopscotch": "0.3.1", diff --git a/client/yarn.lock b/client/yarn.lock index 07ea8a7437..1b721c8e07 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -43,24 +43,24 @@ invariant "^2.2.4" semver "^5.5.0" -"@babel/core@7.10.4", "@babel/core@^7.1.0", "@babel/core@^7.4.5", "@babel/core@^7.7.5": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.4.tgz#780e8b83e496152f8dd7df63892b2e052bf1d51d" - integrity sha512-3A0tS0HWpy4XujGc7QtOIHTeNwUgWaZc/WuS5YQrfhU67jnVmsD6OGPc1AKHH0LJHQICGncy3+YUjIhVlfDdcA== +"@babel/core@7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.5.tgz#1f15e2cca8ad9a1d78a38ddba612f5e7cdbbd330" + integrity sha512-O34LQooYVDXPl7QWCdW9p4NR+QlzOr7xShPPJz8GsuCU3/8ua/wqTr7gmnxXv+WBESiGU/G5s16i6tUvHkNb+w== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.10.4" - "@babel/helper-module-transforms" "^7.10.4" + "@babel/generator" "^7.10.5" + "@babel/helper-module-transforms" "^7.10.5" "@babel/helpers" "^7.10.4" - "@babel/parser" "^7.10.4" + "@babel/parser" "^7.10.5" "@babel/template" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/traverse" "^7.10.5" + "@babel/types" "^7.10.5" 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" @@ -87,6 +87,28 @@ semver "^5.4.1" source-map "^0.5.0" +"@babel/core@^7.1.0", "@babel/core@^7.4.5", "@babel/core@^7.7.5": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.4.tgz#780e8b83e496152f8dd7df63892b2e052bf1d51d" + integrity sha512-3A0tS0HWpy4XujGc7QtOIHTeNwUgWaZc/WuS5YQrfhU67jnVmsD6OGPc1AKHH0LJHQICGncy3+YUjIhVlfDdcA== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.10.4" + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helpers" "^7.10.4" + "@babel/parser" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + "@babel/generator@^7.10.4", "@babel/generator@^7.9.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.4.tgz#e49eeed9fe114b62fa5b181856a43a5e32f5f243" @@ -97,6 +119,15 @@ lodash "^4.17.13" source-map "^0.5.0" +"@babel/generator@^7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.5.tgz#1b903554bc8c583ee8d25f1e8969732e6b829a69" + integrity sha512-3vXxr3FEW7E7lJZiWQ3bM4+v/Vyr9C+hpolQ8BGFr9Y8Ri2tFLWTixmwKBafDujO1WVah4fhZBeU1bieKdghig== + dependencies: + "@babel/types" "^7.10.5" + jsesc "^2.5.1" + source-map "^0.5.0" + "@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" @@ -152,6 +183,18 @@ "@babel/helper-replace-supers" "^7.10.4" "@babel/helper-split-export-declaration" "^7.10.4" +"@babel/helper-create-class-features-plugin@^7.10.5": + 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" @@ -208,6 +251,13 @@ dependencies: "@babel/types" "^7.10.4" +"@babel/helper-member-expression-to-functions@^7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.5.tgz#172f56e7a63e78112f3a04055f24365af702e7ee" + integrity sha512-HiqJpYD5+WopCXIAbQDG0zye5XYVvcO9w/DHp5GsaGkRUaamLj2bEtu6i8rnGGprAhHM3qidCMgp71HF4endhA== + dependencies: + "@babel/types" "^7.10.5" + "@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" @@ -228,6 +278,19 @@ "@babel/types" "^7.10.4" lodash "^4.17.13" +"@babel/helper-module-transforms@^7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.10.5.tgz#120c271c0b3353673fcdfd8c053db3c544a260d6" + integrity sha512-4P+CWMJ6/j1W915ITJaUkadLObmCRRSC234uctJfn/vHrsLNxsR8dwlcXv9ZhJWzl77awf+mWXSZEKt5t0OnlA== + 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.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.5" + 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" @@ -321,6 +384,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.4.tgz#9eedf27e1998d87739fb5028a5120557c06a1a64" integrity sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA== +"@babel/parser@^7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.5.tgz#e7c6bf5a7deff957cec9f04b551e2762909d826b" + integrity sha512-wfryxy4bE1UivvQKSQDU4/X6dr+i8bctjUjj8Zyt3DQy7NtPizJXT8M52nqpNKL+nq2PW8lxk4ZqLj0fD4B4hQ== + "@babel/plugin-proposal-async-generator-functions@^7.10.4", "@babel/plugin-proposal-async-generator-functions@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.4.tgz#4b65abb3d9bacc6c657aaa413e56696f9f170fc6" @@ -346,12 +414,12 @@ "@babel/helper-create-class-features-plugin" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-proposal-decorators@7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.10.4.tgz#fe20ef10cc73f386f70910fca48798041cd357c7" - integrity sha512-JHTWjQngOPv+ZQQqOGv2x6sCCr4IYWy7S1/VH6BE9ZfkoLrdQ2GpEP3tfb5M++G9PwvqjhY8VC/C3tXm+/eHvA== +"@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.4" + "@babel/helper-create-class-features-plugin" "^7.10.5" "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-decorators" "^7.10.4" @@ -486,10 +554,10 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-proposal-pipeline-operator@7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-pipeline-operator/-/plugin-proposal-pipeline-operator-7.10.4.tgz#14d76c110409416f84c520d8a617bbe7f6a754dc" - integrity sha512-NL4M3pQrvBZKrudP2WybWIHWgLR4ZwWiIYPk1T0jbXl665Ao7ODn+OLksv2+1bMGwOIE49vNcmhaAMA0uqRgGA== +"@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.4" "@babel/plugin-syntax-pipeline-operator" "^7.10.4" @@ -880,13 +948,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-proto-to-assign@7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-proto-to-assign/-/plugin-transform-proto-to-assign-7.10.4.tgz#d2a5802a506955618805684a4699e4ee62fb4d6a" - integrity sha512-cu1HAWSPYPzL/ra4FodvPXycLCodjoOY3B3gi8Hz50HEaKJ1YZ/nDeCnCkQEQMVneImA6+B63UyTdmn02YngLA== +"@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.4" - lodash "^4.17.13" + 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.4" @@ -1225,13 +1293,13 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-transform-typescript" "^7.9.0" -"@babel/register@7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.10.4.tgz#53004ba8b04c4af3cbd84508e03ad150669746e4" - integrity sha512-whHmgGiWNVyTVnYTSawtDWhaeYsc+noeU8Rmi+MPnbGhDYmr5QpEDMrQcIA07D2RUv0BlThPcN89XcHCqq/O4g== +"@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" @@ -1252,10 +1320,10 @@ core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" -"@babel/runtime@7.10.4", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.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.4" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.4.tgz#a6724f1a6b8d2f6ea5236dbfe58c7d7ea9c5eb99" - integrity sha512-UpTN5yUJr9b4EX2CnGNWIvER7Ab83ibv0pcvvHc4UOdrBI5jb8bj+32cCwPX6xu0mt2daFNjYhoi+X7beH0RSw== +"@babel/runtime@7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.5.tgz#303d8bd440ecd5a491eae6117fd3367698674c5c" + integrity sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg== dependencies: regenerator-runtime "^0.13.4" @@ -1266,6 +1334,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.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.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.4.tgz#a6724f1a6b8d2f6ea5236dbfe58c7d7ea9c5eb99" + integrity sha512-UpTN5yUJr9b4EX2CnGNWIvER7Ab83ibv0pcvvHc4UOdrBI5jb8bj+32cCwPX6xu0mt2daFNjYhoi+X7beH0RSw== + dependencies: + regenerator-runtime "^0.13.4" + "@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" @@ -1290,6 +1365,21 @@ globals "^11.1.0" lodash "^4.17.13" +"@babel/traverse@^7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.5.tgz#77ce464f5b258be265af618d8fddf0536f20b564" + integrity sha512-yc/fyv2gUjPqzTz0WHeRJH2pv7jA9kA7mBX2tXl/x5iOE81uaVPuGPtaYk7wmkx4b67mQ7NqI8rmT2pF47KYKQ== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.10.5" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" + "@babel/parser" "^7.10.5" + "@babel/types" "^7.10.5" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.19" + "@babel/types@^7.0.0", "@babel/types@^7.10.4", "@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.4" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.4.tgz#369517188352e18219981efd156bfdb199fff1ee" @@ -1299,6 +1389,15 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" +"@babel/types@^7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.5.tgz#d88ae7e2fde86bfbfe851d4d81afa70a997b5d15" + integrity sha512-ixV66KWfCI6GKoA/2H9v6bQdbfXEwwpOdQ8cRvb4F+eyvhlaHxWFMQB4+3d9QFJXZsiiiqVrewNV0DFEQpyT4Q== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -7635,10 +7734,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" @@ -10341,7 +10440,7 @@ 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.19, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.16, lodash@~4.17.10, lodash@~4.17.12: +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.16, 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== From 1415d9e5cd5454e854a24935ef9a767e0dea0cf7 Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 14 Jul 2020 21:45:42 +0200 Subject: [PATCH 193/247] NCI-Agency/anet#2954: Code refactoring IqrBoxPlot Removed not used properties and code. Use a constant for the common default levels value, which is the same as for the LikertScale. --- client/src/components/graphs/IqrBoxPlot.js | 44 ++------------------- client/src/components/graphs/LikertScale.js | 18 ++------- client/src/components/graphs/utils.js | 15 +++++++ 3 files changed, 22 insertions(+), 55 deletions(-) create mode 100644 client/src/components/graphs/utils.js diff --git a/client/src/components/graphs/IqrBoxPlot.js b/client/src/components/graphs/IqrBoxPlot.js index b889971203..5413325ee4 100644 --- a/client/src/components/graphs/IqrBoxPlot.js +++ b/client/src/components/graphs/IqrBoxPlot.js @@ -1,18 +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, { useEffect, useRef } from "react" import useDimensions from "react-use-dimensions" -const IqrBoxPlot = ({ - onChange, - values, - levels, - width, - height, - readonly, - whenUnspecified -}) => { +const IqrBoxPlot = ({ values, levels, width, height, whenUnspecified }) => { const cursorRef = useRef(null) const axisRef = useRef(null) const [containerRef, containerBox] = useDimensions() @@ -116,27 +109,12 @@ const IqrBoxPlot = ({ )} - - {onChange && ( - - - - )} ) } IqrBoxPlot.propTypes = { values: PropTypes.arrayOf(PropTypes.number), - onChange: PropTypes.func, levels: PropTypes.arrayOf( PropTypes.shape({ color: PropTypes.string, @@ -147,25 +125,11 @@ IqrBoxPlot.propTypes = { ).isRequired, width: PropTypes.string.isRequired, height: PropTypes.string.isRequired, - readonly: PropTypes.bool, whenUnspecified: PropTypes.oneOfType([PropTypes.string, PropTypes.object]) } IqrBoxPlot.defaultProps = { - levels: [ - { - color: "red", - endValue: 3 - }, - { - color: "#FFBF00", - endValue: 7 - }, - { - color: "green", - endValue: 10 - } - ], + levels: TRAFFIC_LIGHTS_LEVELS, height: "65", width: "100%", whenUnspecified: null diff --git a/client/src/components/graphs/LikertScale.js b/client/src/components/graphs/LikertScale.js index 2429a102dc..b64684c669 100644 --- a/client/src/components/graphs/LikertScale.js +++ b/client/src/components/graphs/LikertScale.js @@ -1,7 +1,8 @@ -import React, { useCallback, 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" @@ -252,20 +253,7 @@ LikertScale.propTypes = { LikertScale.defaultProps = { value: null, - levels: [ - { - color: "red", - endValue: 3 - }, - { - color: "#FFBF00", - endValue: 7 - }, - { - color: "green", - endValue: 10 - } - ], + levels: TRAFFIC_LIGHTS_LEVELS, height: "65", width: "100%", editable: false, 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 + } +] From 954d25bbfc14204719974b7bd8aebdf90b394a4e Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Tue, 14 Jul 2020 22:29:27 +0200 Subject: [PATCH 194/247] NCI-Agency/anet#2954: Introduce ellipsize util The ellipsize util is being used to display a max number of characters for a string value. --- client/src/components/BarChart.js | 7 ++++--- client/src/components/Kanban.js | 5 ++--- client/src/components/graphs/OrganizationalChart.js | 3 ++- client/src/utils.js | 6 ++++++ 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/client/src/components/BarChart.js b/client/src/components/BarChart.js index f833cb045b..9ed0255290 100644 --- a/client/src/components/BarChart.js +++ b/client/src/components/BarChart.js @@ -51,10 +51,11 @@ const BarChart = ({ const xScale = d3.scaleBand().domain( data.map(function(d) { - xLabels[getPropValue(d, xProp)] = getPropValue(d, label).substring( - 0, + xLabels[getPropValue(d, xProp)] = utils.ellipsize( + getPropValue(d, label), 10 - ) // TODO: Make responsive + ) + // TODO: Make responsive return getPropValue(d, xProp) }) ) 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/graphs/OrganizationalChart.js b/client/src/components/graphs/OrganizationalChart.js index 6449dafbd6..21ba6e5526 100644 --- a/client/src/components/graphs/OrganizationalChart.js +++ b/client/src/components/graphs/OrganizationalChart.js @@ -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!) { @@ -372,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]) diff --git a/client/src/utils.js b/client/src/utils.js index 29c2ac2f7d..71e92b4452 100644 --- a/client/src/utils.js +++ b/client/src/utils.js @@ -34,11 +34,17 @@ const fnRequiredWhen = (boolPropName, props, propName, componentName) => { } } +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)) }, From 81303242a1748fe307bc52165eb751f5f6b536fd Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Wed, 15 Jul 2020 00:09:49 +0200 Subject: [PATCH 195/247] NCI-Agency/anet#2954: Fix getRelatedObjectsEngagementAssessments If for a report we had only tasks assessments, it was also returning a value for attendees assessments. This was not visible to the user as the returned value was returning empty keys for entityUuids and therefore was not be used. And therefore we never noticed this problem before. --- client/src/models/Report.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/client/src/models/Report.js b/client/src/models/Report.js index 0fe64daf23..4f90c18b2b 100644 --- a/client/src/models/Report.js +++ b/client/src/models/Report.js @@ -427,14 +427,13 @@ export default class Report extends Model { n => n.type === NOTE_TYPE.ASSESSMENT && n.noteRelatedObjects.length > 1 ) .map(n => ({ - entityUuids: [ - n.noteRelatedObjects - .filter(ro => ro.relatedObjectType === entityType.relatedObjectType) - .map(ro => ro.relatedObjectUuid) - ], + entityUuids: n.noteRelatedObjects + .filter(ro => ro.relatedObjectType === entityType.relatedObjectType) + .map(ro => ro.relatedObjectUuid), assessmentUuid: n.uuid, assessment: utils.parseJsonSafe(n.text) })) + .filter(n => !_isEmpty(n.entityUuids)) // When updating the instant assessments, we need for each entity the uuid of the // related instant assessment const entitiesAssessmentsUuids = {} @@ -453,12 +452,11 @@ export default class Report extends Model { } getTasksEngagementAssessments() { - const a = this.getRelatedObjectsEngagementAssessments( + return this.getRelatedObjectsEngagementAssessments( Task, Report.TASKS_ASSESSMENTS_PARENT_FIELD, Report.TASKS_ASSESSMENTS_UUIDS_FIELD ) - return a } getAttendeesEngagementAssessments() { From 849e8654b07792ff8e23df77df05ec20d7524bef Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Wed, 15 Jul 2020 08:55:46 +0000 Subject: [PATCH 196/247] Pin dependency webpack-merge to 5.0.9 --- client/package.json | 2 +- client/yarn.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/package.json b/client/package.json index 56b7c890fa..f4e86625e7 100644 --- a/client/package.json +++ b/client/package.json @@ -90,7 +90,7 @@ "webpack": "4.43.0", "webpack-cli": "3.3.12", "webpack-dev-server": "3.11.0", - "webpack-merge": "^5.0.9", + "webpack-merge": "5.0.9", "xhr2": "0.2.0" }, "dependencies": { diff --git a/client/yarn.lock b/client/yarn.lock index d25c2af5e2..58c179780b 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -15374,7 +15374,7 @@ webpack-log@^2.0.0: ansi-colors "^3.0.0" uuid "^3.3.2" -webpack-merge@^5.0.9: +webpack-merge@5.0.9: version "5.0.9" resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.0.9.tgz#d5e0e0ae564ae704836d747893bdd2741544bf31" integrity sha512-P4teh6O26xIDPugOGX61wPxaeP918QOMjmzhu54zTVcLtOS28ffPWtnv+ilt3wscwBUCL2WNMnh97XkrKqt9Fw== From 503ca94c8c73d4385f39dacfbc63dbe5aaa9b981 Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Wed, 15 Jul 2020 11:40:17 +0200 Subject: [PATCH 197/247] Upgrade to Apollo Client v3 --- client/package.json | 3 +- client/src/api.js | 77 ++++---- .../AdvisorReports/AdvisorReportsTable.js | 2 +- .../FilterableAdvisorReportsTable.js | 2 +- client/src/components/AssignPersonModal.js | 2 +- client/src/components/AssignPositionModal.js | 2 +- .../components/CancelledEngagementReports.js | 2 +- .../EditAssociatedPositionsModal.js | 2 +- .../components/FutureEngagementsByLocation.js | 2 +- client/src/components/Model.js | 4 +- client/src/components/OrganizationTable.js | 2 +- .../src/components/PendingApprovalReports.js | 2 +- client/src/components/PositionTable.js | 2 +- client/src/components/RelatedObjectNotes.js | 4 +- client/src/components/ReportCalendar.js | 2 +- client/src/components/ReportMap.js | 2 +- client/src/components/ReportSummary.js | 2 +- client/src/components/ReportTable.js | 2 +- client/src/components/ReportsByDayOfWeek.js | 2 +- client/src/components/ReportsByTask.js | 2 +- .../advancedSearch/AdvancedSelectFilter.js | 2 +- .../advancedSearch/OrganizationFilter.js | 2 +- .../advancedSelectWidget/AdvancedSelect.js | 2 +- .../approvals/ApprovalsDefinition.js | 2 +- .../components/graphs/OrganizationalChart.js | 2 +- client/src/exportUtils.js | 2 +- client/src/index.js | 2 +- client/src/pages/App.js | 2 +- client/src/pages/GraphiQL.js | 2 +- client/src/pages/Help.js | 2 +- client/src/pages/Home.js | 2 +- client/src/pages/Search.js | 2 +- client/src/pages/admin/AuthorizationGroups.js | 2 +- client/src/pages/admin/Index.js | 2 +- client/src/pages/admin/MergePeople.js | 2 +- .../pages/admin/authorizationgroup/Edit.js | 2 +- .../pages/admin/authorizationgroup/Form.js | 2 +- .../pages/admin/authorizationgroup/Show.js | 2 +- .../pages/dashboards/DecisivesDashboard.js | 2 +- .../src/pages/dashboards/KanbanDashboard.js | 2 +- client/src/pages/locations/Edit.js | 2 +- client/src/pages/locations/Form.js | 2 +- client/src/pages/locations/Show.js | 2 +- client/src/pages/onboarding/Edit.js | 2 +- client/src/pages/organizations/Edit.js | 2 +- client/src/pages/organizations/Form.js | 2 +- client/src/pages/organizations/New.js | 2 +- .../pages/organizations/OrganizationTasks.js | 2 +- client/src/pages/organizations/Show.js | 2 +- client/src/pages/people/Edit.js | 2 +- client/src/pages/people/Form.js | 2 +- client/src/pages/people/Show.js | 2 +- client/src/pages/positions/Edit.js | 2 +- client/src/pages/positions/Form.js | 2 +- client/src/pages/positions/New.js | 2 +- client/src/pages/positions/Show.js | 2 +- client/src/pages/reports/Edit.js | 2 +- client/src/pages/reports/Form.js | 2 +- client/src/pages/reports/Minimal.js | 2 +- client/src/pages/reports/Show.js | 2 +- client/src/pages/rollup/Show.js | 2 +- client/src/pages/tasks/Edit.js | 2 +- client/src/pages/tasks/Form.js | 2 +- client/src/pages/tasks/New.js | 2 +- client/src/pages/tasks/Show.js | 2 +- client/src/utils_links.js | 2 +- client/yarn.lock | 168 ++++-------------- 67 files changed, 141 insertions(+), 239 deletions(-) diff --git a/client/package.json b/client/package.json index f4e86625e7..28c6f681b5 100644 --- a/client/package.json +++ b/client/package.json @@ -94,7 +94,7 @@ "xhr2": "0.2.0" }, "dependencies": { - "@apollo/react-hooks": "3.1.5", + "@apollo/client": "3.0.0", "@blueprintjs/core": "3.29.0", "@blueprintjs/datetime": "3.18.3", "@fullcalendar/core": "4.4.2", @@ -103,7 +103,6 @@ "@fullcalendar/list": "4.4.2", "@fullcalendar/react": "4.4.2", "@fullcalendar/timegrid": "4.4.2", - "apollo-boost": "0.4.9", "bootstrap": "3.4.1", "change-case": "4.1.1", "classnames": "2.2.6", diff --git a/client/src/api.js b/client/src/api.js index 402109aba9..22f9bad1d6 100644 --- a/client/src/api.js +++ b/client/src/api.js @@ -1,29 +1,44 @@ 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) => { + const [authHeaderName, authHeaderValue] = API._getAuthHeader() + operation.setContext(({ headers = {} }) => ({ + headers: { + ...headers, + Accept: "application/json", + [authHeaderName]: authHeaderValue + } + })) + + return forward(operation) +}) + const API = { _fetch(url, data, accept) { + const [authHeaderName, authHeaderValue] = API._getAuthHeader() const params = { method: "POST", body: JSON.stringify(data), credentials: "same-origin", headers: { "Content-Type": "application/json", - Accept: accept || "application/json" + Accept: accept || "application/json", + [authHeaderName]: authHeaderValue } } - const authHeader = API._getAuthHeader() - if (authHeader) { - params.headers[authHeader[0]] = authHeader[1] - } - return window.fetch(url, params) }, @@ -138,43 +153,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/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..8b2a1210ee 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" diff --git a/client/src/components/CancelledEngagementReports.js b/client/src/components/CancelledEngagementReports.js index e19376b428..fe731bed8b 100644 --- a/client/src/components/CancelledEngagementReports.js +++ b/client/src/components/CancelledEngagementReports.js @@ -1,6 +1,6 @@ +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" diff --git a/client/src/components/EditAssociatedPositionsModal.js b/client/src/components/EditAssociatedPositionsModal.js index e3886b1813..642e627d9d 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" diff --git a/client/src/components/FutureEngagementsByLocation.js b/client/src/components/FutureEngagementsByLocation.js index f74af67be7..9753d92ea2 100644 --- a/client/src/components/FutureEngagementsByLocation.js +++ b/client/src/components/FutureEngagementsByLocation.js @@ -1,6 +1,6 @@ +import { gql } from "@apollo/client" import { IconNames } from "@blueprintjs/icons" import API from "api" -import { gql } from "apollo-boost" import HorizontalBarChart from "components/HorizontalBarChart" import MosaicLayout from "components/MosaicLayout" import { PageDispatchersPropType, useBoilerplate } from "components/Page" diff --git a/client/src/components/Model.js b/client/src/components/Model.js index 071c2ebf75..18469f26ab 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -1,11 +1,11 @@ -import encodeQuery from "querystring/encode" +import { gql } from "@apollo/client" import _forEach from "lodash/forEach" import _isEmpty from "lodash/isEmpty" import moment from "moment" 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 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..de2bc941c3 100644 --- a/client/src/components/PendingApprovalReports.js +++ b/client/src/components/PendingApprovalReports.js @@ -1,6 +1,6 @@ +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" 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/RelatedObjectNotes.js b/client/src/components/RelatedObjectNotes.js index 89a591780e..5b451a3ad5 100644 --- a/client/src/components/RelatedObjectNotes.js +++ b/client/src/components/RelatedObjectNotes.js @@ -1,8 +1,8 @@ -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" 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/ReportMap.js b/client/src/components/ReportMap.js index c0ae8170b1..7d79755055 100644 --- a/client/src/components/ReportMap.js +++ b/client/src/components/ReportMap.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import Leaflet from "components/Leaflet" import { PageDispatchersPropType, 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/ReportsByDayOfWeek.js b/client/src/components/ReportsByDayOfWeek.js index 3aeb6d6b05..53be824d94 100644 --- a/client/src/components/ReportsByDayOfWeek.js +++ b/client/src/components/ReportsByDayOfWeek.js @@ -1,6 +1,6 @@ +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" diff --git a/client/src/components/ReportsByTask.js b/client/src/components/ReportsByTask.js index 5ba8e64444..a3ae650109 100644 --- a/client/src/components/ReportsByTask.js +++ b/client/src/components/ReportsByTask.js @@ -1,6 +1,6 @@ +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" 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/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/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/graphs/OrganizationalChart.js b/client/src/components/graphs/OrganizationalChart.js index 7e41560e47..62c6126f20 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, 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/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..966a7e260d 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 { diff --git a/client/src/pages/Home.js b/client/src/pages/Home.js index 304d72731b..9167cc5853 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" diff --git a/client/src/pages/Search.js b/client/src/pages/Search.js index 01100c2758..ea8c055134 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" 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..ccf1b7f220 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" 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..cb4de3bbd0 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, 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..ba995cad6a 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" 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/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/locations/Edit.js b/client/src/pages/locations/Edit.js index 9f18895a86..76011da5f2 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, diff --git a/client/src/pages/locations/Form.js b/client/src/pages/locations/Form.js index 60623989f9..ec4e3fa0f1 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" diff --git a/client/src/pages/locations/Show.js b/client/src/pages/locations/Show.js index 5fa3c50f47..b9b34dc22e 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" diff --git a/client/src/pages/onboarding/Edit.js b/client/src/pages/onboarding/Edit.js index cbf330ba06..6222abe2e9 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, diff --git a/client/src/pages/organizations/Edit.js b/client/src/pages/organizations/Edit.js index 011e3a4e6c..93f8421673 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, diff --git a/client/src/pages/organizations/Form.js b/client/src/pages/organizations/Form.js index ac3ddd6b73..6a1d1b2be3 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, 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..5bec7160eb 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" diff --git a/client/src/pages/organizations/Show.js b/client/src/pages/organizations/Show.js index cab7ffc1e0..cb28f0f3d0 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" diff --git a/client/src/pages/people/Edit.js b/client/src/pages/people/Edit.js index 489754b436..8738b760ea 100644 --- a/client/src/pages/people/Edit.js +++ b/client/src/pages/people/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, diff --git a/client/src/pages/people/Form.js b/client/src/pages/people/Form.js index d901d868bd..1856625089 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" diff --git a/client/src/pages/people/Show.js b/client/src/pages/people/Show.js index ebd31ac8c8..15d507b27e 100644 --- a/client/src/pages/people/Show.js +++ b/client/src/pages/people/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 AssignPositionModal from "components/AssignPositionModal" import AvatarDisplayComponent from "components/AvatarDisplayComponent" diff --git a/client/src/pages/positions/Edit.js b/client/src/pages/positions/Edit.js index ae16ce59c3..4bfd0820cd 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, diff --git a/client/src/pages/positions/Form.js b/client/src/pages/positions/Form.js index 98b1c1f2a3..7f1ac68d23 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 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..d11cf805c3 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" diff --git a/client/src/pages/reports/Edit.js b/client/src/pages/reports/Edit.js index ce053a647a..96cacf824f 100644 --- a/client/src/pages/reports/Edit.js +++ b/client/src/pages/reports/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, diff --git a/client/src/pages/reports/Form.js b/client/src/pages/reports/Form.js index bea7a73e6e..aeae5ed907 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, 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/Show.js b/client/src/pages/reports/Show.js index 9e15764259..4516bc2aaf 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,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 { ReadonlyCustomFields } from "components/CustomFields" diff --git a/client/src/pages/rollup/Show.js b/client/src/pages/rollup/Show.js index 9c0752ddc8..878ed81058 100644 --- a/client/src/pages/rollup/Show.js +++ b/client/src/pages/rollup/Show.js @@ -1,10 +1,10 @@ +import { gql } from "@apollo/client" import "@blueprintjs/core/lib/css/blueprint.css" import { DateRangeInput } from "@blueprintjs/datetime" import "@blueprintjs/datetime/lib/css/blueprint-datetime.css" import { IconNames } from "@blueprintjs/icons" import { DEFAULT_PAGE_PROPS, DEFAULT_SEARCH_PROPS } from "actions" import API from "api" -import { gql } from "apollo-boost" import AppContext from "components/AppContext" import "components/BlueprintOverrides.css" import ButtonToggleGroup from "components/ButtonToggleGroup" diff --git a/client/src/pages/tasks/Edit.js b/client/src/pages/tasks/Edit.js index e324af3172..c2683e7109 100644 --- a/client/src/pages/tasks/Edit.js +++ b/client/src/pages/tasks/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, diff --git a/client/src/pages/tasks/Form.js b/client/src/pages/tasks/Form.js index 2312af4afb..ec2380a946 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, 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..2a5f1fb4ff 100644 --- a/client/src/pages/tasks/Show.js +++ b/client/src/pages/tasks/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 AssessmentResultsTable from "components/assessments/AssessmentResultsTable" diff --git a/client/src/utils_links.js b/client/src/utils_links.js index 20f1996ca3..7eb3709b4c 100644 --- a/client/src/utils_links.js +++ b/client/src/utils_links.js @@ -1,5 +1,5 @@ +import { gql } from "@apollo/client" import API from "api" -import { gql } from "apollo-boost" import LinkAnet from "components/editor/LinkAnet" import parse from "html-react-parser" import { PAGE_URLS } from "pages/util" diff --git a/client/yarn.lock b/client/yarn.lock index 58c179780b..838e34380b 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.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.0.0.tgz#d620fdd660e590920a3fcfed85b8602b74d3fe45" + integrity sha512-r9fYhjUpcwcvLJuNmJQlY1gkPyU08icXtekxY3ZNYMR5FUrml0QTIBHsgJTsVQX7HecNF+bPHJyrJhmv5O1jWQ== dependencies: - "@apollo/react-common" "^3.1.4" + "@types/zen-observable" "^0.8.0" + "@wry/context" "^0.5.2" "@wry/equality" "^0.1.9" + fast-json-stable-stringify "^2.0.0" + graphql-tag "^2.10.4" + 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" @@ -2533,10 +2533,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.23" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.23.tgz#676fa0883450ed9da0bb24156213636290892806" - integrity sha512-Z4U8yDAl5TFkmYsZdFPdjeMa57NOvnaf1tljHzhouaPEp7LCj2JKkejpI1ODviIAQuW4CcQmxkQ77rnLsOOoKw== +"@types/node@*": + version "14.0.12" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.12.tgz#9c1d8ffb8084e8936603a6122a7649e40e68e04b" + integrity sha512-/sjzehvjkkpvLpYtN6/2dv5kg41otMGuHQUt9T2aiAuIfleCQRQHXXzF1eAw/qkZTj5Kcf4JSTf7EIizHocy6Q== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -2952,15 +2952,14 @@ "@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": +"@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== @@ -3195,101 +3194,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" @@ -8140,7 +8044,7 @@ 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: +graphql-tag@^2.10.4: version "2.10.4" resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.10.4.tgz#2f301a98219be8b178a6453bb7e33b79b66d8f83" integrity sha512-O7vG5BT3w6Sotc26ybcvLKNTdfr4GfsIVMD+LdYqXCeJIYPRyp8BIsDOUtxw7S1PYvRw5vH3278J2EDezR6mfA== @@ -8354,7 +8258,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== @@ -11341,12 +11245,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" @@ -14338,7 +14242,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== @@ -14700,7 +14604,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== @@ -15735,15 +15639,7 @@ yup@0.29.1: synchronous-promise "^2.0.10" 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== From 7772f6c55941f0ac1e646a62dc690a8a711d8985 Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Wed, 15 Jul 2020 17:14:06 +0200 Subject: [PATCH 198/247] Fix Uncaught TypeError: First argument must be a string Error happened when parseHtmlWithLinkTo() was called with `undefined`. --- client/src/utils_links.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/src/utils_links.js b/client/src/utils_links.js index 7eb3709b4c..12531b5aa6 100644 --- a/client/src/utils_links.js +++ b/client/src/utils_links.js @@ -112,7 +112,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) { From 12117d1303348918a12ab46f11d8902f7895d979 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Wed, 15 Jul 2020 21:46:06 +0000 Subject: [PATCH 199/247] Update dependency @apollo/client to v3.0.1 --- client/package.json | 2 +- client/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/package.json b/client/package.json index 1955bfd364..acdebe1150 100644 --- a/client/package.json +++ b/client/package.json @@ -94,7 +94,7 @@ "xhr2": "0.2.0" }, "dependencies": { - "@apollo/client": "3.0.0", + "@apollo/client": "3.0.1", "@blueprintjs/core": "3.29.0", "@blueprintjs/datetime": "3.18.3", "@fullcalendar/core": "4.4.2", diff --git a/client/yarn.lock b/client/yarn.lock index de164753c3..93babd037b 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@apollo/client@3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.0.0.tgz#d620fdd660e590920a3fcfed85b8602b74d3fe45" - integrity sha512-r9fYhjUpcwcvLJuNmJQlY1gkPyU08icXtekxY3ZNYMR5FUrml0QTIBHsgJTsVQX7HecNF+bPHJyrJhmv5O1jWQ== +"@apollo/client@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.0.1.tgz#51ba7aedd0ee2415fedb582974bf73e4ea97755d" + integrity sha512-d+3f6ZhPPjnhRzUEHMUtaUfRKpx3cFE6QtLh8yuy0TH9phHuXx4CVWJHfnu8KfJ+MfcC3xiRcw4AaMHC2VwLnw== dependencies: "@types/zen-observable" "^0.8.0" "@wry/context" "^0.5.2" From b3bf676bb02fc05018608c4b6ba37da00407fb78 Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Wed, 15 Jul 2020 17:57:37 +0200 Subject: [PATCH 200/247] NCI-Agency/anet#3098: Replace with useContext() --- client/src/components/AssignPositionModal.js | 30 +- client/src/components/CreateButton.js | 18 +- .../EditAssociatedPositionsModal.js | 24 +- client/src/components/GuidedTour.js | 17 +- client/src/components/Nav.js | 28 +- client/src/components/RelatedObjectNotes.js | 19 +- client/src/components/SecurityBanner.js | 54 ++-- client/src/components/TopBar.js | 24 +- client/src/pages/Help.js | 35 +-- client/src/pages/Home.js | 14 +- client/src/pages/Routing.js | 282 +++++++++--------- client/src/pages/admin/Index.js | 17 +- .../pages/admin/authorizationgroup/Show.js | 24 +- client/src/pages/insights/Show.js | 23 +- client/src/pages/locations/Form.js | 22 +- client/src/pages/locations/Show.js | 21 +- client/src/pages/onboarding/Edit.js | 21 +- client/src/pages/organizations/Form.js | 22 +- client/src/pages/organizations/Laydown.js | 18 +- .../pages/organizations/OrganizationTasks.js | 23 +- client/src/pages/organizations/Show.js | 21 +- client/src/pages/people/Form.js | 32 +- client/src/pages/people/Show.js | 17 +- client/src/pages/positions/Form.js | 22 +- client/src/pages/positions/Show.js | 21 +- client/src/pages/reports/Form.js | 19 +- client/src/pages/reports/MyReports.js | 23 +- client/src/pages/reports/New.js | 17 +- client/src/pages/reports/Show.js | 16 +- client/src/pages/rollup/Show.js | 14 +- client/src/pages/tasks/Form.js | 20 +- client/src/pages/tasks/Show.js | 19 +- 32 files changed, 334 insertions(+), 643 deletions(-) diff --git a/client/src/components/AssignPositionModal.js b/client/src/components/AssignPositionModal.js index 8b2a1210ee..a563151955 100644 --- a/client/src/components/AssignPositionModal.js +++ b/client/src/components/AssignPositionModal.js @@ -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/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/EditAssociatedPositionsModal.js b/client/src/components/EditAssociatedPositionsModal.js index 642e627d9d..3e68e00896 100644 --- a/client/src/components/EditAssociatedPositionsModal.js +++ b/client/src/components/EditAssociatedPositionsModal.js @@ -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 @@ -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/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/Nav.js b/client/src/components/Nav.js index 54a68ebe9b..6986430e81 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 @@ -236,17 +235,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 +256,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/RelatedObjectNotes.js b/client/src/components/RelatedObjectNotes.js index 5b451a3ad5..d311b67660 100644 --- a/client/src/components/RelatedObjectNotes.js +++ b/client/src/components/RelatedObjectNotes.js @@ -15,7 +15,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 +33,13 @@ const GQL_DELETE_NOTE = gql` export { GRAPHQL_NOTES_FIELDS } from "components/Model" -const BaseRelatedObjectNotes = ({ - currentUser, +const RelatedObjectNotes = ({ notesElemId, relatedObject, relatedObjectValue, notes: notesProp }) => { + const { currentUser } = useContext(AppContext) const latestNotesProp = useRef(notesProp) const notesPropUnchanged = _isEqualWith( latestNotesProp.current, @@ -421,8 +421,7 @@ const BaseRelatedObjectNotes = ({ }) } } -BaseRelatedObjectNotes.propTypes = { - currentUser: PropTypes.instanceOf(Person), +RelatedObjectNotes.propTypes = { notesElemId: PropTypes.string.isRequired, notes: PropTypes.arrayOf(Model.notePropTypes), relatedObject: PropTypes.shape({ @@ -435,17 +434,9 @@ BaseRelatedObjectNotes.propTypes = { 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/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/pages/Help.js b/client/src/pages/Help.js index 966a7e260d..5a47659635 100644 --- a/client/src/pages/Help.js +++ b/client/src/pages/Help.js @@ -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 9167cc5853..881d5bb08a 100644 --- a/client/src/pages/Home.js +++ b/client/src/pages/Home.js @@ -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, @@ -401,7 +401,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 +473,8 @@ const BaseHome = ({ currentUser, setSearchQuery, pageDispatchers }) => { ) } -BaseHome.propTypes = { +Home.propTypes = { setSearchQuery: PropTypes.func.isRequired, - currentUser: PropTypes.instanceOf(Person), pageDispatchers: PageDispatchersPropType } @@ -486,10 +486,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..612d583504 100644 --- a/client/src/pages/Routing.js +++ b/client/src/pages/Routing.js @@ -1,5 +1,4 @@ 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" @@ -38,154 +37,149 @@ 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 }) => ( - - - - - - - ( - - - - - - - - )} - /> - ( - - - - - - )} - /> - ( - - - - - - )} - /> - ( - - - - - - )} - /> - ( - - - - - - )} - /> - ( - - - - - - )} - /> - ( - - - - - - - - - )} - /> - ( - - - - )} - /> - ( - - - - )} - /> - ( - - - - )} - /> - - currentUser.isNewUser() ? ( +const Routing = () => { + const { currentUser } = useContext(AppContext) + return ( + + + + + + + ( - - + + + + + - ) : ( - // 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/admin/Index.js b/client/src/pages/admin/Index.js index ccf1b7f220..40cc41c1a0 100644 --- a/client/src/pages/admin/Index.js +++ b/client/src/pages/admin/Index.js @@ -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/authorizationgroup/Show.js b/client/src/pages/admin/authorizationgroup/Show.js index ba995cad6a..ba1fa7da0b 100644 --- a/client/src/pages/admin/authorizationgroup/Show.js +++ b/client/src/pages/admin/authorizationgroup/Show.js @@ -17,9 +17,8 @@ import RelatedObjectNotes, { } from "components/RelatedObjectNotes" import ReportCollection 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 +52,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( @@ -146,20 +146,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/insights/Show.js b/client/src/pages/insights/Show.js index 6a20753d7a..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,12 +90,8 @@ 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", @@ -213,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) => ({ @@ -232,12 +227,4 @@ const mapDispatchToProps = (dispatch, ownProps) => { } } -const InsightsShow = props => ( - - {context => ( - - )} - -) - export default connect(mapStateToProps, mapDispatchToProps)(InsightsShow) diff --git a/client/src/pages/locations/Form.js b/client/src/pages/locations/Form.js index ec4e3fa0f1..125ed701a6 100644 --- a/client/src/pages/locations/Form.js +++ b/client/src/pages/locations/Form.js @@ -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 b9b34dc22e..993bf8cfa7 100644 --- a/client/src/pages/locations/Show.js +++ b/client/src/pages/locations/Show.js @@ -24,9 +24,8 @@ 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 +73,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, { @@ -177,17 +177,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 6222abe2e9..64a6c1cd3d 100644 --- a/client/src/pages/onboarding/Edit.js +++ b/client/src/pages/onboarding/Edit.js @@ -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/Form.js b/client/src/pages/organizations/Form.js index 6a1d1b2be3..617f95e04b 100644 --- a/client/src/pages/organizations/Form.js +++ b/client/src/pages/organizations/Form.js @@ -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/OrganizationTasks.js b/client/src/pages/organizations/OrganizationTasks.js index 5bec7160eb..b9f2d54867 100644 --- a/client/src/pages/organizations/OrganizationTasks.js +++ b/client/src/pages/organizations/OrganizationTasks.js @@ -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 cb28f0f3d0..ed7008a05f 100644 --- a/client/src/pages/organizations/Show.js +++ b/client/src/pages/organizations/Show.js @@ -25,11 +25,10 @@ import ReportCollection, { } from "components/ReportCollection" 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 React, { useContext, useState } from "react" import { ListGroup, ListGroupItem, Nav, Button } from "react-bootstrap" import { connect } from "react-redux" import { useLocation, useParams } from "react-router-dom" @@ -124,7 +123,8 @@ 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 { uuid } = useParams() @@ -418,23 +418,14 @@ const BaseOrganizationShow = ({ pageDispatchers, currentUser }) => { } } -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/Form.js b/client/src/pages/people/Form.js index 1856625089..0308380a7a 100644 --- a/client/src/pages/people/Form.js +++ b/client/src/pages/people/Form.js @@ -22,7 +22,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 +48,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) @@ -633,31 +627,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 15d507b27e..e780c0dbdf 100644 --- a/client/src/pages/people/Show.js +++ b/client/src/pages/people/Show.js @@ -30,8 +30,7 @@ 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" @@ -95,7 +94,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 [ @@ -526,15 +526,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/Form.js b/client/src/pages/positions/Form.js index 7f1ac68d23..a853d53796 100644 --- a/client/src/pages/positions/Form.js +++ b/client/src/pages/positions/Form.js @@ -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/Show.js b/client/src/pages/positions/Show.js index d11cf805c3..37cf47ef58 100644 --- a/client/src/pages/positions/Show.js +++ b/client/src/pages/positions/Show.js @@ -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 [ @@ -433,17 +433,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/Form.js b/client/src/pages/reports/Form.js index aeae5ed907..eb020ff849 100644 --- a/client/src/pages/reports/Form.js +++ b/client/src/pages/reports/Form.js @@ -41,7 +41,7 @@ import { AuthorizationGroup, Location, Person, Report, Task } from "models" import moment from "moment" 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" @@ -189,14 +189,14 @@ 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) @@ -1387,25 +1387,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/MyReports.js b/client/src/pages/reports/MyReports.js index 2bf5bb3be4..01778d8b0a 100644 --- a/client/src/pages/reports/MyReports.js +++ b/client/src/pages/reports/MyReports.js @@ -8,17 +8,15 @@ import { import ReportCollection 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] @@ -89,9 +87,8 @@ const BaseMyReports = ({ } } -BaseMyReports.propTypes = { +MyReports.propTypes = { pageDispatchers: PageDispatchersPropType, - currentUser: PropTypes.instanceOf(Person), searchQuery: SearchQueryPropType } @@ -99,10 +96,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..842185fa7f 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, @@ -50,15 +50,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 4516bc2aaf..c502939a13 100644 --- a/client/src/pages/reports/Show.js +++ b/client/src/pages/reports/Show.js @@ -34,7 +34,7 @@ import { Comment, Person, Position, Report } 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 +268,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) @@ -1299,10 +1300,9 @@ const BaseReportShow = ({ currentUser, setSearchQuery, pageDispatchers }) => { } } -BaseReportShow.propTypes = { +ReportShow.propTypes = { pageDispatchers: PageDispatchersPropType, - setSearchQuery: PropTypes.func.isRequired, - currentUser: PropTypes.instanceOf(Person) + setSearchQuery: PropTypes.func.isRequired } const mapDispatchToProps = (dispatch, ownProps) => { @@ -1313,10 +1313,4 @@ const mapDispatchToProps = (dispatch, ownProps) => { } } -const ReportShow = props => ( - - {context => } - -) - export default connect(null, mapDispatchToProps)(ReportShow) diff --git a/client/src/pages/rollup/Show.js b/client/src/pages/rollup/Show.js index 878ed81058..c4e00c24cb 100644 --- a/client/src/pages/rollup/Show.js +++ b/client/src/pages/rollup/Show.js @@ -30,7 +30,7 @@ import { Organization, Report } from "models" import moment from "moment" import pluralize from "pluralize" import PropTypes from "prop-types" -import React, { useMemo, useState } from "react" +import React, { useContext, useMemo, useState } from "react" import { Button, HelpBlock, Modal } from "react-bootstrap" import ContainerDimensions from "react-container-dimensions" import { connect } from "react-redux" @@ -252,7 +252,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 +649,7 @@ const BaseRollupShow = ({ pageDispatchers, appSettings, searchQuery }) => { } } -BaseRollupShow.propTypes = { - appSettings: PropTypes.object, +RollupShow.propTypes = { searchQuery: SearchQueryPropType, pageDispatchers: PageDispatchersPropType } @@ -658,10 +658,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/Form.js b/client/src/pages/tasks/Form.js index ec2380a946..9dae88752d 100644 --- a/client/src/pages/tasks/Form.js +++ b/client/src/pages/tasks/Form.js @@ -24,9 +24,9 @@ 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 +52,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 = [ @@ -533,22 +534,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/Show.js b/client/src/pages/tasks/Show.js index 2a5f1fb4ff..f44df7c792 100644 --- a/client/src/pages/tasks/Show.js +++ b/client/src/pages/tasks/Show.js @@ -20,10 +20,9 @@ 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 { Report, 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" @@ -137,7 +136,8 @@ const GQL_GET_TASK = gql` } ` -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, { @@ -386,15 +386,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) From 3c8ffd9b554132f7e118d02c0e555adf37a35b12 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Thu, 16 Jul 2020 20:42:29 +0000 Subject: [PATCH 201/247] Update dependency chromedriver to v84 --- client/package.json | 2 +- client/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/package.json b/client/package.json index acdebe1150..0c89847653 100644 --- a/client/package.json +++ b/client/package.json @@ -42,7 +42,7 @@ "cache-loader": "4.1.0", "chai": "4.2.0", "chalk": "4.1.0", - "chromedriver": "83.0.1", + "chromedriver": "84.0.0", "clean-webpack-plugin": "3.0.0", "colors": "1.4.0", "config": "3.3.1", diff --git a/client/yarn.lock b/client/yarn.lock index 93babd037b..8d4a340171 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -4815,10 +4815,10 @@ chrome-trace-event@^1.0.2: dependencies: tslib "^1.9.0" -chromedriver@83.0.1: - version "83.0.1" - resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-83.0.1.tgz#c4cf9b3f7076fea5e9ef787e65907cd035ffbd10" - integrity sha512-51/YsLIMRF+L0ooMlM4aZjyoOpDs0gDXGlT6+/CwWEnvK53PUyef9FkotKbzknCaUeL/qUw3ic3IMmsNc+SUxg== +chromedriver@84.0.0: + version "84.0.0" + resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-84.0.0.tgz#980d72bf0990bbfbce282074d15448296c55d89d" + integrity sha512-fNX9eT1C38D1W8r5ss9ty42eDK+GIkCZVKukfeDs0XSBeKfyT0o/vbMdPr9MUkWQ+vIcFAS5hFGp9E3+xoaMeQ== dependencies: "@testim/chrome-version" "^1.0.7" axios "^0.19.2" From 604b796797f857b0b4bc1b7a221d6f667dd3e3b4 Mon Sep 17 00:00:00 2001 From: vassil Date: Fri, 17 Jul 2020 02:45:47 +0200 Subject: [PATCH 202/247] nci-agency/anet#2954: Ensure that value in DefaultAggWidget is a string --- client/src/components/aggregations/DefaultAggWidget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/aggregations/DefaultAggWidget.js b/client/src/components/aggregations/DefaultAggWidget.js index 73a7cc913c..0de8a94d91 100644 --- a/client/src/components/aggregations/DefaultAggWidget.js +++ b/client/src/components/aggregations/DefaultAggWidget.js @@ -31,7 +31,7 @@ const DefaultAggWidget = ({ values, whenUnspecified, ...otherWidgetProps }) => { const keyValue = _uniqueId("value_") return (
- + ) })} From 50943a00304d4a3f933399f07c0dec4b847d03f9 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sat, 18 Jul 2020 19:17:44 +0000 Subject: [PATCH 203/247] Update most non-major dependencies --- build.gradle | 2 +- client/package.json | 22 ++-- client/yarn.lock | 249 ++++++++++++++++++++++++-------------------- 3 files changed, 146 insertions(+), 127 deletions(-) diff --git a/build.gradle b/build.gradle index afb89f9a96..8810aba537 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { id "org.kordamp.markdown.convert" version "1.2.0" - id "com.bmuschko.docker-remote-api" version "6.5.0" + id "com.bmuschko.docker-remote-api" version "6.6.0" id "com.github.node-gradle.node" version "2.2.4" id "com.diffplug.spotless" version "5.1.0" } diff --git a/client/package.json b/client/package.json index acdebe1150..994d968b34 100644 --- a/client/package.json +++ b/client/package.json @@ -27,11 +27,11 @@ "@storybook/addon-actions": "5.3.19", "@storybook/react": "5.3.19", "@wdio/browserstack-service": "6.1.15", - "@wdio/cli": "6.2.0", - "@wdio/local-runner": "6.2.0", - "@wdio/mocha-framework": "6.2.0", - "@wdio/spec-reporter": "6.1.23", - "@wdio/sync": "6.2.0", + "@wdio/cli": "6.3.3", + "@wdio/local-runner": "6.3.3", + "@wdio/mocha-framework": "6.3.0", + "@wdio/spec-reporter": "6.3.0", + "@wdio/sync": "6.3.3", "aigle": "1.14.1", "autoprefixer": "9.8.5", "ava": "3.10.1", @@ -47,12 +47,12 @@ "colors": "1.4.0", "config": "3.3.1", "copy-webpack-plugin": "6.0.3", - "countries-list": "2.5.4", + "countries-list": "2.5.5", "cross-fetch": "3.0.5", "cross-spawn": "7.0.3", "css-loader": "3.6.0", "dotenv": "8.2.0", - "eslint": "7.4.0", + "eslint": "7.5.0", "eslint-config-react-app": "5.2.1", "eslint-config-standard": "14.1.1", "eslint-config-standard-react": "9.2.0", @@ -86,7 +86,7 @@ "style-loader": "1.2.1", "thread-loader": "2.1.3", "wdio-chromedriver-service": "6.0.3", - "webdriverio": "6.2.0", + "webdriverio": "6.3.3", "webpack": "4.43.0", "webpack-cli": "3.3.12", "webpack-dev-server": "3.11.0", @@ -94,9 +94,9 @@ "xhr2": "0.2.0" }, "dependencies": { - "@apollo/client": "3.0.1", - "@blueprintjs/core": "3.29.0", - "@blueprintjs/datetime": "3.18.3", + "@apollo/client": "3.0.2", + "@blueprintjs/core": "3.30.0", + "@blueprintjs/datetime": "3.18.4", "@fullcalendar/core": "4.4.2", "@fullcalendar/daygrid": "4.4.2", "@fullcalendar/interaction": "4.4.2", diff --git a/client/yarn.lock b/client/yarn.lock index 93babd037b..ef8ad820c8 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@apollo/client@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.0.1.tgz#51ba7aedd0ee2415fedb582974bf73e4ea97755d" - integrity sha512-d+3f6ZhPPjnhRzUEHMUtaUfRKpx3cFE6QtLh8yuy0TH9phHuXx4CVWJHfnu8KfJ+MfcC3xiRcw4AaMHC2VwLnw== +"@apollo/client@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.0.2.tgz#fadb2b39a0e32950baaef2566442cb3f6de74a52" + integrity sha512-4ighan5Anlj4tK/tdUHs4Mi1njqXZ7AxRCVolz/H702DjPphAJfm+FRkIadPTmwz+OLO+d+tX+6V1VBshf02rg== dependencies: "@types/zen-observable" "^0.8.0" "@wry/context" "^0.5.2" @@ -1403,10 +1403,10 @@ 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.0", "@blueprintjs/core@^3.30.0": + version "3.30.0" + resolved "https://registry.yarnpkg.com/@blueprintjs/core/-/core-3.30.0.tgz#d847e451741735a7b11216fb3ec1c669f201bb90" + integrity sha512-/fBhPmQ1AJ7ATGzA9YBlnxN8KV7PjNeW9KL+IOWiERUNcF9kuiuKJ88hTs7gSSHNtHmCF+jheD+X0MQq4WYVjA== dependencies: "@blueprintjs/icons" "^3.19.0" "@types/dom4" "^2.0.1" @@ -1420,12 +1420,12 @@ 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.4": + version "3.18.4" + resolved "https://registry.yarnpkg.com/@blueprintjs/datetime/-/datetime-3.18.4.tgz#1fbb4792c4b4bc8319c57434e5c2ee95c18fc189" + integrity sha512-Rk52JS3mwbH8xyqdiGiIKthfoN9i9Uq5tgFfle/frFgdLpOTs9RfETbHeCCDeOtf2h0Lan6hqcmz5/LMtPZhtA== dependencies: - "@blueprintjs/core" "^3.29.0" + "@blueprintjs/core" "^3.30.0" classnames "^2.2" react-day-picker "7.3.2" react-lifecycles-compat "^3.0.4" @@ -2662,6 +2662,13 @@ 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" @@ -2785,14 +2792,14 @@ browserstack-local "^1.4.5" got "^11.0.2" -"@wdio/cli@6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@wdio/cli/-/cli-6.2.0.tgz#2913ad646c921a06cda916f98870ce74c9af9b76" - integrity sha512-5d0efFQBdGLNQR4R/dBxpPzSXCY68T9dDw1FcdltTb/kn9CW27/YzaPUBY60d4qIXTQufmUFBaJmkiRnJGtjZw== +"@wdio/cli@6.3.3": + version "6.3.3" + resolved "https://registry.yarnpkg.com/@wdio/cli/-/cli-6.3.3.tgz#59313cb4fabbaeb1adb2ec7e0867f4cc127ab463" + integrity sha512-WCfBgclhRBu4RQF0Low4zVPBovhduQPe5e1OnhgOzRHb+cYPNoFXszfDp4/J7cXcbxP/d0jYIyaWvmVnosv/Qg== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" - "@wdio/utils" "6.2.0" + "@wdio/utils" "6.3.0" async-exit-hook "^2.0.1" chalk "^4.0.0" chokidar "^3.0.0" @@ -2805,7 +2812,7 @@ lodash.union "^4.6.0" mkdirp "^1.0.4" recursive-readdir "^2.2.2" - webdriverio "6.2.0" + webdriverio "6.3.3" yargs "^15.0.1" yarn-install "^1.0.0" @@ -2818,14 +2825,14 @@ deepmerge "^4.0.0" glob "^7.1.2" -"@wdio/local-runner@6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@wdio/local-runner/-/local-runner-6.2.0.tgz#3057165c819e6fcbaa4b81b38a495c6f8ae75a38" - integrity sha512-fbki4EbwAKAnMrTWYzPHnPDPBVLZQlbNfJdC7iOtlcpLktDe29e9ARnfv8R4EkCjGqeenFAtgRwYSvBXucehrw== +"@wdio/local-runner@6.3.3": + version "6.3.3" + resolved "https://registry.yarnpkg.com/@wdio/local-runner/-/local-runner-6.3.3.tgz#9c99d56f91b93d136ffd9ff80b2304db94fcc26c" + integrity sha512-InmfCZpVWuuZ2eIZ/oiROkmk0drqcGp6quRH8ZWEeLVsHbLcbSTrVtbBsgcRbHQ5P/znLficnNTWuGTuWGL21A== dependencies: "@wdio/logger" "6.0.16" - "@wdio/repl" "6.2.0" - "@wdio/runner" "6.2.0" + "@wdio/repl" "6.3.0" + "@wdio/runner" "6.3.3" async-exit-hook "^2.0.1" stream-buffers "^3.0.2" @@ -2839,70 +2846,71 @@ loglevel-plugin-prefix "^0.8.4" strip-ansi "^6.0.0" -"@wdio/mocha-framework@6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@wdio/mocha-framework/-/mocha-framework-6.2.0.tgz#c4f2b34b32e8a47ca5fb7bee3cacb9ccceebdc92" - integrity sha512-QbSav4vn2zQcKTkTr0LXhsQP7uWbt45r81KGHIDUdXy1Q3i0loz9E3OJQreZqfGtz1nYwjdxs4C5jJCBuShJSw== +"@wdio/mocha-framework@6.3.0": + version "6.3.0" + resolved "https://registry.yarnpkg.com/@wdio/mocha-framework/-/mocha-framework-6.3.0.tgz#c0e99f5291675e35b7d6bff4cb9e099056b9d5a4" + integrity sha512-3lLvzhDYWwOYmiJAjr2fm/nENq6g6uUOtkIeEQFp1kDyBQkDsH1PXGdFklQbRiQT8mAqOPhx1kvXrCA/XpWl7g== dependencies: "@wdio/logger" "6.0.16" - "@wdio/utils" "6.2.0" + "@wdio/utils" "6.3.0" expect-webdriverio "^1.1.5" mocha "^8.0.1" -"@wdio/protocols@6.1.25": - version "6.1.25" - resolved "https://registry.yarnpkg.com/@wdio/protocols/-/protocols-6.1.25.tgz#a5059fce8eb070610792708b228b5e53831d1f33" - integrity sha512-C84qqh5J6nE1zTjwF3svDUah3FvoUzMUGeRe8w//QPBcJIGNRgmVLgeFV7Cp2EwI5ag+BUfXExQ0bFtcZYHIVA== +"@wdio/protocols@6.3.0": + version "6.3.0" + resolved "https://registry.yarnpkg.com/@wdio/protocols/-/protocols-6.3.0.tgz#9dfd37c0e34919977d3e76747f3e530435a05f23" + integrity sha512-1GKzfyCTLW5WkFd3W7NLACih+zNWU7c8kFurbCQXDK1ko1obqJEs7ZjBr85q5XqMWburdks5rDjyml2iEB2LBg== -"@wdio/repl@6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@wdio/repl/-/repl-6.2.0.tgz#3edb83f9b310e007c87cddb31b265ec4404d48a7" - integrity sha512-63yuCBCLrTC1D5uk6wJ6D3lyhi5i3Dvj8sQuqSma66c+xYPQRNA/Jp6V+43CsnOzUDLvhliSjCanrl3/i2sOcg== +"@wdio/repl@6.3.0": + version "6.3.0" + resolved "https://registry.yarnpkg.com/@wdio/repl/-/repl-6.3.0.tgz#6f85abbff97fbb7ce216026fe91c1795019260d9" + integrity sha512-FT3flKOqNdZNG1uYl+QpOfdZIgKAWhLfoQ0s+wL0crLeDNIFvvM2qSDhRBRDYV7a0IFyBi8Z975WBn0dlH03Ig== dependencies: - "@wdio/utils" "6.2.0" + "@wdio/utils" "6.3.0" -"@wdio/reporter@6.1.23": - version "6.1.23" - resolved "https://registry.yarnpkg.com/@wdio/reporter/-/reporter-6.1.23.tgz#d4781cbf4ede1dfded91053dcafd8777a1d4bf6b" - integrity sha512-9OmAd6X/g6lpjNkA/sEPc28prCUCZKxbmoapzgaMrp7mNsb0Wmi2UDCWKvTVwldloQON7A98qQTrHr+k9GcL1w== +"@wdio/reporter@6.3.0": + version "6.3.0" + resolved "https://registry.yarnpkg.com/@wdio/reporter/-/reporter-6.3.0.tgz#485eb8c65a53267ebf83579170695e1edb834168" + integrity sha512-vbwjJvSKZUtsWtQMhuVqT7ZP6RIFAH4+ienjNwW30QPDi38OujZgxC2ZqRoZKsxck6cfTgkxrXfNaxHN0/LHKg== dependencies: fs-extra "^9.0.0" -"@wdio/runner@6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@wdio/runner/-/runner-6.2.0.tgz#394a145499b8d671febeafe42f1c6d3abdd26ba5" - integrity sha512-LqPJca5bfrhHPfMIDFxAepfCEMzLTW0NjUHqTgSHDZGq3HVhe9TC/NyBNcNak2qsAr25gdcOi4KG2oZN+hCZHw== +"@wdio/runner@6.3.3": + version "6.3.3" + resolved "https://registry.yarnpkg.com/@wdio/runner/-/runner-6.3.3.tgz#1672ffcde898d6dc5c3ea8c1c2433cbdb51a3511" + integrity sha512-2LfgFV86FakXFVTdT8y7TMCCduzjyNOsugvn2VoCyuViq4apAwpbC3MD9LQqcDMIVhU9NMSjgZC3acDetkWcJQ== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" - "@wdio/utils" "6.2.0" + "@wdio/utils" "6.3.0" deepmerge "^4.0.0" gaze "^1.1.2" - webdriver "6.2.0" - webdriverio "6.2.0" + webdriver "6.3.0" + webdriverio "6.3.3" -"@wdio/spec-reporter@6.1.23": - version "6.1.23" - resolved "https://registry.yarnpkg.com/@wdio/spec-reporter/-/spec-reporter-6.1.23.tgz#e95c081a5711412afbd41388a85f7a263520f8a7" - integrity sha512-QA6gbrmnV0xWXB5mp86XXSKVgoR75M/euloVxJsIgFAXCfDdh1txUfmzW2wbjRrkv+XSSFKUFBAaHNwcvuWiFQ== +"@wdio/spec-reporter@6.3.0": + version "6.3.0" + resolved "https://registry.yarnpkg.com/@wdio/spec-reporter/-/spec-reporter-6.3.0.tgz#2b24d5845f614720f74bca85b0f0eb3222e6d98e" + integrity sha512-JGZAMcqiOloOw6xcIT5O8GORVaww6kslgH5kZGydVQyoNBj1ZKoLdEjqq2jklJsge1xsscdYdW9u9kMHwm25iA== dependencies: - "@wdio/reporter" "6.1.23" + "@wdio/reporter" "6.3.0" chalk "^4.0.0" easy-table "^1.1.1" pretty-ms "^7.0.0" -"@wdio/sync@6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@wdio/sync/-/sync-6.2.0.tgz#c1b390d552f15f47df1ff3d20bc6628da00856b4" - integrity sha512-b3iMiNrY0vkpyPZ81UFDX/QqH5OPzvETHUdYhj9st1/3OkAeLd07jjTEqD68RheUp6PxxXE8Gpnm8n4ywRKGhg== +"@wdio/sync@6.3.3": + version "6.3.3" + resolved "https://registry.yarnpkg.com/@wdio/sync/-/sync-6.3.3.tgz#87fefb571132b4b62c96a9f42ac44f9586c1e716" + integrity sha512-WNq+hhkgk9LluKLP2nQ/9+EH8HNQnROFFHvYuznxb1aKj/zhZvqWuQPpmMWhPMBSTpkdbdLCYerZWKcamYOcJQ== dependencies: + "@types/puppeteer" "^3.0.1" "@wdio/logger" "6.0.16" fibers "^4.0.1" -"@wdio/utils@6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@wdio/utils/-/utils-6.2.0.tgz#8aa23ecbab9374aa6c80d54c37f6d88caa25d613" - integrity sha512-nPx430WPtZts09pcFwkTMO3zm6F7qvPuOcbvCschSW6ay8ebBvS6lkKnAHxCjrslsIF8+lOESuF0QrWycoouRA== +"@wdio/utils@6.3.0": + version "6.3.0" + resolved "https://registry.yarnpkg.com/@wdio/utils/-/utils-6.3.0.tgz#cc2caad78407a837b9aa070f5c656a5bcb129eef" + integrity sha512-PbeC5fpieamgSAHf7S58MAyraGU1qKxnHdfGMG+ZIWiIo73oo4j/57CcH6ZawQ3YC1wEc/5q+VXg7N5hvqhJOQ== dependencies: "@wdio/logger" "6.0.16" @@ -3111,7 +3119,7 @@ acorn@^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, acorn@^7.3.1: +acorn@^7.1.1, acorn@^7.3.1: version "7.3.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd" integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA== @@ -5384,10 +5392,10 @@ 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.5: + version "2.5.5" + resolved "https://registry.yarnpkg.com/countries-list/-/countries-list-2.5.5.tgz#cb463afc63563fc979e8fa5dbcf0caed16ec36f4" + integrity sha512-FzK1aF50WWNUyrbeOCt+QAUXX/HmnQVJtRwh4GJV7lUmBevbnT+m6+uiGM+M1mC9VvR3plQVAK8d3FxSqQPy8w== crc32-stream@^3.0.1: version "3.0.1" @@ -6160,17 +6168,22 @@ detect-port@^1.3.0: address "^1.0.1" debug "^2.6.0" -devtools@6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/devtools/-/devtools-6.2.0.tgz#c373c0970857ed675efe4ac8c918264bd73ca085" - integrity sha512-PmDKnIlDdP5+b6VurEnrIiLdzpSuWeWfge8tXJWjvFPhoqvwzdw4j5YSFo/QRWusS37Mk/j/rNUUawYP0u/ZKg== +devtools-protocol@0.0.767361: + version "0.0.767361" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.767361.tgz#5977f2558b84f9df36f62501bdddb82f3ae7b66b" + integrity sha512-ziRTdhEVQ9jEwedaUaXZ7kl9w9TF/7A3SXQ0XuqrJB+hMS62POHZUWTbumDN2ehRTfvWqTPc2Jw4gUl/jggmHA== + +devtools@6.3.3: + version "6.3.3" + resolved "https://registry.yarnpkg.com/devtools/-/devtools-6.3.3.tgz#4bc206e95026b27b64487f7e0e4afe5dc3adc91e" + integrity sha512-VHvJH7y2/pHtDzhXF8T9mlT5sqrUl2WSjCWhjvyohTyfMjtIu15p78lx3NowMwfo12N2/3riW9dVGeVOa6WILQ== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" - "@wdio/protocols" "6.1.25" - "@wdio/utils" "6.2.0" + "@wdio/protocols" "6.3.0" + "@wdio/utils" "6.3.0" 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" @@ -6936,22 +6949,22 @@ eslint-scope@^5.1.0: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-utils@^2.0.0: +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: +eslint-visitor-keys@^1.0.0, 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.4.0: - version "7.4.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.4.0.tgz#4e35a2697e6c1972f9d6ef2b690ad319f80f206f" - integrity sha512-gU+lxhlPHu45H3JkEGgYhWhkR9wLHHEXC9FbWFnTlEkbKyZKWgWRLgf61E8zWmBuI6g5xKBph9ltg3NtZMVF8g== +eslint@7.5.0: + version "7.5.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.5.0.tgz#9ecbfad62216d223b82ac9ffea7ef3444671d135" + integrity sha512-vlUP10xse9sWt9SGRtcr1LAC67BENcQMFeV+w5EvLEoFe3xJ8cF1Skd0msziRx/VMC+72B4DxreCE+OR12OA6Q== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.10.0" @@ -6961,9 +6974,9 @@ eslint@7.4.0: 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" @@ -6977,7 +6990,7 @@ eslint@7.4.0: 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" @@ -6990,14 +7003,14 @@ eslint@7.4.0: 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" @@ -7830,6 +7843,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" @@ -10812,11 +10830,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" @@ -12221,16 +12234,17 @@ pupa@^2.0.1: dependencies: escape-goat "^2.0.0" -puppeteer-core@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-4.0.1.tgz#d6026add5fe058de22cd80879967eaa5e9be4cfb" - integrity sha512-8OfHmUkEXU/k7Bmcdm6KRWhIIfmayv/ce1AUDkP0nTLK2IpjulFggxq1dZhWgWHXebeLILbieMvAor7tSf3EqQ== +puppeteer-core@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-5.2.0.tgz#d5474cfb0814440dfe36b949f40fcaa8885b7ae4" + integrity sha512-+gG1mW4ve7e4f1H18KWyEdbSc5Sb9+zxGBlb6CCclCf5rDsuPhYubTfOWJZB4L759D4XDtf04GOp+lmTmd61Nw== dependencies: debug "^4.1.0" + devtools-protocol "0.0.767361" 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" @@ -15248,39 +15262,44 @@ wdio-chromedriver-service@6.0.3: dependencies: fs-extra "^9.0.0" -webdriver@6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/webdriver/-/webdriver-6.2.0.tgz#333983ae0b5aee4c39bcf6202b8b60a92edace0b" - integrity sha512-8jcuMK0ygfVT0ySImE89TD79rmYzvKS3ImG/+xvS9CUzrlYJpXTos8OTM962YaqkX/nEiGlT4HdV+4SH1J27WQ== +webdriver@6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/webdriver/-/webdriver-6.3.0.tgz#c401a5648ca9434073eda017faf2689a475d38af" + integrity sha512-osHp5DX8eQ76Sy6/UYoECmDnUXwLhy5tlBeJh86er7S04FLAlmEqCvYXgxTSb8YtDjh9Xt9gP768RGhxR7ik5A== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" - "@wdio/protocols" "6.1.25" - "@wdio/utils" "6.2.0" + "@wdio/protocols" "6.3.0" + "@wdio/utils" "6.3.0" got "^11.0.2" lodash.merge "^4.6.1" -webdriverio@6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/webdriverio/-/webdriverio-6.2.0.tgz#85c9ba83b0ab61e4b056cefe07a65b3be5f1463a" - integrity sha512-TpikNm7Glm9qqWfvVbO5u9BbmDpPULI1PsJG9eDgL8eP7QoDsJs3gYwAizoBZlcRB9u/m8PESN/+B5H14NCvkA== +webdriverio@6.3.3: + version "6.3.3" + resolved "https://registry.yarnpkg.com/webdriverio/-/webdriverio-6.3.3.tgz#edb46aaf42a92b64996f135b0e66ee4066c0ebac" + integrity sha512-/ahCs6sna4M+/GZ5RPh5LLTEzfh5+gJD0vOpmA4nmarpKjqnfuwtqTETjmQCfqKTjiLVwzqShnsAedbYuw9Q2g== dependencies: + "@types/puppeteer" "^3.0.1" "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" - "@wdio/repl" "6.2.0" - "@wdio/utils" "6.2.0" + "@wdio/repl" "6.3.0" + "@wdio/utils" "6.3.0" archiver "^4.0.1" + atob "^2.1.2" css-value "^0.0.1" - devtools "6.2.0" + devtools "6.3.3" + 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.2.0" + webdriver "6.3.0" webidl-conversions@^5.0.0: version "5.0.0" From 7f52d9a3c508496d3aed2e7beaf71774e3e99984 Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Mon, 20 Jul 2020 14:55:15 +0200 Subject: [PATCH 204/247] Remove unused import --- src/main/java/mil/dds/anet/resources/GraphQlResource.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/mil/dds/anet/resources/GraphQlResource.java b/src/main/java/mil/dds/anet/resources/GraphQlResource.java index 6537f28596..b18f063043 100644 --- a/src/main/java/mil/dds/anet/resources/GraphQlResource.java +++ b/src/main/java/mil/dds/anet/resources/GraphQlResource.java @@ -7,7 +7,6 @@ import graphql.ExecutionResult; import graphql.GraphQL; import graphql.GraphQLError; -import graphql.schema.GraphQLCodeRegistry; import graphql.schema.GraphQLSchema; import graphql.schema.visibility.NoIntrospectionGraphqlFieldVisibility; import io.dropwizard.auth.Auth; From eb8b658601af33945c48f0278eb06fcaa0b8ebaa Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Mon, 20 Jul 2020 14:59:20 +0200 Subject: [PATCH 205/247] Simplify code --- src/main/java/mil/dds/anet/utils/Utils.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/mil/dds/anet/utils/Utils.java b/src/main/java/mil/dds/anet/utils/Utils.java index 494027e363..6811c58580 100644 --- a/src/main/java/mil/dds/anet/utils/Utils.java +++ b/src/main/java/mil/dds/anet/utils/Utils.java @@ -247,9 +247,7 @@ private static void internalSanitizeJsonForHtml(JsonNode jsonNode) { final ArrayNode arrayNode = (ArrayNode) jsonNode; for (int i = 0; i < arrayNode.size(); i++) { if (arrayNode.get(i).isTextual()) { - final String sanitizedValue = sanitizeHtml(arrayNode.get(i).asText()); - arrayNode.remove(i); - arrayNode.insert(i, sanitizedValue); + arrayNode.set(i, arrayNode.textNode(sanitizeHtml(arrayNode.get(i).asText()))); } else { internalSanitizeJsonForHtml(arrayNode.get(i)); } From 55d22e7f76e7ff892786ba8e53cb2f7dbc5e2131 Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Mon, 20 Jul 2020 15:42:22 +0200 Subject: [PATCH 206/247] Fix `null` errors in JSON.parse() --- client/src/pages/reports/Form.js | 13 ++++++++----- client/src/pages/reports/Show.js | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/client/src/pages/reports/Form.js b/client/src/pages/reports/Form.js index eb020ff849..df3064a4c2 100644 --- a/client/src/pages/reports/Form.js +++ b/client/src/pages/reports/Form.js @@ -334,10 +334,13 @@ const ReportForm = ({ reportTasks .filter(t => t.customFields) .forEach(t => { - taskAssessmentsSchemaShape[t.uuid] = createYupObjectShape( - JSON.parse(JSON.parse(t.customFields).assessmentDefinition), - `taskAssessments.${t.uuid}` - ) + const taskCustomFields = JSON.parse(t.customFields) + if (taskCustomFields?.assessmentDefinition) { + taskAssessmentsSchemaShape[t.uuid] = createYupObjectShape( + JSON.parse(taskCustomFields.assessmentDefinition), + `taskAssessments.${t.uuid}` + ) + } }) const reportSchema = _isEmpty(taskAssessmentsSchemaShape) ? Report.yupSchema @@ -1073,7 +1076,7 @@ const ReportForm = ({ return null } const taskCustomFields = JSON.parse(task.customFields) - if (!taskCustomFields.assessmentDefinition) { + if (!taskCustomFields?.assessmentDefinition) { return null } const taskAssessmentDefinition = JSON.parse( diff --git a/client/src/pages/reports/Show.js b/client/src/pages/reports/Show.js index c502939a13..749fec06a1 100644 --- a/client/src/pages/reports/Show.js +++ b/client/src/pages/reports/Show.js @@ -663,7 +663,7 @@ const ReportShow = ({ setSearchQuery, pageDispatchers }) => { return null } const taskCustomFields = JSON.parse(task.customFields) - if (!taskCustomFields.assessmentDefinition) { + if (!taskCustomFields?.assessmentDefinition) { return null } const taskAssessmentDefinition = JSON.parse( From e37295bd8874eab163d712f10ec6a02a49df0445 Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Mon, 20 Jul 2020 15:42:56 +0200 Subject: [PATCH 207/247] Only call JSON.parse() on non-text notes --- client/src/pages/tasks/Show.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/client/src/pages/tasks/Show.js b/client/src/pages/tasks/Show.js index f44df7c792..70a2b8af22 100644 --- a/client/src/pages/tasks/Show.js +++ b/client/src/pages/tasks/Show.js @@ -8,6 +8,7 @@ import * as FieldHelper from "components/FieldHelper" import Fieldset from "components/Fieldset" import LinkTo from "components/LinkTo" import Messages from "components/Messages" +import { NOTE_TYPE } from "components/Model" import { mapPageDispatchersToProps, PageDispatchersPropType, @@ -160,14 +161,22 @@ const TaskShow = ({ pageDispatchers }) => { 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.notes.forEach( + note => + note.type !== NOTE_TYPE.FREE_TEXT && + (note.customFields = JSON.parse(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 = JSON.parse(note.text)) + ) // TODO: Maybe move this code to Task() subTasks.push(new Task(subTask)) }) From faab8d1600c773a4bb1806aa0c9a5018a65e4e93 Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Mon, 20 Jul 2020 15:46:15 +0200 Subject: [PATCH 208/247] Update to latest json-sanitizer --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 72a940520d..d505e954f5 100644 --- a/build.gradle +++ b/build.gradle @@ -89,7 +89,7 @@ dependencies { 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:20200713.1' - implementation 'com.mikesamuel:json-sanitizer:1.2.0' + implementation 'com.mikesamuel:json-sanitizer:1.2.1' // Used for converting GraphQL request output to XML: implementation 'com.github.javadev:underscore-lodash:1.26' From e5ec29b358adbb7eca9262651c9ddbe447e5bc94 Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Tue, 21 Jul 2020 08:49:27 +0200 Subject: [PATCH 209/247] Refactor HTML testcases in preparation for JSON tests --- .../test/resources/PersonResourceTest.java | 8 +-- .../test/resources/ReportsResourceTest.java | 20 ++++--- .../java/mil/dds/anet/utils/UtilsTest.java | 56 ++++++++++--------- 3 files changed, 46 insertions(+), 38 deletions(-) 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..b79e518f4f 100644 --- a/src/test/java/mil/dds/anet/test/resources/PersonResourceTest.java +++ b/src/test/java/mil/dds/anet/test/resources/PersonResourceTest.java @@ -67,7 +67,7 @@ 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()); newPerson.setGender("Female"); newPerson.setCountry("Canada"); newPerson.setCode("123456"); @@ -81,7 +81,7 @@ 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()); newPerson.setName("testCreatePerson updated name"); newPerson.setCountry("The Commonwealth of Canada"); @@ -93,7 +93,7 @@ public void testCreatePerson() throws IOException { newPerson.setAvatar(defaultAvatarData); // update HTML of biography - newPerson.setBiography(UtilsTest.getCombinedTestCase().getInput()); + newPerson.setBiography(UtilsTest.getCombinedHtmlTestCase().getInput()); Integer nrUpdated = graphQLHelper.updateObject(admin, "updatePerson", "person", "PersonInput", newPerson); @@ -105,7 +105,7 @@ 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()); // Test creating a person with a position already set. final OrganizationSearchQuery query = new OrganizationSearchQuery(); 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 f06e98c8b3..4299d34304 100644 --- a/src/test/java/mil/dds/anet/test/resources/ReportsResourceTest.java +++ b/src/test/java/mil/dds/anet/test/resources/ReportsResourceTest.java @@ -270,7 +270,7 @@ 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()); 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 +285,7 @@ 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()); // Have the author submit the report Report submitted = graphQLHelper.updateObject(author, "submitReport", "uuid", FIELDS, "String", @@ -693,7 +693,7 @@ 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()); returned.setAttendees(ImmutableList.of(PersonTest.personToPrimaryReportPerson(roger), PersonTest.personToReportPerson(nick), PersonTest.personToPrimaryReportPerson(elizabeth))); returned.setTasks(ImmutableList.of()); @@ -711,7 +711,8 @@ 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()); // Elizabeth submits the report Report submitted = graphQLHelper.updateObject(elizabeth, "submitReport", "uuid", FIELDS, @@ -1468,7 +1469,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 +1481,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, diff --git a/src/test/java/mil/dds/anet/utils/UtilsTest.java b/src/test/java/mil/dds/anet/utils/UtilsTest.java index aadfc4bb98..8041def574 100644 --- a/src/test/java/mil/dds/anet/utils/UtilsTest.java +++ b/src/test/java/mil/dds/anet/utils/UtilsTest.java @@ -10,12 +10,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 +39,19 @@ public void setOutput(String output) { } } - private static List testCases = new ArrayList<>(); + public static InOut getCombinedHtmlTestCase() { + return getCombinedTestCase(getHtmlTestCases()); + } - 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,44 +61,49 @@ 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()); } From 5e91600cae30e51db1b53df3e906b37f371a28a9 Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Tue, 21 Jul 2020 09:19:26 +0200 Subject: [PATCH 210/247] Add some JSON sanitization testcases --- src/test/java/mil/dds/anet/test/TestData.java | 7 ++++ .../test/resources/PersonResourceTest.java | 13 ++++++- .../test/resources/ReportsResourceTest.java | 13 ++++++- .../anet/test/resources/TaskResourceTest.java | 17 ++++++-- .../java/mil/dds/anet/utils/UtilsTest.java | 39 +++++++++++++++++++ 5 files changed, 84 insertions(+), 5 deletions(-) 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/PersonResourceTest.java b/src/test/java/mil/dds/anet/test/resources/PersonResourceTest.java index b79e518f4f..375a8134be 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 @@ -68,6 +69,8 @@ public void testCreatePerson() throws IOException { newPerson.setStatus(PersonStatus.ACTIVE); // set HTML of biography newPerson.setBiography(UtilsTest.getCombinedHtmlTestCase().getInput()); + // set JSON of customFields + newPerson.setCustomFields(UtilsTest.getCombinedJsonTestCase().getInput()); newPerson.setGender("Female"); newPerson.setCountry("Canada"); newPerson.setCode("123456"); @@ -82,6 +85,9 @@ public void testCreatePerson() throws IOException { assertThat(newPerson.getName()).isEqualTo("testCreatePerson Person"); // check that HTML of biography is sanitized after create 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"); @@ -94,6 +100,8 @@ public void testCreatePerson() throws IOException { // update HTML of biography newPerson.setBiography(UtilsTest.getCombinedHtmlTestCase().getInput()); + // update JSON of customFields + newPerson.setCustomFields(UtilsTest.getCombinedJsonTestCase().getInput()); Integer nrUpdated = graphQLHelper.updateObject(admin, "updatePerson", "person", "PersonInput", newPerson); @@ -106,6 +114,9 @@ public void testCreatePerson() throws IOException { assertThat(retPerson.getAvatar()).isNotNull(); // check that HTML of biography is sanitized after update 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(); 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 4299d34304..96f3748347 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); @@ -271,6 +272,8 @@ public void createReport() { r.setIntent("A testing report to test that reporting reports"); // set HTML of report text 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); @@ -286,6 +289,9 @@ public void createReport() { assertThat(created.getPrincipalOrgUuid()).isEqualTo(principalOrg.getUuid()); // check that HTML of report text is sanitized after create assertThat(created.getReportText()).isEqualTo(UtilsTest.getCombinedHtmlTestCase().getOutput()); + // check that JSON of customFields is sanitized after create + assertThat(created.getCustomFields()) + .isEqualTo(UtilsTest.getCombinedJsonTestCase().getOutput()); // Have the author submit the report Report submitted = graphQLHelper.updateObject(author, "submitReport", "uuid", FIELDS, "String", @@ -694,6 +700,8 @@ public void reportEditTest() { returned.setLocation(loc); // update HTML of report text 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()); @@ -713,6 +721,9 @@ public void reportEditTest() { // check that HTML of report text is sanitized after update 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, 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 8041def574..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; @@ -43,6 +44,10 @@ public static InOut getCombinedHtmlTestCase() { return getCombinedTestCase(getHtmlTestCases()); } + private static void addTestCase(List testCases, InOut inOut) { + testCases.add(inOut); + } + private static void addTestCase(List testCases, String inputOutput) { testCases.add(new InOut(inputOutput)); } @@ -108,6 +113,40 @@ public void testSanitizeHtml() { .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() { From bc892668b5a9ccfc1ddf2a9d049b5b9f92cdef05 Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Tue, 21 Jul 2020 10:27:57 +0200 Subject: [PATCH 211/247] Also retrieve customFields in the GraphQL tests --- src/test/resources/graphQLTests/person-all-paged.gql | 1 + src/test/resources/graphQLTests/person-all.gql | 1 + src/test/resources/graphQLTests/person-recents-maxResults.gql | 1 + src/test/resources/graphQLTests/person-recents.gql | 1 + src/test/resources/graphQLTests/person.gql | 1 + src/test/resources/graphQLTests/report-all-recents.gql | 1 + src/test/resources/graphQLTests/report.gql | 1 + src/test/resources/graphQLTests/reportsAll.gql | 2 ++ src/test/resources/graphQLTests/tasks-with-positions.gql | 1 + src/test/resources/graphQLTests/tasks-with-reports.gql | 1 + src/test/resources/graphQLTests/tasksAll-with-reports.gql | 1 + src/test/resources/graphQLTests/tasksAll.gql | 1 + 12 files changed, 13 insertions(+) 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..5f404e60c3 100644 --- a/src/test/resources/graphQLTests/person.gql +++ b/src/test/resources/graphQLTests/person.gql @@ -63,4 +63,5 @@ person(uuid:"${personUuid}") { relatedObjectUuid } } + customFields } 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..161f54c599 100644 --- a/src/test/resources/graphQLTests/report.gql +++ b/src/test/resources/graphQLTests/report.gql @@ -179,4 +179,5 @@ report(uuid:"${reportUuid}") { relatedObjectUuid } } + 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 } } From 33c24f4fa3bdcfdc5635684d751d4d97a6d28f85 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Tue, 21 Jul 2020 11:49:20 +0000 Subject: [PATCH 212/247] Update most non-major dependencies --- build.gradle | 14 ++++++------- client/package.json | 6 +++--- client/yarn.lock | 48 ++++++++++++++++++++++----------------------- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/build.gradle b/build.gradle index 8810aba537..a396febaf7 100644 --- a/build.gradle +++ b/build.gradle @@ -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.11' - implementation 'io.dropwizard:dropwizard-jdbi3:2.0.11' - implementation 'io.dropwizard:dropwizard-migrations:2.0.11' - implementation 'io.dropwizard:dropwizard-auth:2.0.11' - implementation 'io.dropwizard:dropwizard-views-freemarker:2.0.11' + 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' @@ -105,8 +105,8 @@ dependencies { // For fast and simple image scaling implementation 'net.coobird:thumbnailator:0.4.11' - testImplementation 'io.dropwizard:dropwizard-testing:2.0.11' - testImplementation 'io.dropwizard:dropwizard-client:2.0.11' + 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' diff --git a/client/package.json b/client/package.json index 994d968b34..f97d0243b5 100644 --- a/client/package.json +++ b/client/package.json @@ -27,8 +27,8 @@ "@storybook/addon-actions": "5.3.19", "@storybook/react": "5.3.19", "@wdio/browserstack-service": "6.1.15", - "@wdio/cli": "6.3.3", - "@wdio/local-runner": "6.3.3", + "@wdio/cli": "6.3.4", + "@wdio/local-runner": "6.3.4", "@wdio/mocha-framework": "6.3.0", "@wdio/spec-reporter": "6.3.0", "@wdio/sync": "6.3.3", @@ -86,7 +86,7 @@ "style-loader": "1.2.1", "thread-loader": "2.1.3", "wdio-chromedriver-service": "6.0.3", - "webdriverio": "6.3.3", + "webdriverio": "6.3.4", "webpack": "4.43.0", "webpack-cli": "3.3.12", "webpack-dev-server": "3.11.0", diff --git a/client/yarn.lock b/client/yarn.lock index ef8ad820c8..40f63dcda5 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -2792,10 +2792,10 @@ browserstack-local "^1.4.5" got "^11.0.2" -"@wdio/cli@6.3.3": - version "6.3.3" - resolved "https://registry.yarnpkg.com/@wdio/cli/-/cli-6.3.3.tgz#59313cb4fabbaeb1adb2ec7e0867f4cc127ab463" - integrity sha512-WCfBgclhRBu4RQF0Low4zVPBovhduQPe5e1OnhgOzRHb+cYPNoFXszfDp4/J7cXcbxP/d0jYIyaWvmVnosv/Qg== +"@wdio/cli@6.3.4": + version "6.3.4" + resolved "https://registry.yarnpkg.com/@wdio/cli/-/cli-6.3.4.tgz#e64adb1840b068e691c3629de4b0b3ed816fcc2d" + integrity sha512-eXA4rR6DwhNtXx1Hxknwgl7jGt/q4ZErCB8aOX9rowEoPOxwPQStd6yJcqI2QE8+AC1S72PKC4w+0WImL+M6Bw== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" @@ -2812,7 +2812,7 @@ lodash.union "^4.6.0" mkdirp "^1.0.4" recursive-readdir "^2.2.2" - webdriverio "6.3.3" + webdriverio "6.3.4" yargs "^15.0.1" yarn-install "^1.0.0" @@ -2825,14 +2825,14 @@ deepmerge "^4.0.0" glob "^7.1.2" -"@wdio/local-runner@6.3.3": - version "6.3.3" - resolved "https://registry.yarnpkg.com/@wdio/local-runner/-/local-runner-6.3.3.tgz#9c99d56f91b93d136ffd9ff80b2304db94fcc26c" - integrity sha512-InmfCZpVWuuZ2eIZ/oiROkmk0drqcGp6quRH8ZWEeLVsHbLcbSTrVtbBsgcRbHQ5P/znLficnNTWuGTuWGL21A== +"@wdio/local-runner@6.3.4": + version "6.3.4" + resolved "https://registry.yarnpkg.com/@wdio/local-runner/-/local-runner-6.3.4.tgz#8f8fde286dd5744c1038e67b62278100a0b96a10" + integrity sha512-rKEhFXiNH6H2G86JTgy2cgtEFoNBZ50gRy+P1LEhc7Ko/dAYqYMC+Sy8lnbsDzxz6IZVlbubgs+y7GRREayqoQ== dependencies: "@wdio/logger" "6.0.16" "@wdio/repl" "6.3.0" - "@wdio/runner" "6.3.3" + "@wdio/runner" "6.3.4" async-exit-hook "^2.0.1" stream-buffers "^3.0.2" @@ -2875,10 +2875,10 @@ dependencies: fs-extra "^9.0.0" -"@wdio/runner@6.3.3": - version "6.3.3" - resolved "https://registry.yarnpkg.com/@wdio/runner/-/runner-6.3.3.tgz#1672ffcde898d6dc5c3ea8c1c2433cbdb51a3511" - integrity sha512-2LfgFV86FakXFVTdT8y7TMCCduzjyNOsugvn2VoCyuViq4apAwpbC3MD9LQqcDMIVhU9NMSjgZC3acDetkWcJQ== +"@wdio/runner@6.3.4": + version "6.3.4" + resolved "https://registry.yarnpkg.com/@wdio/runner/-/runner-6.3.4.tgz#e050050148bf29fa8e05522a78bcaf8bb0779929" + integrity sha512-+iOXfTODsSVf9LFBFKAEZqvPzfIClwFCKu7GGFZ7lrOF1svMNzT/0UY0ETsCBZe61Gr8xiI0wbCEly+0DbEh6w== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" @@ -2886,7 +2886,7 @@ deepmerge "^4.0.0" gaze "^1.1.2" webdriver "6.3.0" - webdriverio "6.3.3" + webdriverio "6.3.4" "@wdio/spec-reporter@6.3.0": version "6.3.0" @@ -6173,10 +6173,10 @@ devtools-protocol@0.0.767361: resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.767361.tgz#5977f2558b84f9df36f62501bdddb82f3ae7b66b" integrity sha512-ziRTdhEVQ9jEwedaUaXZ7kl9w9TF/7A3SXQ0XuqrJB+hMS62POHZUWTbumDN2ehRTfvWqTPc2Jw4gUl/jggmHA== -devtools@6.3.3: - version "6.3.3" - resolved "https://registry.yarnpkg.com/devtools/-/devtools-6.3.3.tgz#4bc206e95026b27b64487f7e0e4afe5dc3adc91e" - integrity sha512-VHvJH7y2/pHtDzhXF8T9mlT5sqrUl2WSjCWhjvyohTyfMjtIu15p78lx3NowMwfo12N2/3riW9dVGeVOa6WILQ== +devtools@6.3.4: + version "6.3.4" + resolved "https://registry.yarnpkg.com/devtools/-/devtools-6.3.4.tgz#f4f228ace1baeee200ee1b63d9f830b5a426eca9" + integrity sha512-dOcLdArp5/dJBzD8T5wcT2YgqkA22Mkqo0OS9cXz7JkHNgwOx1FI2Bq9GvP6o0TENHifYSYg3G0K/z0bacekqg== dependencies: "@wdio/config" "6.1.14" "@wdio/logger" "6.0.16" @@ -15274,10 +15274,10 @@ webdriver@6.3.0: got "^11.0.2" lodash.merge "^4.6.1" -webdriverio@6.3.3: - version "6.3.3" - resolved "https://registry.yarnpkg.com/webdriverio/-/webdriverio-6.3.3.tgz#edb46aaf42a92b64996f135b0e66ee4066c0ebac" - integrity sha512-/ahCs6sna4M+/GZ5RPh5LLTEzfh5+gJD0vOpmA4nmarpKjqnfuwtqTETjmQCfqKTjiLVwzqShnsAedbYuw9Q2g== +webdriverio@6.3.4: + version "6.3.4" + resolved "https://registry.yarnpkg.com/webdriverio/-/webdriverio-6.3.4.tgz#434e950ae95fbd921c86dee92e733b84659f377b" + integrity sha512-/53xQEituEFTaJtZMgg5Uz3GXY1Otqyry0LA8dYLYUNkTK0yCa26DL4ycDnWE0i9wEYNFX6YHCgiqTJjHEjKAg== dependencies: "@types/puppeteer" "^3.0.1" "@wdio/config" "6.1.14" @@ -15287,7 +15287,7 @@ webdriverio@6.3.3: archiver "^4.0.1" atob "^2.1.2" css-value "^0.0.1" - devtools "6.3.3" + devtools "6.3.4" get-port "^5.1.1" grapheme-splitter "^1.0.2" lodash.clonedeep "^4.5.0" From 9096e93cb637640c272413c27101ea9ad9b575de Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Tue, 21 Jul 2020 14:08:07 +0200 Subject: [PATCH 213/247] Fix report approval/rejection warnings --- client/src/pages/reports/Show.js | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/client/src/pages/reports/Show.js b/client/src/pages/reports/Show.js index c502939a13..0799f4cd29 100644 --- a/client/src/pages/reports/Show.js +++ b/client/src/pages/reports/Show.js @@ -1113,10 +1113,13 @@ const ReportShow = ({ 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) ? ( @@ -1125,7 +1128,7 @@ const ReportShow = ({ 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" @@ -1209,13 +1212,11 @@ const ReportShow = ({ 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) ? (
- {!_isEmpty(subEntities) && ( - <> - {subEntities?.map(subEntity => ( - - ))} - - )} + <> + {subEntities?.map(subEntity => ( + + ))} + GQL query -const ENTITY_GQL_FIELDS = { - Report: "uuid intent", - Person: "uuid name role avatar(size: 32)", - Organization: "uuid shortName", - Position: "uuid name", - Location: "uuid name", - Task: "uuid shortName longName" -} - const LinkAnetEntity = ({ type, uuid, children }) => { const [entity, setEntity] = useState() @@ -20,7 +11,7 @@ const LinkAnetEntity = ({ type, uuid, children }) => { const modelClass = Models[type] modelClass && modelClass - .fetchByUuid(uuid, ENTITY_GQL_FIELDS) + .fetchByUuid(uuid, GRAPHQL_ENTITY_FIELDS) .then(data => setEntity(data)) }, [type, uuid]) diff --git a/client/src/components/graphs/LikertScale.js b/client/src/components/graphs/LikertScale.js index b64684c669..695de8f6a7 100644 --- a/client/src/components/graphs/LikertScale.js +++ b/client/src/components/graphs/LikertScale.js @@ -43,10 +43,7 @@ const LikertScale = ({ ) const xToValue = useCallback( - newX => { - const a = newX >= scale.range()[0] ? scale.invert(newX) : null - return a - }, + newX => (newX >= scale.range()[0] ? scale.invert(newX) : null), [scale] ) diff --git a/client/src/pages/dashboards/DiagramNode.js b/client/src/pages/dashboards/DiagramNode.js index 805c7a9e87..7bfeb44186 100644 --- a/client/src/pages/dashboards/DiagramNode.js +++ b/client/src/pages/dashboards/DiagramNode.js @@ -22,7 +22,7 @@ import AggregationWidgetContainer, { import AvatarDisplayComponent from "components/AvatarDisplayComponent" import { SPECIAL_WIDGET_TYPES } from "components/CustomFields" import LinkTo from "components/LinkTo" -import { CUSTOM_FIELD_TYPE } from "components/Model" +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" @@ -32,12 +32,12 @@ import PropTypes from "prop-types" import * as React from "react" const ENTITY_GQL_FIELDS = { - Report: "uuid, intent", + Report: GRAPHQL_ENTITY_FIELDS.Report, Person: `uuid, name, role, avatar(size: 64), ${GRAPHQL_NOTES_FIELDS}`, - Organization: "uuid, shortName", - Position: "uuid, name", - Location: "uuid, name", - Task: `uuid, shortName, longName, ${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 = { diff --git a/client/tests/webdriver/specs/showReport.spec.js b/client/tests/webdriver/specs/showReport.spec.js index 5580718a06..c1cc0bb61d 100644 --- a/client/tests/webdriver/specs/showReport.spec.js +++ b/client/tests/webdriver/specs/showReport.spec.js @@ -7,12 +7,12 @@ describe("Show report page", () => { MyReports.open() ShowReport.openAsAdminUser(MyReports.reportWithAssessmentsUrl) }) - describe("When on the show page of a report with assessmnets", () => { + 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 svgAssessmnets = ShowReport.tasksEngagementAssessments.$$("svg") - expect(svgAssessmnets).to.have.length(2) + 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]" diff --git a/client/tests/webdriver/specs/showTask.spec.js b/client/tests/webdriver/specs/showTask.spec.js index d5fb94c3c7..a3124d686b 100644 --- a/client/tests/webdriver/specs/showTask.spec.js +++ b/client/tests/webdriver/specs/showTask.spec.js @@ -10,7 +10,7 @@ describe("Show task page", () => { ShowTask.openAsAdminUser(ShowReport.task12BUrl) }) - describe("When on the show page of a task with assessmnets", () => { + 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.$( From 07b492ca413867ff7f1b17150786a242d1be742e Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Mon, 27 Jul 2020 16:18:02 +0200 Subject: [PATCH 234/247] NCI-Agency/anet#2954: Remove not needed xmlns attribute from svg It is not needed when the svg is part of an HTML page. --- client/src/components/graphs/IqrBoxPlot.js | 7 +------ client/src/components/graphs/LikertScale.js | 1 - client/src/components/graphs/SVGCanvas.js | 7 +------ 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/client/src/components/graphs/IqrBoxPlot.js b/client/src/components/graphs/IqrBoxPlot.js index 5413325ee4..5fb2560b82 100644 --- a/client/src/components/graphs/IqrBoxPlot.js +++ b/client/src/components/graphs/IqrBoxPlot.js @@ -56,12 +56,7 @@ const IqrBoxPlot = ({ values, levels, width, height, whenUnspecified }) => { return whenUnspecified } return ( - + {values?.length > 1 && ( { if (editable && e.clientX) { diff --git a/client/src/components/graphs/SVGCanvas.js b/client/src/components/graphs/SVGCanvas.js index e3cbc340e7..357d5cebd5 100644 --- a/client/src/components/graphs/SVGCanvas.js +++ b/client/src/components/graphs/SVGCanvas.js @@ -56,12 +56,7 @@ const SVGCanvas = ({ width, height, exportTitle, zoomFn, children }) => { )} - + {children} From ad978da7c4ad2e46c11e3e067a89b4cb899bb4da Mon Sep 17 00:00:00 2001 From: Mara Dragan Date: Mon, 27 Jul 2020 16:21:36 +0200 Subject: [PATCH 235/247] NCI-Agency/anet#2954: Fix warning potential type name collision detected Import the Report.EngagementStatus in ReportSearchQuery. --- .../java/mil/dds/anet/beans/search/ReportSearchQuery.java | 5 +---- .../java/mil/dds/anet/search/AbstractReportSearcher.java | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) 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/search/AbstractReportSearcher.java b/src/main/java/mil/dds/anet/search/AbstractReportSearcher.java index 94cc087b03..7218d10ad6 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; From f81436b103e80e01a42134a3d8fb2a9607a403f6 Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Tue, 28 Jul 2020 11:16:42 +0200 Subject: [PATCH 236/247] Only set authHeader when defined Avoid sending an "undefined: undefined" header. Also simplify `_getAuthParams` a little. --- client/src/api.js | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/client/src/api.js b/client/src/api.js index 22f9bad1d6..e384c3f4c2 100644 --- a/client/src/api.js +++ b/client/src/api.js @@ -13,31 +13,36 @@ const GRAPHQL_ENDPOINT = "/graphql" const LOGGING_ENDPOINT = "/api/logging/log" const authMiddleware = new ApolloLink((operation, forward) => { - const [authHeaderName, authHeaderValue] = API._getAuthHeader() - operation.setContext(({ headers = {} }) => ({ - headers: { + operation.setContext(({ headers = {} }) => { + headers = { ...headers, - Accept: "application/json", - [authHeaderName]: authHeaderValue + 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 [authHeaderName, authHeaderValue] = API._getAuthHeader() const params = { method: "POST", body: JSON.stringify(data), credentials: "same-origin", headers: { "Content-Type": "application/json", - Accept: accept || "application/json", - [authHeaderName]: authHeaderValue + Accept: accept || "application/json" } } + const [authHeaderName, authHeaderValue] = API._getAuthHeader() + if (authHeaderName && authHeaderValue) { + params.headers[authHeaderName] = authHeaderValue + } return window.fetch(url, params) }, @@ -126,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 From 4e9e8ca7cd0bfad080234274d06da53727b6161d Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Tue, 28 Jul 2020 11:18:24 +0200 Subject: [PATCH 237/247] Remove obsolete data from window.ANET_DATA --- client/public/index.hbs | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) 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 @@
- From 489eab741130e1d8cc963ccb6ba7993b24e35b59 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Fri, 31 Jul 2020 15:31:32 +0000 Subject: [PATCH 238/247] Update dependency css-loader to v4 --- client/package.json | 2 +- client/yarn.lock | 31 ++++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/client/package.json b/client/package.json index f121246e85..4a105fdf61 100644 --- a/client/package.json +++ b/client/package.json @@ -50,7 +50,7 @@ "countries-list": "2.5.5", "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.5.0", "eslint-config-react-app": "5.2.1", diff --git a/client/yarn.lock b/client/yarn.lock index 1c086525cb..2a01f30956 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -5407,7 +5407,26 @@ 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, css-loader@^3.0.0: +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 "^6.0.0" + cssesc "^3.0.0" + icss-utils "^4.1.1" + 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.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 "^7.3.2" + +css-loader@^3.0.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== @@ -11843,6 +11862,16 @@ postcss-modules-local-by-default@^3.0.2: postcss-selector-parser "^6.0.2" postcss-value-parser "^4.0.0" +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.32" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" + postcss-modules-scope@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee" From 939faeb545866ccd0bda3d4fec2cd264b93abcaf Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Mon, 3 Aug 2020 11:38:35 +0200 Subject: [PATCH 239/247] Update dependency com.microsoft.sqlserver:mssql-jdbc to v8.4.0.jre8 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a040fe0669..5c08836882 100644 --- a/build.gradle +++ b/build.gradle @@ -72,7 +72,7 @@ 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:4.0.0' From 99e6a9905a96cd11231b20418445421f56e7589c Mon Sep 17 00:00:00 2001 From: Gertjan van Oosten Date: Tue, 28 Jul 2020 14:04:34 +0200 Subject: [PATCH 240/247] Make `jar` and `run` depend on buildClient If `classes` depends on it, the CodeQL build action will also process all JS from our dependencies, which takes a long time and isn't helpful. --- build.gradle | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a040fe0669..a90cfd15bd 100644 --- a/build.gradle +++ b/build.gradle @@ -430,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 { From f1c2e1d2df01eb020ace7fdf421f980f0361cd96 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Tue, 4 Aug 2020 07:11:25 +0000 Subject: [PATCH 241/247] Update most non-major dependencies --- build.gradle | 2 +- client/package.json | 50 +- client/yarn.lock | 1250 ++++++++++++++++++++++++++----------------- 3 files changed, 772 insertions(+), 530 deletions(-) diff --git a/build.gradle b/build.gradle index a040fe0669..f3027ce822 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { id "org.kordamp.markdown.convert" version "1.2.0" - id "com.bmuschko.docker-remote-api" version "6.6.0" + id "com.bmuschko.docker-remote-api" version "6.6.1" id "com.github.node-gradle.node" version "2.2.4" id "com.diffplug.spotless" version "5.1.0" } diff --git a/client/package.json b/client/package.json index f121246e85..61bbd8ee26 100644 --- a/client/package.json +++ b/client/package.json @@ -4,7 +4,7 @@ "private": true, "homepage": "/assets/client", "devDependencies": { - "@babel/core": "7.10.5", + "@babel/core": "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", @@ -12,10 +12,10 @@ "@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.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.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", @@ -23,36 +23,36 @@ "@babel/plugin-transform-proto-to-assign": "7.10.5", "@babel/preset-react": "7.10.4", "@babel/register": "7.10.5", - "@babel/runtime": "7.10.5", + "@babel/runtime": "7.11.0", "@storybook/addon-actions": "5.3.19", "@storybook/react": "5.3.19", "@wdio/browserstack-service": "6.1.15", - "@wdio/cli": "6.3.4", - "@wdio/local-runner": "6.3.4", - "@wdio/mocha-framework": "6.3.0", - "@wdio/spec-reporter": "6.3.0", - "@wdio/sync": "6.3.3", + "@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.5", - "ava": "3.10.1", + "autoprefixer": "9.8.6", + "ava": "3.11.1", "babel-eslint": "10.1.0", - "babel-jest": "26.1.0", + "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": "84.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.3", - "countries-list": "2.5.5", + "countries-list": "2.5.6", "cross-fetch": "3.0.5", "cross-spawn": "7.0.3", "css-loader": "3.6.0", "dotenv": "8.2.0", - "eslint": "7.5.0", + "eslint": "7.6.0", "eslint-config-react-app": "5.2.1", "eslint-config-standard": "14.1.1", "eslint-config-standard-react": "9.2.0", @@ -62,7 +62,7 @@ "eslint-plugin-jsx-a11y": "6.3.1", "eslint-plugin-node": "11.1.0", "eslint-plugin-promise": "4.2.1", - "eslint-plugin-react": "7.20.3", + "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", @@ -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,17 +86,17 @@ "style-loader": "1.2.1", "thread-loader": "2.1.3", "wdio-chromedriver-service": "6.0.3", - "webdriverio": "6.3.4", - "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": "5.0.9", + "webpack-merge": "5.1.1", "xhr2": "0.2.0" }, "dependencies": { - "@apollo/client": "3.0.2", - "@blueprintjs/core": "3.30.0", - "@blueprintjs/datetime": "3.18.4", + "@apollo/client": "3.1.2", + "@blueprintjs/core": "3.30.1", + "@blueprintjs/datetime": "3.18.5", "@fullcalendar/core": "4.4.2", "@fullcalendar/daygrid": "4.4.2", "@fullcalendar/interaction": "4.4.2", @@ -140,7 +140,7 @@ "react-dom": "16.13.1", "react-mosaic-component": "3.2.0", "react-notification-badge": "1.5.1", - "react-redux": "7.2.0", + "react-redux": "7.2.1", "react-redux-loading-bar": "4.6.0", "react-router-bootstrap": "0.25.0", "react-router-dom": "5.2.0", @@ -154,7 +154,7 @@ "redux": "4.0.5", "redux-persist": "6.0.0", "use-debounce": "3.4.3", - "yup": "0.29.1" + "yup": "0.29.2" }, "scripts": { "build": "NODE_ENV=production webpack --mode production --config config/webpack.client.prod.js", diff --git a/client/yarn.lock b/client/yarn.lock index 1c086525cb..a56ab5c461 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -2,16 +2,16 @@ # yarn lockfile v1 -"@apollo/client@3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.0.2.tgz#fadb2b39a0e32950baaef2566442cb3f6de74a52" - integrity sha512-4ighan5Anlj4tK/tdUHs4Mi1njqXZ7AxRCVolz/H702DjPphAJfm+FRkIadPTmwz+OLO+d+tX+6V1VBshf02rg== +"@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: "@types/zen-observable" "^0.8.0" "@wry/context" "^0.5.2" - "@wry/equality" "^0.1.9" + "@wry/equality" "^0.2.0" fast-json-stable-stringify "^2.0.0" - graphql-tag "^2.10.4" + graphql-tag "^2.11.0" hoist-non-react-statics "^3.3.2" optimism "^0.12.1" prop-types "^15.7.2" @@ -43,19 +43,19 @@ invariant "^2.2.4" semver "^5.5.0" -"@babel/core@7.10.5", "@babel/core@^7.1.0", "@babel/core@^7.4.5", "@babel/core@^7.7.5": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.5.tgz#1f15e2cca8ad9a1d78a38ddba612f5e7cdbbd330" - integrity sha512-O34LQooYVDXPl7QWCdW9p4NR+QlzOr7xShPPJz8GsuCU3/8ua/wqTr7gmnxXv+WBESiGU/G5s16i6tUvHkNb+w== +"@babel/core@7.11.0": + 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.10.5" - "@babel/helper-module-transforms" "^7.10.5" + "@babel/generator" "^7.11.0" + "@babel/helper-module-transforms" "^7.11.0" "@babel/helpers" "^7.10.4" - "@babel/parser" "^7.10.5" + "@babel/parser" "^7.11.0" "@babel/template" "^7.10.4" - "@babel/traverse" "^7.10.5" - "@babel/types" "^7.10.5" + "@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" @@ -87,6 +87,28 @@ semver "^5.4.1" source-map "^0.5.0" +"@babel/core@^7.1.0", "@babel/core@^7.4.5", "@babel/core@^7.7.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.5.tgz#1f15e2cca8ad9a1d78a38ddba612f5e7cdbbd330" + integrity sha512-O34LQooYVDXPl7QWCdW9p4NR+QlzOr7xShPPJz8GsuCU3/8ua/wqTr7gmnxXv+WBESiGU/G5s16i6tUvHkNb+w== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.10.5" + "@babel/helper-module-transforms" "^7.10.5" + "@babel/helpers" "^7.10.4" + "@babel/parser" "^7.10.5" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.5" + "@babel/types" "^7.10.5" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.19" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + "@babel/generator@^7.10.5", "@babel/generator@^7.9.0": version "7.10.5" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.5.tgz#1b903554bc8c583ee8d25f1e8969732e6b829a69" @@ -96,6 +118,15 @@ jsesc "^2.5.1" source-map "^0.5.0" +"@babel/generator@^7.11.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.11.0" + jsesc "^2.5.1" + source-map "^0.5.0" + "@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" @@ -227,6 +258,19 @@ "@babel/types" "^7.10.5" lodash "^4.17.19" +"@babel/helper-module-transforms@^7.11.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" @@ -275,6 +319,13 @@ "@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": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz#2c70576eaa3b5609b24cb99db2888cc3fc4251d1" @@ -282,6 +333,13 @@ dependencies: "@babel/types" "^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" @@ -320,6 +378,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.5.tgz#e7c6bf5a7deff957cec9f04b551e2762909d826b" integrity sha512-wfryxy4bE1UivvQKSQDU4/X6dr+i8bctjUjj8Zyt3DQy7NtPizJXT8M52nqpNKL+nq2PW8lxk4ZqLj0fD4B4hQ== +"@babel/parser@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.0.tgz#a9d7e11aead25d3b422d17b2c6502c8dddef6a5d" + integrity sha512-qvRvi4oI8xii8NllyEc4MDJjuZiNaRzyb7Y7lup1NqJV8TZHF4O27CcP+72WPn/k1zkgJ6WJfnIbk4jTsVAZHw== + "@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" @@ -412,10 +475,10 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.0" -"@babel/plugin-proposal-logical-assignment-operators@7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.10.4.tgz#e62b5cf38e494d6cc24683e2a26cba4a28f7ea44" - integrity sha512-gyZd+5BZdK3rTpLCw0cTXUESWywH4wvugdzuUYkDKhtP0Obkp2ebZZzVE24UhVOb47vTDNwbUzQpei9psxYj6A== +"@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.4" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" @@ -469,12 +532,13 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@7.10.4", "@babel/plugin-proposal-optional-chaining@^7.10.4", "@babel/plugin-proposal-optional-chaining@^7.9.0": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.4.tgz#750f1255e930a1f82d8cdde45031f81a0d0adff7" - integrity sha512-ZIhQIEeavTgouyMSdZRap4VPPHqJJ3NEs2cuHs5p0erH+iz6khB0qfgU8g7UuJkG88+fBMy23ZiU+nuHvekJeQ== +"@babel/plugin-proposal-optional-chaining@7.11.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.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": @@ -485,6 +549,14 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.0" +"@babel/plugin-proposal-optional-chaining@^7.10.4", "@babel/plugin-proposal-optional-chaining@^7.9.0": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.4.tgz#750f1255e930a1f82d8cdde45031f81a0d0adff7" + integrity sha512-ZIhQIEeavTgouyMSdZRap4VPPHqJJ3NEs2cuHs5p0erH+iz6khB0qfgU8g7UuJkG88+fBMy23ZiU+nuHvekJeQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@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" @@ -1250,10 +1322,10 @@ core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" -"@babel/runtime@7.10.5", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.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.5" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.5.tgz#303d8bd440ecd5a491eae6117fd3367698674c5c" - integrity sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg== +"@babel/runtime@7.11.0", "@babel/runtime@^7.10.5": + 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" @@ -1264,6 +1336,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.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": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.5.tgz#303d8bd440ecd5a491eae6117fd3367698674c5c" + integrity sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg== + dependencies: + regenerator-runtime "^0.13.4" + "@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" @@ -1288,6 +1367,21 @@ globals "^11.1.0" lodash "^4.17.19" +"@babel/traverse@^7.11.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.19" + "@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@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.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.5.tgz#d88ae7e2fde86bfbfe851d4d81afa70a997b5d15" @@ -1297,17 +1391,26 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" +"@babel/types@^7.11.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.4" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@blueprintjs/core@3.30.0", "@blueprintjs/core@^3.30.0": - version "3.30.0" - resolved "https://registry.yarnpkg.com/@blueprintjs/core/-/core-3.30.0.tgz#d847e451741735a7b11216fb3ec1c669f201bb90" - integrity sha512-/fBhPmQ1AJ7ATGzA9YBlnxN8KV7PjNeW9KL+IOWiERUNcF9kuiuKJ88hTs7gSSHNtHmCF+jheD+X0MQq4WYVjA== +"@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" @@ -1319,21 +1422,21 @@ resize-observer-polyfill "^1.5.1" tslib "~1.10.0" -"@blueprintjs/datetime@3.18.4": - version "3.18.4" - resolved "https://registry.yarnpkg.com/@blueprintjs/datetime/-/datetime-3.18.4.tgz#1fbb4792c4b4bc8319c57434e5c2ee95c18fc189" - integrity sha512-Rk52JS3mwbH8xyqdiGiIKthfoN9i9Uq5tgFfle/frFgdLpOTs9RfETbHeCCDeOtf2h0Lan6hqcmz5/LMtPZhtA== +"@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.30.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" @@ -1506,89 +1609,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== +"@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.1.0" - "@jest/reporters" "^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/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" @@ -1599,10 +1706,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" @@ -1620,42 +1727,42 @@ 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" @@ -1672,6 +1779,17 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" +"@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.13" resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-1.6.13.tgz#d58d2db408ee1fb2bfd6314d3cc86c444d08dc52" @@ -2691,14 +2809,14 @@ browserstack-local "^1.4.5" got "^11.0.2" -"@wdio/cli@6.3.4": - version "6.3.4" - resolved "https://registry.yarnpkg.com/@wdio/cli/-/cli-6.3.4.tgz#e64adb1840b068e691c3629de4b0b3ed816fcc2d" - integrity sha512-eXA4rR6DwhNtXx1Hxknwgl7jGt/q4ZErCB8aOX9rowEoPOxwPQStd6yJcqI2QE8+AC1S72PKC4w+0WImL+M6Bw== +"@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.3.0" + "@wdio/utils" "6.3.6" async-exit-hook "^2.0.1" chalk "^4.0.0" chokidar "^3.0.0" @@ -2711,7 +2829,7 @@ lodash.union "^4.6.0" mkdirp "^1.0.4" recursive-readdir "^2.2.2" - webdriverio "6.3.4" + webdriverio "6.3.6" yargs "^15.0.1" yarn-install "^1.0.0" @@ -2724,14 +2842,14 @@ deepmerge "^4.0.0" glob "^7.1.2" -"@wdio/local-runner@6.3.4": - version "6.3.4" - resolved "https://registry.yarnpkg.com/@wdio/local-runner/-/local-runner-6.3.4.tgz#8f8fde286dd5744c1038e67b62278100a0b96a10" - integrity sha512-rKEhFXiNH6H2G86JTgy2cgtEFoNBZ50gRy+P1LEhc7Ko/dAYqYMC+Sy8lnbsDzxz6IZVlbubgs+y7GRREayqoQ== +"@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.3.0" - "@wdio/runner" "6.3.4" + "@wdio/repl" "6.3.6" + "@wdio/runner" "6.3.6" async-exit-hook "^2.0.1" stream-buffers "^3.0.2" @@ -2745,71 +2863,71 @@ loglevel-plugin-prefix "^0.8.4" strip-ansi "^6.0.0" -"@wdio/mocha-framework@6.3.0": - version "6.3.0" - resolved "https://registry.yarnpkg.com/@wdio/mocha-framework/-/mocha-framework-6.3.0.tgz#c0e99f5291675e35b7d6bff4cb9e099056b9d5a4" - integrity sha512-3lLvzhDYWwOYmiJAjr2fm/nENq6g6uUOtkIeEQFp1kDyBQkDsH1PXGdFklQbRiQT8mAqOPhx1kvXrCA/XpWl7g== +"@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.3.0" + "@wdio/utils" "6.3.6" expect-webdriverio "^1.1.5" mocha "^8.0.1" -"@wdio/protocols@6.3.0": - version "6.3.0" - resolved "https://registry.yarnpkg.com/@wdio/protocols/-/protocols-6.3.0.tgz#9dfd37c0e34919977d3e76747f3e530435a05f23" - integrity sha512-1GKzfyCTLW5WkFd3W7NLACih+zNWU7c8kFurbCQXDK1ko1obqJEs7ZjBr85q5XqMWburdks5rDjyml2iEB2LBg== +"@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.3.0": - version "6.3.0" - resolved "https://registry.yarnpkg.com/@wdio/repl/-/repl-6.3.0.tgz#6f85abbff97fbb7ce216026fe91c1795019260d9" - integrity sha512-FT3flKOqNdZNG1uYl+QpOfdZIgKAWhLfoQ0s+wL0crLeDNIFvvM2qSDhRBRDYV7a0IFyBi8Z975WBn0dlH03Ig== +"@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.3.0" + "@wdio/utils" "6.3.6" -"@wdio/reporter@6.3.0": - version "6.3.0" - resolved "https://registry.yarnpkg.com/@wdio/reporter/-/reporter-6.3.0.tgz#485eb8c65a53267ebf83579170695e1edb834168" - integrity sha512-vbwjJvSKZUtsWtQMhuVqT7ZP6RIFAH4+ienjNwW30QPDi38OujZgxC2ZqRoZKsxck6cfTgkxrXfNaxHN0/LHKg== +"@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.3.4": - version "6.3.4" - resolved "https://registry.yarnpkg.com/@wdio/runner/-/runner-6.3.4.tgz#e050050148bf29fa8e05522a78bcaf8bb0779929" - integrity sha512-+iOXfTODsSVf9LFBFKAEZqvPzfIClwFCKu7GGFZ7lrOF1svMNzT/0UY0ETsCBZe61Gr8xiI0wbCEly+0DbEh6w== +"@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.3.0" + "@wdio/utils" "6.3.6" deepmerge "^4.0.0" gaze "^1.1.2" - webdriver "6.3.0" - webdriverio "6.3.4" + webdriver "6.3.6" + webdriverio "6.3.6" -"@wdio/spec-reporter@6.3.0": - version "6.3.0" - resolved "https://registry.yarnpkg.com/@wdio/spec-reporter/-/spec-reporter-6.3.0.tgz#2b24d5845f614720f74bca85b0f0eb3222e6d98e" - integrity sha512-JGZAMcqiOloOw6xcIT5O8GORVaww6kslgH5kZGydVQyoNBj1ZKoLdEjqq2jklJsge1xsscdYdW9u9kMHwm25iA== +"@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.3.0" + "@wdio/reporter" "6.3.6" chalk "^4.0.0" easy-table "^1.1.1" pretty-ms "^7.0.0" -"@wdio/sync@6.3.3": - version "6.3.3" - resolved "https://registry.yarnpkg.com/@wdio/sync/-/sync-6.3.3.tgz#87fefb571132b4b62c96a9f42ac44f9586c1e716" - integrity sha512-WNq+hhkgk9LluKLP2nQ/9+EH8HNQnROFFHvYuznxb1aKj/zhZvqWuQPpmMWhPMBSTpkdbdLCYerZWKcamYOcJQ== +"@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.3.0": - version "6.3.0" - resolved "https://registry.yarnpkg.com/@wdio/utils/-/utils-6.3.0.tgz#cc2caad78407a837b9aa070f5c656a5bcb129eef" - integrity sha512-PbeC5fpieamgSAHf7S58MAyraGU1qKxnHdfGMG+ZIWiIo73oo4j/57CcH6ZawQ3YC1wEc/5q+VXg7N5hvqhJOQ== +"@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" @@ -2965,10 +3083,10 @@ dependencies: tslib "^1.9.3" -"@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" @@ -3033,12 +3151,12 @@ agent-base@5: resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-5.1.1.tgz#e8fb3f242959db44d63be665db7a8e739537a32c" integrity sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g== -agent-base@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" - integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== +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: - es6-promisify "^5.0.0" + debug "4" aggregate-error@^3.0.0: version "3.0.1" @@ -3226,18 +3344,18 @@ archiver-utils@^2.1.0: normalize-path "^3.0.0" readable-stream "^2.0.0" -archiver@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/archiver/-/archiver-4.0.2.tgz#43c72865eadb4ddaaa2fb74852527b6a450d927c" - integrity sha512-B9IZjlGwaxF33UN4oPbfBkyA4V1SxNLeIhR1qY8sRXSsbdUkEHrrOvwlYFPx+8uQeCe9M+FG6KgO+imDmQ79CQ== +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 "^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" @@ -3486,7 +3604,20 @@ 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.5, autoprefixer@^9.7.2: +autoprefixer@9.8.6: + 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.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.5" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.5.tgz#2c225de229ddafe1d1424c02791d0c3e10ccccaa" integrity sha512-C2p5KkumJlsTHoNv9w31NrBRgXhf6eCMteJuHZi2xhkgC+5Vm40MEtCKPhc0qdgAOhox0YPy1SQHTAky05UoKg== @@ -3499,10 +3630,10 @@ autoprefixer@9.8.5, autoprefixer@^9.7.2: postcss "^7.0.32" postcss-value-parser "^4.1.0" -ava@3.10.1: - version "3.10.1" - resolved "https://registry.yarnpkg.com/ava/-/ava-3.10.1.tgz#a4e68b1a2bb248fa0d96529d23dd83f57082e944" - integrity sha512-+w86ZHyFHIGCABi7NUrn/WJMyC+fDj0BSIlFNVS45WDKAD5vxbIiDWeclctxOOc2KDPfQD7tFOURSBz0FBLD0A== +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" @@ -3512,7 +3643,7 @@ ava@3.10.1: 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.1" @@ -3526,7 +3657,7 @@ ava@3.10.1: 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" @@ -3534,14 +3665,14 @@ ava@3.10.1: import-local "^3.0.2" indent-string "^4.0.0" is-error "^2.2.2" - is-plain-object "^3.0.1" + 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" @@ -3558,7 +3689,7 @@ ava@3.10.1: trim-off-newlines "^1.0.1" update-notifier "^4.1.0" write-file-atomic "^3.0.3" - yargs "^15.4.0" + yargs "^15.4.1" aws-sign2@~0.7.0: version "0.7.0" @@ -3643,16 +3774,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" @@ -3707,10 +3838,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" @@ -3902,12 +4033,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": @@ -4522,6 +4653,11 @@ caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001093, caniuse-lite@^1.0.300010 resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001105.tgz#d2cb0b31e5cf2f3ce845033b61c5c01566549abf" integrity sha512-JupOe6+dGMr7E20siZHIZQwYqrllxotAhiaej96y6x00b/48rPt42o+SzOSCPbrpsDWvRja40Hwrj0g0q6LZJg== +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" resolved "https://registry.yarnpkg.com/capital-case/-/capital-case-1.0.3.tgz#339bd77e8fab6cf75111d4fca509b3edf7c117c8" @@ -4678,7 +4814,7 @@ chokidar@^2.0.4, chokidar@^2.1.8: optionalDependencies: fsevents "^1.2.7" -chokidar@^3.0.0, chokidar@^3.4.0: +chokidar@^3.0.0, chokidar@^3.4.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== @@ -4722,16 +4858,16 @@ chrome-trace-event@^1.0.2: dependencies: tslib "^1.9.0" -chromedriver@84.0.0: - version "84.0.0" - resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-84.0.0.tgz#980d72bf0990bbfbce282074d15448296c55d89d" - integrity sha512-fNX9eT1C38D1W8r5ss9ty42eDK+GIkCZVKukfeDs0XSBeKfyT0o/vbMdPr9MUkWQ+vIcFAS5hFGp9E3+xoaMeQ== +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" - https-proxy-agent "^2.2.4" + extract-zip "^2.0.1" + https-proxy-agent "^5.0.0" mkdirp "^1.0.4" tcp-port-used "^1.0.1" @@ -4990,7 +5126,7 @@ 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: +colorette@^1.2.0, 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== @@ -5037,15 +5173,15 @@ component-emitter@^1.2.1: 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" @@ -5291,15 +5427,15 @@ cosmiconfig@^6.0.0: path-type "^4.0.0" yaml "^1.7.2" -countries-list@2.5.5: - version "2.5.5" - resolved "https://registry.yarnpkg.com/countries-list/-/countries-list-2.5.5.tgz#cb463afc63563fc979e8fa5dbcf0caed16ec36f4" - integrity sha512-FzK1aF50WWNUyrbeOCt+QAUXX/HmnQVJtRwh4GJV7lUmBevbnT+m6+uiGM+M1mC9VvR3plQVAK8d3FxSqQPy8w== +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" @@ -5811,7 +5947,7 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6. dependencies: ms "2.0.0" -debug@3.2.6, debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5: +debug@3.2.6, debug@^3.0.0, debug@^3.1.1, debug@^3.2.5: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== @@ -6072,15 +6208,15 @@ devtools-protocol@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.4: - version "6.3.4" - resolved "https://registry.yarnpkg.com/devtools/-/devtools-6.3.4.tgz#f4f228ace1baeee200ee1b63d9f830b5a426eca9" - integrity sha512-dOcLdArp5/dJBzD8T5wcT2YgqkA22Mkqo0OS9cXz7JkHNgwOx1FI2Bq9GvP6o0TENHifYSYg3G0K/z0bacekqg== +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.3.0" - "@wdio/utils" "6.3.0" + "@wdio/protocols" "6.3.6" + "@wdio/utils" "6.3.6" chrome-launcher "^0.13.1" puppeteer-core "^5.1.0" ua-parser-js "^0.7.21" @@ -6474,7 +6610,7 @@ 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: +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== @@ -6532,7 +6668,7 @@ 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, enhanced-resolve@^4.1.1: +enhanced-resolve@^4.1.0, 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== @@ -6626,18 +6762,6 @@ es5-shim@^4.5.13: resolved "https://registry.yarnpkg.com/es5-shim/-/es5-shim-4.5.14.tgz#90009e1019d0ea327447cb523deaff8fe45697ef" integrity sha512-7SwlpL+2JpymWTt8sNLuC2zdhhc+wrfe5cMPI2j0o6WsPdfAiPwmFy2f0AocPB4RQVBOZ9kNTgi5YF7TdhkvEg== -es6-promise@^4.0.3: - version "4.2.8" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" - integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== - -es6-promisify@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" - integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= - dependencies: - es6-promise "^4.0.3" - es6-shim@^0.35.5: version "0.35.5" resolved "https://registry.yarnpkg.com/es6-shim/-/es6-shim-0.35.5.tgz#46f59dc0a84a1c5029e8ff1166ca0a902077a9ab" @@ -6810,10 +6934,10 @@ eslint-plugin-react-hooks@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.3: - version "7.20.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.3.tgz#0590525e7eb83890ce71f73c2cf836284ad8c2f1" - integrity sha512-txbo090buDeyV0ugF3YMWrzLIUqpYTsWSDZV9xLSmExE1P/Kmgg9++PD931r+KEWS66O1c9R4srLVVHmeHpoAg== +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" @@ -6860,10 +6984,10 @@ eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3 resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== -eslint@7.5.0: - version "7.5.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.5.0.tgz#9ecbfad62216d223b82ac9ffea7ef3444671d135" - integrity sha512-vlUP10xse9sWt9SGRtcr1LAC67BENcQMFeV+w5EvLEoFe3xJ8cF1Skd0msziRx/VMC+72B4DxreCE+OR12OA6Q== +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" @@ -7054,7 +7178,7 @@ expect-webdriverio@^1.1.5: expect "^26.0.1" jest-matcher-utils "^26.0.1" -expect@^26.0.1, expect@^26.1.0: +expect@^26.0.1: version "26.1.0" resolved "https://registry.yarnpkg.com/expect/-/expect-26.1.0.tgz#8c62e31d0f8d5a8ebb186ee81473d15dd2fbf7c8" integrity sha512-QbH4LZXDsno9AACrN9eM0zfnby9G+OsdNgZUohjg/P0mLy1O+/bzTAJGT6VSIjVCe8yKM6SzEl/ckEOFBT7Vnw== @@ -7066,6 +7190,18 @@ expect@^26.0.1, expect@^26.1.0: jest-message-util "^26.1.0" jest-regex-util "^26.0.0" +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.2.0" + ansi-styles "^4.0.0" + jest-get-type "^26.0.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: version "4.17.1" resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" @@ -7145,7 +7281,7 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" -extract-zip@^2.0.0: +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== @@ -7818,7 +7954,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== @@ -8061,10 +8197,10 @@ graphql-language-service@^3.0.0: graphql-language-service-interface "^2.4.0" graphql-language-service-types "^1.6.0" -graphql-tag@^2.10.4: - version "2.10.4" - resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.10.4.tgz#2f301a98219be8b178a6453bb7e33b79b66d8f83" - integrity sha512-O7vG5BT3w6Sotc26ybcvLKNTdfr4GfsIVMD+LdYqXCeJIYPRyp8BIsDOUtxw7S1PYvRw5vH3278J2EDezR6mfA== +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.3.0: version "15.3.0" @@ -8494,14 +8630,6 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= -https-proxy-agent@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" - integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg== - dependencies: - agent-base "^4.3.0" - debug "^3.1.0" - https-proxy-agent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz#702b71fb5520a132a66de1f67541d9e62154d82b" @@ -8510,6 +8638,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" @@ -9098,11 +9234,16 @@ 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, is-plain-object@^3.0.1: +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" resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397" @@ -9322,57 +9463,57 @@ 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== +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" + pretty-format "^26.2.0" jest-diff@^26.1.0: version "26.1.0" @@ -9384,6 +9525,16 @@ jest-diff@^26.1.0: jest-get-type "^26.0.0" pretty-format "^26.1.0" +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.2.0" + jest-docblock@^26.0.0: version "26.0.0" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-26.0.0.tgz#3e2fa20899fc928cb13bd0ff68bd3711a36889b5" @@ -9391,95 +9542,99 @@ 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== +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.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" "^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/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" + pretty-format "^26.2.0" jest-matcher-utils@^26.0.1, jest-matcher-utils@^26.1.0: version "26.1.0" @@ -9491,6 +9646,16 @@ jest-matcher-utils@^26.0.1, jest-matcher-utils@^26.1.0: jest-get-type "^26.0.0" pretty-format "^26.1.0" +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.2.0" + jest-get-type "^26.0.0" + 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" @@ -9505,14 +9670,29 @@ 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-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: - "@jest/types" "^26.1.0" + "@babel/code-frame" "^7.0.0" + "@jest/types" "^26.2.0" + "@types/stack-utils" "^1.0.1" + chalk "^4.0.0" + graceful-fs "^4.2.4" + micromatch "^4.0.2" + slash "^3.0.0" + stack-utils "^2.0.2" + +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.2.0" + "@types/node" "*" -jest-pnp-resolver@^1.2.1: +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== @@ -9522,147 +9702,151 @@ jest-regex-util@^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: @@ -9673,22 +9857,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" @@ -11288,7 +11473,7 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" -ora@^4.0.4: +ora@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/ora/-/ora-4.0.5.tgz#7410b5cc2d99fa637fd5099bbb9f02bfbb5a361e" integrity sha512-jCDgm9DqvRcNIAEv2wZPrh7E5PcQiDUnbnWbAfu4NGAE2ZNqPFbDixmWldy1YG2QfLeQhuiu6/h5VRrk6cG50w== @@ -11925,6 +12110,16 @@ pretty-format@^26.1.0: ansi-styles "^4.0.0" react-is "^16.12.0" +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.2.0" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^16.12.0" + pretty-hrtime@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" @@ -12553,10 +12748,10 @@ react-redux-loading-bar@4.6.0: prop-types "^15.6.2" react-lifecycles-compat "^3.0.2" -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" @@ -12778,7 +12973,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== @@ -12800,6 +12995,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" @@ -14273,7 +14475,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== @@ -15141,6 +15343,17 @@ watchpack@^1.6.1: chokidar "^3.4.0" watchpack-chokidar2 "^2.0.0" +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.1" + watchpack-chokidar2 "^2.0.0" + wbuf@^1.1.0, wbuf@^1.7.3: version "1.7.3" resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" @@ -15162,32 +15375,32 @@ wdio-chromedriver-service@6.0.3: dependencies: fs-extra "^9.0.0" -webdriver@6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/webdriver/-/webdriver-6.3.0.tgz#c401a5648ca9434073eda017faf2689a475d38af" - integrity sha512-osHp5DX8eQ76Sy6/UYoECmDnUXwLhy5tlBeJh86er7S04FLAlmEqCvYXgxTSb8YtDjh9Xt9gP768RGhxR7ik5A== +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.3.0" - "@wdio/utils" "6.3.0" + "@wdio/protocols" "6.3.6" + "@wdio/utils" "6.3.6" got "^11.0.2" lodash.merge "^4.6.1" -webdriverio@6.3.4: - version "6.3.4" - resolved "https://registry.yarnpkg.com/webdriverio/-/webdriverio-6.3.4.tgz#434e950ae95fbd921c86dee92e733b84659f377b" - integrity sha512-/53xQEituEFTaJtZMgg5Uz3GXY1Otqyry0LA8dYLYUNkTK0yCa26DL4ycDnWE0i9wEYNFX6YHCgiqTJjHEjKAg== +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.3.0" - "@wdio/utils" "6.3.0" - 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.3.4" + devtools "6.3.6" get-port "^5.1.1" grapheme-splitter "^1.0.2" lodash.clonedeep "^4.5.0" @@ -15199,7 +15412,7 @@ webdriverio@6.3.4: resq "^1.6.0" rgb2hex "^0.2.0" serialize-error "^7.0.0" - webdriver "6.3.0" + webdriver "6.3.6" webidl-conversions@^5.0.0: version "5.0.0" @@ -15296,10 +15509,10 @@ webpack-log@^2.0.0: ansi-colors "^3.0.0" uuid "^3.3.2" -webpack-merge@5.0.9: - version "5.0.9" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.0.9.tgz#d5e0e0ae564ae704836d747893bdd2741544bf31" - integrity sha512-P4teh6O26xIDPugOGX61wPxaeP918QOMjmzhu54zTVcLtOS28ffPWtnv+ilt3wscwBUCL2WNMnh97XkrKqt9Fw== +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: clone-deep "^4.0.1" wildcard "^2.0.0" @@ -15319,7 +15532,36 @@ webpack-virtual-modules@^0.2.0: dependencies: debug "^3.0.0" -webpack@4.43.0, webpack@^4.33.0, webpack@^4.38.0: +webpack@4.44.1: + 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" + "@webassemblyjs/wasm-edit" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + acorn "^6.4.1" + ajv "^6.10.2" + ajv-keywords "^3.4.1" + chrome-trace-event "^1.0.2" + enhanced-resolve "^4.3.0" + eslint-scope "^4.0.3" + json-parse-better-errors "^1.0.2" + loader-runner "^2.4.0" + loader-utils "^1.2.3" + memory-fs "^0.4.1" + micromatch "^3.1.10" + mkdirp "^0.5.3" + neo-async "^2.6.1" + node-libs-browser "^2.2.1" + schema-utils "^1.0.0" + tapable "^1.1.3" + terser-webpack-plugin "^1.4.3" + watchpack "^1.7.4" + webpack-sources "^1.4.1" + +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== @@ -15610,7 +15852,7 @@ 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, yargs@^15.4.0: +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== @@ -15644,17 +15886,17 @@ 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.2: + version "0.29.2" + resolved "https://registry.yarnpkg.com/yup/-/yup-0.29.2.tgz#5302abd9024cca335b987793f8df868e410b7b67" + integrity sha512-FbAAeopli+TnpZ8Lzv2M72wltLw58iWBT7wW8FuAPFPb3CelXmSKCXQbV1o4keywpIK1BZ0ULTLv2s3w1CfOwA== 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@^0.8.14: @@ -15662,11 +15904,11 @@ zen-observable@^0.8.14: 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" From 5b876eb9f6b5b6f4487aa944582310597cf6cfe1 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Tue, 4 Aug 2020 10:47:55 +0000 Subject: [PATCH 242/247] Update dependency react-redux-loading-bar to v5 --- client/package.json | 2 +- client/yarn.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/client/package.json b/client/package.json index 2183f8fc8d..63a7cacb68 100644 --- a/client/package.json +++ b/client/package.json @@ -141,7 +141,7 @@ "react-mosaic-component": "3.2.0", "react-notification-badge": "1.5.1", "react-redux": "7.2.1", - "react-redux-loading-bar": "4.6.0", + "react-redux-loading-bar": "5.0.0", "react-router-bootstrap": "0.25.0", "react-router-dom": "5.2.0", "react-scroll": "1.8.0", diff --git a/client/yarn.lock b/client/yarn.lock index 9e0f5a0182..dd2e5b1d80 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -12697,7 +12697,7 @@ 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== @@ -12769,13 +12769,13 @@ 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.1: version "7.2.1" From 5ba5de4d4b27ff51e728e1d4528c7412af2e03f5 Mon Sep 17 00:00:00 2001 From: Vassil Date: Tue, 4 Aug 2020 12:49:20 +0200 Subject: [PATCH 243/247] nci-agency/anet#2954: Organize imports and remove commented code --- client/src/components/Model.js | 4 ++-- client/src/components/ReportStatistics.js | 4 ++-- client/src/pages/dashboards/BoardDashboard.js | 2 -- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/client/src/components/Model.js b/client/src/components/Model.js index b735ad2f9f..0fe1d4b853 100644 --- a/client/src/components/Model.js +++ b/client/src/components/Model.js @@ -1,12 +1,12 @@ -import API from "api" -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" diff --git a/client/src/components/ReportStatistics.js b/client/src/components/ReportStatistics.js index 54d60924f3..25c98da8e2 100644 --- a/client/src/components/ReportStatistics.js +++ b/client/src/components/ReportStatistics.js @@ -1,8 +1,8 @@ -import API from "api" import { gql } from "@apollo/client" +import API from "api" import AggregationWidgetContainer, { - AGGREGATION_TYPE, AGGERGATION_WIDGET_TYPE, + AGGREGATION_TYPE, getAggregationWidget } from "components/aggregations/AggregationWidgetContainer" import { CUSTOM_FIELD_TYPE } from "components/Model" diff --git a/client/src/pages/dashboards/BoardDashboard.js b/client/src/pages/dashboards/BoardDashboard.js index c924ad2784..c68d6141ed 100644 --- a/client/src/pages/dashboards/BoardDashboard.js +++ b/client/src/pages/dashboards/BoardDashboard.js @@ -237,8 +237,6 @@ const BoardDashboard = () => {
{val}{JSON.stringify(val)}