From fce33aebf84c97e91d060f46d4d99af3a80864d1 Mon Sep 17 00:00:00 2001 From: kartikvirendrar Date: Thu, 22 Feb 2024 10:37:15 +0530 Subject: [PATCH] added analytics page --- package-lock.json | 478 ++++++- package.json | 11 +- .../Analytics/getMetaAnalyticsData.js | 43 + .../Analytics/getTaskAnalyticsData.js | 44 + src/Lib/Store.js | 4 + .../actions/api/Progress/CumulativeTasks.js | 42 + src/app/actions/api/Progress/MetaAnalytics.js | 45 + .../api/Progress/PerformanceAnalytics.js | 41 + .../actions/api/Progress/PeriodicalTasks.js | 42 + src/app/actions/api/Progress/TaskAnalytics.js | 45 + .../api/ProjectDetails/GetProjectDomains.js | 38 + .../api/UserManagement/FetchLanguages.js | 39 + src/app/page.js | 201 +-- .../AudioDurationMetaAnalyticsChart.jsx | 276 ++++ .../progress/MetaAnalytics/MetaAnalytics.jsx | 147 +++ .../SentanceCountMetaAnalyticsChart.jsx | 221 ++++ ...SingleSpeakerAudioTranscriptionEditing.jsx | 221 ++++ .../WordCountMetaAnalyticsChart.jsx | 325 +++++ .../PerformanceAnalytics.jsx | 548 ++++++++ .../ui/pages/progress/ProgressAnalytics.jsx | 1149 +++++++++++++++++ src/app/ui/pages/progress/ProgressList.jsx | 70 + .../TaskAnalytics/AudioTaskAnalyticsChart.jsx | 229 ++++ .../ContextualSentenceVerificationChart.jsx | 158 +++ ...SingleSpeakerAudioTranscriptionEditing.jsx | 229 ++++ .../progress/TaskAnalytics/TaskAnalytics.jsx | 139 ++ .../TaskAnalytics/TaskCountAnalyticsChart.jsx | 229 ++++ .../common/ResponsiveChartContainer.jsx | 20 + src/utils/Colors_JSON/Colors_JSON.js | 100 ++ src/utils/Date_Range/getDateRangeFormat.js | 120 ++ 29 files changed, 5150 insertions(+), 104 deletions(-) create mode 100644 src/Lib/Features/Analytics/getMetaAnalyticsData.js create mode 100644 src/Lib/Features/Analytics/getTaskAnalyticsData.js create mode 100644 src/app/actions/api/Progress/CumulativeTasks.js create mode 100644 src/app/actions/api/Progress/MetaAnalytics.js create mode 100644 src/app/actions/api/Progress/PerformanceAnalytics.js create mode 100644 src/app/actions/api/Progress/PeriodicalTasks.js create mode 100644 src/app/actions/api/Progress/TaskAnalytics.js create mode 100644 src/app/actions/api/ProjectDetails/GetProjectDomains.js create mode 100644 src/app/actions/api/UserManagement/FetchLanguages.js create mode 100644 src/app/ui/pages/progress/MetaAnalytics/AudioDurationMetaAnalyticsChart.jsx create mode 100644 src/app/ui/pages/progress/MetaAnalytics/MetaAnalytics.jsx create mode 100644 src/app/ui/pages/progress/MetaAnalytics/SentanceCountMetaAnalyticsChart.jsx create mode 100644 src/app/ui/pages/progress/MetaAnalytics/SingleSpeakerAudioTranscriptionEditing.jsx create mode 100644 src/app/ui/pages/progress/MetaAnalytics/WordCountMetaAnalyticsChart.jsx create mode 100644 src/app/ui/pages/progress/PerformanaceAnalytics/PerformanceAnalytics.jsx create mode 100644 src/app/ui/pages/progress/ProgressAnalytics.jsx create mode 100644 src/app/ui/pages/progress/ProgressList.jsx create mode 100644 src/app/ui/pages/progress/TaskAnalytics/AudioTaskAnalyticsChart.jsx create mode 100644 src/app/ui/pages/progress/TaskAnalytics/ContextualSentenceVerificationChart.jsx create mode 100644 src/app/ui/pages/progress/TaskAnalytics/SingleSpeakerAudioTranscriptionEditing.jsx create mode 100644 src/app/ui/pages/progress/TaskAnalytics/TaskAnalytics.jsx create mode 100644 src/app/ui/pages/progress/TaskAnalytics/TaskCountAnalyticsChart.jsx create mode 100644 src/components/common/ResponsiveChartContainer.jsx create mode 100644 src/utils/Colors_JSON/Colors_JSON.js create mode 100644 src/utils/Date_Range/getDateRangeFormat.js diff --git a/package-lock.json b/package-lock.json index 53c541f6..49363824 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,22 +16,29 @@ "@mui/material": "^5.14.18", "@mui/styles": "^5.14.18", "@mui/x-date-pickers-pro": "^6.18.4", + "@react-hook/media-query": "^1.1.1", "@reduxjs/toolkit": "^2.0.1", "axios": "^1.6.3", - "date-fns": "^3.2.0", + "chart.js": "^4.4.1", + "date-fns": "^3.3.1", "firebase": "^10.7.1", "firebase-auth": "^0.1.2", + "html2canvas": "^1.4.1", + "jspdf": "^2.5.1", "mui-datatables": "^4.3.0", "next": "^14.0.4", "next-redux-wrapper": "^8.1.0", "react": "^18", + "react-chartjs-2": "^5.2.0", "react-csv": "^2.2.2", "react-date-range": "^2.0.0-alpha.4", "react-dom": "^18", "react-drag-drop-files": "^2.3.10", + "react-hook": "^0.0.1", "react-json-tree": "^0.18.0", "react-redux": "^9.0.4", - "react-router-dom": "^6.21.2" + "react-router-dom": "^6.21.2", + "recharts": "^2.12.0" }, "devDependencies": { "autoprefixer": "^10.4.16", @@ -1426,6 +1433,11 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@kurkle/color": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", + "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" + }, "node_modules/@material-ui/core": { "version": "4.12.4", "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.4.tgz", @@ -2301,6 +2313,14 @@ "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-2.0.0.tgz", "integrity": "sha512-Pc/AFTdwZwEKJxFJvlxrSmGe/di+aAOBn60sremrpLo6VI/6cmiUYNNwlI5KNYttg7uypzA3ILPMPgxB2GYZEg==" }, + "node_modules/@react-hook/media-query": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@react-hook/media-query/-/media-query-1.1.1.tgz", + "integrity": "sha512-VM14wDOX5CW5Dn6b2lTiMd79BFMTut9AZj2+vIRT3LCKgMCYmdqruTtzDPSnIVDQdtxdPgtOzvU9oK20LopuOw==", + "peerDependencies": { + "react": ">=16.8" + } + }, "node_modules/@reduxjs/toolkit": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.0.1.tgz", @@ -2351,6 +2371,60 @@ "resolved": "https://registry.npmjs.org/@types/base16/-/base16-1.0.5.tgz", "integrity": "sha512-OzOWrTluG9cwqidEzC/Q6FAmIPcnZfm8BFRlIx0+UIUqnuAmi5OS88O0RpT3Yz6qdmqObvUhasrbNsCofE4W9A==" }, + "node_modules/@types/d3-array": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", + "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", + "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-shape": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz", + "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz", + "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==" + }, "node_modules/@types/hoist-non-react-statics": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz", @@ -2389,6 +2463,12 @@ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" }, + "node_modules/@types/raf": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz", + "integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==", + "optional": true + }, "node_modules/@types/react": { "version": "18.2.47", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.47.tgz", @@ -2789,6 +2869,17 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, "node_modules/autoprefixer": { "version": "10.4.16", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz", @@ -2906,6 +2997,14 @@ "resolved": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz", "integrity": "sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ==" }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -2968,6 +3067,17 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/btoa": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", + "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", + "bin": { + "btoa": "bin/btoa.js" + }, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -3037,6 +3147,31 @@ } ] }, + "node_modules/canvg": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.10.tgz", + "integrity": "sha512-qwR2FRNO9NlzTeKIPIKpnTY6fqwuYSequ8Ru8c0YkYU7U0oW+hLUvWadLvAu1Rl72OMNiFhoLu4f8eUjQ7l/+Q==", + "optional": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@types/raf": "^3.4.0", + "core-js": "^3.8.3", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.7", + "rgbcolor": "^1.0.1", + "stackblur-canvas": "^2.0.0", + "svg-pathdata": "^6.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/canvg/node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "optional": true + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -3053,6 +3188,17 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chart.js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.1.tgz", + "integrity": "sha512-C74QN1bxwV1v2PEujhmKjOZ7iUM4w6BWs23Md/6aOZZSlwMzeCIDGuZay++rBgChYru7/+QFeoQW0fQoP534Dg==", + "dependencies": { + "@kurkle/color": "^0.3.0" + }, + "engines": { + "pnpm": ">=7" + } + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -3207,6 +3353,17 @@ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, + "node_modules/core-js": { + "version": "3.36.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.36.0.tgz", + "integrity": "sha512-mt7+TUBbTFg5+GngsAxeKBTl5/VS0guFeJacYge9OmHb+m058UwwIm41SE9T4Den7ClatV57B6TYTuJ0CX1MAw==", + "hasInstallScript": true, + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/core-js-pure": { "version": "3.33.3", "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.33.3.tgz", @@ -3254,6 +3411,14 @@ "node": ">=4" } }, + "node_modules/css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/css-to-react-native": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", @@ -3290,6 +3455,116 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "engines": { + "node": ">=12" + } + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -3297,9 +3572,9 @@ "dev": true }, "node_modules/date-fns": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.2.0.tgz", - "integrity": "sha512-E4KWKavANzeuusPi0jUjpuI22SURAznGkx7eZV+4i6x2A+IZxAMcajgkvuDAU1bg40+xuhW1zRdVIIM/4khuIg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.3.1.tgz", + "integrity": "sha512-y8e109LYGgoQDveiEBD3DYXKba1jWf5BA8YU1FL5Tvm0BTdEfy54WLCwnuYWZNnzzvALy/QQ4Hov+Q9RVRv+Zw==", "funding": { "type": "github", "url": "https://github.com/sponsors/kossnocorp" @@ -3321,6 +3596,11 @@ } } }, + "node_modules/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -3438,6 +3718,12 @@ "csstype": "^3.0.2" } }, + "node_modules/dompurify": { + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.7.tgz", + "integrity": "sha512-kxxKlPEDa6Nc5WJi+qRgPbOAbgTpSULL+vI3NUXsZMlkJxTqYI9wg5ZTay2sFrdZRWHPWNi+EdAhcJf81WtoMQ==", + "optional": true + }, "node_modules/electron-to-chromium": { "version": "1.4.605", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.605.tgz", @@ -4032,12 +4318,25 @@ "node": ">=0.10.0" } }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "node_modules/fast-equals": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz", + "integrity": "sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -4098,6 +4397,11 @@ "node": ">=0.8.0" } }, + "node_modules/fflate": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz", + "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==" + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -4693,6 +4997,18 @@ "react-is": "^16.7.0" } }, + "node_modules/html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "dependencies": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/http-parser-js": { "version": "0.5.8", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", @@ -4780,6 +5096,14 @@ "node": ">= 0.4" } }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "engines": { + "node": ">=12" + } + }, "node_modules/is-array-buffer": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", @@ -5232,6 +5556,23 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jspdf": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.1.tgz", + "integrity": "sha512-hXObxz7ZqoyhxET78+XR34Xu2qFGrJJ2I2bE5w4SM8eFaFEkW2xcGRVUss360fYelwRSid/jT078kbNvmoW0QA==", + "dependencies": { + "@babel/runtime": "^7.14.0", + "atob": "^2.1.2", + "btoa": "^1.2.1", + "fflate": "^0.4.8" + }, + "optionalDependencies": { + "canvg": "^3.0.6", + "core-js": "^3.6.0", + "dompurify": "^2.2.0", + "html2canvas": "^1.0.0-rc.5" + } + }, "node_modules/jss": { "version": "10.10.0", "resolved": "https://registry.npmjs.org/jss/-/jss-10.10.0.tgz", @@ -6437,6 +6778,15 @@ "lodash.curry": "^4.1.1" } }, + "node_modules/react-chartjs-2": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.2.0.tgz", + "integrity": "sha512-98iN5aguJyVSxp5U3CblRLH67J8gkfyGNbiK3c+l1QI/G4irHMPQw44aEPmjVag+YKTyQ260NcF82GTQ3bdscA==", + "peerDependencies": { + "chart.js": "^4.1.1", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-csv": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/react-csv/-/react-csv-2.2.2.tgz", @@ -6510,6 +6860,11 @@ "react-dom": "^18.0.0" } }, + "node_modules/react-hook": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/react-hook/-/react-hook-0.0.1.tgz", + "integrity": "sha512-2/Guf88/dGyFgUT7QDtBJ1l7V5yqTcAHlNRIZNTu2xg0KkDjaiYZp79ah49NDaLMI/J7voWcKLU8wMONG4A/1g==" + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -6601,6 +6956,20 @@ "react-dom": ">=16.8" } }, + "node_modules/react-smooth": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.0.tgz", + "integrity": "sha512-2NMXOBY1uVUQx1jBeENGA497HK20y6CPGYL1ZnJLeoQ8rrc3UfmOM82sRxtzpcoCkUMy4CS0RGylfuVhuFjBgg==", + "dependencies": { + "fast-equals": "^5.0.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-sortable-tree-patch-react-17": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/react-sortable-tree-patch-react-17/-/react-sortable-tree-patch-react-17-2.9.0.tgz", @@ -6743,6 +7112,36 @@ "node": ">=8.10.0" } }, + "node_modules/recharts": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.12.0.tgz", + "integrity": "sha512-rVNcdNQ5b7+40Ue7mcEKZJyEv+3SUk2bDEVvOyXPDXXVE7TU3lrvnJUgAvO36hSzhRP2DnAamKXvHLFIFOU0Ww==", + "dependencies": { + "clsx": "^2.0.0", + "eventemitter3": "^4.0.1", + "lodash": "^4.17.19", + "react-is": "^16.10.2", + "react-smooth": "^4.0.0", + "recharts-scale": "^0.4.4", + "tiny-invariant": "^1.3.1", + "victory-vendor": "^36.6.8" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/recharts-scale": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz", + "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==", + "dependencies": { + "decimal.js-light": "^2.4.1" + } + }, "node_modules/redux": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", @@ -6854,6 +7253,15 @@ "node": ">=0.10.0" } }, + "node_modules/rgbcolor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", + "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==", + "optional": true, + "engines": { + "node": ">= 0.8.15" + } + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -7078,6 +7486,15 @@ "node": ">=0.10.0" } }, + "node_modules/stackblur-canvas": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz", + "integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==", + "optional": true, + "engines": { + "node": ">=0.1.14" + } + }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", @@ -7376,6 +7793,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svg-pathdata": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", + "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", + "optional": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/tailwindcss": { "version": "3.3.6", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.6.tgz", @@ -7422,6 +7848,14 @@ "node": ">=6" } }, + "node_modules/text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -7449,6 +7883,11 @@ "node": ">=0.8" } }, + "node_modules/tiny-invariant": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", + "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" + }, "node_modules/tiny-warning": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", @@ -7745,6 +8184,35 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "node_modules/utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, + "node_modules/victory-vendor": { + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.1.tgz", + "integrity": "sha512-+pZIP+U3pEJdDCeFmsXwHzV7vNHQC/eIbHklfe2ZCZqayYRH7lQbHcVgsJ0XOOv27hWs4jH4MONgXxHMObTMSA==", + "dependencies": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + } + }, "node_modules/watchpack": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", diff --git a/package.json b/package.json index 0d6af1b8..d2988f60 100644 --- a/package.json +++ b/package.json @@ -19,22 +19,29 @@ "@mui/material": "^5.14.18", "@mui/styles": "^5.14.18", "@mui/x-date-pickers-pro": "^6.18.4", + "@react-hook/media-query": "^1.1.1", "@reduxjs/toolkit": "^2.0.1", "axios": "^1.6.3", - "date-fns": "^3.2.0", + "chart.js": "^4.4.1", + "date-fns": "^3.3.1", "firebase": "^10.7.1", "firebase-auth": "^0.1.2", + "html2canvas": "^1.4.1", + "jspdf": "^2.5.1", "mui-datatables": "^4.3.0", "next": "^14.0.4", "next-redux-wrapper": "^8.1.0", "react": "^18", + "react-chartjs-2": "^5.2.0", "react-csv": "^2.2.2", "react-date-range": "^2.0.0-alpha.4", "react-dom": "^18", "react-drag-drop-files": "^2.3.10", + "react-hook": "^0.0.1", "react-json-tree": "^0.18.0", "react-redux": "^9.0.4", - "react-router-dom": "^6.21.2" + "react-router-dom": "^6.21.2", + "recharts": "^2.12.0" }, "devDependencies": { "autoprefixer": "^10.4.16", diff --git a/src/Lib/Features/Analytics/getMetaAnalyticsData.js b/src/Lib/Features/Analytics/getMetaAnalyticsData.js new file mode 100644 index 00000000..998eb49b --- /dev/null +++ b/src/Lib/Features/Analytics/getMetaAnalyticsData.js @@ -0,0 +1,43 @@ +import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'; +import fetchParams from '../../fetchParams'; +import ENDPOINTS from "../../../config/apiendpoint" + +const initialState = { + data: [], + status: 'idle', + error: null, +}; +export const fetchMetaAnalyticsData = createAsyncThunk( + 'getMetaAnalyticsData/fetchMetaAnalyticsData', + async ({project_type_filter,progressObj}) => { + let endpoint ; + const body = progressObj + project_type_filter=='AllTypes'? + endpoint = `${ENDPOINTS.getOrganizations}public/${OrgId}/cumulative_tasks_count/?metainfo=true` + : + endpoint = `${ENDPOINTS.getOrganizations}public/${OrgId}/cumulative_tasks_count/?metainfo=true&project_type_filter=${project_type_filter}` + const params = fetchParams(endpoint); + return fetch(params.url, params.options) + .then(response => response.json()) + } +); +const getMetaAnalyticsData = createSlice({ + name: 'getMetaAnalyticsData', + initialState, + reducers: {}, + extraReducers: (builder) => { + builder + .addCase(fetchMetaAnalyticsData.pending, (state) => { + state.status = 'loading'; + }) + .addCase(fetchMetaAnalyticsData.fulfilled, (state, action) => { + state.status = 'succeeded'; + state.data = action.payload; + }) + .addCase(fetchMetaAnalyticsData.rejected, (state, action) => { + state.status = 'failed'; + state.error = action.error.message; + }); + }, +}); +export default getMetaAnalyticsData.reducer; \ No newline at end of file diff --git a/src/Lib/Features/Analytics/getTaskAnalyticsData.js b/src/Lib/Features/Analytics/getTaskAnalyticsData.js new file mode 100644 index 00000000..2ba44302 --- /dev/null +++ b/src/Lib/Features/Analytics/getTaskAnalyticsData.js @@ -0,0 +1,44 @@ +import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'; +import fetchParams from '../../fetchParams'; +import ENDPOINTS from "../../../config/apiendpoint" + +const initialState = { + data: [], + status: 'idle', + error: null, +}; +export const fetchTaskAnalyticsData = createAsyncThunk( + 'getTaskAnalyticsData/fetchTaskAnalyticsData', + async ({project_type_filter,progressObj}) => { + let endpoint ; + const body = progressObj + project_type_filter=='AllTypes'? + endpoint = `${ENDPOINTS.getOrganizations}public/1/cumulative_tasks_count/` + : + endpoint = `${ENDPOINTS.getOrganizations}public/1/cumulative_tasks_count/?project_type_filter=${project_type_filter}` + const params = fetchParams(endpoint); + return fetch(params.url, params.options) + .then(response => response.json()) + } +); +const getTaskAnalyticsData = createSlice({ + name: 'getTaskAnalyticsData', + initialState, + reducers: {}, + extraReducers: (builder) => { + builder + .addCase(fetchTaskAnalyticsData.pending, (state) => { + state.status = 'loading'; + }) + .addCase(fetchTaskAnalyticsData.fulfilled, (state, action) => { + state.status = 'succeeded'; + state.data = action.payload; + }) + .addCase(fetchTaskAnalyticsData.rejected, (state, action) => { + state.status = 'failed'; + state.error = action.error.message; + }); + }, +}); + +export default getTaskAnalyticsData.reducer; diff --git a/src/Lib/Store.js b/src/Lib/Store.js index d157b64e..e4d52a12 100644 --- a/src/Lib/Store.js +++ b/src/Lib/Store.js @@ -56,6 +56,8 @@ import GetDatasetDownloadJSON from './Features/datasets/GetDatasetDownloadJSON'; import GetFileTypes from './Features/datasets/GetFileTypes'; import DatasetSearchPopup from './Features/datasets/DatasetSearchPopup'; import searchProjectCard from './Features/searchProjectCard'; +import getTaskAnalyticsData from './Features/Analytics/getTaskAnalyticsData'; +import getMetaAnalyticsData from './Features/Analytics/getMetaAnalyticsData'; const makeStore = () => { return configureStore({ reducer: { @@ -116,6 +118,8 @@ const makeStore = () => { getWorkspaceData:getWorkspaceData, getOrganizationUsers:getOrganizationUsers, getProjectDetails:getProjectDetails, + getTaskAnalyticsData: getTaskAnalyticsData, + getMetaAnalyticsData: getMetaAnalyticsData }, }); diff --git a/src/app/actions/api/Progress/CumulativeTasks.js b/src/app/actions/api/Progress/CumulativeTasks.js new file mode 100644 index 00000000..bd640b1e --- /dev/null +++ b/src/app/actions/api/Progress/CumulativeTasks.js @@ -0,0 +1,42 @@ +import API from "../../api"; +import ENDPOINTS from "../../../../config/apiendpoint" +import constants from "../../constants"; + + export default class CumulativeTasksAPI extends API { + constructor(progressObj1, OrgId, metaInfo, timeout = 2000) { + super("POST", timeout, false); + this.progressObj1 = progressObj1; + this.type = constants.CUMULATIVE_TASK_DATA; + this.endpoint = `${super.apiEndPointAuto()}${ENDPOINTS.getOrganizations}${OrgId}/cumulative_tasks_count/${metaInfo ? "?metainfo=true" : ""}`; + } + + processResponse(res) { + super.processResponse(res); + if (res) { + this.CumulativeTasks = res; + } + } + + apiEndPoint() { + return this.endpoint; + } + + getBody() { + return this.progressObj1; + } + + getHeaders() { + this.headers = { + headers: { + "Content-Type": "application/json", + "Authorization": `JWT ${localStorage.getItem('shoonya_access_token')}` + }, + }; + return this.headers; + } + + getPayload() { + return this.CumulativeTasks; + } + } + \ No newline at end of file diff --git a/src/app/actions/api/Progress/MetaAnalytics.js b/src/app/actions/api/Progress/MetaAnalytics.js new file mode 100644 index 00000000..a1f72a74 --- /dev/null +++ b/src/app/actions/api/Progress/MetaAnalytics.js @@ -0,0 +1,45 @@ +import API from "../../api"; +import ENDPOINTS from "../../../../config/apiendpoint" +import C from "../../constants"; + + export default class MetaAnalyticsDataAPI extends API { + constructor(OrgId,project_type_filter,progressObj, timeout = 2000) { + super("GET", timeout, false); + this.progressObj = progressObj; + this.type = C.FETCH_META_ANALYTICS_DATA; + project_type_filter=='AllTypes'? + this.endpoint = `${super.apiEndPointAuto()}${ENDPOINTS.getOrganizations}public/${OrgId}/cumulative_tasks_count/?metainfo=true` + : + this.endpoint = `${super.apiEndPointAuto()}${ENDPOINTS.getOrganizations}public/${OrgId}/cumulative_tasks_count/?metainfo=true&project_type_filter=${project_type_filter}` + } + + processResponse(res) { + super.processResponse(res); + if (res) { + this.fetchMetaAnalyticsData = res; + } + } + + apiEndPoint() { + return this.endpoint; + } + + getBody() { + return this.progressObj; + } + + getHeaders() { + this.headers = { + headers: { + "Content-Type": "application/json", + "Authorization": `JWT ${localStorage.getItem('shoonya_access_token')}` + }, + }; + return this.headers; + } + + + getPayload() { + return this.fetchMetaAnalyticsData; + } + } \ No newline at end of file diff --git a/src/app/actions/api/Progress/PerformanceAnalytics.js b/src/app/actions/api/Progress/PerformanceAnalytics.js new file mode 100644 index 00000000..8ae4c06e --- /dev/null +++ b/src/app/actions/api/Progress/PerformanceAnalytics.js @@ -0,0 +1,41 @@ +import API from "../../api"; +import ENDPOINTS from "../../../../config/apiendpoint" +import constants from "../../constants"; + +export default class PerformanceAnalyticsAPI extends API { + constructor(progressObj, OrgId, metaInfo, timeout = 2000) { + super("POST", timeout, false); + this.progressObj = progressObj; + this.type = constants.PERFORMANCE_ANALYTICS_DATA; + this.endpoint = `${super.apiEndPointAuto()}${ENDPOINTS.getOrganizations}${OrgId}/performance_analytics_data/${metaInfo ? "?metainfo=true" : ""}`; + } + + processResponse(res) { + super.processResponse(res); + if (res) { + this.PerformanceAnalytics = res; + } + } + + apiEndPoint() { + return this.endpoint; + } + + getBody() { + return this.progressObj; + } + + getHeaders() { + this.headers = { + headers: { + "Content-Type": "application/json", + "Authorization": `JWT ${localStorage.getItem('shoonya_access_token')}` + }, + }; + return this.headers; + } + + getPayload() { + return this.PerformanceAnalytics; + } +} diff --git a/src/app/actions/api/Progress/PeriodicalTasks.js b/src/app/actions/api/Progress/PeriodicalTasks.js new file mode 100644 index 00000000..f6f07b0a --- /dev/null +++ b/src/app/actions/api/Progress/PeriodicalTasks.js @@ -0,0 +1,42 @@ +import API from "../../api"; +import ENDPOINTS from "../../../../config/apiendpoint" +import constants from "../../constants"; + + export default class PeriodicalTasksAPI extends API { + constructor(progressObj, OrgId, metaInfo, timeout = 2000) { + super("POST", timeout, false); + this.progressObj = progressObj; + this.type = constants.PERODICAL_TASK_DATA; + this.endpoint = `${super.apiEndPointAuto()}${ENDPOINTS. getOrganizations}${OrgId}/periodical_tasks_count/${metaInfo ? "?metainfo=true" : ""}`; + } + + processResponse(res) { + super.processResponse(res); + if (res) { + this.PeriodicalTasks = res; + } + } + + apiEndPoint() { + return this.endpoint; + } + + getBody() { + return this.progressObj; + } + + getHeaders() { + this.headers = { + headers: { + "Content-Type": "application/json", + "Authorization": `JWT ${localStorage.getItem('shoonya_access_token')}` + }, + }; + return this.headers; + } + + getPayload() { + return this.PeriodicalTasks; + } + } + \ No newline at end of file diff --git a/src/app/actions/api/Progress/TaskAnalytics.js b/src/app/actions/api/Progress/TaskAnalytics.js new file mode 100644 index 00000000..4f2053f1 --- /dev/null +++ b/src/app/actions/api/Progress/TaskAnalytics.js @@ -0,0 +1,45 @@ +import API from "../../api"; +import ENDPOINTS from "../../../../config/apiendpoint" +import C from "../../constants"; + + export default class TaskAnalyticsDataAPI extends API { + constructor(project_type_filter,progressObj, timeout = 2000) { + super("GET", timeout, false); + this.progressObj = progressObj; + this.type = C.FETCH_TASK_ANALYTICS_DATA; + project_type_filter=='AllTypes'? + this.endpoint = `${super.apiEndPointAuto()}${ENDPOINTS.getOrganizations}public/1/cumulative_tasks_count/` + : + this.endpoint = `${super.apiEndPointAuto()}${ENDPOINTS.getOrganizations}public/1/cumulative_tasks_count/?project_type_filter=${project_type_filter}` + } + + processResponse(res) { + super.processResponse(res); + if (res) { + this.fetchTaskAnalyticsData = res; + } + } + + apiEndPoint() { + return this.endpoint; + } + + getBody() { + return this.progressObj; + } + + getHeaders() { + this.headers = { + headers: { + "Content-Type": "application/json", + "Authorization": `JWT ${localStorage.getItem('shoonya_access_token')}` + }, + }; + return this.headers; + } + + + getPayload() { + return this.fetchTaskAnalyticsData; + } + } \ No newline at end of file diff --git a/src/app/actions/api/ProjectDetails/GetProjectDomains.js b/src/app/actions/api/ProjectDetails/GetProjectDomains.js new file mode 100644 index 00000000..c7ae46d6 --- /dev/null +++ b/src/app/actions/api/ProjectDetails/GetProjectDomains.js @@ -0,0 +1,38 @@ +import API from "../../api"; +import ENDPOINTS from "../../../../config/apiendpoint" +import constants from "../../constants"; + +export default class GetProjectDomainsAPI extends API { + constructor(timeout = 2000) { + super("GET", timeout, false); + this.type = constants.GET_PROJECT_DOMAINS + this.endpoint = `${super.apiEndPointAuto()}${ENDPOINTS.getProjects}types/`; + } + + processResponse(res) { + super.processResponse(res); + if (res) { + this.domains = res; + } + } + + apiEndPoint() { + return this.endpoint; + } + + getBody() { } + + getHeaders() { + this.headers = { + headers: { + "Content-Type": "application/json", + "Authorization": `JWT ${localStorage.getItem('shoonya_access_token')}` + }, + }; + return this.headers; + } + + getPayload() { + return this.domains; + } +} \ No newline at end of file diff --git a/src/app/actions/api/UserManagement/FetchLanguages.js b/src/app/actions/api/UserManagement/FetchLanguages.js new file mode 100644 index 00000000..a0b47190 --- /dev/null +++ b/src/app/actions/api/UserManagement/FetchLanguages.js @@ -0,0 +1,39 @@ +import API from "../../api"; +import ENDPOINTS from "../../../../config/apiendpoint" +import constants from "../../constants"; + + export default class FetchLanguagesAPI extends API { + constructor(timeout = 2000) { + super("GET", timeout, false); + this.type = constants.GET_LANGUAGES; + this.endpoint = `${super.apiEndPointAuto()}${ENDPOINTS.getLanguages}fetch/`; + } + + processResponse(res) { + super.processResponse(res); + if (res) { + this.Languages = res; + } + } + + apiEndPoint() { + return this.endpoint; + } + + getBody() {} + + getHeaders() { + this.headers = { + headers: { + "Content-Type": "application/json", + "Authorization": `JWT ${localStorage.getItem("shoonya_access_token")}` + }, + }; + return this.headers; + } + + getPayload() { + return this.Languages + } + } + \ No newline at end of file diff --git a/src/app/page.js b/src/app/page.js index b16a5a68..ebf2cf53 100644 --- a/src/app/page.js +++ b/src/app/page.js @@ -24,6 +24,7 @@ import DatasetDetails from "@/components/datasets/DatasetDetails"; import DatasetSettingTabs from "@/components/datasets/DatasetSettingTab"; import AutomateDatasets from "@/components/datasets/AutomateDatasets"; import CreateNewDatasetInstanceAPI from "@/components/datasets/CreateNewDatasetInstance"; +import ProgressList from "./ui/pages/progress/ProgressList"; export default function Root() { if (typeof window !== 'undefined') { @@ -39,101 +40,107 @@ export default function Root() { return {component}; }; - return ( - - - - } /> - } /> - } /> - } /> - } /> - } />)} - /> - } />)} - /> - } />)} - /> - } Backbutton={true} backPressNavigationPath={"/projects"} /> - )} - /> - } Backbutton={true} /> - )} - /> - } Backbutton={true} /> - )} - /> - } Backbutton={true} /> - )} - /> - } Backbutton={true} /> - )} - /> - } Backbutton={true} />)} - /> - } Backbutton={true} />)} - /> - } /> - )} - /> - } Backbutton={true} /> - )} - /> - } Backbutton={true} /> - )} - /> - } Backbutton={true} /> - )} - /> - - } Backbutton={true} />)} - /> - } Backbutton={true} />)} - /> - - - - ) -} + return ( + + + + } /> + } /> + } /> + } /> + } /> + } />)} + /> + } />)} + /> + } />)} + /> + } Backbutton={true} backPressNavigationPath={"/projects"} /> + )} + /> + } Backbutton={true} /> + )} + /> + } Backbutton={true} /> + )} + /> + } Backbutton={true} /> + )} + /> + } Backbutton={true} /> + )} + /> + } Backbutton={true} />)} + /> + } Backbutton={true} />)} + /> + } /> + )} + /> + } Backbutton={true} /> + )} + /> + } Backbutton={true} /> + )} + /> + } Backbutton={true} /> + )} + /> + + } Backbutton={true} />)} + /> + } Backbutton={true} />)} + /> + } /> + )} + /> + + + + ) + } } diff --git a/src/app/ui/pages/progress/MetaAnalytics/AudioDurationMetaAnalyticsChart.jsx b/src/app/ui/pages/progress/MetaAnalytics/AudioDurationMetaAnalyticsChart.jsx new file mode 100644 index 00000000..491463d3 --- /dev/null +++ b/src/app/ui/pages/progress/MetaAnalytics/AudioDurationMetaAnalyticsChart.jsx @@ -0,0 +1,276 @@ +import React from "react"; +import { Grid, ThemeProvider, Box, Typography, Paper } from "@mui/material"; +import { BarChart, Bar, XAxis, YAxis, Tooltip, Legend, Label } from "recharts"; +import DatasetStyle from "@/styles/dataset"; +import { useEffect, useState } from "react"; +import ResponsiveChartContainer from "@/components/common/ResponsiveChartContainer"; + +export default function AudioDurationChart(props) { + const { analyticsData, graphCategory } = props; + const classes = DatasetStyle(); + const [totalAudioHours, setTotalAudioHours] = useState(); + const [totalAnnotationAudioHours, setTotalAnnotationAudioHours] = useState(); + const [totalReviewAudioHours, setTotalReviewAudioHours] = useState(); + const [data, setData] = useState([]); + + useEffect(() => { + if (graphCategory=="rawAudioDuration"){ + analyticsData?.sort( + (a, b) => + b.annotation_raw_aud_duration_tohour - a.annotation_raw_aud_duration_tohour + ); + setData(analyticsData); + let allAnnotatorAudioHours = 0; + let allReviewAudioHours = 0; + var languages; + analyticsData?.map((element, index) => { + allAnnotatorAudioHours += + (element.annotation_raw_aud_duration_tohour?element.annotation_raw_aud_duration_tohour:0); + allReviewAudioHours += (element.review_raw_aud_duration_tohour?element.review_raw_aud_duration_tohour:0); + languages = element.languages; + }); + setTotalAnnotationAudioHours(allAnnotatorAudioHours); + setTotalReviewAudioHours(allReviewAudioHours); + setTotalAudioHours( + allAnnotatorAudioHours + allReviewAudioHours + ); + } + else{ + analyticsData?.sort( + (a, b) => + b.annotation_aud_duration_tohour - a.annotation_aud_duration_tohour + ); + setData(analyticsData); + let allAnnotatorAudioHours = 0; + let allReviewAudioHours = 0; + var languages; + analyticsData?.map((element, index) => { + allAnnotatorAudioHours += + element.annotation_aud_duration_tohour; + allReviewAudioHours += element.review_aud_duration_tohour; + languages = element.languages; + }); + setTotalAnnotationAudioHours(allAnnotatorAudioHours); + setTotalReviewAudioHours(allReviewAudioHours); + setTotalAudioHours( + allAnnotatorAudioHours + allReviewAudioHours + ); + } + }, [analyticsData]); + + const CustomTooltip = ({ active, payload, label }) => { + if (active && payload && payload.length) { + return ( +
+ {graphCategory=='rawAudioDuration'?

+ {`${label}`} +

+ {`Total hours : ${ + payload[0].payload.annotation_raw_aud_duration_tohour + ? new Intl.NumberFormat("en").format( + payload[0].payload.annotation_raw_aud_duration_tohour + ) + : 0 + }`} +

+ {`Total duration : ${payload[0].payload.annotation_raw_aud_duration}`} + + + +

+ {`Annotation duration : ${ + payload[0].payload.diff_annotation_review_raw_aud_duration_tohour + ? new Intl.NumberFormat("en").format( + payload[0].payload + .diff_annotation_review_raw_aud_duration_tohour + ) + : 0 + }`} +

{`Review duration : ${ + payload[0].payload.review_raw_aud_duration_tohour + ? new Intl.NumberFormat("en").format( + payload[0].payload.review_raw_aud_duration_tohour + ) + : 0 + }`}

+

+

+

+

: +

+ {`${label}`} +

+ {`Total hours : ${ + payload[0].payload.annotation_aud_duration_tohour + ? new Intl.NumberFormat("en").format( + payload[0].payload.annotation_aud_duration_tohour + ) + : 0 + }`} +

+ {`Total duration : ${payload[0].payload.annotation_aud_duration}`} +

+ {`Annotation duration : ${ + payload[0].payload.diff_annotation_review_aud_duration_tohour + ? new Intl.NumberFormat("en").format( + payload[0].payload + .diff_annotation_review_aud_duration_tohour + ) + : 0 + }`} +

{`Review duration : ${ + payload[0].payload.review_aud_duration_tohour + ? new Intl.NumberFormat("en").format( + payload[0].payload.review_aud_duration_tohour + ) + : 0 + }`}

+

+

+

+

+ } +
+ ); + } + + return null; + }; + + return ( + + + {`Audio Duration Dashboard - ${analyticsData[0].projectType}`} + + Count of Annotated and Reviewed Audio Type + + + + + + + + {graphCategory=="rawAudioDuration"?"Raw Audio Duration Dashboard":"Audio Duration Dashboard"} + + + + + Total Audio Hours + + + {totalAudioHours && + new Intl.NumberFormat("en").format(totalAudioHours)} + + + + + Total Annotation Audio Hours + + + {totalAnnotationAudioHours && + new Intl.NumberFormat("en").format(totalAnnotationAudioHours)} + + + + + Total Reviewed AudioHours + + + {totalReviewAudioHours && + new Intl.NumberFormat("en").format(totalReviewAudioHours)} + + + + + + + {/* */} + } + height={90} + interval={0} + position="insideLeft" + type="category" + angle={-30} + > + + + + new Intl.NumberFormat("en", { notation: "compact" }).format( + value + ) + } + > + + + {/* + + + + + ); +} diff --git a/src/app/ui/pages/progress/MetaAnalytics/MetaAnalytics.jsx b/src/app/ui/pages/progress/MetaAnalytics/MetaAnalytics.jsx new file mode 100644 index 00000000..a841f842 --- /dev/null +++ b/src/app/ui/pages/progress/MetaAnalytics/MetaAnalytics.jsx @@ -0,0 +1,147 @@ +import React from 'react' +import { useDispatch, useSelector } from "react-redux"; +import { useEffect, useState } from "react"; +import CustomButton from "@/components/common/Button"; +import { Grid, Select, MenuItem, InputLabel, FormControl} from "@mui/material"; +import MetaAnalyticsDataAPI from "@/app/actions/api/Progress/MetaAnalytics" +import APITransport from "@/Lib/apiTransport/apitransport"; +import AudioDurationChart from './AudioDurationMetaAnalyticsChart'; +import Spinner from "@/components/common/Spinner"; +import LightTooltip from '@/components/common/Tooltip'; +import { translate } from "@/config/localisation"; +import InfoIcon from '@mui/icons-material/Info'; +import { MenuProps } from "@/utils/utils"; +import WordCountMetaAnalyticsChart from './WordCountMetaAnalyticsChart'; +import SentanceCountMetaAnalyticsChart from './SentanceCountMetaAnalyticsChart'; + +export default function MetaAnalytics(props) { + const dispatch = useDispatch(); + const {loggedInUserData} = props + const [loading, setLoading] = useState(false); + const apiLoading = useSelector((state) => state.apiStatus.loading); + const [projectTypes, setProjectTypes] = useState([]); + const [selectedType, setSelectedType] = useState("ContextualTranslationEditing"); + const ProjectTypes = useSelector((state) => state.getProjectDomains.data); + const metaAnalyticsData = useSelector( + (state) => state.getMetaAnalyticsData.data + ); + + const getMetaAnalyticsdata = () => { + setLoading(true); + const userObj = new MetaAnalyticsDataAPI(loggedInUserData?.organization?.id,selectedType); + dispatch(APITransport(userObj)); + }; + + const audioProjectTypes=[ + 'AudioTranscription', + 'AudioSegmentation', + 'AudioTranscriptionEditing', + 'AcousticNormalisedTranscriptionEditing' + ] + const translationProjectTypes=[ + 'MonolingualTranslation', + 'TranslationEditing', + 'SemanticTextualSimilarity_Scale5', + 'ContextualTranslationEditing', + 'SentenceSplitting', + 'ContextualSentenceVerification', + 'ContextualSentenceVerificationAndDomainClassification', + ] + + const conversationProjectTypes=[ + 'ConversationTranslation', + 'ConversationTranslationEditing', + 'ConversationVerification' + ] + + const ocrProjectTypes=[ + 'OCRTranscriptionEditing', + ] + + useEffect(() => { + let types=[...audioProjectTypes,...translationProjectTypes,...conversationProjectTypes,...ocrProjectTypes,'AllTypes'] + setProjectTypes(types); + }, []); + + useEffect(() => { + getMetaAnalyticsdata(); + }, []); + const handleSubmit = async () => { + getMetaAnalyticsdata(); + } + + useEffect(() => { + if(metaAnalyticsData.length > 0){ + setLoading(false); + + } + }, [metaAnalyticsData]); + return ( +
+ {console.log(metaAnalyticsData[0])} + + + + + Project Type {" "} + { + + + + } + + + + + + + + + {loading && } + + {metaAnalyticsData.length ? + metaAnalyticsData.map((analyticsData,_index)=>{ + if (analyticsData.length && audioProjectTypes.includes(analyticsData[0].projectType)){ + return ( + + + + )} + if(analyticsData.length && + (translationProjectTypes.includes(analyticsData[0].projectType) || + conversationProjectTypes.includes(analyticsData[0].projectType) + ) + ){ + return + + {analyticsData[0].projectType.includes("Conversation") && } + } + if (analyticsData.length && ocrProjectTypes.includes(analyticsData[0].projectType)){ + return ( + + )} + }) + :''} +
+ ) +} diff --git a/src/app/ui/pages/progress/MetaAnalytics/SentanceCountMetaAnalyticsChart.jsx b/src/app/ui/pages/progress/MetaAnalytics/SentanceCountMetaAnalyticsChart.jsx new file mode 100644 index 00000000..2592d86c --- /dev/null +++ b/src/app/ui/pages/progress/MetaAnalytics/SentanceCountMetaAnalyticsChart.jsx @@ -0,0 +1,221 @@ +import React from 'react'; +import { Grid, ThemeProvider, Box, Typography, Paper } from "@mui/material"; +import { + BarChart, + Bar, + XAxis, + YAxis, + Tooltip, + Legend, + Label, + } from "recharts"; + import DatasetStyle from "@/styles/dataset"; + import { useEffect, useState } from "react"; + import ResponsiveChartContainer from "@/components/common/ResponsiveChartContainer" + +export default function SentanceCountMetaAnalyticsChart(props) { + const {analyticsData} = props + const classes = DatasetStyle(); + const [totalSentanceCount, setTotalSentanceCount] = useState(); + const [totalAnnotationSentanceCount, setTotalAnnotationSentanceCount] = useState(); + const [totalReviewSentanceCount, setTotalReviewSentanceCount] = useState(); + const [data, setData] = useState([]); + + useEffect(() => { + analyticsData?.sort( + (a, b) => + b.annotation_cumulative_sentance_count - + a.annotation_cumulative_sentance_count + ); + setData(analyticsData); + let allAnnotatorCumulativeSentanceCount = 0; + let allReviewCumulativeSentanceCount = 0; + var languages; + analyticsData?.map((element, index) => { + allAnnotatorCumulativeSentanceCount += + (element.annotation_cumulative_sentance_count?element.annotation_cumulative_sentance_count:0); + allReviewCumulativeSentanceCount += (element.review_cumulative_sentance_count?element.review_cumulative_sentance_count:0); + languages = element.languages; + }); + + setTotalAnnotationSentanceCount(allAnnotatorCumulativeSentanceCount); + setTotalReviewSentanceCount(allReviewCumulativeSentanceCount); + setTotalSentanceCount( + allAnnotatorCumulativeSentanceCount + allReviewCumulativeSentanceCount + ); + }, [analyticsData]); + + + const CustomTooltip = ({ active, payload, label }) => { + if (active && payload && payload.length) { + return ( +
+

+ {`${label}`} +

+ {`Total count : ${ + payload[0].payload.annotation_cumulative_sentance_count + ? new Intl.NumberFormat("en").format( + payload[0].payload.annotation_cumulative_sentance_count + ) + : 0 + }`} +

+ {`Annotation : ${ + payload[0].payload.diff_annotation_review_sentance_count + ? new Intl.NumberFormat("en").format( + payload[0].payload.diff_annotation_review_sentance_count + ) + : 0 + }`} +

{`Review : ${ + payload[0].payload.review_cumulative_sentance_count + ? new Intl.NumberFormat("en").format( + payload[0].payload.review_cumulative_sentance_count + ) + : 0 + }`}

+

+

+

+
+ ); + } + + return null; + }; + + return ( + + + {`Sentence Count Dashboard - ${analyticsData[0].projectType}`} + + Count of Annotated and Reviewed Data + + + + + + + Sentence Count Dashboard + + + + + Total Sentance Count + + + {totalSentanceCount && + new Intl.NumberFormat("en").format(totalSentanceCount)} + + + + + Total Annotation Sentance Count + + + {totalAnnotationSentanceCount && + new Intl.NumberFormat("en").format(totalAnnotationSentanceCount)} + + + + + Total Quality/Reviewed Sentance Count + + + {totalReviewSentanceCount && + new Intl.NumberFormat("en").format(totalReviewSentanceCount)} + + + + + + + {/* */} + } + height={90} + interval={0} + position="insideLeft" + type="category" + angle={-30} + > + + + + new Intl.NumberFormat("en", { notation: "compact" }).format( + value + ) + } + > + + + {/* + + + + + + ) +} \ No newline at end of file diff --git a/src/app/ui/pages/progress/MetaAnalytics/SingleSpeakerAudioTranscriptionEditing.jsx b/src/app/ui/pages/progress/MetaAnalytics/SingleSpeakerAudioTranscriptionEditing.jsx new file mode 100644 index 00000000..fa858a25 --- /dev/null +++ b/src/app/ui/pages/progress/MetaAnalytics/SingleSpeakerAudioTranscriptionEditing.jsx @@ -0,0 +1,221 @@ +import React from "react"; +import { Grid, ThemeProvider, Box, Typography, Paper } from "@mui/material"; +import { BarChart, Bar, XAxis, YAxis, Tooltip, Legend, Label } from "recharts"; +import DatasetStyle from "@/styles/dataset"; +import { useEffect, useState } from "react"; +import ResponsiveChartContainer from "@/component/common/ResponsiveChartContainer"; + +export default function SingleSpeakerAudioTranscriptionEditing(props) { + const { metaAnalyticsData } = props; + const classes = DatasetStyle(); + const [totalAudioHours, setTotalAudioHours] = useState(); + const [totalAnnotationAudioHours, setTotalAnnotationAudioHours] = useState(); + const [totalReviewAudioHours, setTotalReviewAudioHours] = useState(); + const [data, setData] = useState([]); + + useEffect(() => { + metaAnalyticsData[2]?.sort( + (a, b) => + b.annotation_aud_duration_tohour - a.annotation_aud_duration_tohour + ); + setData(metaAnalyticsData[2]); + let allAnnotatorAudioHours = 0; + let allReviewAudioHours = 0; + var languages; + metaAnalyticsData[2]?.map((element, index) => { + allAnnotatorAudioHours += + element.annotation_aud_duration_tohour; + allReviewAudioHours += element.review_aud_duration_tohour; + languages = element.languages; + }); + + setTotalAnnotationAudioHours(allAnnotatorAudioHours); + setTotalReviewAudioHours(allReviewAudioHours); + setTotalAudioHours( + allAnnotatorAudioHours + allReviewAudioHours + ); + }, [metaAnalyticsData[2]]); + + const CustomTooltip = ({ active, payload, label }) => { + if (active && payload && payload.length) { + return ( +
+

+ {`${label}`} +

+ {`Total hours : ${ + payload[0].payload.annotation_aud_duration_tohour + ? new Intl.NumberFormat("en").format( + payload[0].payload.annotation_aud_duration_tohour + ) + : 0 + }`} +

+ {`Total duration : ${payload[0].payload.annotation_aud_duration}`} + + + +

+ {`Annotation duration : ${ + payload[0].payload.diff_annotation_review_aud_duration_tohour + ? new Intl.NumberFormat("en").format( + payload[0].payload + .diff_annotation_review_aud_duration_tohour + ) + : 0 + }`} +

{`Review duration : ${ + payload[0].payload.review_aud_duration_tohour + ? new Intl.NumberFormat("en").format( + payload[0].payload.review_aud_duration_tohour + ) + : 0 + }`}

+

+

+

+

+
+ ); + } + + return null; + }; + + return ( + + + Audio Duration Dashboard - Audio Transcription Editing + + Count of Annotated and Reviewed Audio Transcription Editing + + + + + + + + Audio Duration Dashboard + + + + + Total Audio Hours + + + {totalAudioHours && + new Intl.NumberFormat("en").format(totalAudioHours)} + + + + + Total Annotation Audio Hours + + + {totalAnnotationAudioHours && + new Intl.NumberFormat("en").format(totalAnnotationAudioHours)} + + + + + Total Reviewed AudioHours + + + {totalReviewAudioHours && + new Intl.NumberFormat("en").format(totalReviewAudioHours)} + + + + + + + {/* */} + } + height={90} + interval={0} + position="insideLeft" + type="category" + angle={-30} + > + + + + new Intl.NumberFormat("en", { notation: "compact" }).format( + value + ) + } + > + + + {/* + + + + + ); +} diff --git a/src/app/ui/pages/progress/MetaAnalytics/WordCountMetaAnalyticsChart.jsx b/src/app/ui/pages/progress/MetaAnalytics/WordCountMetaAnalyticsChart.jsx new file mode 100644 index 00000000..b6e66677 --- /dev/null +++ b/src/app/ui/pages/progress/MetaAnalytics/WordCountMetaAnalyticsChart.jsx @@ -0,0 +1,325 @@ +import React from 'react'; +import { Grid, ThemeProvider, Box, Typography, Paper } from "@mui/material"; +import { + BarChart, + Bar, + XAxis, + YAxis, + Tooltip, + Legend, + Label, + } from "recharts"; + import DatasetStyle from "@/styles/dataset"; + import { useEffect, useState } from "react"; + import ResponsiveChartContainer from "@/components/common/ResponsiveChartContainer" + +export default function WordCountMetaAnalyticsChart(props) { + const {analyticsData,graphCategory} = props + const classes = DatasetStyle(); + const [totalWordCount, setTotalWordCount] = useState(); + const [totalAnnotationWordCount, setTotalAnnotationWordCount] = useState(); + const [totalReviewWordCount, setTotalReviewWordCount] = useState(); + const [data, setData] = useState([]); + + useEffect(() => { + if (graphCategory=="audioWordCount"){ + analyticsData?.sort( + (a, b) => + b.annotation_audio_word_count - + a.annotation_audio_word_count + ); + setData(analyticsData); + let allAnnotatorAudioWordCount = 0; + let allReviewAudioWordCount = 0; + var languages; + analyticsData?.map((element, index) => { + allAnnotatorAudioWordCount += + (element.annotation_audio_word_count?element.annotation_audio_word_count:0); + allReviewAudioWordCount += (element.review_audio_word_count?element.review_audio_word_count:0); + languages = element.languages; + }); + + setTotalAnnotationWordCount(allAnnotatorAudioWordCount); + setTotalReviewWordCount(allReviewAudioWordCount); + setTotalWordCount( + allAnnotatorAudioWordCount + allReviewAudioWordCount + ); + } + else if (graphCategory=="ocrWordCount"){ + analyticsData?.sort( + (a, b) => + b.ann_ocr_cumulative_word_count - + a.ann_ocr_cumulative_word_count + ); + + setData(analyticsData); + let allAnnotatorCumulativeWordCount = 0; + let allReviewCumulativeWordCount = 0; + var languages; + analyticsData?.map((element, index) => { + allAnnotatorCumulativeWordCount += + element.ann_ocr_cumulative_word_count; + allReviewCumulativeWordCount += element.rew_ocr_cumulative_word_count; + languages = element.languages; + }); + + setTotalAnnotationWordCount(allAnnotatorCumulativeWordCount); + setTotalReviewWordCount(allReviewCumulativeWordCount); + setTotalWordCount( + allAnnotatorCumulativeWordCount + allReviewCumulativeWordCount + ); + } + else{ + analyticsData?.sort( + (a, b) => + b.annotation_cumulative_word_count - + a.annotation_cumulative_word_count + ); + setData(analyticsData); + let allAnnotatorCumulativeWordCount = 0; + let allReviewCumulativeWordCount = 0; + var languages; + analyticsData?.map((element, index) => { + allAnnotatorCumulativeWordCount += + element.annotation_cumulative_word_count; + allReviewCumulativeWordCount += element.review_cumulative_word_count; + languages = element.languages; + }); + + setTotalAnnotationWordCount(allAnnotatorCumulativeWordCount); + setTotalReviewWordCount(allReviewCumulativeWordCount); + setTotalWordCount( + allAnnotatorCumulativeWordCount + allReviewCumulativeWordCount + ); + } + }, [analyticsData]); + + + const CustomTooltip = ({ active, payload, label }) => { + if (active && payload && payload.length) { + return ( +
+

+ {`${label}`} + {graphCategory=="audioWordCount"?

+ {`Total count : ${ + payload[0].payload.annotation_audio_word_count + ? new Intl.NumberFormat("en").format( + payload[0].payload.annotation_audio_word_count + ) + : 0 + }`} +

+ {`Annotation : ${ + payload[0].payload.diff_annotation_review_audio_word + ? new Intl.NumberFormat("en").format( + payload[0].payload.diff_annotation_review_audio_word + ) + : 0 + }`} +

{`Review : ${ + payload[0].payload.review_audio_word_count + ? new Intl.NumberFormat("en").format( + payload[0].payload.review_audio_word_count + ) + : 0 + }`}

+

+

+ : + graphCategory=="ocrWordCount"?(

+ {`Total count : ${ + payload[0].payload.ann_ocr_cumulative_word_count + ? new Intl.NumberFormat("en").format( + payload[0].payload.ann_ocr_cumulative_word_count + ) + : 0 + }`} +

+ {`Annotation : ${ + payload[0].payload.diff_annotation_review_ocr_word + ? new Intl.NumberFormat("en").format( + payload[0].payload.diff_annotation_review_ocr_word + ) + : 0 + }`} +

{`Review : ${ + payload[0].payload.rew_ocr_cumulative_word_count + ? new Intl.NumberFormat("en").format( + payload[0].payload.rew_ocr_cumulative_word_count + ) + : 0 + }`} +

+

+

) + : + (

+ {`Total count : ${ + payload[0].payload.annotation_cumulative_word_count + ? new Intl.NumberFormat("en").format( + payload[0].payload.annotation_cumulative_word_count + ) + : 0 + }`} +

+ {`Annotation : ${ + payload[0].payload.diff_annotation_review + ? new Intl.NumberFormat("en").format( + payload[0].payload.diff_annotation_review + ) + : 0 + }`} +

{`Review : ${ + payload[0].payload.review_cumulative_word_count + ? new Intl.NumberFormat("en").format( + payload[0].payload.review_cumulative_word_count + ) + : 0 + }`} +

+

+

) + } +

+
+ ); + } + + return null; + }; + + return ( + + + {`Word Count Dashboard - ${analyticsData[0].projectType}`} + + Count of Annotated and Reviewed Data + + + + + + + Word Count Dashboard + + + + + Total Word Count + + + {totalWordCount && + new Intl.NumberFormat("en").format(totalWordCount)} + + + + + Total Annotation Word Count + + + {totalAnnotationWordCount && + new Intl.NumberFormat("en").format(totalAnnotationWordCount)} + + + + + Total Quality/Reviewed Word Count + + + {totalReviewWordCount && + new Intl.NumberFormat("en").format(totalReviewWordCount)} + + + + + + + {/* */} + } + height={90} + interval={0} + position="insideLeft" + type="category" + angle={-30} + > + + + + new Intl.NumberFormat("en", { notation: "compact" }).format( + value + ) + } + > + + + {/* + + + + + + ) +} diff --git a/src/app/ui/pages/progress/PerformanaceAnalytics/PerformanceAnalytics.jsx b/src/app/ui/pages/progress/PerformanaceAnalytics/PerformanceAnalytics.jsx new file mode 100644 index 00000000..6c11da2d --- /dev/null +++ b/src/app/ui/pages/progress/PerformanaceAnalytics/PerformanceAnalytics.jsx @@ -0,0 +1,548 @@ +import React, { useEffect, useRef, useState } from "react"; +import { Line } from "react-chartjs-2"; +import { + Chart as ChartJS, + CategoryScale, + LinearScale, + PointElement, + LineElement, + Title, + Tooltip, + Legend, + Filler, // 1. Import Filler plugin +} from "chart.js"; +import { useSelector, useDispatch } from "react-redux"; +import { + Button, + Grid, + Select, + Box, + MenuItem, + Radio, + InputLabel, + FormControl, + Card, + Typography, +} from "@mui/material"; +import Checkbox from "@mui/material/Checkbox"; +import RadioGroup from "@mui/material/RadioGroup"; +import FormControlLabel from "@mui/material/FormControlLabel"; +import CircularProgress from '@mui/material/CircularProgress'; +import { MenuProps } from "@/utils/utils"; +import { DateRangePicker } from "react-date-range"; +import { + addDays, + isSameDay, + format +} from "date-fns"; +import { modifiedStaticRanges } from "@/utils/Date_Range/getDateRangeFormat"; +import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown"; +import ArrowRightIcon from "@mui/icons-material/ArrowRight"; +import GetProjectDomainsAPI from "@/app/actions/api/ProjectDetails/GetProjectDomains"; +import FetchLanguagesAPI from "@/app/actions/api/UserManagement/FetchLanguages"; +import APITransport from "@/Lib/apiTransport/apitransport"; +import axios from "axios"; +import PerformanceAnalyticsAPI from "@/app/actions/api/Progress/PerformanceAnalytics"; + +ChartJS.register( + CategoryScale, + LinearScale, + PointElement, + LineElement, + Title, + Tooltip, + Legend, + Filler // 1. Register Filler plugin +); +ChartJS.register(CategoryScale); + +const ProgressType = [{ ProgressTypename: "daily" }, { ProgressTypename: "weekly" }, { ProgressTypename: "monthly" }, { ProgressTypename: "yearly" }] +const AudioTypes = ["AcousticNormalisedTranscriptionEditing", "AudioSegmentation", "AudioTranscription", "AudioTranscriptionEditing"] + +const footer = (tooltipItems) => { + let sum = 0; + tooltipItems.forEach(function (tooltipItem) { + sum += tooltipItem.parsed.y; + }); + return "Sum: " + sum; +}; + +const labelChart = function (context) { + let label = context.dataset.label || ""; + let dataVal = context.parsed.y; +}; +const options = { + responsive: true, + tension: 0.2, + scales: { + x: { + grid: { + display: false, + }, + display: true, + title: { + display: true, + text: "Date Range", + color: "black", + font: { + family: "Roboto", + size: 16, + weight: "bold", + lineHeight: 1.2, + }, + padding: { top: 20, left: 0, right: 0, bottom: 0 }, + }, + }, + y: { + stacked: true, + display: true, + title: { + display: true, + text: "Compleated Count", + color: "#black", + font: { + family: "Roboto", + size: 16, + style: "normal", + weight: "bold", + lineHeight: 1.2, + paddingBottom: "100px", + }, + padding: { top: 20, left: 0, right: 0, bottom: 20 }, + }, + }, + }, + interaction: { + intersect: false, + mode: "index", + }, + plugins: { + legend: { + position: "bottom", + }, + title: { + display: true, + }, + tooltip: { + callbacks: { + footer: footer, + label: labelChart, + }, + }, + }, +}; + +export default function PerformanceAnalytics() { + const [loading, setLoading] = useState(false); + const [chartData, setChartData] = useState({ labels: [], datasets: [] }); + const [radiobutton, setRadiobutton] = useState("Annotation"); + const [metaInfo, setMetaInfo] = useState(false); + const [selectedType, setSelectedType] = useState(""); + const [projectTypes, setProjectTypes] = useState([]); + const [language, setLanguage] = useState("Hindi"); + const [showPicker, setShowPicker] = useState(false); + const [baseperiod, setBaseperiod] = useState("daily") + const [performanceAnalyticsTasksData, setPerformanceAnalyticsTasksData] = useState([]); + + + const ref = useRef(); + var now = new Date(); + var currentYear = now.getFullYear(); + const [baseperiodDatepicker, setBaseperiodDatepicker] = useState([ + { + startDate: new Date(), + endDate: addDays(new Date(), 1), + key: "selection", + }, + ]); + + const dispatch = useDispatch(); + const userDetails = useSelector((state) => state.getLoggedInData.data); + const ProjectTypes = useSelector((state) => state.getProjectDomains.data); + const workspaceDetails = useSelector((state) => state.getWorkspaceDetails.data); + const LanguageChoices = useSelector((state) => state.getLanguages.data); + + useEffect(() => { + const typesObj = new GetProjectDomainsAPI(); + const langObj = new FetchLanguagesAPI(); + dispatch(APITransport(typesObj)); + dispatch(APITransport(langObj)); + }, []); + + const handleChangeReports = (e) => { + setRadiobutton(e.target.value); + }; + + const handleCloseDatepicker = (e) => { + setShowPicker(!showPicker); + }; + + const handleSubmit = async () => { + setShowPicker(false) + setLoading(true); + metaInfo? + AudioTypes.includes(selectedType)? + options["scales"]["y"]["title"]["text"]="Compleated Audio Duration(Hrs)": + options["scales"]["y"]["title"]["text"]="Compleated Word Count": + options["scales"]["y"]["title"]["text"]="Compleated Tasks Count" + const OrgId = userDetails.organization.id + const payload = { + project_type: selectedType, + periodical_type: baseperiod, + language : language, + start_date: format(baseperiodDatepicker[0].startDate, 'yyyy-MM-dd'), + end_date: format(baseperiodDatepicker[0].endDate, 'yyyy-MM-dd'), + ...(radiobutton==="Review" && {reviewer_reports:true}) , + ...(radiobutton==="Supercheck" && {supercheck_reports:true}) + }; + const performanceAnalyticsAPIObj = new PerformanceAnalyticsAPI(payload, OrgId, metaInfo); + await axios.post(performanceAnalyticsAPIObj.apiEndPoint(), performanceAnalyticsAPIObj.getBody(), performanceAnalyticsAPIObj.getHeaders()) + .then(response => { + if (response.statusText === "OK") { + setPerformanceAnalyticsTasksData(response.data); + setLoading(false); + } else { + setLoading(false); + setPerformanceAnalyticsTasksData([]) + } + }) + .catch(err => { + setLoading(false); + console.log("err - ", err); + setPerformanceAnalyticsTasksData([]) + }) + }; + + const handleProgressType = (e) => { + setBaseperiod(e.target.value) + } + + const handleAnalyticsData = () => { + let labels = []; + let entries = []; + for (let i of performanceAnalyticsTasksData) { + labels.push(i["date_range"]); + if (metaInfo && AudioTypes.includes(selectedType)){ + let t = i["data"][0]["periodical_aud_duration"] + t = t.split(':') + let hoursInDecimal=parseFloat(parseInt(t[0], 10) + parseInt(t[1], 10)/60 + parseInt(t[2], 10)/3600); + entries.push(hoursInDecimal) + } + else if (metaInfo){ + entries.push(i["data"][0]["periodical_word_count"]); + } + else{ + entries.push(i["data"][0]["periodical_tasks_count"]); + } + } + console.log(labels); + console.log(entries); + + setChartData({ + labels: labels, + datasets: [ + { + label: `${metaInfo?"Word Counts":"Task Count"}`, + data: entries, + backgroundColor: "rgba(255, 0, 0)", + fill: { + target: "origin", // 3. Set the fill options + above: "rgba(255, 0, 0, 0.3)", + }, + }, + ], + }); + }; + + useEffect(() => { + handleAnalyticsData(); + }, [performanceAnalyticsTasksData]); + + useEffect(() => { + if (ProjectTypes) { + let types = []; + Object.keys(ProjectTypes).forEach((key) => { + let subTypes = Object.keys(ProjectTypes[key]["project_types"]); + types.push(...subTypes); + }); + setProjectTypes(types); + types?.length && setSelectedType(types[3]); + } + }, [ProjectTypes]); + + + + return ( + <> + + + + Select Report Type : + + + + + + } + label="Annotation" + /> + } + label="Review" + /> + } + label="Supercheck" + /> + + + + + + + + Meta-info based stats: + + setMetaInfo(e.target.checked)} + checked={metaInfo} + /> + + {/* + + + Base period {""} + + + + */} + + + + + + + Target Language + + + + + + + + + Plot Range {""} + + + + + + + + + Project Type {""} + {/* { + + + + } */} + + + + + + + + + + {/* + + */} + + + + + {showPicker && ( + + + setBaseperiodDatepicker([item.selection])} + showSelectionPreview={true} + moveRangeOnFirstSelection={false} + showMonthAndYearPickers={true} + months={2} + ranges={baseperiodDatepicker} + direction="horizontal" + preventSnapRefocus={true} + weekStartsOn={1} + inputRanges={[]} + staticRanges={[ + ...modifiedStaticRanges, + { + label: "This Year", + range: () => ({ + startDate: new Date( + Date.parse(currentYear, "yyyy-MM-ddTHH:mm:ss.SSSZ") + ), + endDate: new Date(), + }), + isSelected(range) { + const definedRange = this.range(); + return ( + isSameDay(range.startDate, definedRange.startDate) && + isSameDay(range.endDate, definedRange.endDate) + ); + }, + }, + { + label: "Last Year", + range: () => ({ + startDate: new Date( + Date.parse(currentYear - 1, "yyyy-MM-ddTHH:mm:ss.SSSZ") + ), + endDate: new Date( + Date.parse(currentYear, "yyyy-MM-ddTHH:mm:ss.SSSZ") + ), + }), + isSelected(range) { + const definedRange = this.range(); + return ( + isSameDay(range.startDate, definedRange.startDate) && + isSameDay(range.endDate, definedRange.endDate) + ); + }, + }, + ].filter((staticRange)=>staticRange.label!=="Today" && staticRange.label!=="Yesterday")} + /> + + + )} + + {/* */} + + {loading && } + {performanceAnalyticsTasksData?.length && !loading?:
} + + ); +} diff --git a/src/app/ui/pages/progress/ProgressAnalytics.jsx b/src/app/ui/pages/progress/ProgressAnalytics.jsx new file mode 100644 index 00000000..40e0ce13 --- /dev/null +++ b/src/app/ui/pages/progress/ProgressAnalytics.jsx @@ -0,0 +1,1149 @@ +import { Button, Grid, ThemeProvider, Select, Box, MenuItem,Radio, InputLabel, FormControl, Card, Typography } from "@mui/material"; +import React, { useEffect, useState, useRef } from "react"; +import CustomButton from "@/components/common/Button"; +import RadioGroup from '@mui/material/RadioGroup'; +import Checkbox from "@mui/material/Checkbox"; +import FormControlLabel from '@mui/material/FormControlLabel'; +import { useSelector, useDispatch } from "react-redux"; +import themeDefault from "@/themes/theme"; +import DatasetStyle from "@/styles/dataset"; +import PeriodicalTasks from "@/app/actions/api/Progress/PeriodicalTasks"; +import CumulativeTasksAPI from "@/app/actions/api/Progress/CumulativeTasks"; +import LightTooltip from '@/components/common/Tooltip'; +import { translate } from "@/config/localisation"; +import { Chart as ChartJS, CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend, } from 'chart.js'; +import InfoIcon from '@mui/icons-material/Info'; +import { Bar } from 'react-chartjs-2'; +import GetProjectDomainsAPI from "@/app/actions/api/ProjectDetails/GetProjectDomains"; +import APITransport from "@/Lib/apiTransport/apitransport"; +import Spinner from "@/components/common/Spinner"; +import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown"; +import ArrowRightIcon from "@mui/icons-material/ArrowRight"; +import { addDays, isSameDay, format, minutesToSeconds, hoursToSeconds, secondsToHours } from "date-fns"; +import { DateRangePicker, defaultStaticRanges, } from "react-date-range"; +import "react-date-range/dist/styles.css"; +import "react-date-range/dist/theme/default.css"; +import colorsData from "@/utils/Colors_JSON/Colors_JSON"; +import axios from "axios"; +import html2canvas from 'html2canvas'; +import locale, { modifiedStaticRanges } from "@/utils/Date_Range/getDateRangeFormat"; +import { MenuProps } from "@/utils/utils"; +import { jsPDF } from "jspdf"; +ChartJS.register( + CategoryScale, + LinearScale, + BarElement, + Title, + Tooltip, + Legend, +); +ChartJS.register(CategoryScale); + +const footer = (tooltipItems) => { + let sum = 0; + tooltipItems.forEach(function (tooltipItem) { + sum += tooltipItem.parsed.y; + }); + return 'Sum: ' + sum; +}; + +const labelChart = function(context) { + let label = context.dataset.label || ''; + let dataVal = context.parsed.y; + + if(dataVal && dataVal !== 0 && dataVal !== null){ + label += " : " + new Intl.NumberFormat('en-US').format(dataVal); + } else { + label = "" + } + return label; +}; + +const defaultOptions = { + responsive: true, + scales: { + x: { + grid: { + display: false, + }, + display: true, + title: { + display: true, + text: 'Language', + color: 'black', + font: { + family: 'Roboto', + size: 16, + weight: 'bold', + lineHeight: 1.2, + }, + padding: { top: 20, left: 0, right: 0, bottom: 0 } + } + }, + y: { + stacked: true, + display: true, + title: { + display: true, + text: '# Annotations Completed ', + color: '#black', + font: { + family: 'Roboto', + size: 16, + style: 'normal', + weight: 'bold', + lineHeight: 1.2, + paddingBottom: "100px", + }, + padding: { top: 20, left: 0, right: 0, bottom: 20 } + } + } + }, + interaction: { + intersect: false, + mode: 'index', + }, + plugins: { + legend: { + position: 'bottom', + }, + title: { + display: true, + }, + tooltip: { + callbacks: { + footer: footer, + label: labelChart + }, + + } + }, +}; + +const TooltipData = [{ name: "Progress chart based on one data selection" }, { name: "Compares progress of two different data selections" }] +const ProgressTypedata = [{ title: "Complete progress for annotations done till date" }, { title: "Yearly stacked progress in selected span of years" }, { title: "Monthly stacked progress in selected span of months" }, { title: "Weekly stacked progress in selected span of weeks" }] +const ChartType = [{ chartTypename: "Individual" }, { chartTypename: "Comparison" }] +const ProgressType = [{ ProgressTypename: "Cumulative" }, { ProgressTypename: "yearly" }, { ProgressTypename: "monthly" }, { ProgressTypename: "weekly" }] +const availableChartType = { Individual: "Individual", Comparison: "Comparison" } + +function ProgressList() { + const dispatch = useDispatch(); + const classes = DatasetStyle(); + const ref = useRef() + const [projectTypes, setProjectTypes] = useState([]); + const [selectedType, setSelectedType] = useState(""); + const [chartTypes, setChartTypes] = useState("Individual") + const [baseperiod, setBaseperiod] = useState("Cumulative") + const [metaInfo, setMetaInfo] = useState(false); + const [showBarChar, setShowBarChar] = useState(false) + const [showPicker, setShowPicker] = useState(false); + const [showPickers, setShowPickers] = useState(false); + const [comparisonperiod, setComparisonperiod] = useState("monthly"); + const [monthvalue, setmonthvalue] = useState([]) + const [weekvalue, setweekvalue] = useState([]) + const [loading, setLoading] = useState(false); + const [yearvalue, setyearvalue] = useState([]); + const [chartData, setChartData] = useState([]); + const [SVGChartData, setSVGChartData] = useState([]); + const [radiobutton, setRadiobutton] = useState("Annotation"); + const [baseperiodDatepicker, setBaseperiodDatepicker] = useState([ + { + startDate: new Date(), + endDate: addDays(new Date(), 1), + key: 'selection' + } + ]); + const [comparisonperiodDatepicker, setComparisonperiodDatepicker] = useState([ + { + startDate: new Date(), + endDate: addDays(new Date(), 1), + key: 'selection' + } + ]); + const [options, setOptions] = useState(defaultOptions); + const ProjectTypes = useSelector((state) => state.getProjectDomains.data); + const userDetails = useSelector((state) => state.getLoggedInData.data); + + const [CumulativeTasksData, setCumulativeTasksData] = useState([]); + const [PeriodicalTasksData, setPeriodicalTasksData] = useState([]); + const [SecondaryPeriodicalTasksData, setSecondaryPeriodicalTasksData] = useState([]); + + useEffect(() => { + if (PeriodicalTasksData.length > 0) { + if (PeriodicalTasksData[0].month_number > 0) { + setmonthvalue(PeriodicalTasksData[0]) + } + else if (PeriodicalTasksData[0].week_number > 0) { + setweekvalue(PeriodicalTasksData[0]) + } + else if (PeriodicalTasksData[0].year_number > 0) { + setyearvalue(PeriodicalTasksData[0]) + } + } + }, [PeriodicalTasksData]) + + useEffect(() => { + if (ProjectTypes) { + let types = []; + Object.keys(ProjectTypes).forEach((key) => { + let subTypes = Object.keys(ProjectTypes[key]["project_types"]); + types.push(...subTypes); + }); + setProjectTypes(types); + types?.length && setSelectedType(types[3]); + } + }, [ProjectTypes]); + + useEffect(() => { + const typesObj = new GetProjectDomainsAPI(); + dispatch(APITransport(typesObj)); + }, []); + + const getCumulativeTasksData = async (payload, OrgId) => { + setLoading(true); + console.log("payload, OrgId", payload, OrgId); + const cumulativeTasksAPIObj = new CumulativeTasksAPI(payload, OrgId, metaInfo); + await axios.post(cumulativeTasksAPIObj.apiEndPoint(), cumulativeTasksAPIObj.getBody(), cumulativeTasksAPIObj.getHeaders()) + .then(response => { + if (response.statusText === "OK") { + setCumulativeTasksData(response.data); + setLoading(false); + console.log("CumulativeTasksData -----", response); + } else { + setLoading(false); + } + }) + .catch(err => { + setLoading(false); + console.log("err - ", err); + }) + } + + const getPeriodicalTasksData = async (payload, OrgId) => { + setLoading(true); + console.log("payload, OrgId", payload, OrgId); + const periodicalTasksAPIObj = new PeriodicalTasks(payload, OrgId, metaInfo); + await axios.post(periodicalTasksAPIObj.apiEndPoint(), periodicalTasksAPIObj.getBody(), periodicalTasksAPIObj.getHeaders()) + .then(response => { + if (response.statusText === "OK") { + setPeriodicalTasksData(response.data); + setLoading(false); + console.log("PeriodicalTasksData -----", response); + } else { + setLoading(false); + } + }) + .catch(err => { + setLoading(false); + console.log("err - ", err); + }) + } + + const getSecondaryPeriodicalTasksData = async (payload, OrgId) => { + setLoading(true); + console.log("payload, OrgId", payload, OrgId); + const periodicalTasksAPIObj = new PeriodicalTasks(payload, OrgId, metaInfo); + await axios.post(periodicalTasksAPIObj.apiEndPoint(), periodicalTasksAPIObj.getBody(), periodicalTasksAPIObj.getHeaders()) + .then(response => { + if (response.statusText === "OK") { + setSecondaryPeriodicalTasksData(response.data); + setLoading(false); + console.log("PeriodicalTasksData -----", response); + } else { + setLoading(false); + } + }) + .catch(err => { + setLoading(false); + console.log("err - ", err); + }) + } + + const handleChartType = (e) => { + setChartTypes(e.target.value) + } + const handleSubmit = async () => { + setShowBarChar(false); + if(metaInfo) { + if(!selectedType.includes("Audio") && !selectedType.includes("Acoustic")) { + setOptions({ + ...defaultOptions, + scales: { + ...defaultOptions.scales, + y: { + ...defaultOptions.scales.y, + title: { + ...defaultOptions.scales.y.title, + text: '# Words Completed', + }, + } + }, + }); + } + else { + setOptions({ + ...defaultOptions, + scales: { + ...defaultOptions.scales, + y: { + ...defaultOptions.scales.y, + title: { + ...defaultOptions.scales.y.title, + text: '# Audio Duration Transcribed', + }, + ticks: { + ...defaultOptions.scales.y.ticks, + callback: function(value) { + if(Math.floor(value) === value) + return secondsToHours(value) + new Date(value * 1000).toISOString().substring(13, 19); + } + } + } + }, + plugins: { + ...defaultOptions.plugins, + tooltip: { + ...defaultOptions.plugins.tooltip, + callbacks: { + ...defaultOptions.plugins.tooltip.callbacks, + label: function(context) { + let label = context.dataset.label || ''; + return label + " : " + context.dataset.time[context.dataIndex]; + }, + footer: (tooltipItems) => { + let sum = 0; + tooltipItems.forEach(function (tooltipItem) { + sum += tooltipItem.parsed.y; + }); + return 'Sum: ' + secondsToHours(sum) + new Date(sum * 1000).toISOString().substring(13, 19); + } + } + } + } + }); + } + } else { + setOptions({...defaultOptions}); + } + + const OrgId = userDetails.organization.id + setShowPicker(false); + setShowPickers(false); + // setLoading(true); + + const Cumulativedata = { + project_type: selectedType, + ...(radiobutton==="Review" && {reviewer_reports:true}), + ...(radiobutton==="Supercheck" && {supercheck_reports:true}) + + }; + const individualPeriodicaldata = { + project_type: selectedType, + periodical_type: baseperiod, + start_date: format(baseperiodDatepicker[0].startDate, 'yyyy-MM-dd'), + end_date: format(baseperiodDatepicker[0].endDate, 'yyyy-MM-dd'), + ...(radiobutton==="Review" && {reviewer_reports:true}), + ...(radiobutton==="Supercheck" && {supercheck_reports:true}) + }; + + if (chartTypes === availableChartType.Individual) { + + if (baseperiod === "Cumulative") { + await getCumulativeTasksData(Cumulativedata, OrgId); + // const progressObj = new CumulativeTasksAPI(Cumulativedata, OrgId); + // dispatch(APITransport(progressObj)) + } + else { + await getPeriodicalTasksData(individualPeriodicaldata, OrgId) + // const progressObj = new PeriodicalTasks(individualPeriodicaldata, OrgId); + // dispatch(APITransport(progressObj)); + } + + + } + else { + + if (comparisonperiod === "Cumulative" && baseperiod === "Cumulative") { + + await getCumulativeTasksData(Cumulativedata, OrgId); + + } else if (comparisonperiod !== "Cumulative" && baseperiod === "Cumulative") { + + const Periodicaldata = { + project_type: selectedType, + periodical_type: comparisonperiod, + start_date: format(comparisonperiodDatepicker[0].startDate, 'yyyy-MM-dd'), + end_date: format(comparisonperiodDatepicker[0].endDate, 'yyyy-MM-dd'), + ...(radiobutton==="Review" && {reviewer_reports:true}), + ...(radiobutton==="Supercheck" && {supercheck_reports:true}) + }; + await getPeriodicalTasksData(Periodicaldata, OrgId); + await getCumulativeTasksData(Cumulativedata, OrgId); + + } else if (comparisonperiod === "Cumulative" && baseperiod !== "Cumulative") { + const individualPeriodicaldata = { + project_type: selectedType, + periodical_type: baseperiod, + start_date: format(baseperiodDatepicker[0].startDate, 'yyyy-MM-dd'), + end_date: format(baseperiodDatepicker[0].endDate, 'yyyy-MM-dd'), + ...(radiobutton==="Review" && {reviewer_reports:true}), + ...(radiobutton==="Supercheck" && {supercheck_reports:true}) + }; + await getPeriodicalTasksData(individualPeriodicaldata, OrgId); + await getCumulativeTasksData(Cumulativedata, OrgId); + } else { + const basePeriodicalPayload = { + project_type: selectedType, + periodical_type: baseperiod, + start_date: format(baseperiodDatepicker[0].startDate, 'yyyy-MM-dd'), + end_date: format(baseperiodDatepicker[0].endDate, 'yyyy-MM-dd'), + ...(radiobutton==="Review" && {reviewer_reports:true}) , + ...(radiobutton==="Supercheck" && {supercheck_reports:true}) + }; + const comparisonPeriodicalPayload = { + project_type: selectedType, + periodical_type: comparisonperiod, + start_date: format(comparisonperiodDatepicker[0].startDate, 'yyyy-MM-dd'), + end_date: format(comparisonperiodDatepicker[0].endDate, 'yyyy-MM-dd'), + ...(radiobutton==="Review" && {reviewer_reports:true}), + ...(radiobutton==="Supercheck" && {supercheck_reports:true}) + }; + + await getPeriodicalTasksData(basePeriodicalPayload, OrgId); + await getSecondaryPeriodicalTasksData(comparisonPeriodicalPayload, OrgId); + + } + } + await handleSwitchBarChartShow(); + + } + + const handleSwitchBarChartShow = async () => { + setShowBarChar(true); + } + + const handleProgressType = (e) => { + setBaseperiod(e.target.value) + + } + const handledatecomparisionprogress = () => { + setShowPickers(!showPickers) + } + + const handleChangeReports = (e) => { + setRadiobutton(e.target.value) + } + const handleDateRangePicker = (item) => { + setComparisonperiodDatepicker([item.selection]) + } + const handleComparisonProgressType = (e) => { + setComparisonperiod(e.target.value) + + } + + const handleCloseDatepicker = (e) => { + setShowPicker(!showPicker) + } + + const keyPress = (e) => { + if (e.code === "Escape" && setShowPicker(false)) { + handleCloseDatepicker(); + } + if (e.code === "Escape" && setShowPickers(false)) { + handledatecomparisionprogress(); + } + }; + + useEffect(() => { + window.addEventListener("keydown", keyPress); + return () => { + window.removeEventListener("keydown", keyPress); + } + }, [keyPress]); + + const formatDateRangeChartLabel = (dataRangeStr) => { + let dateRangeArr = dataRangeStr.split("To"); + let newDateRangeArr = []; + // newDateRangeArr.join + dateRangeArr?.map((el,i)=> { + let trimmedCurrentDate = el.trim(); + newDateRangeArr.push(trimmedCurrentDate.split("-")[2]+"/"+ trimmedCurrentDate.split("-")[1] +"/"+ trimmedCurrentDate.split("-")[0]); + }) + + return newDateRangeArr.join(" To "); + } + + + useEffect(() => { + const checkIfClickedOutside = e => { + + if (showPicker && ref.current && !ref.current.contains(e.target)) { + setShowPicker(false) + } + if (showPickers && ref.current && !ref.current.contains(e.target)) { + setShowPickers(false) + } + + } + document.addEventListener("mousedown", checkIfClickedOutside) + return () => { + + document.removeEventListener("mousedown", checkIfClickedOutside) + } + }, [showPicker, showPickers]) + + useEffect(() => { + const getCumulativeMetaInfo = (e) => { + let val; + if(metaInfo) { + if(selectedType.includes("Audio") || selectedType.includes("Acoustic")) { + let [hours, minutes, seconds] = e.cumulative_aud_duration.split(":"); + val = hoursToSeconds(hours) + minutesToSeconds(minutes) + parseInt(seconds); + } else { + val = e.cumulative_word_count; + } + } + else val = e.cumulative_tasks_count; + return val; + }; + + const getPeriodicalMetaInfo = (e) => { + let val; + if(metaInfo) { + if(selectedType.includes("Audio") || selectedType.includes("Acoustic")) { + let [hours, minutes, seconds] = e.periodical_aud_duration.split(":"); + val = hoursToSeconds(hours) + minutesToSeconds(minutes) + parseInt(seconds); + } else { + val = e.periodical_word_count; + } + } + else val = e.periodical_tasks_count; + return val; + }; + + let chData; + let svgChData; + if (chartTypes === availableChartType.Individual) { + if (baseperiod === "Cumulative") { + // console.log("CumulativeTasksData - ", CumulativeTasksData); + // debugger + svgChData = CumulativeTasksData.map((el, i) => { + return { + name: el.language, + value: getCumulativeMetaInfo(el), + // stack: el.language + } + }) + const labels = CumulativeTasksData && CumulativeTasksData.map((el, i) => el.language) + chData = { + labels, + datasets: [ + { + label: baseperiod, + data: CumulativeTasksData.map((e) => getCumulativeMetaInfo(e)), + time: (metaInfo && (selectedType.includes("Audio") || selectedType.includes("Acoustic"))) ? CumulativeTasksData.map((el, i) => el.cumulative_aud_duration) : null, + stack: "stack 0", + borderWidth: {top: 2, left: 0, right: 0, bottom: 0}, + borderColor: "white", + backgroundColor: colorsData.orange[0].color, + barThickness: 25, + }, + ], + + }; + } else { + const labels = PeriodicalTasksData[0]?.data && PeriodicalTasksData[0]?.data.map((el, i) => el.language); + svgChData = PeriodicalTasksData.map((el, i) => { + return { + name: el.date_range, + value: el.data, + } + }) + console.log("PeriodicalTasksData - ", PeriodicalTasksData); + // debugger + chData = { + labels, + datasets: + PeriodicalTasksData?.map((el, i) => { + console.log("el.date_range ----- ", el.date_range); + console.log("splitted date range --- ", el.date_range.split("To")) + return { + label: formatDateRangeChartLabel(el.date_range), + data: el.data?.map((e) => getPeriodicalMetaInfo(e)), + time: (metaInfo && (selectedType.includes("Audio") || selectedType.includes("Acoustic"))) ? el.data?.map((el, i) => el.periodical_aud_duration) : null, + stack: "stack 0", + borderWidth: {top: 2, left: 0, right: 0, bottom: 0}, + borderColor: "white", + backgroundColor: colorsData.orange[i] ? colorsData.orange[i].color : 'hsla(33, 100%, 48%, 0.05)', + barThickness: 20, + } + }), + + }; + // console.log("data data - ", data); + } + + } else { + + if (baseperiod !== "Cumulative" && comparisonperiod !== "Cumulative" && baseperiod === comparisonperiod) { + const labels = PeriodicalTasksData[0]?.data && PeriodicalTasksData[0]?.data.map((el, i) => el.language); + const PeriodicalTasksDataset = PeriodicalTasksData?.map((el, i) => { + return { + label: formatDateRangeChartLabel(el.date_range), + data: el.data?.map((e) => getPeriodicalMetaInfo(e)), + time: (metaInfo && (selectedType.includes("Audio") || selectedType.includes("Acoustic"))) ? el.data?.map((el, i) => el.periodical_aud_duration) : null, + stack: "stack 0", + borderWidth: {top: 2, left: 0, right: 0, bottom: 0}, + borderColor: "white", + backgroundColor: colorsData.orange[i] ? colorsData.orange[i].color : 'hsla(120, 128%, 25%, 0.05)', + barThickness: 20, + } + }); + + const SecondaryPeriodicalTasksDataset = SecondaryPeriodicalTasksData?.map((el, i) => { + return { + label: formatDateRangeChartLabel(el.date_range), + data: el.data?.map((e) => getPeriodicalMetaInfo(e)), + time: (metaInfo && selectedType.includes("Audio")) ? el.data?.map((el, i) => el.periodical_aud_duration) : null, + stack: "stack 1", + borderWidth: {top: 2, left: 0, right: 0, bottom: 0}, + borderColor: "white", + backgroundColor: colorsData.green[i] ? colorsData.green[i].color : 'hsla(33, 100%, 48%, 0.05)', + barThickness: 20, + } + }); + chData = { + labels, + datasets: PeriodicalTasksDataset.concat(SecondaryPeriodicalTasksDataset), + }; + } else if (baseperiod !== "Cumulative" && comparisonperiod !== "Cumulative" && baseperiod != comparisonperiod) { + const labels = PeriodicalTasksData[0]?.data && PeriodicalTasksData[0]?.data.map((el, i) => el.language); + console.log("baseperiod ---- ", baseperiod); + console.log("comparisonperiod ---- ", comparisonperiod); + const PeriodicalTasksDataset = PeriodicalTasksData?.map((el, i) => { + return { + label: formatDateRangeChartLabel(el.date_range), + data: el.data?.map((e) => getPeriodicalMetaInfo(e)), + time: (metaInfo && (selectedType.includes("Audio") || selectedType.includes("Acoustic"))) ? el.data?.map((el, i) => el.periodical_aud_duration) : null, + stack: "stack 0", + borderWidth: {top: 2, left: 0, right: 0, bottom: 0}, + borderColor: "white", + backgroundColor: colorsData.orange[i] ? colorsData.orange[i].color : 'hsla(33, 100%, 48%, 0.05)', + barThickness: 20, + } + }); + + const SecondaryPeriodicalTasksDataset = SecondaryPeriodicalTasksData?.map((el, i) => { + return { + label: formatDateRangeChartLabel(el.date_range), + data: el.data?.map((e) => getPeriodicalMetaInfo(e)), + time: (metaInfo && (selectedType.includes("Audio") || selectedType.includes("Acoustic"))) ? el.data?.map((el, i) => el.periodical_aud_duration) : null, + stack: "stack 1", + borderWidth: {top: 2, left: 0, right: 0, bottom: 0}, + borderColor: "white", + backgroundColor: colorsData.green[i] ? colorsData.green[i].color : 'hsla(120, 128%, 25%, 0.05)', + barThickness: 20, + } + }); + chData = { + labels, + datasets: PeriodicalTasksDataset.concat(SecondaryPeriodicalTasksDataset), + }; + + } else if(baseperiod !== "Cumulative" && comparisonperiod === "Cumulative"){ + const labels = PeriodicalTasksData[0]?.data && PeriodicalTasksData[0]?.data.map((el, i) => el.language); + const PeriodicalTasksDataset = PeriodicalTasksData?.map((el, i) => { + return { + label: formatDateRangeChartLabel(el.date_range), + data: el.data?.map((e) => getPeriodicalMetaInfo(e)), + time: (metaInfo && (selectedType.includes("Audio") || selectedType.includes("Acoustic"))) ? el.data?.map((el, i) => el.periodical_aud_duration) : null, + stack: "stack 0", + borderWidth: {top: 2, left: 0, right: 0, bottom: 0}, + borderColor: "white", + backgroundColor: colorsData.orange[i] ? colorsData.orange[i].color : 'hsla(33, 100%, 48%, 0.05)', + barThickness: 20, + } + }); + + const cumulativeTasksDataset = { + label: comparisonperiod, + data: CumulativeTasksData.map((e) => getCumulativeMetaInfo(e)), + time: (metaInfo && (selectedType.includes("Audio") || selectedType.includes("Acoustic"))) ? CumulativeTasksData.map((el, i) => el.cumulative_aud_duration) : null, + stack: "stack 1", + borderWidth: {top: 2, left: 0, right: 0, bottom: 0}, + borderColor: "white", + backgroundColor: colorsData.green[0].color, + barThickness: 20, + } + // CumulativeTasksData.map((e) => (e.cumulative_tasks_count)); + + chData = { + labels, + datasets: PeriodicalTasksDataset.concat(cumulativeTasksDataset), + }; + + } else if(baseperiod === "Cumulative" && comparisonperiod !== "Cumulative"){ + const labels = PeriodicalTasksData[0]?.data && PeriodicalTasksData[0]?.data.map((el, i) => el.language); + + const cumulativeTasksDataset = [{ + label: baseperiod, + data: CumulativeTasksData.map((e) => getCumulativeMetaInfo(e)), + time: (metaInfo && (selectedType.includes("Audio") || selectedType.includes("Acoustic"))) ? CumulativeTasksData.map((el, i) => el.cumulative_aud_duration) : null, + stack: "stack 0", + borderWidth: {top: 2, left: 0, right: 0, bottom: 0}, + borderColor: "white", + backgroundColor: colorsData.orange[0].color, + barThickness: 20, + }] + + const PeriodicalTasksDataset = PeriodicalTasksData?.map((el, i) => { + return { + label: formatDateRangeChartLabel(el.date_range), + data: el.data?.map((e) => getPeriodicalMetaInfo(e)), + time: (metaInfo && (selectedType.includes("Audio") || selectedType.includes("Acoustic"))) ? el.data?.map((el, i) => el.periodical_aud_duration) : null, + stack: "stack 1", + borderWidth: {top: 2, left: 0, right: 0, bottom: 0}, + borderColor: "white", + backgroundColor: colorsData.green[i] ? colorsData.green[i].color : 'hsla(120, 128%, 25%, 0.05)', + barThickness: 20, + } + }); + chData = { + labels, + datasets: cumulativeTasksDataset.concat(PeriodicalTasksDataset), + }; + } else { + + //const labels = baseperiod === "Cumulative" ? CumulativeTasksData.map((e) => (e.language)) : baseperiod === "weekly" ? weekvalue?.data?.map((e) => e.language) : baseperiod === "monthly" ? monthvalue?.data?.map((e) => e.language) : yearvalue?.data?.map((e) => e.language) + const labels = CumulativeTasksData && CumulativeTasksData.map((el, i) => el.language) + // const labels = progressTypes === "Cumulative" ? CumulativeTasksData.map((e) => (e.language)) : progressTypes === "weekly" ? weekvalue?.data?.map((e) => e.language) : progressTypes === "monthly" ? monthvalue?.data?.map((e) => e.language) : yearvalue?.data?.map((e) => e.language) + + chData = { + labels, + datasets: [ + + { + label: baseperiod, + data: CumulativeTasksData.map((e) => getCumulativeMetaInfo(e)), + time: (metaInfo && (selectedType.includes("Audio") || selectedType.includes("Acoustic"))) ? CumulativeTasksData.map((el, i) => el.cumulative_aud_duration) : null, + stack: "stack 0", + borderWidth: {top: 2, left: 0, right: 0, bottom: 0}, + borderColor: "white", + backgroundColor: colorsData.orange[0].color, + barThickness: 20, + }, + { + + label: comparisonperiod, + data: CumulativeTasksData.map((e) => getCumulativeMetaInfo(e)), + time: (metaInfo && (selectedType.includes("Audio") || selectedType.includes("Acoustic"))) ? CumulativeTasksData.map((el, i) => el.cumulative_aud_duration) : null, + stack: "stack 1", + borderWidth: {top: 2, left: 0, right: 0, bottom: 0}, + borderColor: "white", + backgroundColor: colorsData.green[0].color, + barThickness: 20, + }, + + ], + + }; + + } + + } + setChartData(chData); + setSVGChartData(svgChData); + }, [PeriodicalTasksData, SecondaryPeriodicalTasksData, CumulativeTasksData]) + + + var now = new Date() + var currentYear = now.getFullYear() + + + + const ToolTipdata1 = TooltipData.map((el, i) => el.name); + + const downloadReportClick = (type) => { + const srcElement = document.getElementById('chart-container'); + html2canvas(srcElement) + .then((canvas) => { + const imgData = canvas.toDataURL('image/png'); + if (type === "img") { + let anchorEle = document.createElement("a"); + anchorEle.href = imgData; + anchorEle.download = "Image.png"; + anchorEle.click(); + } else if (type === "pdf") { + const pdf = new jsPDF(); + pdf.addImage(imgData, 'JPEG', 10, 10, 180, 150); + // pdf.output('dataurlnewwindow'); + pdf.save("download.pdf"); + } + }) + } + + return ( + + {loading && } + + + + + + + + + Select Report Type : + + + + + + + } label="Annotation" /> + } label="Review" /> + } label="Supercheck" /> + + + + + + + + Meta-info based stats: + + setMetaInfo(e.target.checked)} + checked={metaInfo} + /> + + + + + + + + Analytics Type {" "} + { + + + + } + + + + + + + + + + + Project Type {" "} + { + + + + } + + + + + + + + + + + + {(chartTypes === availableChartType.Individual || chartTypes === availableChartType.Comparison) && + + + Base period {" "} + { + + + + } + + + + } + {!(baseperiod === "Cumulative" || chartTypes === "") && + + } + {chartTypes === availableChartType.Comparison && + + + Comparison Period {" "} + { + + + + } + + + + + } + {!(comparisonperiod === "Cumulative" || chartTypes === "" || chartTypes === availableChartType.Individual) && + + } + + + + + + {showPicker && + + setBaseperiodDatepicker([item.selection])} + weekStartsOn={1} + inputRanges={[]} + staticRanges={[ + ...modifiedStaticRanges, + // ...defaultStaticRanges, + // ...locale, + { + label: "This Year", + range: () => ({ + startDate: new Date(Date.parse(currentYear, 'yyyy-MM-ddTHH:mm:ss.SSSZ')), + endDate: new Date(), + }), + isSelected(range) { + const definedRange = this.range(); + return ( + isSameDay(range.startDate, definedRange.startDate) && + isSameDay(range.endDate, definedRange.endDate) + ); + } + }, + { + label: "Last Year", + range: () => ({ + startDate: new Date(Date.parse(currentYear - 1, 'yyyy-MM-ddTHH:mm:ss.SSSZ')), + endDate: new Date(Date.parse(currentYear, 'yyyy-MM-ddTHH:mm:ss.SSSZ')), + }), + isSelected(range) { + const definedRange = this.range(); + return ( + isSameDay(range.startDate, definedRange.startDate) && + isSameDay(range.endDate, definedRange.endDate) + ); + } + }, + ]} + showSelectionPreview={true} + moveRangeOnFirstSelection={false} + showMonthAndYearPickers={true} + months={2} + ranges={baseperiodDatepicker} + direction="horizontal" + preventSnapRefocus={true} + // calendarFocus="backwards" + // weekStartsOn={2} + + /> + + } + {showPickers && + + ({ + startDate: new Date(Date.parse(currentYear, 'yyyy-MM-ddTHH:mm:ss.SSSZ')), + endDate: new Date(), + }), + isSelected(range) { + const definedRange = this.range(); + + return ( + isSameDay(range.startDate, definedRange.startDate) && + isSameDay(range.endDate, definedRange.endDate) + ); + } + }, + { + label: "Last Year", + range: () => ({ + startDate: new Date(Date.parse(currentYear - 1, 'yyyy-MM-ddTHH:mm:ss.SSSZ')), + endDate: new Date(Date.parse(currentYear, 'yyyy-MM-ddTHH:mm:ss.SSSZ') - 86400000), + }), + isSelected(range) { + const definedRange = this.range(); + return ( + isSameDay(range.startDate, definedRange.startDate) && + isSameDay(range.endDate, definedRange.endDate) + ); + } + }, + ]} + showSelectionPreview={true} + moveRangeOnFirstSelection={false} + showMonthAndYearPickers={true} + months={2} + ranges={comparisonperiodDatepicker} + direction="horizontal" + preventSnapRefocus={true} + // calendarFocus="backwards" + /> + + } + + + + {showBarChar && + <> + + + + +
+ +
+ + } + +
+
+
+ ) +} +export default ProgressList; \ No newline at end of file diff --git a/src/app/ui/pages/progress/ProgressList.jsx b/src/app/ui/pages/progress/ProgressList.jsx new file mode 100644 index 00000000..c71a3436 --- /dev/null +++ b/src/app/ui/pages/progress/ProgressList.jsx @@ -0,0 +1,70 @@ +import { Box,Tab, Tabs, Typography} from '@mui/material' +import React from 'react' +import { useState } from 'react' +import ProgressAnalytics from './ProgressAnalytics'; +import TaskAnalytics from "./TaskAnalytics/TaskAnalytics"; +import MetaAnalytics from "./MetaAnalytics/MetaAnalytics"; +import {useSelector} from "react-redux"; +import PerformanceAnalytics from './PerformanaceAnalytics/PerformanceAnalytics'; + + +function TabPanel(props) { + const { children, value, index, ...other } = props; + + return ( + + ); +} + +const ProgressList = () => { + const [tabValue, setTabValue] = useState(0); + const handleTabChange = (e, v) => { + setTabValue(v) + } + const loggedInUserData = useSelector( + (state) => state.getLoggedInData.data + ); + + return ( + + < > + + + + + + + + + + + + + + + + + + + + + + + + + ) +} + +export default ProgressList; diff --git a/src/app/ui/pages/progress/TaskAnalytics/AudioTaskAnalyticsChart.jsx b/src/app/ui/pages/progress/TaskAnalytics/AudioTaskAnalyticsChart.jsx new file mode 100644 index 00000000..1af1036e --- /dev/null +++ b/src/app/ui/pages/progress/TaskAnalytics/AudioTaskAnalyticsChart.jsx @@ -0,0 +1,229 @@ +import { useEffect, useState } from "react"; +import { Grid, ThemeProvider, Box, Typography, Paper } from "@mui/material"; +import { useDispatch, useSelector } from "react-redux"; +import DatasetStyle from "@/styles/dataset"; +import React, { PureComponent } from "react"; +import { + BarChart, + Bar, + Cell, + XAxis, + YAxis, + CartesianGrid, + Tooltip, + Legend, + ResponsiveContainer, + Label, +} from "recharts"; +import ResponsiveChartContainer from "@/components/common/ResponsiveChartContainer" + + +function AudioTaskAnalyticsChart(props) { + const classes = DatasetStyle(); + const dispatch = useDispatch(); + const { analyticsData } = props; + const [totalTaskCount, setTotalTaskCount] = useState(); + const [totalAnnotationTasksCount, setTotalAnnotationTasksCount] = useState(); + const [totalReviewTasksCount, setTotalReviewTasksCount] = useState(); + const [data, setData] = useState([]); + + useEffect(() => { + analyticsData?.sort( + (a, b) => + b.annotation_cumulative_tasks_count - + a.annotation_cumulative_tasks_count + ); + setData(analyticsData); + + let allAnnotatorCumulativeTasksCount = 0; + let allReviewCumulativeTasksCount = 0; + var languages; + analyticsData?.map((element, index) => { + allAnnotatorCumulativeTasksCount += + element.annotation_cumulative_tasks_count; + allReviewCumulativeTasksCount += element.review_cumulative_tasks_count; + languages = element.languages; + }); + + setTotalAnnotationTasksCount(allAnnotatorCumulativeTasksCount); + setTotalReviewTasksCount(allReviewCumulativeTasksCount); + setTotalTaskCount( + allAnnotatorCumulativeTasksCount + allReviewCumulativeTasksCount + ); + }, [analyticsData]); + + const CustomTooltip = ({ active, payload, label }) => { + if (active && payload && payload.length) { + return ( +
+

+ {`${label}`} +

+ {`Total count : ${ + payload[0].payload.annotation_cumulative_tasks_count + ? new Intl.NumberFormat("en").format( + payload[0].payload.annotation_cumulative_tasks_count + ) + : 0 + }`} +

+ {`Annotation : ${ + payload[0].payload.diff_annotation_review + ? new Intl.NumberFormat("en").format( + payload[0].payload.diff_annotation_review + ) + : 0 + }`} +

{`Review : ${ + payload[0].payload.review_cumulative_tasks_count + ? new Intl.NumberFormat("en").format( + payload[0].payload.review_cumulative_tasks_count + ) + : 0 + }`}

+

+

+

+
+ ); + } + + return null; + }; + + return ( + <> + + + {`Tasks Dashboard - ${analyticsData[0].projectType}`} + + Count of Annotated and Reviewed Audio Data + + + + + + + + Tasks Dashboard + + + + + Total Tasks Count + + + {totalTaskCount && + new Intl.NumberFormat("en").format(totalTaskCount)} + + + + + Total Audio Files Annotated + + + {totalAnnotationTasksCount && + new Intl.NumberFormat("en").format(totalAnnotationTasksCount)} + + + + + Total quality/ reviewed audio files + + + {totalReviewTasksCount && + new Intl.NumberFormat("en").format(totalReviewTasksCount)} + + + + + + + {/* */} + } + height={70} + interval={0} + position="insideLeft" + type="category" + angle={-30} + > + + + + new Intl.NumberFormat("en", { notation: "compact" }).format( + value + ) + } + > + + + {/* + + + + + + ); +} +export default AudioTaskAnalyticsChart; diff --git a/src/app/ui/pages/progress/TaskAnalytics/ContextualSentenceVerificationChart.jsx b/src/app/ui/pages/progress/TaskAnalytics/ContextualSentenceVerificationChart.jsx new file mode 100644 index 00000000..d6912e17 --- /dev/null +++ b/src/app/ui/pages/progress/TaskAnalytics/ContextualSentenceVerificationChart.jsx @@ -0,0 +1,158 @@ +import { useEffect, useState } from "react"; +import { Grid, ThemeProvider, Box, Typography, Paper } from "@mui/material"; +import DatasetStyle from "@/styles/dataset"; +import React, { PureComponent } from "react"; +import { + BarChart, + Bar, + XAxis, + YAxis, + Tooltip, + Legend, + Label, +} from "recharts"; +import ResponsiveChartContainer from "@/components/common/ResponsiveChartContainer" + + +function ContextualSentenceVerificationChart(props) { + const classes = DatasetStyle(); + const { taskAnalyticsData } = props; + + const [data, setData] = useState([]); + const [totalTaskCount, setTotalTaskCount] = useState(); + const [totalAnnotationTasksCount, setTotalAnnotationTasksCount] = useState(); + const [totalReviewTasksCount, setTotalReviewTasksCount] = useState(); + useEffect(() => { + taskAnalyticsData[1]?.sort( + (a, b) => + b.annotation_cumulative_tasks_count - + a.annotation_cumulative_tasks_count + ); + setData(taskAnalyticsData[1]); + let allAnnotatorCumulativeTasksCount = 0; + let allReviewCumulativeTasksCount = 0; + var languages; + taskAnalyticsData[1]?.map((element, index) => { + allAnnotatorCumulativeTasksCount += + element.annotation_cumulative_tasks_count; + allReviewCumulativeTasksCount += element.review_cumulative_tasks_count; + languages = element.languages; + }); + + setTotalAnnotationTasksCount(allAnnotatorCumulativeTasksCount); + setTotalReviewTasksCount(allReviewCumulativeTasksCount); + setTotalTaskCount( + allAnnotatorCumulativeTasksCount + allReviewCumulativeTasksCount + ); + }, [taskAnalyticsData[1]]); + + return ( + <> + + + Tasks Dashboard - Sentence Verification + + Count of Annotated Sentence Verification + + + + + + + Tasks Dashboard + + + + + Total Tasks Count + + + {totalTaskCount && + new Intl.NumberFormat("en").format(totalTaskCount)} + + + + + + + {/* */} + } + height={90} + interval={0} + position="insideLeft" + type="category" + angle={-30} + > + + + + new Intl.NumberFormat("en", { notation: "compact" }).format( + value + ) + } + > + + + {/* + + + + + + ); +} +export default ContextualSentenceVerificationChart; diff --git a/src/app/ui/pages/progress/TaskAnalytics/SingleSpeakerAudioTranscriptionEditing.jsx b/src/app/ui/pages/progress/TaskAnalytics/SingleSpeakerAudioTranscriptionEditing.jsx new file mode 100644 index 00000000..722a0b8d --- /dev/null +++ b/src/app/ui/pages/progress/TaskAnalytics/SingleSpeakerAudioTranscriptionEditing.jsx @@ -0,0 +1,229 @@ +import { useEffect, useState } from "react"; +import { Grid, ThemeProvider, Box, Typography, Paper } from "@mui/material"; +import { useDispatch, useSelector } from "react-redux"; +import DatasetStyle from "@/styles/dataset"; +import React, { PureComponent } from "react"; +import { + BarChart, + Bar, + Cell, + XAxis, + YAxis, + CartesianGrid, + Tooltip, + Legend, + ResponsiveContainer, + Label, +} from "recharts"; +import ResponsiveChartContainer from "@/component/common/ResponsiveChartContainer" + + +function SingleSpeakerAudioTranscriptionEditing(props) { + const classes = DatasetStyle(); + const dispatch = useDispatch(); + const { taskAnalyticsData } = props; + const [totalTaskCount, setTotalTaskCount] = useState(); + const [totalAnnotationTasksCount, setTotalAnnotationTasksCount] = useState(); + const [totalReviewTasksCount, setTotalReviewTasksCount] = useState(); + const [data, setData] = useState([]); + + useEffect(() => { + taskAnalyticsData[3]?.sort( + (a, b) => + b.annotation_cumulative_tasks_count - + a.annotation_cumulative_tasks_count + ); + setData(taskAnalyticsData[3]); + + let allAnnotatorCumulativeTasksCount = 0; + let allReviewCumulativeTasksCount = 0; + var languages; + taskAnalyticsData[3]?.map((element, index) => { + allAnnotatorCumulativeTasksCount += + element.annotation_cumulative_tasks_count; + allReviewCumulativeTasksCount += element.review_cumulative_tasks_count; + languages = element.languages; + }); + + setTotalAnnotationTasksCount(allAnnotatorCumulativeTasksCount); + setTotalReviewTasksCount(allReviewCumulativeTasksCount); + setTotalTaskCount( + allAnnotatorCumulativeTasksCount + allReviewCumulativeTasksCount + ); + }, [taskAnalyticsData[3]]); + + const CustomTooltip = ({ active, payload, label }) => { + if (active && payload && payload.length) { + return ( +
+

+ {`${label}`} +

+ {`Total count : ${ + payload[0].payload.annotation_cumulative_tasks_count + ? new Intl.NumberFormat("en").format( + payload[0].payload.annotation_cumulative_tasks_count + ) + : 0 + }`} +

+ {`Annotation : ${ + payload[0].payload.diff_annotation_review + ? new Intl.NumberFormat("en").format( + payload[0].payload.diff_annotation_review + ) + : 0 + }`} +

{`Review : ${ + payload[0].payload.review_cumulative_tasks_count + ? new Intl.NumberFormat("en").format( + payload[0].payload.review_cumulative_tasks_count + ) + : 0 + }`}

+

+

+

+
+ ); + } + + return null; + }; + + return ( + <> + + + Tasks Dashboard - Audio Transcription Editing + + Count of Annotated and Reviewed Audio Transcription Editing + + + + + + + + Tasks Dashboard + + + + + Total Tasks Count + + + {totalTaskCount && + new Intl.NumberFormat("en").format(totalTaskCount)} + + + + + Total Audio Files Annotated + + + {totalAnnotationTasksCount && + new Intl.NumberFormat("en").format(totalAnnotationTasksCount)} + + + + + Total quality/ reviewed audio files + + + {totalReviewTasksCount && + new Intl.NumberFormat("en").format(totalReviewTasksCount)} + + + + + + + {/* */} + } + height={70} + interval={0} + position="insideLeft" + type="category" + angle={-30} + > + + + + new Intl.NumberFormat("en", { notation: "compact" }).format( + value + ) + } + > + + + {/* + + + + + + ); +} +export default SingleSpeakerAudioTranscriptionEditing; diff --git a/src/app/ui/pages/progress/TaskAnalytics/TaskAnalytics.jsx b/src/app/ui/pages/progress/TaskAnalytics/TaskAnalytics.jsx new file mode 100644 index 00000000..2de1d9cf --- /dev/null +++ b/src/app/ui/pages/progress/TaskAnalytics/TaskAnalytics.jsx @@ -0,0 +1,139 @@ +import { Grid, Select, MenuItem, InputLabel, FormControl } from "@mui/material"; +import React from "react"; +import TaskAnalyticsDataAPI from "@/app/actions/api/Progress/TaskAnalytics"; +import { useDispatch, useSelector } from "react-redux"; +import { useEffect, useState } from "react"; +import Spinner from "@/components/common/Spinner"; +import LightTooltip from "@/components/common/Tooltip"; +import { translate } from "@/config/localisation"; +import InfoIcon from '@mui/icons-material/Info'; +import AudioTaskAnalyticsChart from "./AudioTaskAnalyticsChart"; +import TaskCountAnalyticsChart from "./TaskCountAnalyticsChart"; +import { MenuProps } from "@/utils/utils"; +import CustomButton from "@/components/common/Button"; +import APITransport from "@/Lib/apiTransport/apitransport"; + + +const TaskAnalytics = (props) => { + const dispatch = useDispatch(); + const [loading, setLoading] = useState(true); + const [projectTypes, setProjectTypes] = useState([]); + const [selectedType, setSelectedType] = useState("ContextualTranslationEditing"); + const ProjectTypes = useSelector((state) => state.getProjectDomains.data); + const taskAnalyticsData = useSelector( + (state) => state.getTaskAnalyticsData.data + ); + + const getTaskAnalyticsdata = () => { + setLoading(true) + const userObj = new TaskAnalyticsDataAPI(selectedType); + dispatch(APITransport(userObj)); + }; + + const audioProjectTypes=[ + 'AudioTranscription', + 'AudioSegmentation', + 'AudioTranscriptionEditing', + 'AcousticNormalisedTranscriptionEditing' + ] + const translationProjectTypes=[ + 'MonolingualTranslation', + 'TranslationEditing', + 'SemanticTextualSimilarity_Scale5', + 'ContextualTranslationEditing', + 'SentenceSplitting', + 'ContextualSentenceVerification', + 'ContextualSentenceVerificationAndDomainClassification', + ] + const conversationProjectTypes=[ + 'ConversationTranslation', + 'ConversationTranslationEditing', + 'ConversationVerification' + ] + const ocrProjectTypes=[ + 'OCRTranscriptionEditing', + ] + + useEffect(() => { + let types=[...audioProjectTypes,...translationProjectTypes,...conversationProjectTypes,...ocrProjectTypes,'AllTypes'] + setProjectTypes(types); + }, []); + + useEffect(() => { + getTaskAnalyticsdata(); + }, []); + + const handleSubmit = async () => { + getTaskAnalyticsdata(); + } + + useEffect(() => { + if(taskAnalyticsData.length > 0){ + setLoading(false); + } + }, [taskAnalyticsData]); + + return ( + <> + {/* {console.log(taskAnalyticsData[0])} */} + + + + + Project Type {" "} + { + + + + } + + + + + + + + + {loading && } + {taskAnalyticsData.length ? + taskAnalyticsData.map((analyticsData,_index)=>{ + if (analyticsData.length && audioProjectTypes.includes(analyticsData[0].projectType)){ + return ( + + )} + if(analyticsData.length && + (translationProjectTypes.includes(analyticsData[0].projectType) || + conversationProjectTypes.includes(analyticsData[0].projectType) || + (ocrProjectTypes.includes(analyticsData[0].projectType)) + ) + ){ + return + + } + }) + :''} + + ); +}; + +export default TaskAnalytics; diff --git a/src/app/ui/pages/progress/TaskAnalytics/TaskCountAnalyticsChart.jsx b/src/app/ui/pages/progress/TaskAnalytics/TaskCountAnalyticsChart.jsx new file mode 100644 index 00000000..1f1cf015 --- /dev/null +++ b/src/app/ui/pages/progress/TaskAnalytics/TaskCountAnalyticsChart.jsx @@ -0,0 +1,229 @@ +import { useEffect, useState } from "react"; +import { Grid, ThemeProvider, Box, Typography, Paper } from "@mui/material"; +import { useDispatch, useSelector } from "react-redux"; +import DatasetStyle from "@/styles/dataset"; +import React, { PureComponent } from "react"; +import { + BarChart, + Bar, + Cell, + XAxis, + YAxis, + CartesianGrid, + Tooltip, + Legend, + ResponsiveContainer, + Label, +} from "recharts"; +import ResponsiveChartContainer from "@/components/common/ResponsiveChartContainer" + + +function TaskCountAnalyticsChart(props) { + const classes = DatasetStyle(); + const dispatch = useDispatch(); + const { analyticsData } = props; + + const [totalTaskCount, setTotalTaskCount] = useState(); + const [totalAnnotationTasksCount, setTotalAnnotationTasksCount] = useState(); + const [totalReviewTasksCount, setTotalReviewTasksCount] = useState(); + const [data, setData] = useState([]); + + useEffect(() => { + analyticsData?.sort( + (a, b) => + b.annotation_cumulative_tasks_count - + a.annotation_cumulative_tasks_count + ); + setData(analyticsData); + + let allAnnotatorCumulativeTasksCount = 0; + let allReviewCumulativeTasksCount = 0; + var languages; + analyticsData?.map((element, index) => { + allAnnotatorCumulativeTasksCount += + element.annotation_cumulative_tasks_count; + allReviewCumulativeTasksCount += element.review_cumulative_tasks_count; + languages = element.languages; + }); + + setTotalAnnotationTasksCount(allAnnotatorCumulativeTasksCount); + setTotalReviewTasksCount(allReviewCumulativeTasksCount); + setTotalTaskCount( + allAnnotatorCumulativeTasksCount + allReviewCumulativeTasksCount + ); + }, [analyticsData]); + + const CustomTooltip = ({ active, payload, label }) => { + if (active && payload && payload.length) { + return ( +
+

+ {`${label}`} +

+ {`Total count : ${ + payload[0].payload.annotation_cumulative_tasks_count + ? new Intl.NumberFormat("en").format( + payload[0].payload.annotation_cumulative_tasks_count + ) + : 0 + }`} +

+ {`Annotation : ${ + payload[0].payload.diff_annotation_review + ? new Intl.NumberFormat("en").format( + payload[0].payload.diff_annotation_review + ) + : 0 + }`} +

{`Review : ${ + payload[0].payload.review_cumulative_tasks_count + ? new Intl.NumberFormat("en").format( + payload[0].payload.review_cumulative_tasks_count + ) + : 0 + }`}

+

+

+

+
+ ); + } + + return null; + }; + + return ( + <> + + + {`Tasks Dashboard - ${analyticsData[0].projectType}`} + + Count of Annotated and Reviewed Data + + + + + + + Tasks Dashboard + + + + + Total Tasks Count + + + {totalTaskCount && + new Intl.NumberFormat("en").format(totalTaskCount)} + + + + + Total Sentence Pairs + + + {totalAnnotationTasksCount && + new Intl.NumberFormat("en").format(totalAnnotationTasksCount)} + + + + + Total Quality/Reviewed Sentence Pairs + + + {totalReviewTasksCount && + new Intl.NumberFormat("en").format(totalReviewTasksCount)} + + + + + + + {/* */} + } + height={90} + interval={0} + position="insideLeft" + type="category" + angle={-30} + > + + + + new Intl.NumberFormat("en", { notation: "compact" }).format( + value + ) + } + > + + + {/* + + + + + + ); +} +export default TaskCountAnalyticsChart; diff --git a/src/components/common/ResponsiveChartContainer.jsx b/src/components/common/ResponsiveChartContainer.jsx new file mode 100644 index 00000000..d725e4a8 --- /dev/null +++ b/src/components/common/ResponsiveChartContainer.jsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { useMediaQuery, useMediaQueries } from '@react-hook/media-query' +import { ResponsiveContainer } from 'recharts'; +import { Box } from '@mui/material'; + +const ResponsiveChartContainer = (props) => { + const matches = useMediaQuery('only screen and (max-width: 700px)'); + + if (matches) { + return + {props.children} + + } else { + return + {props.children} + + } +} + +export default ResponsiveChartContainer; \ No newline at end of file diff --git a/src/utils/Colors_JSON/Colors_JSON.js b/src/utils/Colors_JSON/Colors_JSON.js new file mode 100644 index 00000000..ef3d52ec --- /dev/null +++ b/src/utils/Colors_JSON/Colors_JSON.js @@ -0,0 +1,100 @@ +// const greenBase = { +// h: "120", +// s: "128%", +// l: "25%" +// } + +// const orangeBase = { +// h: "33", +// s: "100%", +// l: "48%" +// } + +// const generateColor = (baseColor) => { +// // let totalColors = 10; +// let opacityDiff = 0.05; +// let colorArr = []; + +// while (opacityDiff <= 1) { +// colorArr.push({ +// color: `hsla(${baseColor.h}, ${baseColor.s}, ${baseColor.l}, ${opacityDiff})` +// }); +// if(opacityDiff > 0.6){ +// opacityDiff +=0.08 +// } else { +// opacityDiff += 0.05; +// } +// } + +// for (let index = 0; index < totalColors; index++) { +// // const element = array[index]; +// colorArr.push({ +// color: `hsla(${baseColor.h}, ${baseColor.s}, ${baseColor.l}, ${opacityDiff})` +// }) +// opacityDiff += 0.1; +// } + +// console.log("colorArr --- ", colorArr); + +// return colorArr; +// } + +const greenColorCodeArr = [ + "#003b00", "#006200", "#008900", "#00b100", "#00ff00", "#4eff4e", "#9dff9d", "#c4ffc4", + "#226745", "#2c8458", "#36a26c", "#40bf80", "#5dc993", "#7bd3a7", "#98ddba", "#b5e6ce", + "#00896e", "#00b18d", "#00d8ad", "#00ffcc", "#76ffe4", "#9dffeb", "#c4fff3", "#bbff76", + "#00b176", "#00d890", "#00ffaa", "#27ffb7", "#76ffd1", "#9dffde", "#c4ffeb", "#ebfff8", + "#ebfff8", "#476a6a", "#568181", "#669999", "#7ea9a9", "#95b8b8", "#c4d8d8", "#dce7e7", + "#dce7e7", "#1b6e6e", "#238d8d", "#2badad", "#33cccc", "#52d4d4", "#91e4e4", "#b1ebeb", + "#d0f3f3", "#486969", "#7fa7a7", "#aec7c7", "#c5d7d7" +]; +const orangeColorCodeArr = [ + "#b14700", "#d85600", "#ff6600", "#ff7e27", "#ff954e", "#ffad76", "#ffc49d", "#ffdcc4", + "#d86c00", "#ff8000", "#ff9427", "#ffa74e", "#ffbb76", "#ffce9d", "#ffe2c4", "#ca935c", + "#deba97", "#d84800", "#ff5500", "#ff6f27", "#ff894e", "#ffa376", "#ffbe9d", "#ffd8c4", + "#b10000", "#ff0000", "#ff4e4e", "#ff7676", "#ff9d9d", "#ffc4c4", "#ffc4c4", "#ffc4c4", + "#ffc4c4", "#ffda76", "#ffe59d", "#ffefc4", "#b16a00", "#d88100", "#ff9900", "#ffb84e", + "#ffc876", "#890037", "#b10047", "#d80056", "#ff0066", "#ff4e95", "#ff76ad", "#ff9dc4", + "#620034", "#620034", "#ff4ef9", "#ff76fb", "#ff9dfc", "#ffc4fd", +]; + +const colors = { + orange: orangeColorCodeArr.map(el=>{ + return {color: el} + }), + green: greenColorCodeArr.map(el=>{ + return {color: el} + }) + // orange: generateColor(orangeBase).reverse(), + // green: generateColor(greenBase).reverse(), + // orange: [ + // { color: "#e07b00" }, + // { color: "#ff930f" }, + // { color: "#ffa83d" }, + // { color: "#ffbc6b" }, + // { color: "#ffca8a" }, + // { color: "#ffdfb8" }, + // { color: "#ffa280" }, + // { color: "#ffc3ad" }, + // { color: "#ffc65c" }, + // { color: "#ffd68a" }, + // { color: "#ffe1a8" }, + // { color: "#fff6e6" }, + // ], + // green: [ + // { color: "#006400" }, + // { color: "#005700" }, + // { color: "#138808" }, + // { color: "#009900" }, + // { color: "#009e00" }, + // { color: "#00cc00" }, + // { color: "#00eb00" }, + // { color: "#1aff1a" }, + // { color: "#85ff85" }, + // { color: "#94ff94" }, + // { color: "#b3ffb3" }, + // { color: "#e0ffe0" }, + // ] +}; + +export default colors; \ No newline at end of file diff --git a/src/utils/Date_Range/getDateRangeFormat.js b/src/utils/Date_Range/getDateRangeFormat.js new file mode 100644 index 00000000..428c0a6d --- /dev/null +++ b/src/utils/Date_Range/getDateRangeFormat.js @@ -0,0 +1,120 @@ +import { + addDays, + endOfDay, + startOfDay, + startOfMonth, + endOfMonth, + addMonths, + startOfWeek, + endOfWeek, + isSameDay, + differenceInCalendarDays, + } from 'date-fns'; + + const defineds = { + startOfWeek: startOfWeek(new Date(), {weekStartsOn: 1}), + endOfWeek: endOfWeek(new Date(), {weekStartsOn: 1}), + startOfLastWeek: startOfWeek(addDays(new Date(), -7), {weekStartsOn: 1}), + endOfLastWeek: endOfWeek(addDays(new Date(), -7), {weekStartsOn: 1}), + startOfToday: startOfDay(new Date()), + endOfToday: endOfDay(new Date()), + startOfYesterday: startOfDay(addDays(new Date(), -1)), + endOfYesterday: endOfDay(addDays(new Date(), -1)), + startOfMonth: startOfMonth(new Date()), + endOfMonth: endOfMonth(new Date()), + startOfLastMonth: startOfMonth(addMonths(new Date(), -1)), + endOfLastMonth: endOfMonth(addMonths(new Date(), -1)), + }; + + const staticRangeHandler = { + range: {}, + isSelected(range) { + const definedRange = this.range(); + return ( + isSameDay(range.startDate, definedRange.startDate) && + isSameDay(range.endDate, definedRange.endDate) + ); + }, + }; + + export function createStaticRanges(ranges) { + return ranges.map(range => ({ ...staticRangeHandler, ...range })); + } + + export const modifiedStaticRanges = createStaticRanges([ + { + label: 'Today', + range: () => ({ + startDate: defineds.startOfToday, + endDate: defineds.endOfToday, + }), + }, + { + label: 'Yesterday', + range: () => ({ + startDate: defineds.startOfYesterday, + endDate: defineds.endOfYesterday, + }), + }, + + { + label: 'This Week', + range: () => ({ + startDate: defineds.startOfWeek, + endDate: defineds.endOfWeek, + }), + }, + { + label: 'Last Week', + range: () => ({ + startDate: defineds.startOfLastWeek, + endDate: defineds.endOfLastWeek, + }), + }, + { + label: 'This Month', + range: () => ({ + startDate: defineds.startOfMonth, + endDate: defineds.endOfMonth, + }), + }, + { + label: 'Last Month', + range: () => ({ + startDate: defineds.startOfLastMonth, + endDate: defineds.endOfLastMonth, + }), + }, + ]); + + export const defaultInputRanges = [ + { + label: 'days up to today', + range(value) { + return { + startDate: addDays(defineds.startOfToday, (Math.max(Number(value), 1) - 1) * -1), + endDate: defineds.endOfToday, + }; + }, + getCurrentValue(range) { + if (!isSameDay(range.endDate, defineds.endOfToday)) return '-'; + if (!range.startDate) return '∞'; + return differenceInCalendarDays(defineds.endOfToday, range.startDate) + 1; + }, + }, + { + label: 'days starting today', + range(value) { + const today = new Date(); + return { + startDate: today, + endDate: addDays(today, Math.max(Number(value), 1) - 1), + }; + }, + getCurrentValue(range) { + if (!isSameDay(range.startDate, defineds.startOfToday)) return '-'; + if (!range.endDate) return '∞'; + return differenceInCalendarDays(range.endDate, defineds.startOfToday) + 1; + }, + }, + ]; \ No newline at end of file