diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 67486a3f3..319b38942 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -5,12 +5,15 @@ "packages": { "": { "dependencies": { + "@reduxjs/toolkit": "1.9.5", "core-js": "3.6.5", + "js-cookie": "3.0.5", "mattermost-redux": "5.27.0", "react": "18.2.0", "react-bootstrap": "2.8.0", "react-dom": "18.2.0", "react-redux": "7.2.0", + "react-select": "5.7.4", "redux": "4.0.5", "typescript": "5.1.6" }, @@ -115,7 +118,6 @@ "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", - "dev": true, "dependencies": { "@babel/highlight": "^7.22.5" }, @@ -311,7 +313,6 @@ "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", - "dev": true, "dependencies": { "@babel/types": "^7.22.5" }, @@ -434,7 +435,6 @@ "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -443,7 +443,6 @@ "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -490,7 +489,6 @@ "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", - "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.5", "chalk": "^2.0.0", @@ -1706,7 +1704,6 @@ "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.22.5", "@babel/helper-validator-identifier": "^7.22.5", @@ -1738,6 +1735,24 @@ "node": ">=0.1.95" } }, + "node_modules/@emotion/babel-plugin": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/serialize": "^1.1.2", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, "node_modules/@emotion/babel-plugin-jsx-pragmatic": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/@emotion/babel-plugin-jsx-pragmatic/-/babel-plugin-jsx-pragmatic-0.1.5.tgz", @@ -1750,6 +1765,94 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@emotion/babel-plugin/node_modules/@babel/runtime": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz", + "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==", + "dependencies": { + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/serialize": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.2.tgz", + "integrity": "sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==", + "dependencies": { + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + }, + "node_modules/@emotion/babel-plugin/node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + }, + "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@emotion/babel-preset-css-prop": { "version": "10.0.27", "resolved": "https://registry.npmjs.org/@emotion/babel-preset-css-prop/-/babel-preset-css-prop-10.0.27.tgz", @@ -1876,6 +1979,99 @@ "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", "dev": true }, + "node_modules/@emotion/react": { + "version": "11.11.1", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.1.tgz", + "integrity": "sha512-5mlW1DquU5HaxjLkfkGN1GA/fvVGdyHURRiX/0FHl2cfIfRxSOfmxEH5YS43edp0OldZrZ+dkBKbngxcNCdZvA==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.2", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/react/node_modules/@babel/runtime": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz", + "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==", + "dependencies": { + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emotion/react/node_modules/@emotion/cache": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", + "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", + "dependencies": { + "@emotion/memoize": "^0.8.1", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/react/node_modules/@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, + "node_modules/@emotion/react/node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/react/node_modules/@emotion/serialize": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.2.tgz", + "integrity": "sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==", + "dependencies": { + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/react/node_modules/@emotion/sheet": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", + "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" + }, + "node_modules/@emotion/react/node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, + "node_modules/@emotion/react/node_modules/@emotion/utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + }, + "node_modules/@emotion/react/node_modules/@emotion/weak-memoize": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" + }, + "node_modules/@emotion/react/node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + }, "node_modules/@emotion/serialize": { "version": "0.11.16", "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-0.11.16.tgz", @@ -1907,6 +2103,14 @@ "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==", "dev": true }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/@emotion/utils": { "version": "0.11.3", "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-0.11.3.tgz", @@ -1919,6 +2123,28 @@ "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==", "dev": true }, + "node_modules/@floating-ui/core": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.4.1.tgz", + "integrity": "sha512-jk3WqquEJRlcyu7997NtR5PibI+y5bi+LS3hPmguVClypenMsCY3CBa3LAQnozRCtCrYWSEtAdiskpamuJRFOQ==", + "dependencies": { + "@floating-ui/utils": "^0.1.1" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.1.tgz", + "integrity": "sha512-KwvVcPSXg6mQygvA1TjbN/gh///36kKtllIF8SUm0qpFj8+rvYrpvlYdL1JoA71SHpDqgSSdGOSoQ0Mp3uY5aw==", + "dependencies": { + "@floating-ui/core": "^1.4.1", + "@floating-ui/utils": "^0.1.1" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.1.tgz", + "integrity": "sha512-m0G6wlnhm/AX0H12IOWtK8gASEMffnX08RtKkCgTdHb9JpHKGloI7icFfLg9ZmQeavcvR0PKmzxClyuFPSjKWw==" + }, "node_modules/@formatjs/ecma402-abstract": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.17.0.tgz", @@ -2898,6 +3124,37 @@ "react-native": ">=0.59" } }, + "node_modules/@reduxjs/toolkit": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.5.tgz", + "integrity": "sha512-Rt97jHmfTeaxL4swLRNPD/zV4OxTes4la07Xc4hetpUW/vc75t5m1ANyxG6ymnEQ2FsLQsoMlYB2vV1sO3m8tQ==", + "dependencies": { + "immer": "^9.0.21", + "redux": "^4.2.1", + "redux-thunk": "^2.4.2", + "reselect": "^4.1.8" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18", + "react-redux": "^7.2.1 || ^8.0.2" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, + "node_modules/@reduxjs/toolkit/node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, "node_modules/@restart/hooks": { "version": "0.4.9", "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.9.tgz", @@ -3115,8 +3372,7 @@ "node_modules/@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" }, "node_modules/@types/prettier": { "version": "2.7.3", @@ -3200,7 +3456,6 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.0.tgz", "integrity": "sha512-/QfLHGpu+2fQOqQaXh8MG9q03bFENooTb/it4jr5kKaZlDQfWvjqWZg48AwzPVMBHlRuTRAY7hRHCEOXz5kV6w==", - "dev": true, "dependencies": { "@types/react": "*" } @@ -3800,7 +4055,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -5002,7 +5256,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, "engines": { "node": ">=6" } @@ -5080,7 +5333,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -5331,7 +5583,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "dependencies": { "color-name": "1.1.3" } @@ -5339,8 +5590,7 @@ "node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/combined-stream": { "version": "1.0.8", @@ -5431,8 +5681,7 @@ "node_modules/convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, "node_modules/cookiejar": { "version": "2.1.4", @@ -5564,6 +5813,12 @@ "integrity": "sha512-Arj1hncvEVqQ2p7Ega08uHLr1JuRYBuO5cIvcA+WWEQ5+VmkOE3ZXzl04NbQxeQpWX78G7u6MqxKuNX3wvYZxg==", "dev": true }, + "node_modules/create-emotion/node_modules/stylis": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz", + "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==", + "dev": true + }, "node_modules/create-hash": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", @@ -6399,7 +6654,6 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, "dependencies": { "is-arrayish": "^0.2.1" } @@ -6511,7 +6765,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, "engines": { "node": ">=0.8.0" } @@ -7492,8 +7745,7 @@ "node_modules/find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", - "dev": true + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" }, "node_modules/find-up": { "version": "4.1.0", @@ -7833,8 +8085,7 @@ "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "node_modules/function.prototype.name": { "version": "1.1.5", @@ -8265,7 +8516,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "dependencies": { "function-bind": "^1.1.1" }, @@ -8307,7 +8557,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, "engines": { "node": ">=4" } @@ -8796,11 +9045,19 @@ "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", "dev": true }, + "node_modules/immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -8816,7 +9073,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, "engines": { "node": ">=4" } @@ -9050,8 +9306,7 @@ "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" }, "node_modules/is-bigint": { "version": "1.0.4", @@ -9128,7 +9383,6 @@ "version": "2.12.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", - "dev": true, "dependencies": { "has": "^1.0.3" }, @@ -11615,6 +11869,14 @@ "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", "dev": true }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "engines": { + "node": ">=14" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -11729,8 +11991,7 @@ "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "node_modules/json-schema": { "version": "0.4.0", @@ -11901,8 +12162,7 @@ "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, "node_modules/linked-list": { "version": "0.1.0", @@ -12388,6 +12648,12 @@ "lodash-es": "^4.17.4" } }, + "node_modules/mattermost-webapp/node_modules/memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", + "dev": true + }, "node_modules/mattermost-webapp/node_modules/mime-db": { "version": "1.40.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", @@ -12545,6 +12811,41 @@ "redux": "^2.0.0 || ^3.0.0 || ^4.0.0-0" } }, + "node_modules/mattermost-webapp/node_modules/react-select": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/react-select/-/react-select-2.4.4.tgz", + "integrity": "sha512-C4QPLgy9h42J/KkdrpVxNmkY6p4lb49fsrbDk/hRcZpX7JvZPNb6mGj+c5SzyEtBv1DmQ9oPH4NmhAFvCrg8Jw==", + "dev": true, + "dependencies": { + "classnames": "^2.2.5", + "emotion": "^9.1.2", + "memoize-one": "^5.0.0", + "prop-types": "^15.6.0", + "raf": "^3.4.0", + "react-input-autosize": "^2.2.1", + "react-transition-group": "^2.2.1" + }, + "peerDependencies": { + "react": "^15.3.0 || ^16.0.0", + "react-dom": "^15.3.0 || ^16.0.0" + } + }, + "node_modules/mattermost-webapp/node_modules/react-select/node_modules/react-transition-group": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz", + "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==", + "dev": true, + "dependencies": { + "dom-helpers": "^3.4.0", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2", + "react-lifecycles-compat": "^3.0.4" + }, + "peerDependencies": { + "react": ">=15.0.0", + "react-dom": ">=15.0.0" + } + }, "node_modules/mattermost-webapp/node_modules/redux": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.4.tgz", @@ -12620,10 +12921,9 @@ } }, "node_modules/memoize-one": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", - "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", - "dev": true + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" }, "node_modules/memory-fs": { "version": "0.2.0", @@ -13947,7 +14247,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, "dependencies": { "callsites": "^3.0.0" }, @@ -13987,7 +14286,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -14087,8 +14385,7 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-to-regexp": { "version": "1.8.0", @@ -14109,7 +14406,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, "engines": { "node": ">=8" } @@ -15089,47 +15385,81 @@ } }, "node_modules/react-select": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/react-select/-/react-select-2.4.4.tgz", - "integrity": "sha512-C4QPLgy9h42J/KkdrpVxNmkY6p4lb49fsrbDk/hRcZpX7JvZPNb6mGj+c5SzyEtBv1DmQ9oPH4NmhAFvCrg8Jw==", - "dev": true, - "dependencies": { - "classnames": "^2.2.5", - "emotion": "^9.1.2", - "memoize-one": "^5.0.0", + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.7.4.tgz", + "integrity": "sha512-NhuE56X+p9QDFh4BgeygHFIvJJszO1i1KSkg/JPcIJrbovyRtI+GuOEa4XzFCEpZRAEoEI8u/cAHK+jG/PgUzQ==", + "dependencies": { + "@babel/runtime": "^7.12.0", + "@emotion/cache": "^11.4.0", + "@emotion/react": "^11.8.1", + "@floating-ui/dom": "^1.0.1", + "@types/react-transition-group": "^4.4.0", + "memoize-one": "^6.0.0", "prop-types": "^15.6.0", - "raf": "^3.4.0", - "react-input-autosize": "^2.2.1", - "react-transition-group": "^2.2.1" + "react-transition-group": "^4.3.0", + "use-isomorphic-layout-effect": "^1.1.2" }, "peerDependencies": { - "react": "^15.3.0 || ^16.0.0", - "react-dom": "^15.3.0 || ^16.0.0" + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/react-select/node_modules/dom-helpers": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz", - "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==", - "dev": true, + "node_modules/react-select/node_modules/@babel/runtime": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz", + "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==", "dependencies": { - "@babel/runtime": "^7.1.2" + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/react-select/node_modules/@emotion/cache": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", + "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", + "dependencies": { + "@emotion/memoize": "^0.8.1", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "stylis": "4.2.0" } }, + "node_modules/react-select/node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/react-select/node_modules/@emotion/sheet": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", + "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" + }, + "node_modules/react-select/node_modules/@emotion/utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + }, + "node_modules/react-select/node_modules/@emotion/weak-memoize": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" + }, "node_modules/react-select/node_modules/react-transition-group": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz", - "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==", - "dev": true, + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", "dependencies": { - "dom-helpers": "^3.4.0", + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", "loose-envify": "^1.4.0", - "prop-types": "^15.6.2", - "react-lifecycles-compat": "^3.0.4" + "prop-types": "^15.6.2" }, "peerDependencies": { - "react": ">=15.0.0", - "react-dom": ">=15.0.0" + "react": ">=16.6.0", + "react-dom": ">=16.6.0" } }, "node_modules/react-test-renderer": { @@ -15604,6 +15934,14 @@ "node-localstorage": "^1.3.0" } }, + "node_modules/redux-thunk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", + "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", + "peerDependencies": { + "redux": "^4" + } + }, "node_modules/reflect.ownkeys": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz", @@ -15894,11 +16232,15 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true }, + "node_modules/reselect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" + }, "node_modules/resolve": { "version": "1.22.2", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", - "dev": true, "dependencies": { "is-core-module": "^2.11.0", "path-parse": "^1.0.7", @@ -17073,7 +17415,6 @@ "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -17553,10 +17894,9 @@ } }, "node_modules/stylis": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz", - "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==", - "dev": true + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" }, "node_modules/stylis-rule-sheet": { "version": "0.0.10", @@ -17646,7 +17986,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -17692,7 +18031,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -17994,7 +18332,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, "engines": { "node": ">=4" } @@ -18684,6 +19021,19 @@ "node": ">=0.10.0" } }, + "node_modules/use-isomorphic-layout-effect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", + "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/util": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", @@ -19908,7 +20258,6 @@ "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, "engines": { "node": ">= 6" } diff --git a/webapp/package.json b/webapp/package.json index 5d6fd4599..7f69f2a23 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -61,12 +61,15 @@ "webpack-cli": "3.3.12" }, "dependencies": { + "@reduxjs/toolkit": "1.9.5", "core-js": "3.6.5", + "js-cookie": "3.0.5", "mattermost-redux": "5.27.0", "react": "18.2.0", - "react-dom": "18.2.0", "react-bootstrap": "2.8.0", + "react-dom": "18.2.0", "react-redux": "7.2.0", + "react-select": "5.7.4", "redux": "4.0.5", "typescript": "5.1.6" }, diff --git a/webapp/src/api/api_wrapper.ts b/webapp/src/api/api_wrapper.ts new file mode 100644 index 000000000..5c3ba7a91 --- /dev/null +++ b/webapp/src/api/api_wrapper.ts @@ -0,0 +1,20 @@ +import Utils from 'utils'; + +export const fetchChannels = async (mmSiteUrl: string) => { + const url = Utils.getBaseUrls(mmSiteUrl).mattermostApiBaseUrl + '/channels?exclude_default_channels=true'; + const response = await fetch(url, { + method: 'GET', + headers: {Authentication: Utils.getAuthToken()}, + }); + return response.json(); +}; + +export const fetchTeams = async (mmSiteUrl: string) => { + const url = Utils.getBaseUrls(mmSiteUrl).mattermostApiBaseUrl + '/teams'; + const response = await fetch(url, { + method: 'GET', + headers: {Authentication: Utils.getAuthToken()}, + }); + return response.json(); +}; + diff --git a/webapp/src/components/modals/actionModal.tsx b/webapp/src/components/modals/actionModal.tsx new file mode 100644 index 000000000..95a54162c --- /dev/null +++ b/webapp/src/components/modals/actionModal.tsx @@ -0,0 +1,163 @@ +import React, {useEffect, useState} from 'react'; + +import Button from 'react-bootstrap/Button'; +import Modal from 'react-bootstrap/Modal'; +import Table from 'react-bootstrap/Table'; +import Form from 'react-bootstrap/Form'; +import {OverlayTrigger, Tooltip} from 'react-bootstrap'; + +import './styles.scss'; + +type Props = { + visibility: boolean; + setVisibility: React.Dispatch>; + config: Configs[]; + configIndex: number; +} + +const ActionModal = ({visibility, setVisibility, config, configIndex}: Props) => { + const [attachmentMessageAvailable, setAttachmentMessageAvailable] = useState(false); + + const actionsLength = config[configIndex]?.actions?.length; + + const checkAttachmentMessage = () => { + if (config[configIndex]?.attachmentMessage?.length) { + setAttachmentMessageAvailable(Boolean(config[configIndex]?.attachmentMessage?.[0])); + return; + } + + setAttachmentMessageAvailable(false); + }; + + useEffect(() => { + checkAttachmentMessage(); + }, []); + + const handleClose = () => setVisibility(false); + + return ( + + + {'Actions'} + + + + {attachmentMessageAvailable || (config[configIndex]?.actions && actionsLength) ? (<> + {attachmentMessageAvailable ? ( +
+ + {'Attachment Message'} + + +
+ ) : (

{'No attachment message configured'}

) + } + {config[configIndex]?.actions && actionsLength ? ( +
+
+ + {'Actions'} + +
+
+ + + + + + + + + + + + { + config[configIndex].actions?.map((val, i) => + ( + + + + + + + + ), + ) + } + +
{'Type'}{'Display Name'}{'Name'}{'Add to Channels'}{'Success Message'}
+ {val.actionType}} + > +

+ {val.actionType} +

+
+
+ {val.actionDisplayName}} + > +

