diff --git a/package-lock.json b/package-lock.json index ce99433d..078e1979 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,6 +25,7 @@ "dotenv": "^16.4.5", "firebase": "^10.7.1", "firebase-auth": "^0.1.2", + "franc-min": "^6.2.0", "html-react-parser": "^5.1.10", "html2canvas": "^1.4.1", "install": "^0.13.0", @@ -43,12 +44,15 @@ "react-json-tree": "^0.18.0", "react-markdown": "^9.0.1", "react-material-ui-carousel": "^3.4.2", + "react-media-recorder": "^1.6.6", "react-quill": "^2.0.0", "react-quilljs": "^1.3.3", "react-redux": "^9.0.4", "react-router-dom": "^6.21.2", + "react-speech-recognition": "^3.10.0", "react-syntax-highlighter": "^15.5.0", - "recharts": "^2.12.0" + "recharts": "^2.12.0", + "regenerator-runtime": "^0.14.1" }, "devDependencies": { "autoprefixer": "^10.4.16", @@ -550,9 +554,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.0.tgz", - "integrity": "sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==", + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.6.tgz", + "integrity": "sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -2958,6 +2962,18 @@ "node": ">= 4.5.0" } }, + "node_modules/automation-events": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/automation-events/-/automation-events-7.0.5.tgz", + "integrity": "sha512-Ni6vhZg0mKmVlew1kxWAzWL7QY1LYDdoYgp6yF9OHeskDrjyJp2SqoKoPQYeiMYjeIlbSpnxXm/JI55VcmX5Wg==", + "dependencies": { + "@babel/runtime": "^7.24.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.2.0" + } + }, "node_modules/autoprefixer": { "version": "10.4.16", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz", @@ -3123,6 +3139,17 @@ "node": ">=8" } }, + "node_modules/broker-factory": { + "version": "3.0.98", + "resolved": "https://registry.npmjs.org/broker-factory/-/broker-factory-3.0.98.tgz", + "integrity": "sha512-IgwhsnhlIF2S014S61XGcZkxZVDTrPxeYAg78P9xOmVFFyoaa+liGiQfd5f0seCB3nEaUgnbSreh6xnElbsd0g==", + "dependencies": { + "@babel/runtime": "^7.24.5", + "fast-unique-numbers": "^9.0.5", + "tslib": "^2.6.2", + "worker-factory": "^7.0.25" + } + }, "node_modules/browserslist": { "version": "4.22.2", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", @@ -3413,6 +3440,15 @@ "node": ">=6" } }, + "node_modules/collapse-white-space": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", + "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/color": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", @@ -3495,6 +3531,20 @@ "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "dev": true }, + "node_modules/compilerr": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/compilerr/-/compilerr-10.0.2.tgz", + "integrity": "sha512-CFwUXxJ9OuWsSvnLSbefxi+GLsZ0YnuJh40ry5QdmZ1FWK59OG+QB8XSj6t7Kq+/c5DSS7en+cML6GlzHKH58A==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "dashify": "^2.0.0", + "indefinite-article": "0.0.2", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.15.4" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -3724,6 +3774,14 @@ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true }, + "node_modules/dashify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dashify/-/dashify-2.0.0.tgz", + "integrity": "sha512-hpA5C/YrPjucXypHPPc0oJ1l9Hf6wWbiOL7Ik42cxnsUOhWiCB/fylKbKqqJalW9FgkNQCw16YO8uW9Hs0Iy1A==", + "engines": { + "node": ">=4" + } + }, "node_modules/date-fns": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.3.1.tgz", @@ -4625,6 +4683,52 @@ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, + "node_modules/extendable-media-recorder": { + "version": "6.6.10", + "resolved": "https://registry.npmjs.org/extendable-media-recorder/-/extendable-media-recorder-6.6.10.tgz", + "integrity": "sha512-gnSmLqDFq40ZdbGfuarnMLNqYPLCPpPr0p21V+g67wG4Pv2oCc/ga8sfsZrEM5GywEi7FcpyRm3z99JWZ/0aPw==", + "dependencies": { + "@babel/runtime": "^7.18.9", + "media-encoder-host": "^8.0.76", + "multi-buffer-data-view": "^3.0.20", + "recorder-audio-worklet": "^5.1.26", + "standardized-audio-context": "^25.3.29", + "subscribable-things": "^2.1.6", + "tslib": "^2.4.0" + } + }, + "node_modules/extendable-media-recorder-wav-encoder": { + "version": "7.0.111", + "resolved": "https://registry.npmjs.org/extendable-media-recorder-wav-encoder/-/extendable-media-recorder-wav-encoder-7.0.111.tgz", + "integrity": "sha512-wGrCr0f1dbKuYZ9V04zKOn58F8cghutrD+dTW2YZpGsyKIS02gKU9h0kV66kB8B2nL0kXJA6v/UXjSTYERCVFA==", + "dependencies": { + "@babel/runtime": "^7.24.5", + "extendable-media-recorder-wav-encoder-broker": "^7.0.102", + "extendable-media-recorder-wav-encoder-worker": "^8.0.99", + "tslib": "^2.6.2" + } + }, + "node_modules/extendable-media-recorder-wav-encoder-broker": { + "version": "7.0.102", + "resolved": "https://registry.npmjs.org/extendable-media-recorder-wav-encoder-broker/-/extendable-media-recorder-wav-encoder-broker-7.0.102.tgz", + "integrity": "sha512-TwamIdx6IpE/unEwdL/LnCPvu7YAZ31KZ18LXLpKiRHGknvI1kAsr2IFSjhaburwMqhPGhn/cfSp+7ua+VJjoQ==", + "dependencies": { + "@babel/runtime": "^7.24.5", + "broker-factory": "^3.0.98", + "extendable-media-recorder-wav-encoder-worker": "^8.0.99", + "tslib": "^2.6.2" + } + }, + "node_modules/extendable-media-recorder-wav-encoder-worker": { + "version": "8.0.99", + "resolved": "https://registry.npmjs.org/extendable-media-recorder-wav-encoder-worker/-/extendable-media-recorder-wav-encoder-worker-8.0.99.tgz", + "integrity": "sha512-CgelTHa9w9eF7TZZ88XLASvyVrVuSB9Yoru/Z6bhcajCHp/JmhcEyZyTvvQigZ5Hu5rQGOPPnayNVWJnVVuEyA==", + "dependencies": { + "@babel/runtime": "^7.24.5", + "tslib": "^2.6.2", + "worker-factory": "^7.0.25" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -4684,6 +4788,18 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-unique-numbers": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/fast-unique-numbers/-/fast-unique-numbers-9.0.5.tgz", + "integrity": "sha512-wVA1YcLQn0eAo4P1DXu4UI3wx68Llwm2/iCtpoOGuTi3jm/13KFYjCt3Nlq2fseSuyaBz43RKimj5G68GDzjjg==", + "dependencies": { + "@babel/runtime": "^7.24.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.2.0" + } + }, "node_modules/fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -4989,6 +5105,18 @@ "tslib": "^2.1.0" } }, + "node_modules/franc-min": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/franc-min/-/franc-min-6.2.0.tgz", + "integrity": "sha512-1uDIEUSlUZgvJa2AKYR/dmJC66v/PvGQ9mWfI9nOr/kPpMFyvswK0gPXOwpYJYiYD008PpHLkGfG58SPjQJFxw==", + "dependencies": { + "trigram-utils": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/fs-extra": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", @@ -6223,6 +6351,11 @@ "node": ">=0.8.19" } }, + "node_modules/indefinite-article": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/indefinite-article/-/indefinite-article-0.0.2.tgz", + "integrity": "sha512-Au/2XzRkvxq2J6w5uvSSbBKPZ5kzINx5F2wb0SF8xpRL8BP9Lav81TnRbfPp6p+SYjYxwaaLn4EUwI3/MmYKSw==" + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -7147,6 +7280,40 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/media-encoder-host": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/media-encoder-host/-/media-encoder-host-8.1.0.tgz", + "integrity": "sha512-VwX3ex48ltl+K1ObGEq3IcZp/XqpNTWemd9brC9ovo89rYmCRKTZAp1FCyfAY86RdvSMrUs26lbo45DIDVyERg==", + "dependencies": { + "@babel/runtime": "^7.24.4", + "media-encoder-host-broker": "^7.1.0", + "media-encoder-host-worker": "^9.2.0", + "tslib": "^2.6.2" + } + }, + "node_modules/media-encoder-host-broker": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/media-encoder-host-broker/-/media-encoder-host-broker-7.1.0.tgz", + "integrity": "sha512-Emu3f45Wbf6AoRJxfvZ8e5nh8fRVviBfkABgYNvVUsVBgJ7+l137gn324g/JmNVQhhVQ89fjmGT1kHIJ9JG5Nw==", + "dependencies": { + "@babel/runtime": "^7.24.4", + "broker-factory": "^3.0.97", + "fast-unique-numbers": "^9.0.4", + "media-encoder-host-worker": "^9.2.0", + "tslib": "^2.6.2" + } + }, + "node_modules/media-encoder-host-worker": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/media-encoder-host-worker/-/media-encoder-host-worker-9.2.0.tgz", + "integrity": "sha512-LrJJgNBDZH2y1PYBLaiYQw9uFU5i3yPvDkDxdko+L3Z4qzhKq9+4eYxKDqlwO4EdOlaiggvMpkgZl3roOniz2A==", + "dependencies": { + "@babel/runtime": "^7.24.4", + "extendable-media-recorder-wav-encoder-broker": "^7.0.100", + "tslib": "^2.6.2", + "worker-factory": "^7.0.24" + } + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -7675,6 +7842,18 @@ "node": ">=6" } }, + "node_modules/multi-buffer-data-view": { + "version": "3.0.24", + "resolved": "https://registry.npmjs.org/multi-buffer-data-view/-/multi-buffer-data-view-3.0.24.tgz", + "integrity": "sha512-jm7Ycplx37ExXyQmqhwl7zfQmAj81y5LLzVx0XyWea4omP9W/xJhLEHs/5b+WojGyYSRt8BHiXZVcYzu68Ma0Q==", + "dependencies": { + "@babel/runtime": "^7.20.6", + "tslib": "^2.4.1" + }, + "engines": { + "node": ">=12.20.1" + } + }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -7686,6 +7865,15 @@ "thenify-all": "^1.0.0" } }, + "node_modules/n-gram": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/n-gram/-/n-gram-2.0.2.tgz", + "integrity": "sha512-S24aGsn+HLBxUGVAUFOwGpKs7LBcG4RudKU//eWzt/mQ97/NMKQxDWHyHx63UNWk/OOdihgmzoETn1tf5nQDzQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -9007,6 +9195,15 @@ "react-dom": "^17.0.2 || ^18.0.0" } }, + "node_modules/react-media-recorder": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/react-media-recorder/-/react-media-recorder-1.6.6.tgz", + "integrity": "sha512-VdC4bUINMWJyqOAHw1DaZ8HZhdCyVBK85zJ4cHMo9tsrekui3wq5ZxNtBmNe6nbAFQBTNj/pRnLEsiVrCW+TNQ==", + "dependencies": { + "extendable-media-recorder": "^6.6.5", + "extendable-media-recorder-wav-encoder": "^7.0.68" + } + }, "node_modules/react-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/react-property/-/react-property-2.0.2.tgz", @@ -9178,6 +9375,14 @@ "object-assign": "^4.1.1" } }, + "node_modules/react-speech-recognition": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/react-speech-recognition/-/react-speech-recognition-3.10.0.tgz", + "integrity": "sha512-EVSr4Ik8l9urwdPiK2r0+ADrLyDDrjB0qBRdUWO+w2MfwEBrj6NuRmy1GD3x7BU/V6/hab0pl8Lupen0zwlJyw==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/react-syntax-highlighter": { "version": "15.5.0", "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.5.0.tgz", @@ -9298,6 +9503,53 @@ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" }, + "node_modules/recorder-audio-worklet": { + "version": "5.1.39", + "resolved": "https://registry.npmjs.org/recorder-audio-worklet/-/recorder-audio-worklet-5.1.39.tgz", + "integrity": "sha512-w/RazoBwZnkFnEPRsJYNThOHznLQC98/IzWRrutpJQVvCcL0nbLsVSLDaRrnrqVpRUI11VgiXRh30HaHiSdVhQ==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "broker-factory": "^3.0.75", + "fast-unique-numbers": "^7.0.2", + "recorder-audio-worklet-processor": "^4.2.21", + "standardized-audio-context": "^25.3.41", + "subscribable-things": "^2.1.14", + "tslib": "^2.5.0", + "worker-factory": "^6.0.76" + } + }, + "node_modules/recorder-audio-worklet-processor": { + "version": "4.2.21", + "resolved": "https://registry.npmjs.org/recorder-audio-worklet-processor/-/recorder-audio-worklet-processor-4.2.21.tgz", + "integrity": "sha512-oiiS2sp6eMxkvjt13yetSYUJvnAxBZk60mIxz0Vf/2lDWa/4svCyMLHIDzYKbHahkISd0UYyqLS9dI7xDlUOCA==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "tslib": "^2.5.0" + } + }, + "node_modules/recorder-audio-worklet/node_modules/fast-unique-numbers": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/fast-unique-numbers/-/fast-unique-numbers-7.0.2.tgz", + "integrity": "sha512-xnqpsnu889bHbq5cbDMwCJ2BPf6kjFPMu+RHfqKvisRxeEbTOVxY5aW/ZNsZ/r8OlwatxmjdFEVQog2xAhLkvg==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.15.4" + } + }, + "node_modules/recorder-audio-worklet/node_modules/worker-factory": { + "version": "6.0.76", + "resolved": "https://registry.npmjs.org/worker-factory/-/worker-factory-6.0.76.tgz", + "integrity": "sha512-W1iBNPmE9p0asU4aFmYJYCnMxhkvk4qlKc660GlHxWgmflY64NxxTbmKqipu4K5p9LiKKPjqXfcQme6153BZEQ==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "compilerr": "^10.0.2", + "fast-unique-numbers": "^7.0.2", + "tslib": "^2.5.0" + } + }, "node_modules/redux": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", @@ -9438,9 +9690,9 @@ } }, "node_modules/regenerator-runtime": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", - "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, "node_modules/regexp.prototype.flags": { "version": "1.5.1", @@ -9561,6 +9813,11 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rxjs-interop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/rxjs-interop/-/rxjs-interop-2.0.0.tgz", + "integrity": "sha512-ASEq9atUw7lualXB+knvgtvwkCEvGWV2gDD/8qnASzBkzEARZck9JAyxmY8OS6Nc1pCPEgDTKNcx+YqqYfzArw==" + }, "node_modules/safe-array-concat": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", @@ -9765,6 +10022,16 @@ "node": ">=0.1.14" } }, + "node_modules/standardized-audio-context": { + "version": "25.3.72", + "resolved": "https://registry.npmjs.org/standardized-audio-context/-/standardized-audio-context-25.3.72.tgz", + "integrity": "sha512-Dvwu2NuqafQqWxUWoo6G9ze/cvVNlFDpmIOA8XjuItrfR0h/REjgjoYCT3Y7nbkUJKGoz8SqqVzR7JATQV4XeQ==", + "dependencies": { + "@babel/runtime": "^7.24.5", + "automation-events": "^7.0.5", + "tslib": "^2.6.2" + } + }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", @@ -10027,6 +10294,16 @@ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" }, + "node_modules/subscribable-things": { + "version": "2.1.36", + "resolved": "https://registry.npmjs.org/subscribable-things/-/subscribable-things-2.1.36.tgz", + "integrity": "sha512-IAFC0jGsoMFiG6LTXEcp7hMrRS2RvEXPVFOGGH7xV5/c36DWet93x5aGD8KOrht/7dSiOdaV9rnPehnHB8BnGw==", + "dependencies": { + "@babel/runtime": "^7.24.5", + "rxjs-interop": "^2.0.0", + "tslib": "^2.6.2" + } + }, "node_modules/sucrase": { "version": "3.34.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz", @@ -10226,6 +10503,19 @@ "node": ">=8.0" } }, + "node_modules/trigram-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/trigram-utils/-/trigram-utils-2.0.1.tgz", + "integrity": "sha512-nfWIXHEaB+HdyslAfMxSqWKDdmqY9I32jS7GnqpdWQnLH89r6A5sdk3fDVYqGAZ0CrT8ovAFSAo6HRiWcWNIGQ==", + "dependencies": { + "collapse-white-space": "^2.0.0", + "n-gram": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -10668,6 +10958,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/worker-factory": { + "version": "7.0.25", + "resolved": "https://registry.npmjs.org/worker-factory/-/worker-factory-7.0.25.tgz", + "integrity": "sha512-JIcaoOIuYgIC6PNy7jB35mR129x6MQT+g6xBo2c0x+uQuZyOa31gxIW9Z6FdSFOgLpSj5Z3CQieTRV+F9GWB1Q==", + "dependencies": { + "@babel/runtime": "^7.24.5", + "fast-unique-numbers": "^9.0.5", + "tslib": "^2.6.2" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", diff --git a/package.json b/package.json index 34870898..d24e4eff 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "dotenv": "^16.4.5", "firebase": "^10.7.1", "firebase-auth": "^0.1.2", + "franc-min": "^6.2.0", "html-react-parser": "^5.1.10", "html2canvas": "^1.4.1", "install": "^0.13.0", @@ -46,12 +47,15 @@ "react-json-tree": "^0.18.0", "react-markdown": "^9.0.1", "react-material-ui-carousel": "^3.4.2", + "react-media-recorder": "^1.6.6", "react-quill": "^2.0.0", "react-quilljs": "^1.3.3", "react-redux": "^9.0.4", "react-router-dom": "^6.21.2", + "react-speech-recognition": "^3.10.0", "react-syntax-highlighter": "^15.5.0", - "recharts": "^2.12.0" + "recharts": "^2.12.0", + "regenerator-runtime": "^0.14.1" }, "devDependencies": { "autoprefixer": "^10.4.16", diff --git a/src/app/actions/api/Projects/EditGuestWorkspace.js b/src/app/actions/api/Projects/EditGuestWorkspace.js new file mode 100644 index 00000000..d8f890cf --- /dev/null +++ b/src/app/actions/api/Projects/EditGuestWorkspace.js @@ -0,0 +1,47 @@ +/** + * Login API + */ +import API from "../../api"; +import ENDPOINTS from "../../../../config/apiendpoint" +import constants from "../../constants"; + +export default class EditGuestWorkspace extends API { + constructor(workspaceId,workspacePassword ,timeout = 2000) { + super("PATCH", timeout, false); + this.workspace_password = workspacePassword + this.type = constants.ARCHIVE_WORKSPACE; + this.endpoint = `${super.apiEndPointAuto()}${ENDPOINTS.getWorkspaces}${workspaceId}/edit_workspace/`; + } + + processResponse(res) { + super.processResponse(res); + if (res) { + this.editworkspace= res; + } + } + + apiEndPoint() { + return this.endpoint; + } + + getBody() { + return { + workspace_password:this.workspace_password, + } + } + + + getHeaders() { + this.headers = { + headers: { + "Content-Type": "application/json", + "Authorization": `JWT ${localStorage.getItem('anudesh_access_token')}` + }, + }; + return this.headers; + } + + getPayload() { + return this.archiveworkspace; + } +} diff --git a/src/app/actions/api/Projects/EditWorkspace.js b/src/app/actions/api/Projects/EditWorkspace.js new file mode 100644 index 00000000..37c85c2c --- /dev/null +++ b/src/app/actions/api/Projects/EditWorkspace.js @@ -0,0 +1,46 @@ +/** + * Login API + */ +import API from "../../api"; +import ENDPOINTS from "../../../../config/apiendpoint" +import constants from "../../constants"; + +export default class EditWorkspace extends API { + constructor(workspaceId, timeout = 2000) { + super("PATCH", timeout, false); + this.type = constants.ARCHIVE_WORKSPACE; + this.endpoint = `${super.apiEndPointAuto()}${ENDPOINTS.getWorkspaces}${workspaceId}/edit_workspace/`; + } + + processResponse(res) { + super.processResponse(res); + if (res) { + this.editworkspace= res; + } + } + + apiEndPoint() { + return this.endpoint; + } + + getBody() { + return { + guest_workspace: false + } + } + + + getHeaders() { + this.headers = { + headers: { + "Content-Type": "application/json", + "Authorization": `JWT ${localStorage.getItem('anudesh_access_token')}` + }, + }; + return this.headers; + } + + getPayload() { + return this.archiveworkspace; + } +} diff --git a/src/app/actions/api/Projects/createWorkspace.js b/src/app/actions/api/Projects/createWorkspace.js new file mode 100644 index 00000000..71dd6336 --- /dev/null +++ b/src/app/actions/api/Projects/createWorkspace.js @@ -0,0 +1,48 @@ +/** + * Login API + */ +import API from "../../api"; +import ENDPOINTS from "../../../../config/apiendpoint" +import constants from "../../constants"; + +export default class CreateGuestWorkspace extends API { + constructor(workspaceId,workspacePassword ,timeout = 2000) { + super("PATCH", timeout, false); + this.workspace_password = workspacePassword + this.type = constants.ARCHIVE_WORKSPACE; + this.endpoint = `${super.apiEndPointAuto()}${ENDPOINTS.getWorkspaces}${workspaceId}/edit_workspace/`; + } + + processResponse(res) { + super.processResponse(res); + if (res) { + this.editworkspace= res; + } + } + + apiEndPoint() { + return this.endpoint; + } + + getBody() { + return { + workspace_password:this.workspace_password, + guest_workspace: true + } + } + + + getHeaders() { + this.headers = { + headers: { + "Content-Type": "application/json", + "Authorization": `JWT ${localStorage.getItem('anudesh_access_token')}` + }, + }; + return this.headers; + } + + getPayload() { + return this.archiveworkspace; + } +} diff --git a/src/app/page.js b/src/app/page.js index 313b41bb..b74b29d5 100644 --- a/src/app/page.js +++ b/src/app/page.js @@ -1,4 +1,5 @@ "use client"; +// import 'regenerator-runtime/runtime' import RootLayout from "./layout"; import Home from "./ui/pages/home/home" import { HashRouter, Route, Routes, Navigate } from "react-router-dom" diff --git a/src/app/ui/pages/chat/AnnotatePage.jsx b/src/app/ui/pages/chat/AnnotatePage.jsx index 9078e0bb..3c25536e 100644 --- a/src/app/ui/pages/chat/AnnotatePage.jsx +++ b/src/app/ui/pages/chat/AnnotatePage.jsx @@ -1012,7 +1012,7 @@ const AnnotatePage = () => { } > - + :} )} diff --git a/src/app/ui/pages/home/home.js b/src/app/ui/pages/home/home.js index 29d5fca7..70553293 100644 --- a/src/app/ui/pages/home/home.js +++ b/src/app/ui/pages/home/home.js @@ -2,7 +2,7 @@ import "./home.css"; import { useEffect } from "react"; import Image from "next/image"; -import { useNavigate } from "react-router-dom"; +import { Link, useNavigate } from "react-router-dom"; import ChatIcon from "@mui/icons-material/Chat"; import IntegrationInstructionsIcon from "@mui/icons-material/IntegrationInstructions"; import RateReviewIcon from "@mui/icons-material/RateReview"; @@ -165,9 +165,11 @@ const Home = () => { {banner.subheading}
- +
- ))} + ))}
@@ -267,7 +291,7 @@ const ModelInteractionEvaluation = ({currentInteraction,setCurrentInteraction}) ? currentInteraction.additional_note : null } - style={{minHeight:"50px",maxHeight:"10rem",height:"50px"}} + style={{ minHeight: "50px", maxHeight: "10rem", height: "50px" }} onChange={handleNoteChange} className={classes.notesTextarea} /> @@ -285,7 +309,7 @@ const ModelInteractionEvaluation = ({currentInteraction,setCurrentInteraction}) return newExpanded; }); }; - + return (
{pairs.map((pair, index) => { @@ -300,7 +324,7 @@ const ModelInteractionEvaluation = ({currentInteraction,setCurrentInteraction}) boxShadow: expanded[index] ? "0px 4px 6px rgba(0, 0, 0, 0.1)" : "0px 4px 6px rgba(0, 0, 0, 0.1)", - borderBottom: "none", + borderBottom: "none", }} > - + {pair.output} -
); }; - + const QuestionList = ({ questions }) => { return ( -
-
- {questions.map((question, index) => ( - handleQuestionClick(question)} - > - {question} - - ))} -
+
+
+ {questions.map((question, index) => ( + handleQuestionClick(question)} + > + {question} + + ))} +
); }; @@ -390,18 +425,18 @@ const ModelInteractionEvaluation = ({currentInteraction,setCurrentInteraction}) // maxWidth={"70%"} enable={{ right: true, top: false, bottom: false, left: false }} > -
+
{translate("modal.interact")}
- + {interactions && ( )} -
+
{translate("modal.quelist")}
- + ); }; @@ -409,9 +444,9 @@ const ModelInteractionEvaluation = ({currentInteraction,setCurrentInteraction}) return ( <>
- - - + + + {leftPanelVisible && } {EvaluationForm()} diff --git a/src/app/ui/pages/progress/PerformanaceAnalytics/PerformanceAnalytics.jsx b/src/app/ui/pages/progress/PerformanaceAnalytics/PerformanceAnalytics.jsx index 90613009..4fcfacb2 100644 --- a/src/app/ui/pages/progress/PerformanaceAnalytics/PerformanceAnalytics.jsx +++ b/src/app/ui/pages/progress/PerformanaceAnalytics/PerformanceAnalytics.jsx @@ -416,7 +416,7 @@ export default function PerformanceAnalytics() { - + Target Language Project Type {""} {/* { diff --git a/src/app/ui/pages/workspace/AddWorkspaceDialog.js b/src/app/ui/pages/workspace/AddWorkspaceDialog.js index 1da7ec7b..68defb94 100644 --- a/src/app/ui/pages/workspace/AddWorkspaceDialog.js +++ b/src/app/ui/pages/workspace/AddWorkspaceDialog.js @@ -1,33 +1,86 @@ -import { Button, CircularProgress, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, FormControlLabel, Switch, TextField } from '@mui/material' +import { Button, CircularProgress, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, FormControlLabel, Switch, TextField, FormControl, InputLabel, Input, IconButton, FormHelperText, Typography, OutlinedInput } from '@mui/material' import React, { useState } from 'react' import CustomButton from '../../../../components/common/Button' import { useDispatch, useSelector } from 'react-redux'; import CreateWorkspaceAPI from '../../../actions/api/workspace/CreateWorkspace' +import InputAdornment from '@mui/material/InputAdornment'; +import Visibility from '@mui/icons-material/Visibility'; +import VisibilityOff from '@mui/icons-material/VisibilityOff'; import GetWorkspaceAPI from '../../../actions/api/workspace/GetWorkspaceData'; -import { fetchWorkspaceCreateData } from '@/Lib/Features/getWorkspaceData'; -const AddWorkspaceDialog = ({ isOpen, dialogCloseHandler}) => { +// import { fetchWorkspaceCreateData } from '@/Lib/Features/getWorkspaceData'; +import CustomizedSnackbars from '@/components/common/Snackbar'; +import AuthenticateToWorkspaceAPI from '@/app/actions/api/workspace/AuthenticateToWorkspaceAPI'; +import CreateGuestWorkspace from '@/app/actions/api/Projects/createWorkspace'; +import { useEffect } from 'react'; +// import { fetchWorkspaceDetails } from '@/Lib/Features/getWorkspaceDetails'; +import { fetchWorkspaceData } from '@/Lib/Features/GetWorkspace'; + +const AddWorkspaceDialog = ({ isOpen, dialogCloseHandler,orgId}) => { const dispatch = useDispatch(); const [workspaceName, setWorkspaceName] = useState('') const [loading, setLoading] = useState(false); + const [password1, setPassword1] = useState(''); + const [password2, setPassword2] = useState(''); + const [showPassword1, setShowPassword1] = useState(false); + const [showPassword2, setShowPassword2] = useState(false); + const [passwordErrors, setPasswordErrors] = useState([]); + const [publicanalytics,setpublicanalytics] = useState(true); + const [guestWorkspace, setGuestWorkspace] = useState(true); + // const workspaceData = useSelector((state) => state.GetWorkspace.data); + const [currentWorkspaceName, setCurrentWorkspaceName] = useState(""); + const [currentWorkspaceId, setWorkspaceCurrentId] = useState(""); + const [passwordEqual, setPasswordEqual] = useState(true); + const workspaceData1= useSelector((state) => console.log(state)); - const [publicanalytics,setpublicanalytics] = useState(true) - - + const [snackbar, setSnackbarInfo] = useState({ + open: false, + message: "", + variant: "success", + }); + const validatePassword = () => { + const errors = []; + if(password1.length>0){ + if (password1.length < 8) { + errors.push("This password is too short. It must contain at least 8 characters."); + } + const commonPasswords = ["password", "12345678", "qwerty"]; + if (commonPasswords.includes(password1)) { + errors.push("This password is too common."); + } + setPasswordErrors(errors); + return errors.length === 0; + } + }; + useEffect(() => { + validatePassword() + equal() - const handlepublicanalytics = async () => { + }, [password1,password2]); + useEffect(() => { + dispatch(fetchWorkspaceData()); +}, []); + const equal =()=>{ + if(password2.length>0){ + setPasswordEqual(password1===password2) + } + } + const handlepublicanalytics = async () => { // setLoading(true); setpublicanalytics((publicanalytics)=>!publicanalytics) }; - - + const handleguestworkspace = async () => { + // setLoading(true); + setGuestWorkspace((guestWorkspace)=>!guestWorkspace) + }; const addBtnClickHandler = async (event) => { + console.log("lll"); setLoading(true); if (!workspaceName) return; // setLoading(true); const createWorkspaceObj = new CreateWorkspaceAPI( - 1, + orgId, workspaceName, publicanalytics ); @@ -44,14 +97,71 @@ const AddWorkspaceDialog = ({ isOpen, dialogCloseHandler}) => { const createWorkspaceRespData = await createWorkspaceRes.json(); if (createWorkspaceRes.ok) { - dispatch(fetchWorkspaceCreateData(1)); + const getWorkspaceApiObj = new GetWorkspaceAPI(); // Correctly instantiate the class + const workspaceDataRes = await fetch(getWorkspaceApiObj.apiEndPoint(), { + method: "GET", + headers: { + Authorization: `JWT ${token}`, + 'Content-Type': 'application/json', + }, + }); + const workspaceData = await workspaceDataRes.json(); + + + const workspaceDetails = workspaceData.find(ws => ws.workspace_name === workspaceName); + console.log(workspaceDetails,workspaceName); + if(guestWorkspace){ const apiObj = new CreateGuestWorkspace(workspaceDetails.id,password1); + const res = await fetch(apiObj.apiEndPoint(), { + method: "PATCH", + body: JSON.stringify(apiObj.getBody()), + headers: apiObj.getHeaders().headers, + }); + const resp = await res.json(); + setLoading(false); + if (res.ok) { + // dispatch(fetchWorkspaceDetails(orgId)); + setSnackbarInfo({ + open: true, + message: resp?.message, + variant: "success", + }) + } else { + setSnackbarInfo({ + open: true, + message: resp?.message, + variant: "error", + }) + } } + + } dialogCloseHandler(); setLoading(false); setWorkspaceName(''); return createWorkspaceRespData; } + const handlePasswordChange1 = (event) => { + setPassword1(event.target.value); + // validatePassword(event.target.value) + // console.log(event.target.value === password1); + // setPasswordEqual(event.target.value === password2); + + }; + + const handlePasswordChange2 = (event) => { + setPassword2(event.target.value); + // validatePassword(password1) + // setPasswordEqual(event.target.value === password1); + }; + + const handleTogglePasswordVisibility1 = () => { + setShowPassword1(!showPassword1); + }; + + const handleTogglePasswordVisibility2 = () => { + setShowPassword2(!showPassword2); + }; const handleUserDialogClose = () => { setWorkspaceName(''); @@ -61,8 +171,24 @@ const AddWorkspaceDialog = ({ isOpen, dialogCloseHandler}) => { const handleTextField=(e)=>{ setWorkspaceName(e.target.value) } - + console.log(passwordEqual); + const renderSnackBar = () => { + return ( + + setSnackbarInfo({ open: false, message: "", variant: "" }) + } + anchorOrigin={{ vertical: "top", horizontal: "right" }} + variant={snackbar.variant} + message={[snackbar.message]} + /> + ); + }; + return ( + <> + {renderSnackBar()} Enter workspace details @@ -74,6 +200,67 @@ const AddWorkspaceDialog = ({ isOpen, dialogCloseHandler}) => { checked={publicanalytics} onChange={handlepublicanalytics} /> + + } + labelPlacement="start" + label ="Guest Workspace" + checked={guestWorkspace} + onChange={handleguestworkspace} + sx={{marginLeft: "35%"}} + /> +
+ {guestWorkspace && ( + <> + + Enter Password + + + {showPassword1 ? : } + + + } + label="Enter Password" + /> + {passwordErrors.map((error, index) => ( + {error} + ))} + + + Confirm Password + + + {showPassword2 ? : } + + + } + label="Re-enter Password" + /> + {passwordEqual==true ? "" : The passwords don't match} + + + )} +
+ ) } diff --git a/src/app/ui/pages/workspace/WorkspaceSetting.jsx b/src/app/ui/pages/workspace/WorkspaceSetting.jsx index 57a57a4e..e77bfb24 100644 --- a/src/app/ui/pages/workspace/WorkspaceSetting.jsx +++ b/src/app/ui/pages/workspace/WorkspaceSetting.jsx @@ -1,37 +1,124 @@ import React, { useEffect, useState } from "react"; import CustomButton from "../../../../components/common/Button"; -import "@/styles/Dataset.css"; +import "@/styles/Dataset.css"; import CustomizedSnackbars from "../../../../components/common/Snackbar"; import Dialog from "@mui/material/Dialog"; -import { Button,Grid } from "@mui/material"; +import { Button, FormControl, FormControlLabel, FormGroup, Grid, IconButton, InputAdornment, InputLabel, OutlinedInput, Switch, Typography } from "@mui/material"; import DialogActions from "@mui/material/DialogActions"; import DialogContent from "@mui/material/DialogContent"; import DialogContentText from "@mui/material/DialogContentText"; import TextField from '@mui/material/TextField'; import DatasetStyle from "@/styles/dataset"; -import { useDispatch,useSelector } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; import LoginAPI from "../../../actions/api/user/Login" -import { useNavigate,useParams } from "react-router-dom"; +import { useNavigate, useParams } from "react-router-dom"; import DownloadAllProjects from "../../../actions/api/Projects/DownloadAllProjects"; import { fetchArchiveProject } from "../../../../Lib/Features/projects/GetArchiveProject"; import ArchiveWorkspaceAPI from "@/app/actions/api/Projects/GetArchiveProjectAPI"; +import OutlinedTextField from "@/components/common/OutlinedTextField"; +import { translate } from "@/config/localisation"; +import { VisibilityOff } from "@mui/icons-material"; +import { Visibility } from "@material-ui/icons"; +import CreateGuestWorkspace from "@/app/actions/api/Projects/createWorkspace"; +import EditWorkspace from "@/app/actions/api/Projects/EditWorkspace"; +import EditGuestWorkspace from "@/app/actions/api/Projects/EditGuestWorkspace"; function WorkspaceSetting(props) { - /* eslint-disable react-hooks/exhaustive-deps */ + /* eslint-disable react-hooks/exhaustive-deps */ - const { onArchiveWorkspace } = props + const { onArchiveWorkspace } = props; const { id } = useParams(); const classes = DatasetStyle(); const dispatch = useDispatch(); const [loading, setLoading] = useState(false); const [currentPageNumber, setCurrentPageNumber] = useState(1); + const [newpassword, setnewpassword] = useState(''); + const [confirmpassword, setconfirmpassword] = useState(''); + const [shownewpassword, setShownewpassword] = useState(false); + const [showconfirmpassword, setShowconfirmpassword] = useState(false); + const [passwordEqual, setPasswordEqual] = useState(true); const [snackbar, setSnackbarInfo] = useState({ open: false, message: "", variant: "success", }); + const validatePassword = () => { + const errors = []; + if(newpassword.length>0){ + if (newpassword.length < 8) { + errors.push("This password is too short. It must contain at least 8 characters."); + } + const commonPasswords = ["password", "12345678", "qwerty"]; // Simplified common password list + if (commonPasswords.includes(newpassword)) { + errors.push("This password is too common."); + } + setPasswordErrors(errors); + return errors.length === 0; + } + + }; + useEffect(()=>{ + validatePassword() + equal() + },[newpassword,confirmpassword]) + const equal =()=>{ + if(confirmpassword.length>0){ + setPasswordEqual(newpassword===confirmpassword) + } + } const workspaceDtails = useSelector(state => state.getWorkspaceDetails.data); + const [guestWorkspace, setGuestWorkspace] = useState(workspaceDtails?.guest_workspace_display =="No"?false:true); + const [openPasswordDialog, setOpenPasswordDialog] = useState(false); + const [openToggleDialog, setOpenToggleDialog] = useState(false); + const [passwordErrors, setPasswordErrors] = useState([]); + + const handleToggleChange = async() => { + if (!guestWorkspace) { + setOpenToggleDialog(true); + } else { + const apiObj = new EditWorkspace(id); + const res = await fetch(apiObj.apiEndPoint(), { + method: "PATCH", + body: JSON.stringify(apiObj.getBody()), + headers: apiObj.getHeaders().headers, + }); + const resp = await res.json(); + setLoading(false); + if (res.ok) { + setSnackbarInfo({ + open: true, + message: resp?.message, + variant: "success", + }) + } else { + setSnackbarInfo({ + open: true, + message: "Successfully switched off guest workspace mode", + variant: "success", + }) + } + setGuestWorkspace(false); + setnewpassword("") + setconfirmpassword("") + } + }; + + const handleToggleDialogOpen = () => { + setOpenToggleDialog(true); + }; + + const handleToggleDialogClose = () => { + setOpenToggleDialog(false); + }; + + const handlePasswordDialogOpen = () => { + setOpenPasswordDialog(true); + }; + + const handlePasswordDialogClose = () => { + setOpenPasswordDialog(false); + }; const handleArchiveWorkspace = async () => { const projectObj = new ArchiveWorkspaceAPI(id, id); @@ -48,8 +135,7 @@ function WorkspaceSetting(props) { message: "success", variant: "success", }) - onArchiveWorkspace() - // window.location.reload(); + onArchiveWorkspace(); } else { setSnackbarInfo({ open: true, @@ -57,9 +143,87 @@ function WorkspaceSetting(props) { variant: "error", }) } - } + const handlenewpassword = (event) => { + setnewpassword(event.target.value); + }; + + const handleconfirmpassword = (event) => { + setconfirmpassword(event.target.value); + }; + + const handleTogglenewpasswordVisibility = () => { + setShownewpassword(!shownewpassword); + }; + + const handleToggleconfirmpasswordVisibility = () => { + setShowconfirmpassword(!showconfirmpassword); + }; + + const handlePasswordCreate = async() => { + if (newpassword !== confirmpassword) { + setPasswordEqual(false); + return; + } + setPasswordEqual(true); + const apiObj = new CreateGuestWorkspace(id,newpassword); + const res = await fetch(apiObj.apiEndPoint(), { + method: "PATCH", + body: JSON.stringify(apiObj.getBody()), + headers: apiObj.getHeaders().headers, + }); + const resp = await res.json(); + setLoading(false); + if (res.ok) { + setSnackbarInfo({ + open: true, + message: resp?.message, + variant: "success", + }) + } else { + setSnackbarInfo({ + open: true, + message: resp?.message, + variant: "error", + }) + } + setGuestWorkspace(true); + handleToggleDialogClose(); + setnewpassword("") + setconfirmpassword("") + }; + + const handlePasswordUpdate = async() => { + + const apiObj = new EditGuestWorkspace(id,newpassword); + const res = await fetch(apiObj.apiEndPoint(), { + method: "PATCH", + body: JSON.stringify(apiObj.getBody()), + headers: apiObj.getHeaders().headers, + }); + const resp = await res.json(); + setLoading(false); + if (res.ok) { + handlePasswordDialogClose(); + setSnackbarInfo({ + open: true, + message: resp?.message, + variant: "success", + }) + } else { + handlePasswordDialogClose(); + setSnackbarInfo({ + open: true, + message: resp?.message, + variant: "error", + }) + } + setnewpassword("") + setconfirmpassword("") + }; + + const renderSnackBar = () => { return ( state.getLoggedInData?.data); const handleDownloadProject = async () => { - const projectObj = new DownloadAllProjects(workspaceDtails.id,user.id); + const projectObj = new DownloadAllProjects(workspaceDtails.id, user.id); const res = await fetch(projectObj.apiEndPoint(), { method: "POST", body: JSON.stringify(projectObj.getBody()), @@ -113,7 +277,6 @@ function WorkspaceSetting(props) { message: resp?.message, variant: "success", }) - } else { setSnackbarInfo({ open: true, @@ -121,8 +284,8 @@ function WorkspaceSetting(props) { variant: "error", }) } - }; + return (
{renderSnackBar()} @@ -149,42 +312,184 @@ function WorkspaceSetting(props) { /> - - + + - - - + + + Update Password + + + + + Enter Password + + + {shownewpassword ? : } + + + } + label="Enter Password" + /> + {passwordErrors.map((error, index) => ( + {error} + ))} + + + + + Confirm Password + + + {showconfirmpassword ? : } + + + } + label="Confirm Password" + /> + {passwordEqual==true ? "" : The passwords don't match} + + + + + + + + + + + + + + Enable Guest Workspace + + + + + Enter Password + + + {shownewpassword ? : } + + + } + label="Enter Password" + /> + {passwordErrors.map((error, index) => ( + {error} + ))} + + + + + Confirm Password + + + {showconfirmpassword ? : } + + + } + label="Confirm Password" + /> + {passwordEqual==true ? "" : The passwords don't match} + + + + + + + + + + + + + + Guest workspace + + } + /> + + {guestWorkspace && ( + + )} + + + + +
- ) + ); } -export default WorkspaceSetting; \ No newline at end of file + +export default WorkspaceSetting; diff --git a/src/components/Chat/AudioRecorder.jsx b/src/components/Chat/AudioRecorder.jsx new file mode 100644 index 00000000..fb2efca9 --- /dev/null +++ b/src/components/Chat/AudioRecorder.jsx @@ -0,0 +1,114 @@ +import React, { useState, useEffect } from 'react'; +import { useReactMediaRecorder } from 'react-media-recorder'; +import IconButton from '@mui/material/IconButton'; +import PlayArrowIcon from '@mui/icons-material/PlayArrow'; +import PauseIcon from '@mui/icons-material/Pause'; +import DeleteIcon from '@mui/icons-material/Delete'; +import MicIcon from '@mui/icons-material/Mic'; +import StopIcon from '@mui/icons-material/Stop'; +import Button from '@mui/material/Button'; +import { franc } from 'franc-min'; + +const AudioRecorder = ({ onTranscription, prompt }) => { + const { startRecording, stopRecording, mediaBlobUrl, pauseRecording, resumeRecording } = useReactMediaRecorder({ audio: true }); + const [isRecording, setIsRecording] = useState(false); + const [audioUrl, setAudioUrl] = useState(null); + const [recognizer, setRecognizer] = useState(null); + + const handleStart = () => { + setIsRecording(true); + startRecording(); + }; + + const handleStop = () => { + setIsRecording(false); + stopRecording(); + }; + + const handlePause = () => { + pauseRecording(); + }; + + const handleResume = () => { + resumeRecording(); + }; + + const handleDelete = () => { + setAudioUrl(null); + onTranscription(''); + }; + + const handleSetText = () => { + if (mediaBlobUrl) { + const recognizer = new window.webkitSpeechRecognition(); + recognizer.lang = 'en-US'; // Default language + recognizer.interimResults = false; + recognizer.maxAlternatives = 1; + + console.log(recognizer); + recognizer.onresult = (event) => { + const transcript = event.results[0][0].transcript; + onTranscription(transcript); + }; + + recognizer.onerror = (event) => { + console.error('Speech recognition error:', event.error); + }; + + recognizer.onaudioend = () => { + stopRecording(); + }; + + setRecognizer(recognizer); + + const audio = new Audio(mediaBlobUrl); + audio.onplay = () => recognizer.start(); + audio.onended = () => recognizer.stop(); + + // Detect language + const language = franc(prompt); + if (language && language !== 'und') { + recognizer.lang = language; + } else { + recognizer.lang = 'en-US'; + } + console.log('Detected language:', recognizer.lang); + + audio.play(); + } + }; + + useEffect(() => { + if (mediaBlobUrl) { + setAudioUrl(mediaBlobUrl); + prompt=mediaBlobUrl + } + // Clean up recognizer when the component unmounts + return () => { + if (recognizer) { + recognizer.onresult = null; + recognizer.onerror = null; + recognizer.onaudioend = null; + } + }; + }, [mediaBlobUrl, recognizer]); + + return ( +
+ + {isRecording ? : } + + {audioUrl && ( +
+
+ )} +
+ ); +}; + +export default AudioRecorder; diff --git a/src/components/Chat/TextArea.jsx b/src/components/Chat/TextArea.jsx index 313d6911..a8e6ff79 100644 --- a/src/components/Chat/TextArea.jsx +++ b/src/components/Chat/TextArea.jsx @@ -8,6 +8,7 @@ import SendRoundedIcon from "@mui/icons-material/SendRounded"; import CircularProgress from "@mui/material/CircularProgress"; import { TextareaAutosize as BaseTextareaAutosize } from "@mui/base/TextareaAutosize"; import { IndicTransliterate } from "@ai4bharat/indic-transliterate"; +// import AudioRecorder from "./AudioRecorder"; const orange = { 200: "pink", @@ -49,6 +50,11 @@ export default function Textarea({ event.target.style.borderColor = orange[400]; }; + // const handleTranscription = (transcript) => { + // setText(transcript); + // }; + + const handleMouseLeave = (event) => { event.target.style.borderColor = grey[200]; }; @@ -183,6 +189,8 @@ export default function Textarea({ }} /> )} + {/* */} + { diff --git a/src/components/Tabs/Invites.jsx b/src/components/Tabs/Invites.jsx index 874eeac3..a0e2e954 100644 --- a/src/components/Tabs/Invites.jsx +++ b/src/components/Tabs/Invites.jsx @@ -21,6 +21,7 @@ const Invites = (props) => { const dispatch = useDispatch(); const {orgId} = useParams() const OrganizationUserData = useSelector(state => state.getOrganizationUsers.data); + const OrganizationUserDatas = useSelector(state => console.log(state)); const apiLoading = useSelector((state) => state.getOrganizationUsers.status !== "succeeded"); const ManagerSuggestions = useSelector(state => state.getManagerSuggestions?.data); const [tabValue, setTabValue] = useState(0); @@ -59,7 +60,7 @@ const Invites = (props) => { key={1} reSendButton ={reSendButton} hideButton = {hideButton ? hideButton : false} - dataSource={OrganizationUserData && OrganizationUserData.length > 0 && OrganizationUserData.filter((el, i) => { return !el.has_accepted_invite })} + dataSource={OrganizationUserData?.length > 0 && OrganizationUserData.filter((el, i) => { return el.has_accepted_invite==false})} /> : <> { const OrganizationDetails = useSelector(state => state.getLoggedInData?.data.organization); @@ -403,6 +409,15 @@ const OrganizationReports = () => { /> ); }; + const handleChange = (event) => { + const { + target: { value }, + } = event; + setParticipationTypes( + typeof value === 'string' ? value.split(',') : value, + ); + }; + return ( @@ -446,26 +461,30 @@ const OrganizationReports = () => {
{radiobutton === "ProjectReports" && - - Type - - + + Type + + } - Project Type + Project Type { } {radiobutton === "PaymentReports" && - - Participation Types - - + + Participation Types + + } {radiobutton === "UsersReports" && - Report Type + Report Type { - Target Language + Target Language setProjectReportType(e.target.value)} - > - High-Level Reports - Detailed Reports - - + + Type + + } {(radioButton !== "project") && { xl={3} > - + Report Type { {radioButton === "user" && - Projects Filter + Projects Filter { } {radioButton === "payment" && - Participation Types + Participation Types setProjectReportType(e.target.value)} - > - High-Level Reports - Detailed Reports - - + + + Type + + + { xl={3} > - + Project Type