diff --git a/package-lock.json b/package-lock.json index f3e873c9bc78..2db89fb7513f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,8 +19,13 @@ "@fortawesome/free-regular-svg-icons": "^5.15.4", "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/react-fontawesome": "^0.1.16", + "@monaco-editor/react": "^4.5.2", "@popperjs/core": "^2.10.2", "@reduxjs/toolkit": "^1.7.0", + "@rjsf/bootstrap-4": "^5.12.1", + "@rjsf/core": "^5.12.1", + "@rjsf/utils": "^5.12.1", + "@rjsf/validator-ajv8": "^5.12.1", "@wojtekmaj/enzyme-adapter-react-17": "^0.6.3", "axios": "^0.24.0", "buffer": "^6.0.3", @@ -37,6 +42,7 @@ "prop-types": "^15.7.2", "react": "^17.0.2", "react-app-polyfill": "^2.0.0", + "react-bootstrap": "^1.6.5", "react-copy-to-clipboard": "^5.0.4", "react-data-table-component": "^7.4.5", "react-datepicker": "^4.10.0", @@ -1771,10 +1777,11 @@ } }, "node_modules/@babel/runtime": { - "version": "7.17.2", - "license": "MIT", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.15.tgz", + "integrity": "sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==", "dependencies": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.14.0" }, "engines": { "node": ">=6.9.0" @@ -1792,6 +1799,11 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/runtime/node_modules/regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + }, "node_modules/@babel/template": { "version": "7.16.7", "license": "MIT", @@ -3057,6 +3069,30 @@ "dev": true, "license": "MIT" }, + "node_modules/@monaco-editor/loader": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.3.3.tgz", + "integrity": "sha512-6KKF4CTzcJiS8BJwtxtfyYt9shBiEv32ateQ9T4UVogwn4HM/uPo9iJd2Dmbkpz8CM6Y0PDUpjnZzCwC+eYo2Q==", + "dependencies": { + "state-local": "^1.0.6" + }, + "peerDependencies": { + "monaco-editor": ">= 0.21.0 < 1" + } + }, + "node_modules/@monaco-editor/react": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.5.2.tgz", + "integrity": "sha512-emcWu6vg1OpXPiYll4aPOaXe8bwYB4UaaNTwtArFLgMoNGBzRZb2Xn0Bra2HMIFM7QLgs7fCGunHO5LkfT2LBA==", + "dependencies": { + "@monaco-editor/loader": "^1.3.3" + }, + "peerDependencies": { + "monaco-editor": ">= 0.25.0 < 1", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "dev": true, @@ -3147,13 +3183,22 @@ } }, "node_modules/@popperjs/core": { - "version": "2.11.2", - "license": "MIT", + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" } }, + "node_modules/@react-icons/all-files": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@react-icons/all-files/-/all-files-4.1.0.tgz", + "integrity": "sha512-hxBI2UOuVaI3O/BhQfhtb4kcGn9ft12RWAFVMUeNjqqhLsHvFtzIkFaptBJpFDANTKoDfdVoHTKZDlwKCACbMQ==", + "peerDependencies": { + "react": "*" + } + }, "node_modules/@reduxjs/toolkit": { "version": "1.8.0", "license": "MIT", @@ -3183,6 +3228,121 @@ "@babel/runtime": "^7.9.2" } }, + "node_modules/@restart/context": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@restart/context/-/context-2.1.4.tgz", + "integrity": "sha512-INJYZQJP7g+IoDUh/475NlGiTeMfwTXUEr3tmRneckHIxNolGOW9CTq83S8cxq0CgJwwcMzMJFchxvlwe7Rk8Q==", + "peerDependencies": { + "react": ">=16.3.2" + } + }, + "node_modules/@restart/hooks": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.11.tgz", + "integrity": "sha512-Ft/ncTULZN6ldGHiF/k5qt72O8JyRMOeg0tApvCni8LkoiEahO+z3TNxfXIVGy890YtWVDvJAl662dVJSJXvMw==", + "dependencies": { + "dequal": "^2.0.3" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@rjsf/bootstrap-4": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/@rjsf/bootstrap-4/-/bootstrap-4-5.12.1.tgz", + "integrity": "sha512-aUnijxIlYWza8klJ+GvgoYk4gFSaQQV97LLdujMQY096iLm12ryxWLEjyLyPPNOymyp4kdkNO4FCTiWMs2bh3Q==", + "dependencies": { + "@react-icons/all-files": "^4.1.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@rjsf/core": "^5.8.x", + "@rjsf/utils": "^5.8.x", + "react": "^16.14.0 || >=17", + "react-bootstrap": "^1.6.5" + } + }, + "node_modules/@rjsf/core": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/@rjsf/core/-/core-5.12.1.tgz", + "integrity": "sha512-1YFhZ90/uHRx1akQmDdIjBxGMjs/5gtuTLUFwl6GbOwTm2fhZRh3qXRFyTXz81Oy6TGcbrxBJEYvFg2iHjYKCA==", + "dependencies": { + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "markdown-to-jsx": "^7.3.2", + "nanoid": "^3.3.6", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@rjsf/utils": "^5.8.x", + "react": "^16.14.0 || >=17" + } + }, + "node_modules/@rjsf/utils": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/@rjsf/utils/-/utils-5.12.1.tgz", + "integrity": "sha512-/k8+7WdLwhaYsOQvH5BQINipj2IJvjEW3QQv4jQQ7sXtkpdUjieZayRfaE8DHfRdm9HjgJURJFDy3EODkWPl6A==", + "dependencies": { + "json-schema-merge-allof": "^0.8.1", + "jsonpointer": "^5.0.1", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "react-is": "^18.2.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.14.0 || >=17" + } + }, + "node_modules/@rjsf/utils/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, + "node_modules/@rjsf/validator-ajv8": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/@rjsf/validator-ajv8/-/validator-ajv8-5.12.1.tgz", + "integrity": "sha512-m4QO44yp60LTIfd4RPUu/h07B8U9umbD3I4Nh4iv9oyUudncaZFFXRopKcBm08v30VkN0tjMwuu0SxGDpzMtHA==", + "dependencies": { + "ajv": "^8.12.0", + "ajv-formats": "^2.1.1", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@rjsf/utils": "^5.8.x" + } + }, + "node_modules/@rjsf/validator-ajv8/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@rjsf/validator-ajv8/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "dev": true, @@ -3660,6 +3820,11 @@ "@types/node": "*" } }, + "node_modules/@types/invariant": { + "version": "2.2.35", + "resolved": "https://registry.npmjs.org/@types/invariant/-/invariant-2.2.35.tgz", + "integrity": "sha512-DxX1V9P8zdJPYQat1gHyY0xj3efl8gnMVjiM9iCY6y27lj+PoQWkgjt8jDqmovPqULkKVpKRg8J36iQiA+EtEg==" + }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", "dev": true, @@ -3777,8 +3942,9 @@ } }, "node_modules/@types/react-transition-group": { - "version": "4.4.4", - "license": "MIT", + "version": "4.4.6", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.6.tgz", + "integrity": "sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew==", "dependencies": { "@types/react": "*" } @@ -3839,6 +4005,11 @@ "version": "2.0.6", "license": "MIT" }, + "node_modules/@types/warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz", + "integrity": "sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA==" + }, "node_modules/@types/ws": { "version": "8.5.2", "dev": true, @@ -4723,7 +4894,6 @@ }, "node_modules/ajv-formats": { "version": "2.1.1", - "dev": true, "license": "MIT", "dependencies": { "ajv": "^8.0.0" @@ -4739,7 +4909,6 @@ }, "node_modules/ajv-formats/node_modules/ajv": { "version": "8.10.0", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -4754,7 +4923,6 @@ }, "node_modules/ajv-formats/node_modules/json-schema-traverse": { "version": "1.0.0", - "dev": true, "license": "MIT" }, "node_modules/ajv-keywords": { @@ -5905,8 +6073,9 @@ "license": "MIT" }, "node_modules/classnames": { - "version": "2.3.1", - "license": "MIT" + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" }, "node_modules/clean-css": { "version": "5.2.4", @@ -6074,6 +6243,27 @@ "dev": true, "license": "MIT" }, + "node_modules/compute-gcd": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/compute-gcd/-/compute-gcd-1.2.1.tgz", + "integrity": "sha512-TwMbxBNz0l71+8Sc4czv13h4kEqnchV9igQZBi6QUaz09dnz13juGnnaWWJTRsP3brxOoxeB4SA2WELLw1hCtg==", + "dependencies": { + "validate.io-array": "^1.0.3", + "validate.io-function": "^1.0.2", + "validate.io-integer-array": "^1.0.0" + } + }, + "node_modules/compute-lcm": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/compute-lcm/-/compute-lcm-1.1.2.tgz", + "integrity": "sha512-OFNPdQAXnQhDSKioX8/XYT6sdUlXwpeMjfd6ApxMJfyZ4GxmLR1xvMERctlYhlHwIiz6CSpBc2+qYKjHGZw4TQ==", + "dependencies": { + "compute-gcd": "^1.2.1", + "validate.io-array": "^1.0.3", + "validate.io-function": "^1.0.2", + "validate.io-integer-array": "^1.0.0" + } + }, "node_modules/concat-map": { "version": "0.0.1", "dev": true, @@ -6815,6 +7005,14 @@ "node": ">= 0.6" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, "node_modules/desandro-matches-selector": { "version": "2.0.2", "license": "MIT" @@ -9561,7 +9759,6 @@ }, "node_modules/invariant": { "version": "2.2.4", - "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.0.0" @@ -11886,6 +12083,27 @@ "dev": true, "license": "(AFL-2.1 OR BSD-3-Clause)" }, + "node_modules/json-schema-compare": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/json-schema-compare/-/json-schema-compare-0.2.2.tgz", + "integrity": "sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ==", + "dependencies": { + "lodash": "^4.17.4" + } + }, + "node_modules/json-schema-merge-allof": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/json-schema-merge-allof/-/json-schema-merge-allof-0.8.1.tgz", + "integrity": "sha512-CTUKmIlPJbsWfzRRnOXz+0MjIqvnleIXwFTzz+t9T86HnYX/Rozria6ZVGLktAU9e+NygNljveP+yxqtQp/Q4w==", + "dependencies": { + "compute-lcm": "^1.1.2", + "json-schema-compare": "^0.2.2", + "lodash": "^4.17.20" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "license": "MIT" @@ -11923,9 +12141,9 @@ } }, "node_modules/jsonpointer": { - "version": "5.0.0", - "dev": true, - "license": "MIT", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", "engines": { "node": ">=0.10.0" } @@ -12078,6 +12296,11 @@ "version": "4.17.21", "license": "MIT" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "node_modules/lodash.debounce": { "version": "4.0.8", "license": "MIT" @@ -12204,6 +12427,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/markdown-to-jsx": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.3.2.tgz", + "integrity": "sha512-B+28F5ucp83aQm+OxNrPkS8z0tMKaeHiy0lHJs3LqCyDQFtWuenaIrkaVTgAm1pf1AU85LXltva86hlaT17i8Q==", + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "react": ">= 0.14.0" + } + }, "node_modules/masonry-layout": { "version": "4.2.2", "license": "MIT", @@ -12485,6 +12719,12 @@ "node": "*" } }, + "node_modules/monaco-editor": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.41.0.tgz", + "integrity": "sha512-1o4olnZJsiLmv5pwLEAmzHTE/5geLKQ07BrGxlF4Ri/AXAc2yyDGZwHjiTqD8D/ROKUZmwMA28A+yEowLNOEcA==", + "peer": true + }, "node_modules/moo": { "version": "0.5.1", "license": "BSD-3-Clause" @@ -12506,9 +12746,15 @@ } }, "node_modules/nanoid": { - "version": "3.3.4", - "dev": true, - "license": "MIT", + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -14469,6 +14715,23 @@ "react-is": "^16.13.1" } }, + "node_modules/prop-types-extra": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", + "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==", + "dependencies": { + "react-is": "^16.3.2", + "warning": "^4.0.0" + }, + "peerDependencies": { + "react": ">=0.14.0" + } + }, + "node_modules/prop-types-extra/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/prop-types/node_modules/react-is": { "version": "16.13.1", "license": "MIT" @@ -14665,6 +14928,34 @@ "node": ">=10" } }, + "node_modules/react-bootstrap": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-1.6.7.tgz", + "integrity": "sha512-IzCYXuLSKDEjGFglbFWk0/iHmdhdcJzTmtS6lXxc0kaNFx2PFgrQf5jKnx5sarF2tiXh9Tgx3pSt3pdK7YwkMA==", + "dependencies": { + "@babel/runtime": "^7.14.0", + "@restart/context": "^2.1.4", + "@restart/hooks": "^0.4.7", + "@types/invariant": "^2.2.33", + "@types/prop-types": "^15.7.3", + "@types/react": ">=16.14.8", + "@types/react-transition-group": "^4.4.1", + "@types/warning": "^3.0.0", + "classnames": "^2.3.1", + "dom-helpers": "^5.2.1", + "invariant": "^2.2.4", + "prop-types": "^15.7.2", + "prop-types-extra": "^1.1.0", + "react-overlays": "^5.1.2", + "react-transition-group": "^4.4.1", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, "node_modules/react-copy-to-clipboard": { "version": "5.0.4", "license": "MIT", @@ -14899,6 +15190,11 @@ "version": "17.0.2", "license": "MIT" }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, "node_modules/react-loading-skeleton": { "version": "3.1.0", "license": "MIT", @@ -14941,6 +15237,25 @@ "react-dom": "^15.5.x || ^16.x || ^17.x || ^18.x" } }, + "node_modules/react-overlays": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-5.2.1.tgz", + "integrity": "sha512-GLLSOLWr21CqtJn8geSwQfoJufdt3mfdsnIiQswouuQ2MMPns+ihZklxvsTDKD3cR2tF8ELbi5xUsvqVhR6WvA==", + "dependencies": { + "@babel/runtime": "^7.13.8", + "@popperjs/core": "^2.11.6", + "@restart/hooks": "^0.4.7", + "@types/warning": "^3.0.0", + "dom-helpers": "^5.2.0", + "prop-types": "^15.7.2", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + }, + "peerDependencies": { + "react": ">=16.3.0", + "react-dom": ">=16.3.0" + } + }, "node_modules/react-papaparse": { "version": "3.18.2", "license": "MIT", @@ -15218,8 +15533,9 @@ "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" }, "node_modules/react-transition-group": { - "version": "4.4.2", - "license": "BSD-3-Clause", + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", "dependencies": { "@babel/runtime": "^7.5.5", "dom-helpers": "^5.0.1", @@ -15582,7 +15898,6 @@ }, "node_modules/require-from-string": { "version": "2.0.2", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -16378,6 +16693,11 @@ "dev": true, "license": "MIT" }, + "node_modules/state-local": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz", + "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==" + }, "node_modules/statuses": { "version": "1.5.0", "dev": true, @@ -17270,8 +17590,9 @@ } }, "node_modules/tslib": { - "version": "2.3.1", - "license": "0BSD" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -17380,6 +17701,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/uncontrollable": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz", + "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==", + "dependencies": { + "@babel/runtime": "^7.6.3", + "@types/react": ">=16.9.11", + "invariant": "^2.2.4", + "react-lifecycles-compat": "^3.0.4" + }, + "peerDependencies": { + "react": ">=15.0.0" + } + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "dev": true, @@ -17586,6 +17921,38 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/validate.io-array": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/validate.io-array/-/validate.io-array-1.0.6.tgz", + "integrity": "sha512-DeOy7CnPEziggrOO5CZhVKJw6S3Yi7e9e65R1Nl/RTN1vTQKnzjfvks0/8kQ40FP/dsjRAOd4hxmJ7uLa6vxkg==" + }, + "node_modules/validate.io-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/validate.io-function/-/validate.io-function-1.0.2.tgz", + "integrity": "sha512-LlFybRJEriSuBnUhQyG5bwglhh50EpTL2ul23MPIuR1odjO7XaMLFV8vHGwp7AZciFxtYOeiSCT5st+XSPONiQ==" + }, + "node_modules/validate.io-integer": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/validate.io-integer/-/validate.io-integer-1.0.5.tgz", + "integrity": "sha512-22izsYSLojN/P6bppBqhgUDjCkr5RY2jd+N2a3DCAUey8ydvrZ/OkGvFPR7qfOpwR2LC5p4Ngzxz36g5Vgr/hQ==", + "dependencies": { + "validate.io-number": "^1.0.3" + } + }, + "node_modules/validate.io-integer-array": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/validate.io-integer-array/-/validate.io-integer-array-1.0.0.tgz", + "integrity": "sha512-mTrMk/1ytQHtCY0oNO3dztafHYyGU88KL+jRxWuzfOmQb+4qqnWmI+gykvGp8usKZOM0H7keJHEbRaFiYA0VrA==", + "dependencies": { + "validate.io-array": "^1.0.3", + "validate.io-integer": "^1.0.4" + } + }, + "node_modules/validate.io-number": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/validate.io-number/-/validate.io-number-1.0.3.tgz", + "integrity": "sha512-kRAyotcbNaSYoDnXvb4MHg/0a1egJdLwS6oJ38TJY7aw9n93Fl/3blIXdyYvPOp55CNxywooG/3BcrwNrBpcSg==" + }, "node_modules/vary": { "version": "1.1.2", "dev": true, @@ -19493,9 +19860,18 @@ } }, "@babel/runtime": { - "version": "7.17.2", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.15.tgz", + "integrity": "sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==", "requires": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.14.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + } } }, "@babel/runtime-corejs3": { @@ -20330,6 +20706,22 @@ "version": "2.0.3", "dev": true }, + "@monaco-editor/loader": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.3.3.tgz", + "integrity": "sha512-6KKF4CTzcJiS8BJwtxtfyYt9shBiEv32ateQ9T4UVogwn4HM/uPo9iJd2Dmbkpz8CM6Y0PDUpjnZzCwC+eYo2Q==", + "requires": { + "state-local": "^1.0.6" + } + }, + "@monaco-editor/react": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.5.2.tgz", + "integrity": "sha512-emcWu6vg1OpXPiYll4aPOaXe8bwYB4UaaNTwtArFLgMoNGBzRZb2Xn0Bra2HMIFM7QLgs7fCGunHO5LkfT2LBA==", + "requires": { + "@monaco-editor/loader": "^1.3.3" + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "dev": true, @@ -20372,7 +20764,15 @@ } }, "@popperjs/core": { - "version": "2.11.2" + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==" + }, + "@react-icons/all-files": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@react-icons/all-files/-/all-files-4.1.0.tgz", + "integrity": "sha512-hxBI2UOuVaI3O/BhQfhtb4kcGn9ft12RWAFVMUeNjqqhLsHvFtzIkFaptBJpFDANTKoDfdVoHTKZDlwKCACbMQ==", + "requires": {} }, "@reduxjs/toolkit": { "version": "1.8.0", @@ -20391,6 +20791,88 @@ } } }, + "@restart/context": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@restart/context/-/context-2.1.4.tgz", + "integrity": "sha512-INJYZQJP7g+IoDUh/475NlGiTeMfwTXUEr3tmRneckHIxNolGOW9CTq83S8cxq0CgJwwcMzMJFchxvlwe7Rk8Q==", + "requires": {} + }, + "@restart/hooks": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.11.tgz", + "integrity": "sha512-Ft/ncTULZN6ldGHiF/k5qt72O8JyRMOeg0tApvCni8LkoiEahO+z3TNxfXIVGy890YtWVDvJAl662dVJSJXvMw==", + "requires": { + "dequal": "^2.0.3" + } + }, + "@rjsf/bootstrap-4": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/@rjsf/bootstrap-4/-/bootstrap-4-5.12.1.tgz", + "integrity": "sha512-aUnijxIlYWza8klJ+GvgoYk4gFSaQQV97LLdujMQY096iLm12ryxWLEjyLyPPNOymyp4kdkNO4FCTiWMs2bh3Q==", + "requires": { + "@react-icons/all-files": "^4.1.0" + } + }, + "@rjsf/core": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/@rjsf/core/-/core-5.12.1.tgz", + "integrity": "sha512-1YFhZ90/uHRx1akQmDdIjBxGMjs/5gtuTLUFwl6GbOwTm2fhZRh3qXRFyTXz81Oy6TGcbrxBJEYvFg2iHjYKCA==", + "requires": { + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "markdown-to-jsx": "^7.3.2", + "nanoid": "^3.3.6", + "prop-types": "^15.8.1" + } + }, + "@rjsf/utils": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/@rjsf/utils/-/utils-5.12.1.tgz", + "integrity": "sha512-/k8+7WdLwhaYsOQvH5BQINipj2IJvjEW3QQv4jQQ7sXtkpdUjieZayRfaE8DHfRdm9HjgJURJFDy3EODkWPl6A==", + "requires": { + "json-schema-merge-allof": "^0.8.1", + "jsonpointer": "^5.0.1", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "react-is": "^18.2.0" + }, + "dependencies": { + "react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + } + } + }, + "@rjsf/validator-ajv8": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/@rjsf/validator-ajv8/-/validator-ajv8-5.12.1.tgz", + "integrity": "sha512-m4QO44yp60LTIfd4RPUu/h07B8U9umbD3I4Nh4iv9oyUudncaZFFXRopKcBm08v30VkN0tjMwuu0SxGDpzMtHA==", + "requires": { + "ajv": "^8.12.0", + "ajv-formats": "^2.1.1", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21" + }, + "dependencies": { + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + } + } + }, "@rollup/plugin-babel": { "version": "5.3.1", "dev": true, @@ -20695,6 +21177,11 @@ "@types/node": "*" } }, + "@types/invariant": { + "version": "2.2.35", + "resolved": "https://registry.npmjs.org/@types/invariant/-/invariant-2.2.35.tgz", + "integrity": "sha512-DxX1V9P8zdJPYQat1gHyY0xj3efl8gnMVjiM9iCY6y27lj+PoQWkgjt8jDqmovPqULkKVpKRg8J36iQiA+EtEg==" + }, "@types/istanbul-lib-coverage": { "version": "2.0.4", "dev": true @@ -20792,7 +21279,9 @@ } }, "@types/react-transition-group": { - "version": "4.4.4", + "version": "4.4.6", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.6.tgz", + "integrity": "sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew==", "requires": { "@types/react": "*" } @@ -20844,6 +21333,11 @@ "@types/unist": { "version": "2.0.6" }, + "@types/warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz", + "integrity": "sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA==" + }, "@types/ws": { "version": "8.5.2", "dev": true, @@ -21370,14 +21864,12 @@ }, "ajv-formats": { "version": "2.1.1", - "dev": true, "requires": { "ajv": "^8.0.0" }, "dependencies": { "ajv": { "version": "8.10.0", - "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -21386,8 +21878,7 @@ } }, "json-schema-traverse": { - "version": "1.0.0", - "dev": true + "version": "1.0.0" } } }, @@ -22100,7 +22591,9 @@ "dev": true }, "classnames": { - "version": "2.3.1" + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" }, "clean-css": { "version": "5.2.4", @@ -22218,6 +22711,27 @@ } } }, + "compute-gcd": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/compute-gcd/-/compute-gcd-1.2.1.tgz", + "integrity": "sha512-TwMbxBNz0l71+8Sc4czv13h4kEqnchV9igQZBi6QUaz09dnz13juGnnaWWJTRsP3brxOoxeB4SA2WELLw1hCtg==", + "requires": { + "validate.io-array": "^1.0.3", + "validate.io-function": "^1.0.2", + "validate.io-integer-array": "^1.0.0" + } + }, + "compute-lcm": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/compute-lcm/-/compute-lcm-1.1.2.tgz", + "integrity": "sha512-OFNPdQAXnQhDSKioX8/XYT6sdUlXwpeMjfd6ApxMJfyZ4GxmLR1xvMERctlYhlHwIiz6CSpBc2+qYKjHGZw4TQ==", + "requires": { + "compute-gcd": "^1.2.1", + "validate.io-array": "^1.0.3", + "validate.io-function": "^1.0.2", + "validate.io-integer-array": "^1.0.0" + } + }, "concat-map": { "version": "0.0.1", "dev": true @@ -22666,6 +23180,11 @@ "version": "1.1.2", "dev": true }, + "dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" + }, "desandro-matches-selector": { "version": "2.0.2" }, @@ -24410,7 +24929,6 @@ }, "invariant": { "version": "2.2.4", - "dev": true, "requires": { "loose-envify": "^1.0.0" } @@ -25866,6 +26384,24 @@ "version": "0.4.0", "dev": true }, + "json-schema-compare": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/json-schema-compare/-/json-schema-compare-0.2.2.tgz", + "integrity": "sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ==", + "requires": { + "lodash": "^4.17.4" + } + }, + "json-schema-merge-allof": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/json-schema-merge-allof/-/json-schema-merge-allof-0.8.1.tgz", + "integrity": "sha512-CTUKmIlPJbsWfzRRnOXz+0MjIqvnleIXwFTzz+t9T86HnYX/Rozria6ZVGLktAU9e+NygNljveP+yxqtQp/Q4w==", + "requires": { + "compute-lcm": "^1.1.2", + "json-schema-compare": "^0.2.2", + "lodash": "^4.17.20" + } + }, "json-schema-traverse": { "version": "0.4.1" }, @@ -25891,8 +26427,9 @@ } }, "jsonpointer": { - "version": "5.0.0", - "dev": true + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==" }, "jspdf": { "version": "2.5.1", @@ -25989,6 +26526,11 @@ "lodash": { "version": "4.17.21" }, + "lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "lodash.debounce": { "version": "4.0.8" }, @@ -26075,6 +26617,12 @@ "version": "4.3.0", "dev": true }, + "markdown-to-jsx": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.3.2.tgz", + "integrity": "sha512-B+28F5ucp83aQm+OxNrPkS8z0tMKaeHiy0lHJs3LqCyDQFtWuenaIrkaVTgAm1pf1AU85LXltva86hlaT17i8Q==", + "requires": {} + }, "masonry-layout": { "version": "4.2.2", "requires": { @@ -26246,6 +26794,12 @@ "moment": { "version": "2.29.4" }, + "monaco-editor": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.41.0.tgz", + "integrity": "sha512-1o4olnZJsiLmv5pwLEAmzHTE/5geLKQ07BrGxlF4Ri/AXAc2yyDGZwHjiTqD8D/ROKUZmwMA28A+yEowLNOEcA==", + "peer": true + }, "moo": { "version": "0.5.1" }, @@ -26261,8 +26815,9 @@ } }, "nanoid": { - "version": "3.3.4", - "dev": true + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==" }, "natural-compare": { "version": "1.4.0", @@ -27366,6 +27921,22 @@ } } }, + "prop-types-extra": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", + "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==", + "requires": { + "react-is": "^16.3.2", + "warning": "^4.0.0" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } + } + }, "property-information": { "version": "5.6.0", "requires": { @@ -27482,6 +28053,30 @@ "whatwg-fetch": "^3.4.1" } }, + "react-bootstrap": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-1.6.7.tgz", + "integrity": "sha512-IzCYXuLSKDEjGFglbFWk0/iHmdhdcJzTmtS6lXxc0kaNFx2PFgrQf5jKnx5sarF2tiXh9Tgx3pSt3pdK7YwkMA==", + "requires": { + "@babel/runtime": "^7.14.0", + "@restart/context": "^2.1.4", + "@restart/hooks": "^0.4.7", + "@types/invariant": "^2.2.33", + "@types/prop-types": "^15.7.3", + "@types/react": ">=16.14.8", + "@types/react-transition-group": "^4.4.1", + "@types/warning": "^3.0.0", + "classnames": "^2.3.1", + "dom-helpers": "^5.2.1", + "invariant": "^2.2.4", + "prop-types": "^15.7.2", + "prop-types-extra": "^1.1.0", + "react-overlays": "^5.1.2", + "react-transition-group": "^4.4.1", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + } + }, "react-copy-to-clipboard": { "version": "5.0.4", "requires": { @@ -27632,6 +28227,11 @@ "react-is": { "version": "17.0.2" }, + "react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, "react-loading-skeleton": { "version": "3.1.0", "requires": {} @@ -27657,6 +28257,21 @@ "integrity": "sha512-NMXGa223OnsrGVp5dJHkuKxQ4czdLmXSp5jSV9OqiCky9LOpPATn3vLldc+q5fK3gKbEHvr7J1u0yhBh/xYkpA==", "requires": {} }, + "react-overlays": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-5.2.1.tgz", + "integrity": "sha512-GLLSOLWr21CqtJn8geSwQfoJufdt3mfdsnIiQswouuQ2MMPns+ihZklxvsTDKD3cR2tF8ELbi5xUsvqVhR6WvA==", + "requires": { + "@babel/runtime": "^7.13.8", + "@popperjs/core": "^2.11.6", + "@restart/hooks": "^0.4.7", + "@types/warning": "^3.0.0", + "dom-helpers": "^5.2.0", + "prop-types": "^15.7.2", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + } + }, "react-papaparse": { "version": "3.18.2", "requires": { @@ -27844,7 +28459,9 @@ } }, "react-transition-group": { - "version": "4.4.2", + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", "requires": { "@babel/runtime": "^7.5.5", "dom-helpers": "^5.0.1", @@ -28093,8 +28710,7 @@ "dev": true }, "require-from-string": { - "version": "2.0.2", - "dev": true + "version": "2.0.2" }, "requires-port": { "version": "1.0.0", @@ -28608,6 +29224,11 @@ "version": "1.2.1", "dev": true }, + "state-local": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz", + "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==" + }, "statuses": { "version": "1.5.0", "dev": true @@ -29201,7 +29822,9 @@ } }, "tslib": { - "version": "2.3.1" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "tsutils": { "version": "3.21.0", @@ -29265,6 +29888,17 @@ "which-boxed-primitive": "^1.0.2" } }, + "uncontrollable": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz", + "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==", + "requires": { + "@babel/runtime": "^7.6.3", + "@types/react": ">=16.9.11", + "invariant": "^2.2.4", + "react-lifecycles-compat": "^3.0.4" + } + }, "unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "dev": true @@ -29393,6 +30027,38 @@ "spdx-expression-parse": "^3.0.0" } }, + "validate.io-array": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/validate.io-array/-/validate.io-array-1.0.6.tgz", + "integrity": "sha512-DeOy7CnPEziggrOO5CZhVKJw6S3Yi7e9e65R1Nl/RTN1vTQKnzjfvks0/8kQ40FP/dsjRAOd4hxmJ7uLa6vxkg==" + }, + "validate.io-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/validate.io-function/-/validate.io-function-1.0.2.tgz", + "integrity": "sha512-LlFybRJEriSuBnUhQyG5bwglhh50EpTL2ul23MPIuR1odjO7XaMLFV8vHGwp7AZciFxtYOeiSCT5st+XSPONiQ==" + }, + "validate.io-integer": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/validate.io-integer/-/validate.io-integer-1.0.5.tgz", + "integrity": "sha512-22izsYSLojN/P6bppBqhgUDjCkr5RY2jd+N2a3DCAUey8ydvrZ/OkGvFPR7qfOpwR2LC5p4Ngzxz36g5Vgr/hQ==", + "requires": { + "validate.io-number": "^1.0.3" + } + }, + "validate.io-integer-array": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/validate.io-integer-array/-/validate.io-integer-array-1.0.0.tgz", + "integrity": "sha512-mTrMk/1ytQHtCY0oNO3dztafHYyGU88KL+jRxWuzfOmQb+4qqnWmI+gykvGp8usKZOM0H7keJHEbRaFiYA0VrA==", + "requires": { + "validate.io-array": "^1.0.3", + "validate.io-integer": "^1.0.4" + } + }, + "validate.io-number": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/validate.io-number/-/validate.io-number-1.0.3.tgz", + "integrity": "sha512-kRAyotcbNaSYoDnXvb4MHg/0a1egJdLwS6oJ38TJY7aw9n93Fl/3blIXdyYvPOp55CNxywooG/3BcrwNrBpcSg==" + }, "vary": { "version": "1.1.2", "dev": true diff --git a/package.json b/package.json index 6040e8710664..9d1cc1f15d02 100644 --- a/package.json +++ b/package.json @@ -38,8 +38,13 @@ "@fortawesome/free-regular-svg-icons": "^5.15.4", "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/react-fontawesome": "^0.1.16", + "@monaco-editor/react": "^4.5.2", "@popperjs/core": "^2.10.2", "@reduxjs/toolkit": "^1.7.0", + "@rjsf/bootstrap-4": "^5.12.1", + "@rjsf/core": "^5.12.1", + "@rjsf/utils": "^5.12.1", + "@rjsf/validator-ajv8": "^5.12.1", "@wojtekmaj/enzyme-adapter-react-17": "^0.6.3", "axios": "^0.24.0", "buffer": "^6.0.3", @@ -56,6 +61,7 @@ "prop-types": "^15.7.2", "react": "^17.0.2", "react-app-polyfill": "^2.0.0", + "react-bootstrap": "^1.6.5", "react-copy-to-clipboard": "^5.0.4", "react-data-table-component": "^7.4.5", "react-datepicker": "^4.10.0", diff --git a/public/version_latest.txt b/public/version_latest.txt index 99eba4de9311..d87edbfc1069 100644 --- a/public/version_latest.txt +++ b/public/version_latest.txt @@ -1 +1 @@ -4.1.0 \ No newline at end of file +4.2.1 \ No newline at end of file diff --git a/src/App.js b/src/App.js index 3ed5f1f12ae4..f3fa887346d6 100644 --- a/src/App.js +++ b/src/App.js @@ -9,6 +9,10 @@ import Skeleton from 'react-loading-skeleton' import TimeAgo from 'javascript-time-ago' import en from 'javascript-time-ago/locale/en.json' TimeAgo.addDefaultLocale(en) +import { library } from '@fortawesome/fontawesome-svg-core' +import { fas } from '@fortawesome/free-solid-svg-icons' + +library.add(fas) // Containers const DefaultLayout = React.lazy(() => import('./layout/DefaultLayout')) diff --git a/src/_nav.js b/src/_nav.js index 5f802d6144bc..2f8d05e25f85 100644 --- a/src/_nav.js +++ b/src/_nav.js @@ -171,6 +171,11 @@ const _nav = [ name: 'Individual Domain Check', to: '/tenant/standards/individual-domains', }, + { + component: CNavItem, + name: 'BPA Report Builder', + to: '/tenant/tools/bpa-report-builder', + }, ], }, { diff --git a/src/components/header/AppHeaderDropdown.js b/src/components/header/AppHeaderDropdown.js index 568e03211542..93b9c499d493 100644 --- a/src/components/header/AppHeaderDropdown.js +++ b/src/components/header/AppHeaderDropdown.js @@ -18,24 +18,30 @@ const AppHeaderDropdown = () => { const [profileVisible, setProfileVisible] = useState(false) const [cippQueueExtendedInfo, setCippQueueExtendedInfo] = useState([]) const [cippQueueVisible, setCippQueueVisible] = useState(false) - const [cippQueueRefresh, setCippQueueRefresh] = useState('') + const [cippQueueRefresh, setCippQueueRefresh] = useState( + (Math.random() + 1).toString(36).substring(7), + ) const { data: profile } = authApi.endpoints.loadClientPrincipal.useQueryState() const [getCippQueueList, cippQueueList] = useLazyGenericGetRequestQuery() function loadCippQueue() { setCippQueueVisible(true) + getCippQueueList({ path: 'api/ListCippQueue', params: { refresh: cippQueueRefresh } }) + } + + function refreshCippQueue() { setCippQueueRefresh((Math.random() + 1).toString(36).substring(7)) - getCippQueueList({ path: `api/ListCippQueue?refresh=${cippQueueRefresh}` }) + loadCippQueue() } useEffect(() => { - if (cippQueueList.isFetching) { + if (cippQueueList.isFetching || cippQueueList.isLoading) { setCippQueueExtendedInfo([ { label: 'Fetching recent jobs', value: 'Please wait', - timpestamp: Date(), + timestamp: Date(), link: '#', }, ]) @@ -101,6 +107,7 @@ const AppHeaderDropdown = () => { title="Recent Jobs" extendedInfo={[]} cards={cippQueueExtendedInfo} + refreshFunction={refreshCippQueue} actions={[ { label: 'Clear History', diff --git a/src/components/layout/AppFooter.js b/src/components/layout/AppFooter.js index ecfba658b219..967f7bb3d1ff 100644 --- a/src/components/layout/AppFooter.js +++ b/src/components/layout/AppFooter.js @@ -8,7 +8,7 @@ import netfriends from 'src/assets/images/netfriends.png' //todo: Add darkmode detection and change logos accordingly. const AppFooter = () => { return ( - +