+ {val.actionDisplayName} +

+
+
+ {val.actionName}} + > +

+ {val.actionName} +

+
+
+ {val.channelsAddedTo.join(', ')}} + > +

+ {val.channelsAddedTo.join(', ')} +

+
+
+ {val.actionSuccessfullMessage.join(',')}} + > +

+ {val.actionSuccessfullMessage.join(',')} +

+
+
+
+
+ ) : (

{'No action configured'}

) + } + ) : (

{'No attachment message or action configured'}

)} +
+ + + + +
+ ); +}; + +export default ActionModal; diff --git a/webapp/src/components/modals/configModal.tsx b/webapp/src/components/modals/configModal.tsx new file mode 100644 index 000000000..c7f05a437 --- /dev/null +++ b/webapp/src/components/modals/configModal.tsx @@ -0,0 +1,760 @@ +import React, {useEffect, useState} from 'react'; + +import Button from 'react-bootstrap/Button'; +import Modal from 'react-bootstrap/Modal'; +import Form from 'react-bootstrap/Form'; +import Table from 'react-bootstrap/Table'; +import ButtonGroup from 'react-bootstrap/ButtonGroup'; +import {OverlayTrigger, Tooltip, ToggleButton} from 'react-bootstrap'; + +import Select, {MultiValue, SingleValue} from 'react-select'; + +import {useSelector} from 'react-redux'; + +import {GlobalState} from 'mattermost-redux/types/store'; + +import {fetchChannels, fetchTeams} from 'api/api_wrapper'; + +import {DeleteSvg, EditSvg} from '../svgIcons/svg'; + +import './styles.scss'; + +type Props = { + visibility: boolean; + setVisibility: React.Dispatch>; + configIndex: number | null; + config: Configs[]; + onChange: (config: Configs[]) => void; + modalHeader: string; +} + +const ConfigModal = ({visibility, setVisibility, configIndex, config, onChange, modalHeader}: Props) => { + const guest = [ + {name: 'true', value: 'true'}, + {name: 'false', value: 'false'}, + ]; + const actionTypes = [ + {name: 'button', value: 'button'}, + {name: 'automatic', value: 'automatic'}, + ]; + + const actionElement: Actions = { + actionType: '', + actionName: '', + actionDisplayName: '', + channelsAddedTo: [''], + actionSuccessfullMessage: [''], + }; + + const newAction: Actions[] = []; + + const newConfig: Configs = { + teamName: '', + delayInSeconds: 0, + message: [''], + includeGuests: '', + attachmentMessage: [''], + actions: newAction, + }; + + const [show, setShow] = useState(true); + const [isConfigVisible, setIsConfigVisible] = useState(true); + const [isActionVisible, setIsActionVisible] = useState(false); + const [isDeleteVisible, setIsDeleteVisible] = useState(false); + + const [existingConfig, setExistingConfig] = useState(configIndex === null ? newConfig : config[configIndex]); + + const [teamName, setTeamName] = useState(existingConfig.teamName); + const [delay, setDelay] = useState(existingConfig.delayInSeconds); + const [message, setMessage] = useState(existingConfig.message); + const [attachmentMessage, setAttachmentMessage] = useState(existingConfig.attachmentMessage ?? ['']); + const [guestValue, setGuestValue] = useState(existingConfig.includeGuests); + + const [actionTypesValue, setActionTypesValue] = useState(''); + const [actionDisplayName, setActionDisplayName] = useState(''); + const [actionChannelsAddedTo, setActionChannelsAddedTo] = useState(['']); + const [actionSuccessfullMessage, setActionSuccessfullMessage] = useState(['']); + const [actionName, setActionName] = useState(''); + const [actionIndex, setActionIndex] = useState(0); + + const [teamNameValid, setTeamNameValid] = useState(false); + const [messageValid, setMessageValid] = useState(false); + const [delayValid, setDelayValid] = useState(false); + + const [actionTypesValueValid, setActionTypesValueValid] = useState(false); + const [actionDisplayNameValid, setActionDisplayNameValid] = useState(false); + const [actionChannelsAddedToValid, setActionChannelsAddedToValid] = useState(false); + const [actionSuccessfullMessageValid, setActionSuccessfullMessageValid] = useState(false); + const [actionNameValid, setActionNameValid] = useState(false); + + const [validated, setValidated] = useState(false); + + const [deleteAction, setDeleteAction] = useState(''); + + const [selectedTeam, setSelectedTeam] = useState(''); + + const [teamSelectionWarning, setTeamSelectionWarning] = useState(false); + + const [actionClicked, setActionClicked] = useState(false); + + const [teamOptionList, setTeamOptionList] = useState([]); + const [channelOptionList, setChannelOptionList] = useState([]); + + const [teamDropdownDisabled, setTeamDropdownDisabled] = useState(false); + const [teamApiCalled, setTeamApiCalled] = useState(true); + const [teamApiError, setTeamApiError] = useState(''); + + const [chanelDropdownDisabled, setChannelDropdownDisabled] = useState(false); + const [channelApiCalled, setChannelApiCalled] = useState(true); + const [channelApiError, setChannelApiError] = useState(''); + + const actionLength = existingConfig?.actions?.length ?? 0; + + const reduxState = useSelector((state: GlobalState) => state); + const mmSiteUrl = reduxState?.entities?.general?.config?.SiteURL as string; + + useEffect(() => { + setShow(visibility); + setIsConfigVisible(visibility); + }, [visibility]); + + useEffect(() => { + setExistingConfig(configIndex === null ? newConfig : config[configIndex]); + }, [config]); + + useEffect(() => { + getTeam(mmSiteUrl); + getChannel(mmSiteUrl); + if (configIndex !== null) { + setSelectedTeam(existingConfig.teamName); + setTeamName(existingConfig.teamName); + setDelay(existingConfig.delayInSeconds); + setMessage(existingConfig.message); + setGuestValue(existingConfig?.includeGuests ?? ''); + setAttachmentMessage(existingConfig?.attachmentMessage ?? []); + } + }, []); + + useEffect(() => { + preFillActions(); + }, [actionIndex]); + + useEffect(() => { + setTeamNameValid(Boolean(teamName.trim())); + + setTeamSelectionWarning(Boolean(teamName.trim())); + + if (message.length) { + setMessageValid(Boolean(message[0].trim())); + } else { + setMessageValid(false); + } + + setDelayValid(delay >= 0); + + setActionTypesValueValid(Boolean(actionTypesValue)); + + setActionDisplayNameValid(Boolean(actionDisplayName.trim())); + + setActionNameValid(Boolean(actionName.trim())); + + if (actionChannelsAddedTo.length) { + setActionChannelsAddedToValid(Boolean(actionChannelsAddedTo[0])); + } else { + setActionChannelsAddedToValid(false); + } + + if (actionSuccessfullMessage.length) { + setActionSuccessfullMessageValid(Boolean(actionSuccessfullMessage[0].trim())); + } else { + setActionSuccessfullMessageValid(false); + } + }, [teamName, delay, message, attachmentMessage, actionTypesValue, actionDisplayName, actionChannelsAddedTo, actionSuccessfullMessage, actionName]); + + const handlePrimary = () => { + if (isActionVisible) { + if (actionChannelsAddedToValid && actionDisplayNameValid && actionSuccessfullMessageValid && actionTypesValueValid && actionNameValid && channelApiError === '') { + if (configIndex !== null) { + if (actionIndex === null) { + actionElement.actionDisplayName = actionDisplayName; + actionElement.actionName = actionName; + actionElement.actionSuccessfullMessage = actionSuccessfullMessage; + actionElement.actionType = actionTypesValue; + actionElement.channelsAddedTo = actionChannelsAddedTo; + const actions = existingConfig?.actions; + if (actions) { + actions.push(actionElement); + existingConfig.actions = actions; + } + } else { + structureActions(); + } + } else if (configIndex === null) { + if (actionIndex === null) { + structureNewActions(); + } else { + structureActions(); + } + } + setIsActionVisible(false); + setIsConfigVisible(true); + setValidated(false); + onChange(config); + setActionClicked(false); + } else { + setValidated(true); + } + } + if (isConfigVisible) { + if (teamNameValid && messageValid && teamApiError === '') { + if (configIndex === null) { + structureNewConfig(); + config.push(existingConfig); + } else { + structureConfig(); + } + onChange(config); + setValidated(false); + handleSecondary(); + } else { + setValidated(true); + } + } + if (isDeleteVisible && actionIndex !== null) { + const l = existingConfig.actions?.splice(actionIndex, 1); + if (configIndex !== null) { + config[configIndex] = existingConfig; + onChange(config); + } + handleSecondary(); + } + }; + + const handleSecondary = () => { + if (isActionVisible) { + setValidated(false); + setIsActionVisible(false); + setIsConfigVisible(true); + setActionClicked(false); + return; + } else if (isDeleteVisible) { + setValidated(false); + setIsDeleteVisible(false); + setIsConfigVisible(true); + return; + } + + setValidated(false); + setShow(false); + setVisibility(false); + setTeamApiCalled(false); + }; + + const handleEditAction = (i: number) => { + setActionIndex(i); + setIsActionVisible(true); + setIsConfigVisible(false); + }; + + const handleAddActions = () => { + setActionClicked(true); + if (selectedTeam === '') { + setTeamSelectionWarning(false); + } else if (teamApiError === '') { + setTeamSelectionWarning(true); + setValidated(false); + resetActionElement(); + setActionIndex(null); + preFillActions(); + setIsActionVisible(true); + setIsConfigVisible(false); + } + }; + + const handleActionDelete = (index: number, action: string) => { + setDeleteAction(action); + setActionIndex(index); + setIsDeleteVisible(true); + setIsConfigVisible(false); + }; + const handleChannelSelect = (channels: MultiValue) => { + const selectedChannels = channels.map((option: OptionTypes) => option.value); + setActionChannelsAddedTo(selectedChannels); + }; + + const handleTeamSelect = (teams: SingleValue) => { + if (teams === null) { + setTeamName(''); + return; + } + + setTeamName(teams.value); + setSelectedTeam(teams.value); + }; + + const getTeam = async (SiteUrl: string) => { + try { + setTeamDropdownDisabled(true); + setTeamApiCalled(true); + const teamData = await fetchTeams(SiteUrl); + const TeamOptions = teamData.map((team: Teams) => ({ + value: team.display_name, + label: team.display_name, + })); + setTeamOptionList(TeamOptions); + } catch (error) { + setTeamApiError('Some error occured fetching the team list'); + } finally { + setTeamDropdownDisabled(false); + } + }; + + const getChannel = async (SiteUrl: string) => { + try { + setChannelDropdownDisabled(true); + setChannelApiCalled(true); + const channelData = await fetchChannels(SiteUrl); + const channelOptions = channelData.map((channel: Channels) => ({ + value: channel.display_name, + label: channel.display_name, + data: channel.team_name, + })); + setChannelOptionList(channelOptions); + } catch (error) { + setChannelApiError('Some error occured fetching the channel list'); + } finally { + setChannelDropdownDisabled(false); + } + }; + + const resetActionElement = () => { + actionElement.actionType = ''; + actionElement.actionName = ''; + actionElement.actionDisplayName = ''; + actionElement.channelsAddedTo = ['']; + actionElement.actionSuccessfullMessage = ['']; + }; + + const preFillActions = () => { + if (existingConfig?.actions && actionIndex !== null) { + const action = existingConfig?.actions?.[actionIndex] ?? actionElement; + setActionTypesValue(action.actionType); + setActionDisplayName(action.actionDisplayName); + setActionChannelsAddedTo(action.channelsAddedTo); + setActionSuccessfullMessage(action.actionSuccessfullMessage); + setActionName(action.actionName); + return; + } + + setActionTypesValue(actionElement.actionType); + setActionDisplayName(actionElement.actionDisplayName); + setActionChannelsAddedTo(actionElement.channelsAddedTo); + setActionSuccessfullMessage(actionElement.actionSuccessfullMessage); + setActionName(actionElement.actionName); + }; + + const structureConfig = () => { + if (configIndex !== null) { + config[configIndex].message = message; + config[configIndex].delayInSeconds = delay; + config[configIndex].includeGuests = guestValue; + config[configIndex].attachmentMessage = attachmentMessage; + config[configIndex].teamName = teamName; + } + }; + + const structureNewConfig = () => { + existingConfig.message = message; + existingConfig.delayInSeconds = delay; + existingConfig.includeGuests = guestValue; + existingConfig.attachmentMessage = attachmentMessage; + existingConfig.teamName = teamName; + }; + + const structureActions = () => { + const actions = existingConfig?.actions; + if (actions && actionIndex !== null) { + const action = actions[actionIndex]; + action.actionDisplayName = actionDisplayName; + action.actionName = actionName; + action.actionSuccessfullMessage = actionSuccessfullMessage; + action.actionType = actionTypesValue; + action.channelsAddedTo = actionChannelsAddedTo; + existingConfig.actions = [...actions]; + } + }; + const structureNewActions = () => { + actionElement.actionDisplayName = actionDisplayName; + actionElement.actionName = actionName; + actionElement.actionSuccessfullMessage = actionSuccessfullMessage; + actionElement.actionType = actionTypesValue; + actionElement.channelsAddedTo = actionChannelsAddedTo; + const _ = existingConfig.actions?.push(actionElement); + }; + + return ( +
+ + + + {modalHeader} + + + + {isConfigVisible &&
+
+
+ + {'TeamName*'} + channel.data === selectedTeam, + )} + value={channelOptionList.filter((option) => actionChannelsAddedTo.includes(option.value))} + /> + {((validated && !actionChannelsAddedToValid) || (channelApiCalled && channelApiError !== '')) && + + {channelApiError === '' ? 'Please provide at least one channel name' : channelApiError} + } + +
+
+ + {'Action Type*'} + + {actionTypes.map((radio, index) => ( + setActionTypesValue(e.currentTarget.value)} + > + {radio.name} + + ))} + + {validated && !actionTypesValueValid && + + {'Please select an action type'} + } + +
+
+ + {'Action Display Name*'} + setActionDisplayName(e.target.value)} + /> + {validated && !actionDisplayNameValid && + + {'Please provide the display name for your action'} + } + +
+
+ + {'Action Name*'} + setActionName(e.target.value)} + /> + {validated && !actionNameValid && + + {'Please provide a name for your action'} + } + +
+
+ + {'Action Successfull Message*'} + setActionSuccessfullMessage([e.target.value])} + /> + {validated && !actionSuccessfullMessageValid && + + {'Please provide a message'} + } + +
+
+
} + {!isDeleteVisible && !isActionVisible &&
+ +
} + {isDeleteVisible &&
+

{`Are you sure you would like to delete the action ${deleteAction}?`}

+
} +
+ + + + +
+
+ ); +}; + +export default ConfigModal; diff --git a/webapp/src/components/modals/deleteModal.tsx b/webapp/src/components/modals/deleteModal.tsx new file mode 100644 index 000000000..cace15d72 --- /dev/null +++ b/webapp/src/components/modals/deleteModal.tsx @@ -0,0 +1,62 @@ +import React, {useEffect, useState} from 'react'; + +import Button from 'react-bootstrap/Button'; +import Modal from 'react-bootstrap/Modal'; + +import './styles.scss'; + +type Props = { + visibility: boolean; + setVisibility: React.Dispatch>; + config: Configs[]; + configIndex: number; + onChange: (config: Configs[]) => void; +} + +const DeleteModal = ({visibility, setVisibility, config, configIndex, onChange}: Props) => { + const [show, setShow] = useState(false); + + useEffect(() => { + setShow(visibility); + }, [visibility]); + + const handleDelete: () => void = () => { + config.splice(configIndex, 1); + onChange(config); + handleClose(); + }; + + const handleClose = () => { + setShow(false); + setVisibility(false); + }; + + return ( + + + {'Delete Config'} + + + +

{`Are you sure you would like to delete the configs for team ${config[configIndex].teamName}?`}

+
+ + + + + +
+ ); +}; + +export default DeleteModal; diff --git a/webapp/src/components/modals/styles.scss b/webapp/src/components/modals/styles.scss new file mode 100644 index 000000000..38328008c --- /dev/null +++ b/webapp/src/components/modals/styles.scss @@ -0,0 +1,283 @@ +$color_1: #000000; +$color_2: #FF0000; +$border-color_1: transparent; + +@keyframes fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes fade-out { + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +.custom-modal.modal { + opacity: 1; + padding-top: 230px; +} + +.modal-open { + .modal { + overflow-x: hidden; + overflow-y: hidden; + } +} + +.modal-dialog { + .modal-header { + display: flex; + } + .modal-body { + display: flex; + flex-direction: column; + } + width: 615px; + max-width: 615px; +} + +.custom-modal-body { + height: 80%; + overflow-y: auto; +} + +.fade-enter { + opacity: 0; + animation: fade-in 300ms forwards; +} + +.fade-exit { + opacity: 1; + animation: fade-out 300ms forwards; +} + +.btn-group { + display: flex; + justify-content: space-between; + .btn.btn-default { + background: none; + border-color: $border-color_1; + border: transparent; + &:hover { + background: transparent; + color: $color_1; + } + &:focus { + background: transparent; + color: $color_1; + } + } +} + +.radio.btn-group { + justify-content: flex-start; +} + +.options { + .btn.btn-primary { + background: transparent; + } +} + +.radio { + margin-top: 0; + margin-bottom: 0; +} + +.radio-form { + margin-bottom: 0px; +} + +.add-actions { + margin-top: 15px; +} + +.validation-warning { + color: $color_2; + font-size: 12px; +} + +.config-form { + width: 100%; +} + +.add-action-button { + display: block; +} + +.guest-button.active { + box-shadow: none; + outline: transparent; +} + +.action-typeButton.active { + box-shadow: none; + outline: transparent; +} + +.warning { + margin-bottom: 27px; + color: $color_1; + .form-group { + position: relative; + } +} + +.gapping { + margin-bottom: 25px; +} + +.form-group { + position: relative; + margin-bottom: 10px; +} + +.warnings { + margin-bottom: 25px; + .form-group { + position: relative; + } +} + +.form-label { + color: $color_1; +} + +.type { + width: 87px; +} + +.successfull-message { + width: 110px; +} + +.successfull-message-content { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.channels-added { + width: 111px; + display: flex; + justify-content: center; +} + +.channels-added-content { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.action-name { + vertical-align: middle; + width: 87px; +} + +.action-name-content { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.display-name { + vertical-align: middle; + width: 87px; +} + +.display-name-content { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.type-action { + width: 87px; +} + +.success-message-action { + width: 111px; +} + +.channels-added-action { + width: 174px; + display: flex; + text-align: center; +} + +.name-action { + width: 87px; +} + +.display-name-action { + width: 122px; +} + +.option-buttons { + width: 100px; +} + +.list-table { + .table { + tbody { + tr { + td { + border: 1px solid #dddddd; + vertical-align: middle; + } + } + } + thead { + tr { + th { + border: 1px solid #dddddd; + vertical-align: middle; + td { + white-space: nowrap; + } + } + } + border: 1px solid #dddddd; + vertical-align: middle; + width: 100%; + } + td { + text-align: center; + vertical-align: middle; + } + th { + text-align: center; + vertical-align: bottom; + } + width: 100%; + margin-top: 0; + margin-bottom: 0; + table-layout: fixed; + tr { + display: flex; + width: 100%; + } + } + th { + text-align: center; + } +} + +.team-name-dropdown { + color: $color_1; +} + +.guest-button { + &:focus { + outline: none; + box-shadow: none; + } +} diff --git a/webapp/src/components/svgIcons/svg.tsx b/webapp/src/components/svgIcons/svg.tsx new file mode 100644 index 000000000..15626e932 --- /dev/null +++ b/webapp/src/components/svgIcons/svg.tsx @@ -0,0 +1,72 @@ +import React from 'react'; + +const EditSvg = () => ( + + + + +); + +const DeleteSvg = () => ( + + + + + + +); + +const ViewSvg = () => ( + + + + +); + +export {EditSvg, DeleteSvg, ViewSvg}; diff --git a/webapp/src/components/tables/existingConfigTable.tsx b/webapp/src/components/tables/existingConfigTable.tsx new file mode 100644 index 000000000..8017ecbcc --- /dev/null +++ b/webapp/src/components/tables/existingConfigTable.tsx @@ -0,0 +1,187 @@ +import React, {useState} from 'react'; + +import {FormGroup, Table, ButtonGroup, Button, OverlayTrigger, Tooltip} from 'react-bootstrap'; + +import ActionModal from '../modals/actionModal'; +import DeleteModal from '../modals/deleteModal'; +import ConfigModal from '../modals/configModal'; + +import {DeleteSvg, EditSvg, ViewSvg} from '../svgIcons/svg'; + +import './styles.scss'; + +type Props = { + onChange: (config: Configs[]) => void; + value: Configs[]; +} + +const ExistingConfigTable = ({value, onChange}: Props) => { + const [isviewVisible, setIsViewVisible] = useState(false); + const [isdeleteVisible, setIsDeleteVisible] = useState(false); + const [iseditVisible, setIsEditVisible] = useState(false); + const [isaddVisible, setIsAddVisible] = useState(false); + + const [configIndex, setConfigIndex] = useState(0); + + const handleView = (index: number) => { + setConfigIndex(index); + setIsViewVisible(true); + }; + + const handleDelete = (index: number) => { + setConfigIndex(index); + setIsDeleteVisible(true); + }; + + const handleEdit = (index: number) => { + setConfigIndex(index); + setIsEditVisible(true); + }; + + const handleAdd = () => setIsAddVisible(true); + + return ( +
+ { + isviewVisible && + + } + {isdeleteVisible && + + } + {iseditVisible && + + } + {isaddVisible && + + } + +
+ {'Existing Configs'} +
+
+ {value.length > 0 && + + + + + + + + + + + + { + value.map((val, i) => + ( + + + + + + + + ), + ) + } + +
{'Team Name'}{'Delay (in sec)'}{'Message'}{'Include Guests'}{'Options'}
+ {val.teamName}} + > +

+ {val.teamName} +

+
+
{val.delayInSeconds} + {val.message.join(',')}} + > +

+ {val.message.join(',')} +

+
+
{val.includeGuests ? val.includeGuests : '-'} +
+ + {'View actions'}} + > + + + {'Edit config'}} + > + + + {'Delete Config'}} + > + + + +
+
} + +
+
+
+ ); +}; + +export default ExistingConfigTable; diff --git a/webapp/src/components/tables/styles.scss b/webapp/src/components/tables/styles.scss new file mode 100644 index 000000000..b0ae3ea0e --- /dev/null +++ b/webapp/src/components/tables/styles.scss @@ -0,0 +1,153 @@ +$color_1: #000000; +$border-color_1: transparent; + +.existing-config-table.btn-group { + display: flex; + justify-content: space-between; + gap: 10px; + gap: 1px; + .btn.btn-default { + background: none; + border-color: $border-color_1; + border: transparent; + } +} + +.existing-config-table.table.table { + tbody { + tr { + td { + border: 2px solid #dddddd; + vertical-align: middle; + } + } + } + thead { + tr { + th { + border: 2px solid #dddddd; + vertical-align: middle; + } + } + border: 2px solid #dddddd; + vertical-align: middle; + } +} + +.existing-config-table.table { + td { + text-align: center; + vertical-align: middle; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + th { + text-align: center; + vertical-align: bottom; + } + width: 100%; + table-layout: fixed; + thead { + tr { + th { + td { + white-space: nowrap; + } + } + } + } + .messageValue { + text-align: left; + vertical-align: middle; + } +} + +.existing-config-table.table-body { + width: 100%; +} + +.existing-config-table { + .btn-group.btn.btn-default { + &:hover { + background: transparent; + color: $color_1; + } + } +} + +.btn-group { + .btn.btn-default { + &:focus { + background: transparent; + color: $color_1; + } + } +} + +.add-config-btn { + margin: 15px 0 0 0; +} + +.config { + .form-group { + margin-left: 0px; + } +} + +.name { + font-weight: 600; + font-size: 14px; + margin-bottom: 1em; +} + +.team-name { + max-width: 138px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.delay { + width: 110px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.message { + width: 413px; +} + +.include-guests { + width: 119px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.option { + width: 138px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.message-content { + text-align: left; + width: 100%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.svg-buttons { + &:focus { + outline: none; + box-shadow: none; + } + &:active { + outline: none; + box-shadow: none; + } +} diff --git a/webapp/src/constants/apiConstants.ts b/webapp/src/constants/apiConstants.ts new file mode 100644 index 000000000..fc10e26bd --- /dev/null +++ b/webapp/src/constants/apiConstants.ts @@ -0,0 +1,7 @@ +export const getChannel = '/channels?exclude_default_channels=true'; +export const getTeam = '/teams'; +export const apiVersion1 = '/api/v1'; +export const apiVersion4 = '/api/v4'; +export const plugins = '/plugins'; +export const mmAuthToken = 'MMAUTHTOKEN'; +export const bearer = 'Bearer '; diff --git a/webapp/src/containers/components/modals/actionModal.tsx b/webapp/src/containers/components/modals/actionModal.tsx deleted file mode 100644 index 24f978cd7..000000000 --- a/webapp/src/containers/components/modals/actionModal.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import React, {useEffect} from 'react'; - -import Button from 'react-bootstrap/Button'; -import Modal from 'react-bootstrap/Modal'; -import Table from 'react-bootstrap/Table'; -import Form from 'react-bootstrap/Form'; - -import './styles.css'; - -type Props = { - visibility: boolean; - setVisibility: React.Dispatch>; - config: Configs[]; - configIndex: number; -} - -function ActionModal({visibility, setVisibility, config, configIndex}: Props) { - const actionsLength = config[configIndex]?.actions?.length ?? 0; - const attachmentMessageLength = config[configIndex]?.attachmentMessage?.length ?? 0; - - useEffect(() => { - setVisibility(visibility); - }, [visibility]); - - const handleClose = () => { - setVisibility(false); - }; - return ( - - - {'Actions'} - - - - {(config[configIndex].attachmentMessage && attachmentMessageLength) || (config[configIndex]?.actions && actionsLength) ? (<> - {config[configIndex].attachmentMessage && attachmentMessageLength ? ( -
- - {'Attachment Message'} - - -
- ) : (

{'No Attachment message configured'}

) - } - {config[configIndex]?.actions && actionsLength ? ( -
-
- - {'Actions'} - -
- - - - - - - - - - - - {config[configIndex].actions?.map((val, i) => - ( - - - - - - - - ), - )} - -
{'Type'}{'Name'}{'Display Name'}{'Channels Added to'}{'Success Message'}
{val.actionType}{val.actionName}{val.actionDisplayName}{val.channelsAddedTo}{val.actionSuccessfullMessage}
-
- ) : (

{'No Action configured'}

) - } - ) : (

{'No Attachment message or Action configured'}

)} -
- - - -
- ); -} - -export default ActionModal; diff --git a/webapp/src/containers/components/modals/configModal.tsx b/webapp/src/containers/components/modals/configModal.tsx deleted file mode 100644 index c7f035629..000000000 --- a/webapp/src/containers/components/modals/configModal.tsx +++ /dev/null @@ -1,432 +0,0 @@ -import React, {useEffect, useState} from 'react'; - -import Button from 'react-bootstrap/Button'; -import Modal from 'react-bootstrap/Modal'; -import Form from 'react-bootstrap/Form'; -import Table from 'react-bootstrap/Table'; -import ButtonGroup from 'react-bootstrap/ButtonGroup'; -import {OverlayTrigger, Tooltip, ToggleButton} from 'react-bootstrap'; - -import './styles.css'; - -type Props = { - visibility: boolean; - setVisibility: React.Dispatch>; - configIndex: number | null; - config: Configs[]; - onChange: any; - modalHeader: string; -} - -function ConfigModal({visibility, setVisibility, config}: Props) { - const [show, setShow] = useState(false); - const [isActionVisible, setIsActionVisible] = useState(false); - const [isConfigVisible, setIsConfigVisible] = useState(false); - const [isDeleteVisible, setIsDeleteVisible] = useState(false); - const [radioValue, setRadioValue] = useState(''); - - const handleCloseButton = ( - variant: string, - text: string, - ) => ( - - ); - - const guest = [ - {name: 'true', value: 'true'}, - {name: 'false', value: 'false'}, - ]; - - const buttonTypes = [ - {name: 'button', value: 'button'}, - {name: 'automatic', value: 'automatic'}, - ]; - - useEffect(() => { - setShow(visibility); - setIsConfigVisible(visibility); - }, [visibility]); - - const handleClose = () => { - if (isActionVisible) { - setIsActionVisible(false); - setIsConfigVisible(true); - } else if (isDeleteVisible) { - setIsDeleteVisible(false); - setIsConfigVisible(true); - } else { - setShow(false); - setVisibility(false); - } - setShow(false); - setVisibility(false); - }; - - const handleActions = () => { - setIsActionVisible(true); - setIsConfigVisible(false); - }; - - const handleDelete = () => { - setIsDeleteVisible(true); - setIsConfigVisible(false); - }; - - return ( - <> - - - - {config ? (

{isConfigVisible &&

{'Edit config'}

}{isActionVisible &&

{'Edit actions'}

}{isDeleteVisible &&

{'Delete Config'}

}

) : (

{isConfigVisible &&

{'Add config'}

}{isActionVisible &&

{'Add action'}

}

)} -
-
- - - {isConfigVisible &&
-
- - {'Team name'} - - - - {'Delay (in sec)'} - - - - {'Message'} - - - - {'Include guests'} - - {guest.map((radio, index) => ( - setRadioValue(e.currentTarget.value)} - > - {radio.name} - - ))} - - - - {'Attachment Message'} - - - - {'Actions'} - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{'Type'}{'Display Name'}{'Channels Added to'}{'Success Message'}{'Options'}
{'Button'}{'Import'}{'channel1, channel2, channel3'}{'Welcome to your new team mate !'} - - {'Edit action'}} - > - - - {'Delete action'}} - > - - - -
{'Automatic'}{'Export'}{'channel1, channel2'}{'Welcome to your new team mate !'} - - {'Edit action'}} - > - - - {'Delete action'}} - > - - - -
{'Button'}{'Deport'}{'channel1, channel3'}{'Welcome to your new team mate !'} - - {'Edit action'}} - > - - - {'Delete action'}} - > - - - -
-
} - - {isActionVisible &&
-
- - {'Action Type'} - - {buttonTypes.map((radio, index) => ( - setRadioValue(e.currentTarget.value)} - > - {radio.name} - - ))} - - - - {'Action Display Name'} - - - - {'Channels Added to'} - - - - {'Action Successfull message'} - - -
-
} - {!config && !isActionVisible &&
- -
} - - {isDeleteVisible &&
-

{'Are you sure you would like to delete the action ?'}

-
} -
- - {isConfigVisible && handleCloseButton('primary', 'Save changes')} - {isActionVisible && handleCloseButton('primary', 'Add action')} - {isConfigVisible && handleCloseButton('secondary', 'Close')} - {isActionVisible && handleCloseButton('secondary', 'Cancel')} - {isDeleteVisible && handleCloseButton('secondary', 'Cancel')} - {isDeleteVisible && handleCloseButton('danger', 'Delete action')} - -
- - ); -} - -export default ConfigModal; diff --git a/webapp/src/containers/components/modals/deleteModal.tsx b/webapp/src/containers/components/modals/deleteModal.tsx deleted file mode 100644 index 6f902947f..000000000 --- a/webapp/src/containers/components/modals/deleteModal.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import React from 'react'; - -import Button from 'react-bootstrap/Button'; -import Modal from 'react-bootstrap/Modal'; - -import './styles.css'; - -type Props = { - visible: boolean; - setVisible: React.Dispatch>; - config: Configs[]; - configIndex: number; - onChange: any; -} - -const DeleteModal = ({visible, setVisible, config, configIndex, onChange}: Props) => { - const [show, setShow] = useState(false); - - useEffect(() => { - setShow(visible); - }, [visible]); - - const handleClose = () => { - setVisible(false); - }; - - const handleDelete = () => { - config.splice(configIndex, 1); - onChange(config); - handleClose(); - }; - - return ( - <> - - - {'Delete Config'} - - - -

{`Are you sure you would like to delete the configs for the team ${config[configIndex].teamName}?`}

-
- - - - - -
- - ); -}; - -export default DeleteModal; diff --git a/webapp/src/containers/components/modals/styles.css b/webapp/src/containers/components/modals/styles.css deleted file mode 100644 index 021331ee8..000000000 --- a/webapp/src/containers/components/modals/styles.css +++ /dev/null @@ -1,111 +0,0 @@ -.modal { - opacity: 1; - padding-top: 12%; -} - -.configModal { - display: block; -} - -.modal-dialog{ - overflow-y: initial; -} - -.configModalBody{ - height: 80%; - overflow-y: auto; -} - -.buttons { - padding-bottom: 0; -} - -@keyframes fade-in { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - -@keyframes fade-out { - from { - opacity: 1; - } - to { - opacity: 0; - } -} - -.fade-enter { - opacity: 0; - animation: fade-in 300ms forwards; -} - -.fade-exit { - opacity: 1; - animation: fade-out 300ms forwards; -} - -.btn-group { - display: flex; - justify-content: space-between; -} - -table.table tbody tr td, -table.table thead tr th, -table.table thead { - border: 2px solid #ddd; - vertical-align: middle; -} - -.table td { - text-align: center; - vertical-align: middle; -} - -.tale th { - text-align: center; - vertical-align: bottom; -} - -.table { - width: 100%; -} - -.table thead tr th td{ - white-space:nowrap -} - -.btn-group .btn.btn-default { - background: none; - border-color: transparent; - border: transparent; -} - -.btn-group .btn.btn-default:hover, .btn-group .btn.btn-default:focus { - background: transparent; - color: #000000; -} - -.radio.btn-group { - justify-content: flex-start; -} - -.options .btn.btn-primary { - background: transparent; -} - -.radio { - margin-top: 0; - margin-bottom: 0; -} - -.list-table { - margin-bottom: 0; -} - -.add-actions { - margin-top: 15px; -} diff --git a/webapp/src/containers/components/tables/existingConfigTable.tsx b/webapp/src/containers/components/tables/existingConfigTable.tsx deleted file mode 100644 index d8a81f512..000000000 --- a/webapp/src/containers/components/tables/existingConfigTable.tsx +++ /dev/null @@ -1,216 +0,0 @@ -import React, {useState} from 'react'; - -import Table from 'react-bootstrap/Table'; -import Button from 'react-bootstrap/Button'; -import OverlayTrigger from 'react-bootstrap/OverlayTrigger'; -import Tooltip from 'react-bootstrap/Tooltip'; -import ButtonGroup from 'react-bootstrap/ButtonGroup'; -import './styles.css'; - -import ActionModal from '../modals/actionModal'; -import ConfigModal from '../modals/configModal'; - -type HelpText = { - key: string | null; - props: { - isMarkdown: boolean; - isTranslated: boolean; - text: string; - } -} - -type Props = { - onChange: any - value: Configs[] -} - -const ExistingConfigTable = ({value, onChange}: Props) => { - const [viewVisible, setViewVisible] = useState(false); - const [deleteVisible, setDeleteVisible] = useState(false); - const [editVisible, setEditVisible] = useState(false); - const [addVisible, setAddVisible] = useState(false); - const [configIndex, setConfigIndex] = useState(0); - - const handleView = (index: number) => { - setConfigIndex(index); - setViewVisible(true); - }; - const handleDelete = (index: number) => { - setConfigIndex(index); - setDeleteVisible(true); - }; - const handleEdit = (index: number) => { - setConfigIndex(index); - setEditVisible(true); - }; - - const handleAdd = () => { - setIsAddVisible(true); - }; - - return ( -
- {deleteVisible && - - } - {isEditVisible && - - } - {isAddVisible && - - } - -
- {'Existing Configs'} -
-
- - - - - - - - - - - - { - value.map((val, i) => - ( - - - - - - - - ), - ) - } - -
{'Team Name'}{'Delay (in sec)'}{'Message'}{'Include Guests'}{'Options'}
{val.teamName}{val.delayInSeconds}{val.message}{val.includeGuests ? val.includeGuests : '-'} -
- - {'View actions'}} - > - - - {'Edit config'}} - > - - - {'Delete Config'}} - > - - - -
-
- -
-
- {'label'} -
-
- ); -}; - -export default ExistingConfigTable; diff --git a/webapp/src/containers/components/tables/styles.css b/webapp/src/containers/components/tables/styles.css deleted file mode 100644 index 919aeeb0e..000000000 --- a/webapp/src/containers/components/tables/styles.css +++ /dev/null @@ -1,93 +0,0 @@ -.existing-config-table.btn-group { - display: flex; - justify-content: space-between; - gap: 10px; -} - -.existing-config-table.table.table tbody tr td, -.existing-config-table.table.table thead tr th, -.existing-config-table.table.table thead { - border: 2px solid #dddddd; - vertical-align: middle; -} - -.existing-config-table.table td { - text-align: center; - vertical-align: middle; -} - -.existing-config-table.table th { - text-align: center; - vertical-align: bottom; -} - -.existing-config-table.table { - max-width: 100%; -} -.existing-config-table.table thead tr th td{ - white-space:nowrap -} - -.existing-config-table.btn-group { - gap: 1px; -} - -.existing-config-table.btn-group .btn.btn-default { - background: none; - border-color: transparent; - border: transparent; -} - -.existing-config-table .btn-group.btn.btn-default:hover, .btn-group .btn.btn-default:focus { - background: transparent; - color: #000000; -} - -.add-config-btn { - margin: 1px 0 0 0; -} - -.config { - padding-left: 15px; -} - -.name { - font-weight: 600; - font-size: 14px; - margin-bottom: 1em; -} - -.team-name { - max-width: 15%; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.delay { - width: 10%; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.message { - width: 55%; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.include-guests { - width: 10%; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.option { - width: 10%; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} diff --git a/webapp/src/index.tsx b/webapp/src/index.tsx index 4c4c03f56..d08df62ec 100644 --- a/webapp/src/index.tsx +++ b/webapp/src/index.tsx @@ -1,11 +1,9 @@ import {Store, Action} from 'redux'; - import {GlobalState} from 'mattermost-redux/types/store'; -// eslint-disable-next-line import/no-unresolved import {PluginRegistry} from 'types/mattermostWebapp'; -import ExistingConfigTable from 'containers/components/tables/existingConfigTable'; +import ExistingConfigTable from 'components/tables/existingConfigTable'; import {id} from './manifest'; diff --git a/webapp/src/types/plugin/common.d.ts b/webapp/src/types/plugin/common.d.ts index c3c0be1ae..21fd2ec09 100644 --- a/webapp/src/types/plugin/common.d.ts +++ b/webapp/src/types/plugin/common.d.ts @@ -4,13 +4,33 @@ type Actions = { actionDisplayName: string, channelsAddedTo: string[], actionSuccessfullMessage: string[] -} +}; type Configs = { teamName: string, - delayInSeconds: string, + delayInSeconds: number, message: string[], includeGuests: string | null, attachmentMessage: string[] | null, actions: Actions[] | null -} +}; + +type GroupTypes = { + label: string; + value: string; +}; + +type OptionTypes = { + value: string; + label: string; + data: string; +}; + +type Teams = { + display_name: string; +}; + +type Channels = { + display_name: string; + team_name: string, +}; diff --git a/webapp/src/utils/index.ts b/webapp/src/utils/index.ts index b8349a3bf..c1bfceb09 100644 --- a/webapp/src/utils/index.ts +++ b/webapp/src/utils/index.ts @@ -1,26 +1,23 @@ +import Cookies from 'js-cookie'; + +import {plugins, apiVersion1, apiVersion4, bearer, mmAuthToken} from 'constants/apiConstants'; + import {id} from 'manifest'; const getBaseUrls = (mmSiteUrl: string): {pluginApiBaseUrl: string; mattermostApiBaseUrl: string} => { - const pluginUrl = `${mmSiteUrl}/plugins/${id}`; - const pluginApiBaseUrl = `${pluginUrl}/api/v1`; - const mattermostApiBaseUrl = `${mmSiteUrl}/api/v4`; + const pluginUrl = `${mmSiteUrl}${plugins}/${id}`; + const pluginApiBaseUrl = `${pluginUrl}${apiVersion1}`; + const mattermostApiBaseUrl = `${mmSiteUrl}${apiVersion4}`; return {pluginApiBaseUrl, mattermostApiBaseUrl}; }; -export const getCommandArgs = (command: string) => { - const myRegexp = /[^\s"]+|"([^"]*)"/gi; - const myArray = []; - let match; - do { - match = myRegexp.exec(command); - if (match != null) { - myArray.push(match[1] ?? match[0]); - } - } while (match != null); - return myArray.length > 2 ? myArray.slice(2) : []; +const getAuthToken = () => { + const authToken = bearer + Cookies.get(`${mmAuthToken}`) || ''; + return authToken; }; export default { getBaseUrls, + getAuthToken, };