This application is sponsored by{' '} diff --git a/src/components/tables/CellDelegatedPrivilege.js b/src/components/tables/CellDelegatedPrivilege.js new file mode 100644 index 000000000000..66d44d8a65c0 --- /dev/null +++ b/src/components/tables/CellDelegatedPrivilege.js @@ -0,0 +1,25 @@ +import PropTypes from 'prop-types' +import { CellBadge } from './CellBadge' + +export function CellDelegatedPrivilege({ cell }) { + if (!cell) { + return + } + if (cell.toLowerCase() == 'none') { + return + } + if (cell === 'delegatedAdminPrivileges') { + return + } + if (cell === 'delegatedAndGranularDelegetedAdminPrivileges') { + return + } + if (cell === 'granularDelegatedAdminPrivileges') { + return + } + return +} + +CellDelegatedPrivilege.propTypes = { + cell: PropTypes.string, +} diff --git a/src/components/tables/CippTable.js b/src/components/tables/CippTable.js index 4cdad5b0c56f..fa11d257ea78 100644 --- a/src/components/tables/CippTable.js +++ b/src/components/tables/CippTable.js @@ -14,6 +14,7 @@ import { CModalBody, CModalTitle, CCallout, + CFormSelect, } from '@coreui/react' import DataTable, { createTheme } from 'react-data-table-component' import PropTypes from 'prop-types' @@ -24,6 +25,7 @@ import { cellGenericFormatter } from './CellGenericFormat' import { ModalService } from '../utilities' import { useLazyGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app' import { ConfirmModal } from '../utilities/SharedModal' +import { useState } from 'react' const FilterComponent = ({ filterText, @@ -156,6 +158,40 @@ export default function CippTable({ const [selectedRows, setSelectedRows] = React.useState(false) const [genericGetRequest, getResults] = useLazyGenericGetRequestQuery() const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery() + const [getDrowndownInfo, dropDownInfo] = useLazyGenericGetRequestQuery() + const [modalContent, setModalContent] = useState(null) + useEffect(() => { + if (dropDownInfo.isFetching) { + handleModal( + , + modalContent.item.modalUrl, + modalContent.item.modalType, + modalContent.item.modalBody, + modalContent.item.modalInput, + modalContent.item.modalDropdown, + ) + } + if (dropDownInfo.isSuccess) { + console.log(modalContent) + handleModal( + modalContent.item.modalMessage, + modalContent.item.modalUrl, + modalContent.item.modalType, + modalContent.item.modalBody, + modalContent.item.modalInput, + modalContent.item.modalDropdown, + ) + } else if (dropDownInfo.isError) { + handleModal( + 'Error connecting to the API.', + modalContent.item.modalUrl, + modalContent.item.modalType, + modalContent.item.modalBody, + modalContent.item.modalInput, + modalContent.item.modalDropdown, + ) + } + }, [dropDownInfo]) const handleSelectedChange = ({ selectedRows }) => { setSelectedRows(selectedRows) if (selectedRows.length < 1) { @@ -229,84 +265,118 @@ export default function CippTable({ }, }, } - const subHeaderComponentMemo = React.useMemo(() => { - const handleClear = () => { - if (filterText) { - setResetPaginationToggle(!resetPaginationToggle) - setFilterText('') - } - } - const handleModal = (modalMessage, modalUrl, modalType = 'GET', modalBody, modalInput) => { - if (modalType === 'GET') { - ModalService.confirm({ - body: ( -

-
{modalMessage}
-
- ), - title: 'Confirm', - onConfirm: async () => { - const resultsarr = [] - for (const row of selectedRows) { - setLoopRunning(true) - const urlParams = new URLSearchParams(modalUrl.split('?')[1]) - for (let [paramName, paramValue] of urlParams.entries()) { - if (paramValue.startsWith('!')) { - urlParams.set(paramName, row[paramValue.replace('!', '')]) - } + const handleModal = ( + modalMessage, + modalUrl, + modalType = 'GET', + modalBody, + modalInput, + modalDropdown, + ) => { + if (modalType === 'GET') { + ModalService.confirm({ + body: ( +
+
{modalMessage}
+
+ ), + title: 'Confirm', + onConfirm: async () => { + const resultsarr = [] + for (const row of selectedRows) { + setLoopRunning(true) + const urlParams = new URLSearchParams(modalUrl.split('?')[1]) + for (let [paramName, paramValue] of urlParams.entries()) { + if (paramValue.startsWith('!')) { + urlParams.set(paramName, row[paramValue.replace('!', '')]) } - const NewModalUrl = `${modalUrl.split('?')[0]}?${urlParams.toString()}` - const results = await genericGetRequest({ path: NewModalUrl, refreshParam: row.id }) - resultsarr.push(results) - setMassResults(resultsarr) } - setLoopRunning(false) - }, - }) - } else { - ModalService.confirm({ - body: ( -
- {modalInput && ( -
- -
- )} -
{modalMessage}
-
- ), - title: 'Confirm', - onConfirm: async () => { - const resultsarr = [] - for (const row of selectedRows) { - setLoopRunning(true) - const urlParams = new URLSearchParams(modalUrl.split('?')[1]) - for (let [paramName, paramValue] of urlParams.entries()) { - if (paramValue.toString().startsWith('!')) { - urlParams.set(paramName, row[paramValue.replace('!', '')]) - } + const NewModalUrl = `${modalUrl.split('?')[0]}?${urlParams.toString()}` + const results = await genericGetRequest({ path: NewModalUrl, refreshParam: row.id }) + resultsarr.push(results) + setMassResults(resultsarr) + } + setLoopRunning(false) + }, + }) + } else { + ModalService.confirm({ + body: ( +
+ {modalInput && ( +
+ +
+ )} + {modalDropdown && ( +
+ {dropDownInfo.isSuccess && ( + ({ + value: data[modalDropdown.valueField], + label: data[modalDropdown.labelField], + }))} + /> + )} +
+ )} +
{modalMessage}
+
+ ), + title: 'Confirm', + onConfirm: async () => { + const resultsarr = [] + for (const row of selectedRows) { + setLoopRunning(true) + const urlParams = new URLSearchParams(modalUrl.split('?')[1]) + for (let [paramName, paramValue] of urlParams.entries()) { + if (paramValue.toString().startsWith('!')) { + urlParams.set(paramName, row[paramValue.replace('!', '')]) } - const newModalBody = {} - for (let [objName, objValue] of Object.entries(modalBody)) { - if (objValue.toString().startsWith('!')) { - newModalBody[objName] = row[objValue.replace('!', '')] - } + } + const newModalBody = {} + for (let [objName, objValue] of Object.entries(modalBody)) { + if (objValue.toString().startsWith('!')) { + newModalBody[objName] = row[objValue.replace('!', '')] } - const NewModalUrl = `${modalUrl.split('?')[0]}?${urlParams.toString()}` - const results = await genericPostRequest({ - path: NewModalUrl, - values: { ...modalBody, ...newModalBody, ...{ input: inputRef.current.value } }, - }) - resultsarr.push(results) - setMassResults(resultsarr) } - setLoopRunning(false) - }, - }) + const NewModalUrl = `${modalUrl.split('?')[0]}?${urlParams.toString()}` + const results = await genericPostRequest({ + path: NewModalUrl, + values: { ...modalBody, ...newModalBody, ...{ input: inputRef.current.value } }, + }) + resultsarr.push(results) + setMassResults(resultsarr) + } + setLoopRunning(false) + }, + }) + } + } + const subHeaderComponentMemo = React.useMemo(() => { + const handleClear = () => { + if (filterText) { + setResetPaginationToggle(!resetPaginationToggle) + setFilterText('') } } + const executeselectedAction = (item) => { - handleModal(item.modalMessage, item.modalUrl, item.modalType, item.modalBody, item.modalInput) + setModalContent({ + item, + }) + if (item.modalDropdown) { + getDrowndownInfo({ path: item.modalDropdown.url }) + } + handleModal( + item.modalMessage, + item.modalUrl, + item.modalType, + item.modalBody, + item.modalInput, + item.modalDropdown, + ) } const defaultActions = [] const dataKeys = () => { diff --git a/src/components/tables/index.js b/src/components/tables/index.js index 3358c488e18b..6c45e48aa1c1 100644 --- a/src/components/tables/index.js +++ b/src/components/tables/index.js @@ -4,6 +4,7 @@ import { CellDate, cellDateFormatter } from 'src/components/tables/CellDate' import { CellTip, CellTipButton, CellTipIcon } from 'src/components/tables/CellTip' import { CellNullText, cellNullTextFormatter } from 'src/components/tables/CellNullText' import { CellProgressBar, cellProgressBarFormatter } from 'src/components/tables/CellProgressBar' +import { CellDelegatedPrivilege } from './CellDelegatedPrivilege' import CippDatatable from 'src/components/tables/CippDatatable' import CippOffcanvasTable from 'src/components/tables/CippOffcanvasTable' import CippTable from 'src/components/tables/CippTable' @@ -27,4 +28,5 @@ export { CippOffcanvasTable, CippTable, WizardTableField, + CellDelegatedPrivilege, } diff --git a/src/components/utilities/CippActionsOffcanvas.js b/src/components/utilities/CippActionsOffcanvas.js index bdf28fae5cff..371276f49375 100644 --- a/src/components/utilities/CippActionsOffcanvas.js +++ b/src/components/utilities/CippActionsOffcanvas.js @@ -8,6 +8,7 @@ import { CCardText, CCardTitle, CFormInput, + CFormSelect, CListGroup, CListGroupItem, COffcanvasTitle, @@ -20,17 +21,60 @@ import { useLazyGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 's import { Link, useNavigate } from 'react-router-dom' import { stringCamelCase } from 'src/components/utilities/CippCamelCase' import ReactTimeAgo from 'react-time-ago' +import { useEffect } from 'react' +import { useState } from 'react' export default function CippActionsOffcanvas(props) { const inputRef = useRef('') const [genericGetRequest, getResults] = useLazyGenericGetRequestQuery() const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery() + const [getDrowndownInfo, dropDownInfo] = useLazyGenericGetRequestQuery() + const [modalContent, setModalContent] = useState(null) + + useEffect(() => { + if (dropDownInfo.isFetching) { + handleModal( + , + modalContent.modalUrl, + modalContent.modalType, + modalContent.modalBody, + modalContent.modalInput, + modalContent.modalDropdown, + ) + } + if (dropDownInfo.isSuccess) { + handleModal( + modalContent.modalMessage, + modalContent.modalUrl, + modalContent.modalType, + modalContent.modalBody, + modalContent.modalInput, + modalContent.modalDropdown, + ) + } else if (dropDownInfo.isError) { + handleModal( + 'Error connecting to the API.', + modalContent.modalUrl, + modalContent.modalType, + modalContent.modalBody, + modalContent.modalInput, + modalContent.modalDropdown, + ) + } + }, [dropDownInfo]) const handleLink = useNavigate() const handleExternalLink = (link) => { window.open(link, '_blank') } - const handleModal = (modalMessage, modalUrl, modalType = 'GET', modalBody, modalInput) => { + const handleModal = ( + modalMessage, + modalUrl, + modalType = 'GET', + modalBody, + modalInput, + modalDropdown, + ) => { if (modalType === 'GET') { ModalService.confirm({ body: ( @@ -43,6 +87,7 @@ export default function CippActionsOffcanvas(props) { }) } else { ModalService.confirm({ + key: modalContent, body: (
{modalInput && ( @@ -50,6 +95,19 @@ export default function CippActionsOffcanvas(props) {
)} + {modalDropdown && ( +
+ {dropDownInfo.isSuccess && ( + ({ + value: data[modalDropdown.valueField], + label: data[modalDropdown.labelField], + }))} + /> + )} +
+ )}
{modalMessage}
), @@ -72,6 +130,7 @@ export default function CippActionsOffcanvas(props) { modalType, modalBody, modalInput, + modalDropdown, ) => { if (link) { if (external) { @@ -80,7 +139,12 @@ export default function CippActionsOffcanvas(props) { handleLink(link) } } else if (modal) { - handleModal(modalMessage, modalUrl, modalType, modalBody, modalInput) + if (modalDropdown) { + getDrowndownInfo({ path: modalDropdown.url }) + } + setModalContent({ modalMessage, modalUrl, modalType, modalBody, modalInput, modalDropdown }) + + handleModal(modalMessage, modalUrl, modalType, modalBody, modalInput, modalDropdown) } } @@ -101,7 +165,7 @@ export default function CippActionsOffcanvas(props) { try { cardContent = props.cards.map((action, index) => ( <> - + Report Name: {action.label} @@ -112,9 +176,7 @@ export default function CippActionsOffcanvas(props) { )) - } catch (error) { - console.error('An error occurred building OCanvas actions' + error.toString()) - } + } catch (error) {} const extendedInfoContent = let actionsContent @@ -134,6 +196,7 @@ export default function CippActionsOffcanvas(props) { action.modalType, action.modalBody, action.modalInput, + action.modalDropdown, ) } key={index} @@ -178,6 +241,7 @@ export default function CippActionsOffcanvas(props) { visible={props.visible} id={props.id} hideFunction={props.hideFunction} + refreshFunction={props.refreshFunction} > {getResults.isFetching && ( @@ -231,6 +295,7 @@ const CippActionsOffcanvasPropTypes = { modal: PropTypes.bool, modalUrl: PropTypes.string, modalBody: PropTypes.object, + modalDropdown: PropTypes.object, modalType: PropTypes.string, modalInput: PropTypes.bool, modalMessage: PropTypes.string, @@ -251,6 +316,7 @@ const CippActionsOffcanvasPropTypes = { modalType: PropTypes.string, modalInput: PropTypes.bool, modalMessage: PropTypes.string, + modalDropdown: PropTypes.object, external: PropTypes.bool, }), ), diff --git a/src/components/utilities/CippCodeOffcanvas.js b/src/components/utilities/CippCodeOffcanvas.js new file mode 100644 index 000000000000..c8cdbf175d35 --- /dev/null +++ b/src/components/utilities/CippCodeOffcanvas.js @@ -0,0 +1,68 @@ +import React, { useState } from 'react' +import { CButton, CCallout, CCol, CRow, CSpinner } from '@coreui/react' +import { CippOffcanvas } from 'src/components/utilities' +import { useLazyGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app' + +import { Editor } from '@monaco-editor/react' +import { useSelector } from 'react-redux' + +function CippCodeOffCanvas({ row, state, hideFunction, type }) { + const [SaveTemplate, templateDetails] = useLazyGenericPostRequestQuery() + const currentTheme = useSelector((state) => state.app.currentTheme) + const [templateData, setFormData] = useState(row) + const [invalidJSON, setInvalid] = useState(false) + + function handleEditorChange(value, event) { + try { + setFormData(JSON.parse(value)) + setInvalid(false) + } catch { + setInvalid(true) + } + } + return ( + <> + + + + + + SaveTemplate({ + path: `/api/ExecEditTemplate?type=${type}`, + method: 'POST', + values: templateData, + }) + } + > + Save changes {templateDetails.isFetching && } + + + + {templateDetails.isSuccess && !templateDetails.isFetching && ( + {templateDetails.data.Results} + )} + + + ) +} + +export default CippCodeOffCanvas diff --git a/src/components/utilities/CippFuzzySearch.js b/src/components/utilities/CippFuzzySearch.js new file mode 100644 index 000000000000..a97625dcd818 --- /dev/null +++ b/src/components/utilities/CippFuzzySearch.js @@ -0,0 +1,29 @@ +var _fuse = _interopRequireDefault(require('fuse.js')) + +function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { default: obj } +} + +function CippfuzzySearch(options) { + var fuse = new _fuse['default'](options, { + keys: ['name', 'groupName', 'items.name'], + threshold: 0.5, + location: 0, + ignoreLocation: true, + useExtendedSearch: true, + includeMatches: true, + includeScore: true, + useExtendedSearch: true, + }) + return function (value) { + if (!value.length) { + return options + } + + return fuse.search(value).map((_ref) => { + let { item } = _ref + return item + }) + } +} +export default CippfuzzySearch diff --git a/src/components/utilities/CippOffcanvas.js b/src/components/utilities/CippOffcanvas.js index 624f26c135ba..3148f5992ecb 100644 --- a/src/components/utilities/CippOffcanvas.js +++ b/src/components/utilities/CippOffcanvas.js @@ -8,7 +8,7 @@ export default function CippOffcanvas(props) { return (

{props.title}

- - - + + {props.refreshFunction && ( + { + console.log('refresh') + props.refreshFunction() + }} + > + + + )} + + + +
{props.children}
@@ -33,6 +47,7 @@ export const CippOffcanvasPropTypes = { visible: PropTypes.bool, id: PropTypes.string.isRequired, hideFunction: PropTypes.func.isRequired, + refreshFunction: PropTypes.func, } CippOffcanvas.propTypes = CippOffcanvasPropTypes diff --git a/src/components/utilities/CippTenantOffcanvas.js b/src/components/utilities/CippTenantOffcanvas.js new file mode 100644 index 000000000000..79f249452f6e --- /dev/null +++ b/src/components/utilities/CippTenantOffcanvas.js @@ -0,0 +1,106 @@ +import React, { useState } from 'react' +import { CButton, CTooltip } from '@coreui/react' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faEdit, faEllipsisV, faBuilding } from '@fortawesome/free-solid-svg-icons' +import { CippActionsOffcanvas } from 'src/components/utilities' +import { useLazyGenericGetRequestQuery } from 'src/store/api/app' +import Skeleton from 'react-loading-skeleton' +import Portals from 'src/data/portals' + +export const CippTenantOffcanvasRow = (row, rowIndex, formatExtraData) => { + const tenant = row + return CippTenantOffcanvas({ tenant: row }) +} + +function CippTenantOffcanvas({ tenant, buildingIcon = false }) { + const [getTenantDetails, tenantDetails] = useLazyGenericGetRequestQuery() + const [ocVisible, setOCVisible] = useState(false) + function loadOffCanvasDetails(domainName) { + setOCVisible(true) + getTenantDetails({ path: `api/ListTenantDetails?tenantfilter=${domainName}` }) + } + + function tenantProperty(tenantDetails, propertyName) { + return ( + <> + {tenantDetails.isFetching && } + {!tenantDetails.isFetching && + tenantDetails.isSuccess && + (tenantDetails.data[propertyName]?.toString() ?? ' ')} + + ) + } + const actions = Portals.map((portal) => ({ + icon: , + label: portal.label, + external: true, + color: 'info', + link: portal.url.replace(portal.variable, tenant[portal.variable]), + })) + return ( + <> + + loadOffCanvasDetails(tenant.defaultDomainName)} + > + + + + , + label: 'Edit Tenant', + link: `/tenant/administration/tenants/Edit?tenantFilter=${tenant.defaultDomainName}&customerId=${tenant.customerId}`, + color: 'warning', + }, + ...actions, + ]} + placement="end" + visible={ocVisible} + id={tenant.id} + hideFunction={() => setOCVisible(false)} + /> + + ) +} + +export default CippTenantOffcanvas diff --git a/src/components/utilities/TenantSelector.js b/src/components/utilities/TenantSelector.js index bf4020eceb62..570f2f30c002 100644 --- a/src/components/utilities/TenantSelector.js +++ b/src/components/utilities/TenantSelector.js @@ -9,6 +9,8 @@ import { useNavigate, useSearchParams } from 'react-router-dom' import { queryString } from 'src/helpers' import { faBuilding } from '@fortawesome/free-solid-svg-icons' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import CippTenantOffcanvas from './CippTenantOffcanvas' +import CippfuzzySearch from './CippFuzzySearch' const TenantSelector = ({ action, showAllTenantSelector = true, NavSelector = false }) => { const currentTenant = useSelector((state) => state.app.currentTenant) @@ -57,7 +59,6 @@ const TenantSelector = ({ action, showAllTenantSelector = true, NavSelector = fa return t.customerId === customerId }) dispatch(setCurrentTenant({ tenant: selectedTenant[0] })) - if (typeof action === 'function') { action(selectedTenant[0]) } else { @@ -75,38 +76,44 @@ const TenantSelector = ({ action, showAllTenantSelector = true, NavSelector = fa return ( <> {NavSelector && ( - - - - {currentTenant?.defaultDomainName ? ( - <> - {currentTenant.displayName} - - ) : ( - placeholder - )} - - - ({ - value: customerId, - name: [displayName] + [` (${defaultDomainName})`], - }))} - /> - - + <> + + + {currentTenant?.customerId !== 'AllTenants' ? ( + + ) : ( + + )} + {currentTenant?.defaultDomainName ? ( + <> + {currentTenant.displayName} + + ) : ( + placeholder + )} + + + ({ + value: customerId, + name: `${displayName} (${defaultDomainName})`, + }))} + /> + + + )} {!NavSelector && ( const BestPracticeAnalyzer = React.lazy(() => import('src/views/tenant/standards/BestPracticeAnalyser'), ) +const BPAReportBuilder = React.lazy(() => import('src/views/tenant/standards/BPAReportBuilder')) const DomainsAnalyser = React.lazy(() => import('src/views/tenant/standards/DomainsAnalyser')) const OffboardingWizard = React.lazy(() => import('src/views/identity/administration/OffboardingWizard'), @@ -385,6 +386,11 @@ const routes = [ name: 'Geo IP Lookup', component: GeoIPLookup, }, + { + path: '/tenant/tools/bpa-report-builder', + name: 'BPA Report Builder', + component: BPAReportBuilder, + }, { path: '/tenant/standards/alert-list', name: 'Alert List (Alpha)', component: ListAlerts }, { path: '/endpoint', name: 'Endpoint' }, { path: '/endpoint/applications', name: 'Applications' }, diff --git a/src/scss/_custom.scss b/src/scss/_custom.scss index 95f65a7aa949..4536cb3bab38 100644 --- a/src/scss/_custom.scss +++ b/src/scss/_custom.scss @@ -217,6 +217,9 @@ } } } +.offcanvas-large { + width: 800px !important; +} .cipp-offcanvas { background-color: var(--cui-body-bg); @@ -243,7 +246,7 @@ background-color: var(--cipp-offcanvas-title-bg); color: var(--cipp-offcanvas-title-color); padding-bottom: 1rem; - padding-top: 0.5rem; + padding-top: 1rem; } .cipp-extendedinfo-label { @@ -572,7 +575,6 @@ } .no-colour { - .text-success { color: var(--cui-body-color) !important; } @@ -584,4 +586,28 @@ .teams-wide-card { width: 500px; -} \ No newline at end of file +} + +i.glyphicon { + display: none; +} + +.btn-add::after { + content: 'Add'; +} + +.array-item-copy::after { + content: 'Copy'; +} + +.array-item-move-up::after { + content: 'Move Up'; +} + +.array-item-move-down::after { + content: 'Move Down'; +} + +.array-item-remove::after { + content: 'Remove'; +} diff --git a/src/views/cipp/AppApproval.js b/src/views/cipp/AppApproval.js index 9c957db0707b..66d88991a92b 100644 --- a/src/views/cipp/AppApproval.js +++ b/src/views/cipp/AppApproval.js @@ -112,12 +112,20 @@ const GraphExplorer = () => { Approval Settings - setVisibleA(!visibleA)}> + setVisibleA(!visibleA)} + > - +
+ + +
{ }} /> - - + +
diff --git a/src/views/cipp/CIPPSettings.js b/src/views/cipp/CIPPSettings.js index f3206116d62d..09d06f708953 100644 --- a/src/views/cipp/CIPPSettings.js +++ b/src/views/cipp/CIPPSettings.js @@ -20,6 +20,7 @@ import { CLink, CSpinner, CCardText, + CTooltip, } from '@coreui/react' import { useGenericGetRequestQuery, @@ -80,6 +81,7 @@ import { TitleButton } from 'src/components/buttons' import Skeleton from 'react-loading-skeleton' import { Buffer } from 'buffer' import Extensions from 'src/data/Extensions.json' +import { CellDelegatedPrivilege } from 'src/components/tables/CellDelegatedPrivilege' const CIPPSettings = () => { const [active, setActive] = useState(1) @@ -658,28 +660,34 @@ const ExcludedTenantsSettings = () => { return ( <> {row.Excluded && ( - handleRemoveExclusion(row.defaultDomainName)} - > - - + + handleRemoveExclusion(row.defaultDomainName)} + > + + + )} {!row.Excluded && ( - handleConfirmExcludeTenant({ value: row.customerId })} - > - - + + handleConfirmExcludeTenant({ value: row.customerId })} + > + + + )} - handleCPVPermissions(row)}> - - + + handleCPVPermissions(row)}> + + + ) } @@ -702,25 +710,7 @@ const ExcludedTenantsSettings = () => { name: 'Relationship Type', selector: (row) => row['delegatedPrivilegeStatus'], sortable: true, - cell: (row, index, column) => { - const cell = column.selector(row) - if (!cell) { - return - } - if (cell.toLowerCase() == 'none') { - return - } - if (cell === 'delegatedAdminPrivileges') { - return - } - if (cell === 'delegatedAndGranularDelegetedAdminPrivileges') { - return - } - if (cell === 'granularDelegatedAdminPrivileges') { - return - } - return - }, + cell: (row) => CellDelegatedPrivilege({ cell: row['delegatedPrivilegeStatus'] }), exportSelector: 'delegatedPrivilegeStatus', }, { diff --git a/src/views/cipp/Logs.js b/src/views/cipp/Logs.js index e7733a152fff..b1e93e85d8c8 100644 --- a/src/views/cipp/Logs.js +++ b/src/views/cipp/Logs.js @@ -126,12 +126,20 @@ const Logs = () => { Logbook Settings - setVisibleA(!visibleA)}> + setVisibleA(!visibleA)} + > - + + + + { }} /> - - + +
diff --git a/src/views/email-exchange/connectors/ListConnectorTemplates.js b/src/views/email-exchange/connectors/ListConnectorTemplates.js index 48e8a92ec80b..0923fcb3c923 100644 --- a/src/views/email-exchange/connectors/ListConnectorTemplates.js +++ b/src/views/email-exchange/connectors/ListConnectorTemplates.js @@ -2,17 +2,18 @@ import React, { useState } from 'react' import { useSelector } from 'react-redux' import { CippCodeBlock, CippOffcanvas } from 'src/components/utilities' import { CellTip } from 'src/components/tables' -import { CButton, CCallout, CSpinner } from '@coreui/react' +import { CButton, CCallout, CCol, CRow, CSpinner } from '@coreui/react' import { faEye, faTrash } from '@fortawesome/free-solid-svg-icons' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { useLazyGenericGetRequestQuery } from 'src/store/api/app' import { CippPageList } from 'src/components/layout' import { ModalService } from 'src/components/utilities' import { TitleButton } from 'src/components/buttons' +import { Editor } from '@monaco-editor/react' +import CippCodeOffCanvas from 'src/components/utilities/CippCodeOffcanvas' const ConnectorListTemplates = () => { const tenant = useSelector((state) => state.app.currentTenant) - const [ExecuteGetRequest, getResults] = useLazyGenericGetRequestQuery() const Offcanvas = (row, rowIndex, formatExtraData) => { const [ocVisible, setOCVisible] = useState(false) @@ -44,15 +45,12 @@ const ConnectorListTemplates = () => { - setOCVisible(false)} - > - - + /> ) } diff --git a/src/views/email-exchange/reports/MessageTrace.js b/src/views/email-exchange/reports/MessageTrace.js index c3ef99d51d4f..253aa6821beb 100644 --- a/src/views/email-exchange/reports/MessageTrace.js +++ b/src/views/email-exchange/reports/MessageTrace.js @@ -95,12 +95,20 @@ const MessageTrace = () => { Message Trace Settings - setVisibleA(!visibleA)}> + setVisibleA(!visibleA)} + > - + + + + { }} /> - - + +
diff --git a/src/views/email-exchange/spamfilter/ListSpamfilterTemplates.js b/src/views/email-exchange/spamfilter/ListSpamfilterTemplates.js index 13afb7fa99a4..076a7879c423 100644 --- a/src/views/email-exchange/spamfilter/ListSpamfilterTemplates.js +++ b/src/views/email-exchange/spamfilter/ListSpamfilterTemplates.js @@ -9,6 +9,7 @@ import { useLazyGenericGetRequestQuery } from 'src/store/api/app' import { CippPageList } from 'src/components/layout' import { ModalService } from 'src/components/utilities' import { TitleButton } from 'src/components/buttons' +import CippCodeOffCanvas from 'src/components/utilities/CippCodeOffcanvas' const SpamFilterListTemplates = () => { const tenant = useSelector((state) => state.app.currentTenant) @@ -44,15 +45,12 @@ const SpamFilterListTemplates = () => { - setOCVisible(false)} - > - - + /> ) } diff --git a/src/views/email-exchange/transport/ListTransportTemplates.js b/src/views/email-exchange/transport/ListTransportTemplates.js index 3a8cf38287bd..c0cfb1148979 100644 --- a/src/views/email-exchange/transport/ListTransportTemplates.js +++ b/src/views/email-exchange/transport/ListTransportTemplates.js @@ -9,6 +9,7 @@ import { useLazyGenericGetRequestQuery } from 'src/store/api/app' import { CippPageList } from 'src/components/layout' import { ModalService } from 'src/components/utilities' import { TitleButton } from 'src/components/buttons' +import CippCodeOffCanvas from 'src/components/utilities/CippCodeOffcanvas' const TransportListTemplates = () => { const tenant = useSelector((state) => state.app.currentTenant) @@ -44,15 +45,12 @@ const TransportListTemplates = () => { - setOCVisible(false)} - > - - + /> ) } diff --git a/src/views/endpoint/intune/MEMListPolicyTemplates.js b/src/views/endpoint/intune/MEMListPolicyTemplates.js index 73324c19b7f1..645744383d56 100644 --- a/src/views/endpoint/intune/MEMListPolicyTemplates.js +++ b/src/views/endpoint/intune/MEMListPolicyTemplates.js @@ -16,6 +16,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { useLazyGenericGetRequestQuery } from 'src/store/api/app' import { CippPage } from 'src/components/layout' import { ModalService } from 'src/components/utilities' +import CippCodeOffCanvas from 'src/components/utilities/CippCodeOffcanvas' //todo: expandable with RAWJson property. @@ -52,15 +53,12 @@ const AutopilotListTemplates = () => { > - setOCVisible(false)} - > - - + /> ) } diff --git a/src/views/home/Home.js b/src/views/home/Home.js index 9e3741288987..e3025e587fda 100644 --- a/src/views/home/Home.js +++ b/src/views/home/Home.js @@ -25,6 +25,9 @@ import { ActionContentCard } from 'src/components/contentcards' import { useSelector } from 'react-redux' import allStandardsList from 'src/data/standards' import ReactTimeAgo from 'react-time-ago' +import { CellDelegatedPrivilege } from 'src/components/tables/CellDelegatedPrivilege' +import Portals from 'src/data/portals' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' const Home = () => { const currentTenant = useSelector((state) => state.app.currentTenant) @@ -82,48 +85,12 @@ const Home = () => { }, }) - const actions1 = [ - { - label: 'M365 Admin', - link: `https://portal.office.com/Partner/BeginClientSession.aspx?CTID=${currentTenant.customerId}&CSDEST=o365admincenter`, - target: '_blank', - icon: faCog, - }, - { - label: 'Exchange', - link: `https://admin.exchange.microsoft.com/?landingpage=homepage&form=mac_sidebar&delegatedOrg=${currentTenant.defaultDomainName}#`, - target: '_blank', - icon: faMailBulk, - }, - { - label: 'Intune', - link: `https://intune.microsoft.com/${currentTenant.defaultDomainName}`, - target: '_blank', - icon: faLaptopCode, - }, - { - label: 'Entra', - link: `https://entra.microsoft.com/${currentTenant.defaultDomainName}`, - target: '_blank', - icon: faUsers, - }, - { - label: 'Security', - link: `https://security.microsoft.com/?tid=${currentTenant.customerId}`, - target: '_blank', - icon: faShieldAlt, - }, - { - label: 'Azure', - link: `https://portal.azure.com/#@${currentTenant.customerId}`, - icon: faServer, - }, - { - label: 'Sharepoint', - link: `https://admin.microsoft.com/Partner/beginclientsession.aspx?CTID=${currentTenant.customerId}&CSDEST=SharePoint`, - icon: faBook, - }, - ] + const actions1 = Portals.map((portal) => ({ + icon: portal.icon, + label: portal.label, + target: '_blank', + link: portal.url.replace(portal.variable, currentTenant[portal.variable]), + })) const actions2 = [ { @@ -171,173 +138,188 @@ const Home = () => { - - - -
- {issuccessUserCounts && !isFetchingUserCount ? dashboard?.Users : } -
-
-
- - -
- {issuccessUserCounts && !isFetchingUserCount ? dashboard?.LicUsers : } -
-
-
- - -
{issuccessUserCounts && !isFetchingUserCount ? dashboard?.Gas : }
-
-
- - -
- {issuccessUserCounts && !isFetchingUserCount ? dashboard?.Guests : } -
-
-
-
- - - - - -

Tenant Name

- {currentTenant?.displayName} -
- -

Tenant ID

- {currentTenant?.customerId} -
- -

Default Domain Name

- {currentTenant?.defaultDomainName} -
-
- - -

Tenant Status

- {currentTenant?.delegatedPrivilegeStatus} -
- -

Creation Date

- {(isLoadingOrg || isFetchingOrg) && } - {organization && !isFetchingOrg && organization?.createdDateTime} -
- -

AD Connect Status

- {(isLoadingOrg || isFetchingOrg) && } - {!isLoadingOrg && !isFetchingOrg && organization?.onPremisesSyncEnabled ? ( - <> -
  • - Directory Sync: - {organization?.onPremisesLastSyncDateTime ? ( - - ) : ( - 'Never' - )} -
  • -
  • - Password Sync: - {organization?.onPremisesLastPasswordSyncDateTime ? ( - - ) : ( - 'Never' - )} -
  • - - ) : ( - 'Disabled' - )} -
    -
    - - -

    Domain(s)

    - {(isLoadingOrg || isFetchingOrg) && } - {!isFetchingOrg && - issuccessOrg && - organization?.verifiedDomains?.map((item) =>
  • {item.name}
  • )} -
    - -

    Capabilities

    - {(isLoadingOrg || isFetchingOrg) && } - {!isFetchingOrg && - issuccessOrg && - organization?.assignedPlans - ?.filter((p) => p.capabilityStatus == 'Enabled') - .reduce((plan, curr) => { - if (!plan.includes(curr.service)) { - plan.push(curr.service) - } - return plan - }, []) - .map((plan) => ( + {currentTenant?.customerId !== 'AllTenants' ? ( + <> + + + +
    + {issuccessUserCounts && !isFetchingUserCount ? dashboard?.Users : } +
    +
    +
    + + +
    + {issuccessUserCounts && !isFetchingUserCount ? dashboard?.LicUsers : } +
    +
    +
    + + +
    + {issuccessUserCounts && !isFetchingUserCount ? dashboard?.Gas : } +
    +
    +
    + + +
    + {issuccessUserCounts && !isFetchingUserCount ? dashboard?.Guests : } +
    +
    +
    +
    + + + + + +

    Tenant Name

    + {currentTenant?.displayName} +
    + +

    Tenant ID

    + {currentTenant?.customerId} +
    + +

    Default Domain Name

    + {currentTenant?.defaultDomainName} +
    +
    + + +

    Tenant Status

    + +
    + +

    Creation Date

    + {(isLoadingOrg || isFetchingOrg) && } + {organization && !isFetchingOrg && organization?.createdDateTime} +
    + +

    AD Connect Status

    + {(isLoadingOrg || isFetchingOrg) && } + {!isLoadingOrg && !isFetchingOrg && organization?.onPremisesSyncEnabled ? ( <> - {plan == 'exchange' &&
  • Exchange
  • } - {plan == 'AADPremiumService' &&
  • AAD Premium
  • } - {plan == 'WindowsDefenderATP' &&
  • Windows Defender
  • } +
  • + Directory Sync: + {organization?.onPremisesLastSyncDateTime ? ( + + ) : ( + 'Never' + )} +
  • +
  • + Password Sync: + {organization?.onPremisesLastPasswordSyncDateTime ? ( + + ) : ( + 'Never' + )} +
  • - ))} -
    - -

    Sharepoint Quota

    - {(isLoadingSPQuota || isFetchingSPQuota) && } - {sharepoint && !isFetchingSPQuota && sharepoint?.Dashboard} -
    - -

    Applied Standards

    - {(isLoadingStandards || isFetchingStandards) && } - {issuccessStandards && - !isFetchingStandards && - standards - .filter( - (p) => - p.displayName == 'AllTenants' || - p.displayName == currentTenant.defaultDomainName, - ) - .flatMap((tenant) => { - return Object.keys(tenant.standards).map((standard) => { - const standardDisplayname = allStandardsList.filter((p) => - p.name.includes(standard), - ) - return ( -
  • - {standardDisplayname[0]?.label} ({tenant.displayName}) -
  • + ) : ( + 'Disabled' + )} +
    +
    + + +

    Domain(s)

    + {(isLoadingOrg || isFetchingOrg) && } + {!isFetchingOrg && + issuccessOrg && + organization?.verifiedDomains?.map((item) =>
  • {item.name}
  • )} +
    + +

    Capabilities

    + {(isLoadingOrg || isFetchingOrg) && } + {!isFetchingOrg && + issuccessOrg && + organization?.assignedPlans + ?.filter((p) => p.capabilityStatus == 'Enabled') + .reduce((plan, curr) => { + if (!plan.includes(curr.service)) { + plan.push(curr.service) + } + return plan + }, []) + .map((plan) => ( + <> + {plan == 'exchange' &&
  • Exchange
  • } + {plan == 'AADPremiumService' &&
  • AAD Premium
  • } + {plan == 'WindowsDefenderATP' &&
  • Windows Defender
  • } + + ))} +
    + +

    Sharepoint Quota

    + {(isLoadingSPQuota || isFetchingSPQuota) && } + {sharepoint && !isFetchingSPQuota && sharepoint?.Dashboard} +
    + +

    Applied Standards

    + {(isLoadingStandards || isFetchingStandards) && } + {issuccessStandards && + !isFetchingStandards && + standards + .filter( + (p) => + p.displayName == 'AllTenants' || + p.displayName == currentTenant.defaultDomainName, ) - }) - })} -
    - -

    Partner Relationships

    - {(isLoadingPartners || isFetchingPartners) && } - {issuccessPartners && - !isFetchingPartners && - partners.map((partner) => { - if (partner.TenantInfo) { - return ( -
  • - {partner.TenantInfo.displayName} ({partner.TenantInfo.defaultDomainName}) -
  • - ) - } - })} -
    -
    -
    -
    -
    - - - - - - - - + .flatMap((tenant) => { + return Object.keys(tenant.standards).map((standard) => { + const standardDisplayname = allStandardsList.filter((p) => + p.name.includes(standard), + ) + return ( +
  • + {standardDisplayname[0]?.label} ({tenant.displayName}) +
  • + ) + }) + })} +
    + +

    Partner Relationships

    + {(isLoadingPartners || isFetchingPartners) && } + {issuccessPartners && + !isFetchingPartners && + partners.map((partner) => { + if (partner.TenantInfo) { + return ( +
  • + {partner.TenantInfo.displayName} ( + {partner.TenantInfo.defaultDomainName}) +
  • + ) + } + })} +
    +
    +
    +
    +
    + + + + + + + + + + ) : ( + + + + Select a Tenant to show the dashboard + + + + )} ) } diff --git a/src/views/identity/administration/GroupTemplates.js b/src/views/identity/administration/GroupTemplates.js index 67ce049e327c..590bf91cd3eb 100644 --- a/src/views/identity/administration/GroupTemplates.js +++ b/src/views/identity/administration/GroupTemplates.js @@ -9,6 +9,7 @@ import { useLazyGenericGetRequestQuery } from 'src/store/api/app' import { CippPageList } from 'src/components/layout' import { ModalService } from 'src/components/utilities' import { TitleButton } from 'src/components/buttons' +import CippCodeOffCanvas from 'src/components/utilities/CippCodeOffcanvas' const GroupTemplates = () => { const tenant = useSelector((state) => state.app.currentTenant) @@ -43,15 +44,12 @@ const GroupTemplates = () => { > - setOCVisible(false)} - > - - + /> ) } diff --git a/src/views/identity/administration/OffboardingWizard.js b/src/views/identity/administration/OffboardingWizard.js index 4e6318addf9d..58c425a52b2d 100644 --- a/src/views/identity/administration/OffboardingWizard.js +++ b/src/views/identity/administration/OffboardingWizard.js @@ -45,9 +45,9 @@ const OffboardingWizard = () => { TenantFilter: tenantDomain, OOO: values.OOO ? values.OOO : '', forward: values.forward ? values.forward.value : '', - OnedriveAccess: values.OnedriveAccess ? values.OnedriveAccess.value : '', - AccessNoAutomap: values.AccessNoAutomap ? values.AccessNoAutomap.value : '', - AccessAutomap: values.AccessAutomap ? values.AccessAutomap.value : '', + OnedriveAccess: values.OnedriveAccess ? values.OnedriveAccess : '', + AccessNoAutomap: values.AccessNoAutomap ? values.AccessNoAutomap : '', + AccessAutomap: values.AccessAutomap ? values.AccessAutomap : '', ConvertToShared: values.ConvertToShared, HideFromGAL: values.HideFromGAL, DisableSignIn: values.DisableSignIn, @@ -130,6 +130,7 @@ const OffboardingWizard = () => { x.mail) .map((user) => ({ @@ -143,6 +144,7 @@ const OffboardingWizard = () => { x.mail) .map((user) => ({ @@ -156,6 +158,7 @@ const OffboardingWizard = () => { x.mail) .map((user) => ({ diff --git a/src/views/identity/administration/Users.js b/src/views/identity/administration/Users.js index da5db287e270..4f64168fa419 100644 --- a/src/views/identity/administration/Users.js +++ b/src/views/identity/administration/Users.js @@ -113,6 +113,25 @@ const Offcanvas = (row, rowIndex, formatExtraData) => { modalUrl: `/api/ExecConvertToSharedMailbox?TenantFilter=${tenant.defaultDomainName}&ID=${row.userPrincipalName}`, modalMessage: 'Are you sure you want to convert this user to a shared mailbox?', }, + { + label: 'Add OneDrive Shortcut', + color: 'info', + modal: true, + modalType: 'POST', + modalBody: { + username: row.userPrincipalName, + userid: row.id, + TenantFilter: tenant.defaultDomainName, + message: row.message, + }, + modalUrl: `/api/ExecOneDriveShortCut`, + modalDropdown: { + url: `/api/listSites?TenantFilter=${tenant.defaultDomainName}&type=SharePointSiteUsage`, + labelField: 'URL', + valueField: 'URL', + }, + modalMessage: 'Select the sharepoint site to create a shortcut for', + }, { label: 'Enable Online Archive', color: 'info', @@ -416,6 +435,25 @@ const Users = (row) => { modalUrl: `/api/ExecRevokeSessions?Enable=true&TenantFilter=!Tenant&ID=!userPrincipalName`, modalMessage: 'Are you sure you want to revoke all sessions for these users?', }, + { + label: 'Create OneDrive Shortcut', + color: 'info', + modal: true, + modalType: 'POST', + modalBody: { + username: '!userPrincipalName', + userid: '!id', + TenantFilter: tenant.defaultDomainName, + }, + modalUrl: `/api/ExecOneDriveShortCut`, + modalMessage: + 'Select a SharePoint URL to create a OneDrive shortcut for and press continue.', + modalDropdown: { + url: `/api/listSites?TenantFilter=${tenant.defaultDomainName}&type=SharePointSiteUsage`, + labelField: 'URL', + valueField: 'URL', + }, + }, { label: 'Set Out of Office', color: 'info', diff --git a/src/views/identity/reports/SignIns.js b/src/views/identity/reports/SignIns.js index 7e6ec7fe2488..aea60797072b 100644 --- a/src/views/identity/reports/SignIns.js +++ b/src/views/identity/reports/SignIns.js @@ -125,16 +125,24 @@ const SignInsReport = () => { <> - + Sign In log Settings - setVisibleA(!visibleA)}> + setVisibleA(!visibleA)} + > - + + + + { }} /> - - + +
    diff --git a/src/views/tenant/administration/AlertWizard.js b/src/views/tenant/administration/AlertWizard.js index 40a310af660d..b0d8a9dbdfbf 100644 --- a/src/views/tenant/administration/AlertWizard.js +++ b/src/views/tenant/administration/AlertWizard.js @@ -95,8 +95,8 @@ const AlertWizard = () => {

    - These alerts will be sent to the user or webhook configured in the CIPP notification - settings menu. + Alerts setup on this page will be sent to webhook configured in CIPPs settings, and be + delivered as messages

    { Microsoft sends them to CIPP. These alerts generate a ticket, email or webhook message per alert, with more information about the alert.

    + +

    + "Alerts setup on this page will be sent to the webhook configured in CIPPs settings, and + be delivered as raw json information. Warning: Teams, Slack, and Discord do not support + receiving raw json messages" +

    { Report Settings - setVisibleA(!visibleA)}> + setVisibleA(!visibleA)} + > - + + + + { }} /> - - + +
    diff --git a/src/views/tenant/administration/ListAlertsQueue.js b/src/views/tenant/administration/ListAlertsQueue.js index 8b52ee6d9624..d1da4bb53479 100644 --- a/src/views/tenant/administration/ListAlertsQueue.js +++ b/src/views/tenant/administration/ListAlertsQueue.js @@ -7,6 +7,7 @@ import { CippPageList } from 'src/components/layout' import { ModalService } from 'src/components/utilities' import { useLazyGenericGetRequestQuery } from 'src/store/api/app' import { cellBooleanFormatter } from 'src/components/tables' +import { CellTip } from 'src/components/tables/CellGenericFormat' const ListAlertsQueue = () => { const [ExecuteGetRequest, getResults] = useLazyGenericGetRequestQuery() @@ -75,24 +76,28 @@ const ListAlertsQueue = () => { selector: (row) => row['Expiration'], sortable: true, exportSelector: 'Expiration', + cell: (row) => CellTip(row['Expiration']), }, { name: 'Monitored Resource', selector: (row) => row['Resource'], sortable: true, exportSelector: 'Resource', + cell: (row) => CellTip(row['Resource']), }, { name: 'Monitored Actions', selector: (row) => row['Operations'], sortable: true, exportSelector: 'Operations', + cell: (row) => CellTip(row['Operations']), }, { name: 'Webhook URL', selector: (row) => row['WebhookNotificationUrl'], sortable: true, exportSelector: 'WebhookNotificationUrl', + cell: (row) => CellTip(row['WebhookNotificationUrl']), }, { name: 'Actions', @@ -255,7 +260,7 @@ const ListAlertsQueue = () => { label: 'Delete alerts', color: 'info', modal: true, - modalUrl: `/api/RemoveQueuedAlert?ID=!tenantId`, + modalUrl: `/api/RemoveQueuedAlert?ID=!tenantid`, modalMessage: 'Are you sure you want to delete these alerts?', }, ], @@ -281,7 +286,7 @@ const ListAlertsQueue = () => { label: 'Delete webhook', color: 'info', modal: true, - modalUrl: `/api/RemoveWebhookAlert?CIPPID=!CIPPID&tenantfilter=!tenantid`, + modalUrl: `/api/RemoveWebhookAlert?CIPPID=!CIPPID&tenantfilter=!tenantName`, modalMessage: 'Are you sure you want to delete this webhook alert?', }, ], diff --git a/src/views/tenant/administration/Tenants.js b/src/views/tenant/administration/Tenants.js index 3347f1f84471..24b700a30f08 100644 --- a/src/views/tenant/administration/Tenants.js +++ b/src/views/tenant/administration/Tenants.js @@ -1,106 +1,12 @@ import React, { useState } from 'react' import { useSelector } from 'react-redux' -import { CButton } from '@coreui/react' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { - faCheckCircle, - faCog, - faEdit, - faEllipsisV, - faExclamationTriangle, -} from '@fortawesome/free-solid-svg-icons' +import { faCog } from '@fortawesome/free-solid-svg-icons' import { CippPageList } from 'src/components/layout' -import { CellTip, CellTipIcon } from 'src/components/tables' -import { CippActionsOffcanvas } from 'src/components/utilities' -import { useLazyGenericGetRequestQuery } from 'src/store/api/app' -import Skeleton from 'react-loading-skeleton' +import { CellTip } from 'src/components/tables' import { TitleButton } from 'src/components/buttons' import Portals from 'src/data/portals' - -const Offcanvas = (row, rowIndex, formatExtraData) => { - const [getTenantDetails, tenantDetails] = useLazyGenericGetRequestQuery() - const [ocVisible, setOCVisible] = useState(false) - - function loadOffCanvasDetails(domainName) { - setOCVisible(true) - getTenantDetails({ path: `api/ListTenantDetails?tenantfilter=${domainName}` }) - } - - function tenantProperty(tenantDetails, propertyName) { - return ( - <> - {tenantDetails.isFetching && } - {!tenantDetails.isFetching && - tenantDetails.isSuccess && - (tenantDetails.data[propertyName]?.toString() ?? ' ')} - - ) - } - const actions = Portals.map((portal) => ({ - icon: , - label: portal.label, - external: true, - color: 'info', - link: portal.url.replace(portal.variable, row[portal.variable]), - })) - return ( - <> - loadOffCanvasDetails(row.defaultDomainName)}> - - - , - label: 'Edit Tenant', - link: `/tenant/administration/tenants/Edit?tenantFilter=${row.defaultDomainName}&customerId=${row.customerId}`, - color: 'warning', - }, - ...actions, - ]} - placement="end" - visible={ocVisible} - id={row.id} - hideFunction={() => setOCVisible(false)} - /> - - ) -} +import { CippTenantOffcanvasRow } from 'src/components/utilities/CippTenantOffcanvas' const TenantsList = () => { const TenantListSelector = useSelector((state) => state.app.TenantListSelector) @@ -119,7 +25,7 @@ const TenantsList = () => { className="dlink" rel="noreferrer" > - + ), }) @@ -148,7 +54,7 @@ const TenantsList = () => { { name: 'Actions', center: true, - cell: Offcanvas, + cell: CippTenantOffcanvasRow, }, ] const titleButton = ( diff --git a/src/views/tenant/conditional/ListCATemplates.js b/src/views/tenant/conditional/ListCATemplates.js index f19472d10587..835ed3fef2ff 100644 --- a/src/views/tenant/conditional/ListCATemplates.js +++ b/src/views/tenant/conditional/ListCATemplates.js @@ -17,6 +17,7 @@ import { useLazyGenericGetRequestQuery } from 'src/store/api/app' import { CippPage } from 'src/components/layout' import { ModalService } from 'src/components/utilities' import { CellTip } from 'src/components/tables' +import CippCodeOffCanvas from 'src/components/utilities/CippCodeOffcanvas' //todo: expandable with RAWJson property. @@ -53,15 +54,12 @@ const AutopilotListTemplates = () => { > - setOCVisible(false)} - > - - + /> ) } diff --git a/src/views/tenant/standards/BPAReportBuilder.js b/src/views/tenant/standards/BPAReportBuilder.js new file mode 100644 index 000000000000..b649a86556d6 --- /dev/null +++ b/src/views/tenant/standards/BPAReportBuilder.js @@ -0,0 +1,264 @@ +import React, { useState, useEffect, useRef } from 'react' +import { CippPage } from 'src/components/layout' +import BPAReportSchema from 'src/data/BPAReport.schema.v1' +import BPAReportUISchema from 'src/data/BPAReport.uischema.v1' +import validator from '@rjsf/validator-ajv8' +import Form from '@rjsf/bootstrap-4' +import { CippContentCard } from 'src/components/layout' +import Editor from '@monaco-editor/react' +import { useSelector } from 'react-redux' +import useQuery from 'src/hooks/useQuery' +import { + CFormInput, + CFormSelect, + CFormSwitch, + CRow, + CCol, + CCard, + CCardHeader, + CCardTitle, + CButton, + CCollapse, + CCardBody, + CForm, + CSpinner, + CFormLabel, + CTooltip, +} from '@coreui/react' +import { useGenericGetRequestQuery } from 'src/store/api/app' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import CopyToClipboard from 'react-copy-to-clipboard' + +const CippTextWidget = (props) => { + return ( + props.onChange(event.target.value)} + /> + ) +} +const CippSelectWidget = (props) => { + const options = props?.options.length > 0 ? props.options : props.options.enumOptions + return ( + props.onChange(event.target.value)} + > + {options.map(({ label, value }, idx) => ( + + ))} + + ) +} + +const CippCheckboxWidget = (props) => { + return ( + { + props.onChange(event.target.checked) + }} + /> + ) +} +const CippWidgets = { + TextWidget: CippTextWidget, + SelectWidget: CippSelectWidget, + CheckboxWidget: CippCheckboxWidget, +} + +const BPAReportBuilder = () => { + let query = useQuery() + const [refreshValue, setRefreshValue] = useState('') + const Report = query.get('Report') + const [filename, setFilename] = useState() + const [visibleA, setVisibleA] = useState(true) + const { data: templates = [], isLoading: templatesfetch } = useGenericGetRequestQuery({ + path: 'api/listBPATemplates?RawJson=true&Refresh=' + refreshValue, + }) + const [formData, setFormData] = useState(null) + const editorRef = useRef(null) + const currentTheme = useSelector((state) => state.app.currentTheme) + + function handleRefresh() { + setRefreshValue((Math.random() + 1).toString(36).substring(7)) + } + + function handleEditorChange(value, event) { + try { + setFormData(JSON.parse(value)) + } catch { + setFormData({}) + } + } + const handleSubmit = async (event) => { + event.preventDefault() + var reportTemplate = event.target.form[0].value + setVisibleA(false) + if (reportTemplate !== 'New') { + var template = templates.filter(function (tpl) { + return tpl.name == reportTemplate + }) + setFormData(template[0]) + } else { + setFormData({}) + } + } + useEffect(() => { + var reportName = formData?.name ? formData?.name?.replace(/[\W]/g, '') : 'NewReport' + var newfilename = reportName + '.BPATemplate.json' + setFilename(newfilename) + }, [filename, formData]) + + const handlePublish = async (event) => { + event.preventDefault() + const data = new FormData(event.target) + const ghuser = data.get('GitHubUser') + const reportfilename = data.get('ReportFilename') + const report = JSON.stringify(formData, null, 2) + const url = + 'https://github.com/' + ghuser + '/CIPP-API/new/master/Config?filename=' + reportfilename + window.open(url, '_blank') + } + + const options = { + wordWrap: true, + } + + return ( + + + + + + + Report Settings + setVisibleA(!visibleA)} + > + + + + + + + + + + + + + + + Load Existing Report + + + {templates.map((template, idx) => ( + + ))} + + + {templatesfetch && } + + + + + + Load Report + + + + + + + + + + + + + GitHub Username/Org Name + + Report Filename + + + + + + + + + + Publish + + + + + + + + + + + + + +
    + + + + setFormData(e.formData)} + enable={true} + showErrorList="none" + omitExtraData={true} + liveOmit={true} + widgets={CippWidgets} + /> + + + + + + + + +
    + ) +} + +export default BPAReportBuilder diff --git a/src/views/tenant/standards/BestPracticeAnalyser.js b/src/views/tenant/standards/BestPracticeAnalyser.js index 68356121e425..a18f42909746 100644 --- a/src/views/tenant/standards/BestPracticeAnalyser.js +++ b/src/views/tenant/standards/BestPracticeAnalyser.js @@ -198,7 +198,7 @@ const BestPracticeAnalyser = () => { name: col.name, selector: (row) => getNestedValue(row, col.value), sortable: true, - exportSelector: col.value, + exportSelector: col.value.split('.').join('/'), cell: cellSelector, // Use the determined cell selector }) }) @@ -226,12 +226,20 @@ const BestPracticeAnalyser = () => { Report Settings - setVisibleA(!visibleA)}> + setVisibleA(!visibleA)} + > - + + + + { }} /> - - + +

    diff --git a/src/views/tenant/standards/ListAppliedStandards.js b/src/views/tenant/standards/ListAppliedStandards.js index 01cd41c41be2..94bcc688001b 100644 --- a/src/views/tenant/standards/ListAppliedStandards.js +++ b/src/views/tenant/standards/ListAppliedStandards.js @@ -482,7 +482,7 @@ const ListAppliedStandards = () => { name: template.Displayname, }))} placeholder="Select a template" - label="Choose your intune templates to apply" + label="Choose your group templates to apply" /> )} diff --git a/version_latest.txt b/version_latest.txt index 99eba4de9311..d87edbfc1069 100644 --- a/version_latest.txt +++ b/version_latest.txt @@ -1 +1 @@ -4.1.0 \ No newline at end of file +4.2.1 \ No newline at end of file