From 7754b2feedb0f89821d2960da6329690f8bc4c3c Mon Sep 17 00:00:00 2001 From: hc00364289 <71371046+hc00364289@users.noreply.github.com> Date: Mon, 14 Dec 2020 16:48:46 +0530 Subject: [PATCH 1/8] intial commit for Metrics screen UI --- frontend/package.json | 6 + frontend/src/App.js | 10 +- frontend/src/assets/styles/_colors.scss | 12 + frontend/src/components/teamsAndOrgs/teams.js | 447 +++++++++++++++++- .../components/userDetail/elementsMapped.js | 419 +++++++++++++++- frontend/src/views/teams.js | 327 ++++++++++++- 6 files changed, 1216 insertions(+), 5 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index 13f0b2ea2..e7498ff95 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -24,6 +24,7 @@ "@turf/line-to-polygon": "^6.0.1", "@turf/transform-scale": "^5.1.5", "@webscopeio/react-textarea-autocomplete": "^4.7.2", + "@wojtekmaj/react-daterange-picker": "^3.0.0", "axios": "^0.20.0", "chart.js": "^2.9.3", "dompurify": "^2.0.17", @@ -36,6 +37,7 @@ "mapbox-gl-draw-circle": "^1.1.1", "mapbox-gl-draw-rectangle-mode": "^1.0.4", "marked": "^1.1.1", + "moment": "^2.29.1", "node-sass": "^4.14.1", "osmtogeojson": "^3.0.0-beta.3", "query-string": "^6.13.2", @@ -43,6 +45,8 @@ "react-calendar-heatmap": "^1.8.1", "react-chartjs-2": "^2.10.0", "react-click-outside": "^3.0.1", + "react-data-table-component": "^6.11.5", + "react-data-table-component-extensions": "^1.5.0", "react-dom": "^16.13.1", "react-dropzone": "^11.2.0", "react-final-form": "^6.5.1", @@ -54,10 +58,12 @@ "react-select": "^3.1.0", "react-tooltip": "^4.2.10", "reactjs-popup": "^1.5.0", + "react-tabs": "^3.1.1", "redux": "^4.0.5", "redux-thunk": "^2.3.0", "short-number": "^1.0.7", "shpjs": "^3.6.0", + "styled-components": "^5.2.0", "tachyons": "^4.12.0", "use-query-params": "^1.1.8", "webfontloader": "^1.6.28" diff --git a/frontend/src/App.js b/frontend/src/App.js index 619dd52a4..70bf014d4 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -29,7 +29,14 @@ import { Welcome } from './views/welcome'; import { Settings } from './views/settings'; import { ManagementPageIndex, ManagementSection } from './views/management'; import { ListOrganisations, CreateOrganisation, EditOrganisation } from './views/organisations'; -import { MyTeams, ManageTeams, CreateTeam, EditTeam, TeamDetail } from './views/teams'; +import { + MyTeams, + ManageTeams, + CreateTeam, + EditTeam, + TeamDetail, + MyTeamsUserSatsIndetailed, +} from './views/teams'; import { ListCampaigns, CreateCampaign, EditCampaign } from './views/campaigns'; import { ListInterests, CreateInterest, EditInterest } from './views/interests'; import { ListLicenses, CreateLicense, EditLicense } from './views/licenses'; @@ -88,6 +95,7 @@ let App = (props) => { + diff --git a/frontend/src/assets/styles/_colors.scss b/frontend/src/assets/styles/_colors.scss index 70d90f086..23b7040c1 100644 --- a/frontend/src/assets/styles/_colors.scss +++ b/frontend/src/assets/styles/_colors.scss @@ -103,6 +103,18 @@ Background colors /* Background colors hover */ + +.rangepicker{ + color: $blue-grey; + border:thin solid $grey-light +} +.rangepicker input { + color:$blue-grey +} +.rangepicker button { + fill: $red; +} + .hover-bg-red:hover, .hover-bg-red:focus { background-color: $red; diff --git a/frontend/src/components/teamsAndOrgs/teams.js b/frontend/src/components/teamsAndOrgs/teams.js index e04ee49e1..dc237d394 100644 --- a/frontend/src/components/teamsAndOrgs/teams.js +++ b/frontend/src/components/teamsAndOrgs/teams.js @@ -1,10 +1,10 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import { useSelector } from 'react-redux'; import { Link } from '@reach/router'; import { FormattedMessage } from 'react-intl'; import ReactPlaceholder from 'react-placeholder'; import { Form, Field } from 'react-final-form'; - +import { fetchLocalJSONAPI } from '../../network/genericJSONRequest'; import messages from './messages'; import { useEditTeamAllowed } from '../../hooks/UsePermissions'; import { UserAvatar, UserAvatarList } from '../user/avatar'; @@ -12,6 +12,13 @@ import { AddButton, ViewAllLink, Management, VisibilityBox, InviteOnlyBox } from import { SwitchToggle, RadioField, OrganisationSelect } from '../formInputs'; import { EditModeControl } from './editMode'; import { Button, EditButton } from '../button'; +import { Tabs, TabList, Tab, TabPanel } from 'react-tabs'; +import 'react-tabs/style/react-tabs.css'; +import DataTable from 'react-data-table-component'; +import DateRangePicker from '@wojtekmaj/react-daterange-picker'; +import 'react-calendar/dist/Calendar.css'; +import Select from 'react-select'; +import moment from 'moment'; export function TeamsManagement({ teams, @@ -371,6 +378,442 @@ export function TeamsBoxList({ teams }: Object) { ); } +export function TeamsStats() { + // const mappingTeams = teams.filter((team) => team.role === 'MAPPER'); + // const validationTeams = teams.filter((team) => team.role === 'VALIDATOR'); + const token = useSelector((state) => state.auth.get('token')); + const userDetails = useSelector((state) => state.auth.get('userDetails')); + const userName = userDetails.username; + const userId = userDetails.id; + const [selectedOption, setSelectedOption] = useState(null); + const [selectedUser, setSelectedUser] = useState({}); + const maxDateApp = new Date(); + var dateObj = new Date(); + dateObj.setDate(dateObj.getDate() - 7); + + const [value, onChange] = useState([dateObj, new Date()]); + const [teamMetricsStats, setTeamMetricsStats] = useState({}); + const [teamNames, setTeamNames] = useState({}); + + const startDate = moment(value[0]).format('YYYY-MM -DD'); + + const endDate = moment(value[1]).format('YYYY-MM -DD'); + + useEffect(() => { + getTeamMetricsStats(); + getTeamNames(); + }, []); + + const getTeamNames = async () => { + const response = await fetchLocalJSONAPI(`teams/?member=${userId}`, token); + + const jsonData = await response.teams; + //const jsonDataForDays = await response.day; + setTeamNames(jsonData); + + console.log('team names are ***', jsonData); + }; + + let selectItems = [{ value: 'All', label: 'All' }]; + //selectItems + for (var i = 0; i < teamNames.length; i++) { + var obj = {}; + obj.value = teamNames[i].teamId; + obj.label = teamNames[i].name; + selectItems.push(obj); + } + const getTeamMetricsStats = async () => { + const response = await fetchLocalJSONAPI( + `users/${userName}/usersteamstats/?start_date=${startDate}&end_date=${endDate}`, + token, + ); + + const jsonData = await response.team; + //const jsonDataForDays = await response.day; + setTeamMetricsStats(jsonData); + + console.log('user metrics stats are ***', jsonData); + }; + console.log('team metrics stats are ***', teamMetricsStats); + var convertSeconds = (sec) => { + var hrs = Math.floor(sec / 3600); + var min = Math.floor((sec - hrs * 3600) / 60); + var seconds = sec - hrs * 3600 - min * 60; + seconds = Math.round(seconds * 100) / 100; + + var result = hrs < 10 ? '0' + hrs : hrs; + result += ':' + (min < 10 ? '0' + min : min); + result += ':' + (seconds < 10 ? '0' + seconds : seconds); + return result; + }; + + let dataSummaryResponse = []; + //totaltime, mappingTotal, ValidationTotal; + + for (let i = 0; i < teamMetricsStats.length; i++) { + let obj = {}; + + obj.userid = teamMetricsStats[i].user_id; + obj.UserName = teamMetricsStats[i].user_name; + obj.TimeinOSMTM = convertSeconds(teamMetricsStats[i].time_spent_mapping); + obj.MappingTotal = teamMetricsStats[i].tasks_mapped; + obj.ValidationTotal = teamMetricsStats[i].tasks_validated; + + dataSummaryResponse.push(obj); + } + let dataMappedResponse = []; + for (let i = 0; i < teamMetricsStats.length; i++) { + let obj = {}; + + obj.UserName = teamMetricsStats[i].user_name; + obj.TasksDone = teamMetricsStats[i].tasks_mapped; + obj.TotalTaskstime = convertSeconds(teamMetricsStats[i].time_spent_mapping); + obj.AverageTimePerTask = convertSeconds(teamMetricsStats[i].average_time_spent_mapping); + + dataMappedResponse.push(obj); + } + let dataValidatedResponse = []; + for (let i = 0; i < teamMetricsStats.length; i++) { + let obj = {}; + obj.UserName = teamMetricsStats[i].user_name; + obj.TasksDone = teamMetricsStats[i].tasks_validated; + obj.TotalTaskstime = convertSeconds(teamMetricsStats[i].time_spent_validating); + obj.AverageTimePerTask = convertSeconds(teamMetricsStats[i].average_time_spent_validating); + + dataValidatedResponse.push(obj); + } + + const columnsSummary = [ + { + name: 'User Name', + selector: 'UserName', + sortable: true, + grow: 2, + minWidth: '100px', + cell: (row) => ( + + {' '} + {row.UserName}{' '} + + ), + }, + + { + name: 'Total Time (hh:mm:ss) ', + selector: 'TimeinOSMTM', + sortable: true, + grow: 2, + minWidth: '100px', + }, + { + name: 'Mapping Total', + selector: 'MappingTotal', + sortable: true, + grow: 2, + + minWidth: '100px', + }, + { + name: 'Validation Total', + selector: 'ValidationTotal', + sortable: true, + grow: 2, + + minWidth: '200px', + }, + ]; + + function submitSelected(Values) { + console.log('param sent is', Values.value); + console.log('start time is', value[0]); + console.log('end time is', value[1]); + + generateTeamMetricsStats(Values.value, value[0], value[1]); + } + var generateTeamMetricsStats = (teamId, startDate, endDate) => { + // console.log('select box value inside api call is', selectBoxValue.value); + var startDateFormatted = moment(startDate).format('YYYY-MM -DD'); + + var endDateFormatted = moment(endDate).format('YYYY-MM -DD'); + + // const response = await fetchLocalJSONAPI( + // `users/${userName}/userstaskmapped/ ?project_id=6&start_date=${startDateFormatted}&end_date=${endDateFormatted}`, + // token, + // ); + + // const jsonData = await response.task; + //const response = await fetchLocalJSONAPI(`users/HanumanthMapper/usersteamstats/`, token); + + let url = ''; + if (teamId === 'All') { + url = `users/${userName}/usersteamstats/?start_date=${startDateFormatted}&end_date=${endDateFormatted}`; + //url = `users/${userName}/userstaskmapped/?start_date=${startDateFormatted}&end_date=${endDateFormatted}`; + } else { + url = `users/${userName}/usersteamstats/?team_id=${teamId}&start_date=${startDateFormatted}&end_date=${endDateFormatted}`; + } + fetchLocalJSONAPI(url, token) + .then((res) => { + // setUserMetricsStats(res.team); + setTeamMetricsStats(res.team); + //setUserMetricsGraphData(res.day); + }) + .catch((e) => console.log('call back failed in task index file' + e)); + }; + const columnsForValidated = [ + { + name: 'User Name', + selector: 'UserName', + sortable: true, + grow: 2, + minWidth: '100px', + cell: (row) => ( + + {row.UserName} + + ), + }, + + { + name: 'Tasks Done ', + selector: 'TasksDone', + sortable: true, + grow: 2, + minWidth: '100px', + }, + { + name: 'Total Tasks time (hh:mm:ss)', + selector: 'TotalTaskstime', + sortable: true, + grow: 2, + minWidth: '100px', + }, + { + name: 'Average time per task(hh:mm:ss)', + selector: 'AverageTimePerTask', + sortable: true, + grow: 2, + minWidth: '200px', + }, + ]; + const columnsForMapped = [ + { + name: 'User Name', + selector: 'UserName', + sortable: true, + grow: 2, + minWidth: '100px', + cell: (row) => ( + + {row.UserName} + + ), + }, + + { + name: 'Tasks Done ', + selector: 'TasksDone', + sortable: true, + grow: 2, + minWidth: '100px', + }, + { + name: 'Total Tasks time (hh:mm:ss)', + selector: 'TotalTaskstime', + sortable: true, + grow: 2, + minWidth: '100px', + }, + { + name: 'Average time per task(hh:mm:ss)', + selector: 'AverageTimePerTask', + sortable: true, + grow: 2, + minWidth: '200px', + }, + ]; + const exporttoCsv = (dataArray, fileName) => { + console.log('array data', dataArray); + console.log('afile name is', fileName); + console.log('Start Date', value[0]); + console.log('End Date is', value[1]); + const link = document.createElement('a'); + let csv = convertArrayOfObjectsToCSV(dataArray); + if (csv == null) return; + + const filename = fileName + 'export.csv'; + + if (!csv.match(/^data:text\/csv/i)) { + csv = `data:text/csv;charset=utf-8,${csv}`; + } + + link.setAttribute('href', encodeURI(csv)); + link.setAttribute('download', filename); + link.click(); + }; + function convertArrayOfObjectsToCSV(array) { + let result; + + const columnDelimiter = ','; + const lineDelimiter = '\n'; + const keys = Object.keys(array[0]); + + result = ''; + result += keys.join(columnDelimiter); + result += lineDelimiter; + + array.forEach((item) => { + let ctr = 0; + keys.forEach((key) => { + if (ctr > 0) result += columnDelimiter; + + result += item[key]; + + ctr++; + }); + result += lineDelimiter; + }); + + return result; + } + + function handleRowClick(row, event) { + console.log('row event clicked', row.UserName); + setSelectedUser(row.UserName); + console.log('inside handle Row click for popup 1112', selectedUser); + } + + const customStyles = { + headCells: { + style: { + fontSize: '15px', + fontWeight: 'bold', + }, + }, + + cells: { + style: { + fontSize: '14px', + }, + }, + }; + return ( +
+
+
+
+

Team Metrics

+
+ + + + + + + + +
+ + + + + + +
+
+
+ + + Summary + + Mapped + Validated + + + +

+ + + +
+
+

+
+ +

+ + + +

+
+ +

+ + + +

+
+
+
+
+
+ ); +} export const TeamBox = ({ team, className }: Object) => ( diff --git a/frontend/src/components/userDetail/elementsMapped.js b/frontend/src/components/userDetail/elementsMapped.js index 7fd34fa15..af1849d1e 100644 --- a/frontend/src/components/userDetail/elementsMapped.js +++ b/frontend/src/components/userDetail/elementsMapped.js @@ -2,8 +2,16 @@ import React from 'react'; import humanizeDuration from 'humanize-duration'; import ReactTooltip from 'react-tooltip'; import { FormattedMessage } from 'react-intl'; - +import { Tabs, TabList, Tab, TabPanel } from 'react-tabs'; +import 'react-tabs/style/react-tabs.css'; import messages from './messages'; +import { useState, useEffect } from 'react'; +import { fetchLocalJSONAPI } from '../../network/genericJSONRequest'; +import { useSelector } from 'react-redux'; +import { Button } from '../button'; +import { Line } from 'react-chartjs-2'; +import Select from 'react-select'; +import moment from 'moment'; import { ClockIcon, RoadIcon, @@ -15,6 +23,9 @@ import { ValidatedIcon, } from '../svgIcons'; import { StatsCardContent } from '../statsCardContent'; +import DataTable from 'react-data-table-component'; +import 'react-data-table-component-extensions/dist/index.css'; +import DateRangePicker from '@wojtekmaj/react-daterange-picker'; const getFieldData = (field) => { const iconClass = 'h-50 w-50'; @@ -72,6 +83,281 @@ const Element = ({ field, value }) => { }; export const TaskStats = ({ userStats, username }) => { + const [selectedOption, setSelectedOption] = useState(null); + const [userMetricsStats, setUserMetricsStats] = useState({}); + const [userMetricsGraphData, setUserMetricsGraphData] = useState({}); + const token = useSelector((state) => state.auth.get('token')); + const [projectNames, setProjectNames] = useState({}); + const userDetails = useSelector((state) => state.auth.get('userDetails')); + const userName = userDetails.username; + + useEffect(() => { + getUserMetricsStats(); + getProjectNames(); + }, []); + + var convertSeconds = (sec) => { + var hrs = Math.floor(sec / 3600); + var min = Math.floor((sec - hrs * 3600) / 60); + var seconds = sec - hrs * 3600 - min * 60; + seconds = Math.round(seconds * 100) / 100; + + var result = hrs < 10 ? '0' + hrs : hrs; + result += ':' + (min < 10 ? '0' + min : min); + result += ':' + (seconds < 10 ? '0' + seconds : seconds); + return result; + }; + + const maxDateApp = new Date(); + + var dateObj = new Date(); + + // subtract seven days from current time + dateObj.setDate(dateObj.getDate() - 7); + + const [value, onChange] = useState([dateObj, new Date()]); + const startDate = moment(value[0]).format('YYYY-MM -DD'); + const endDate = moment(value[1]).format('YYYY-MM -DD'); + const getProjectNames = async () => { + const response = await fetchLocalJSONAPI(`projects/`, token); + const jsonData = await response.results; + setProjectNames(jsonData); + }; + let selectItems = [{ value: 'All', label: 'All' }]; + for (var i = 0; i < projectNames.length; i++) { + var obj = {}; + obj.value = projectNames[i].projectId; + obj.label = projectNames[i].name; + selectItems.push(obj); + } + + const getUserMetricsStats = async () => { + const response = await fetchLocalJSONAPI( + `users/${userName}/userstaskmapped/?start_date=${startDate}&end_date=${endDate}`, + token, + ); + const jsonData = await response.task; + const jsonDataForDays = await response.day; + setUserMetricsStats(jsonData); + setUserMetricsGraphData(jsonDataForDays); + }; + + const columnsSummary = [ + { + name: 'Project Name', + selector: 'ProjectName', + sortable: true, + grow: 2, + minWidth: '100px', + }, + + { + name: 'Total Time (hh:mm:ss) ', + selector: 'TimeinOSMTM', + sortable: true, + grow: 2, + minWidth: '100px', + }, + { + name: 'Mapping Total', + selector: 'MappingTotal', + sortable: true, + grow: 2, + + minWidth: '100px', + }, + { + name: 'Validation Total', + selector: 'ValidationTotal', + sortable: true, + grow: 2, + + minWidth: '200px', + }, + ]; + + let graphDays = []; + let graphMappedValues = []; + let graphValidationValues = []; + + for (let i = 0; i < userMetricsGraphData.length; i++) { + let date = ''; + let mapped = ''; + let validated = ''; + date = moment(userMetricsGraphData[i].date).format('DD-MMM'); + + mapped = userMetricsGraphData[i].tasks_mapped; + validated = userMetricsGraphData[i].tasks_validated; + graphDays.push(date); + graphMappedValues.push(mapped); + graphValidationValues.push(validated); + } + + let dataSummaryResponse = []; + for (let i = 0; i < userMetricsStats.length; i++) { + let obj = {}; + obj.id = i + 1; + obj.ProjectName = userMetricsStats[i].project_name; + obj.TimeinOSMTM = convertSeconds(userMetricsStats[i].time_spent_mapping); + obj.MappingTotal = userMetricsStats[i].tasks_mapped; + obj.ValidationTotal = userMetricsStats[i].tasks_validated; + + dataSummaryResponse.push(obj); + } + let dataMappedResponse = []; + for (let i = 0; i < userMetricsStats.length; i++) { + let obj = {}; + obj.id = i + 1; + obj.ProjectName = userMetricsStats[i].project_name; + obj.TasksDone = userMetricsStats[i].tasks_mapped; + obj.TotalTaskstime = convertSeconds(userMetricsStats[i].time_spent_mapping); + obj.AverageTimePerTask = convertSeconds(userMetricsStats[i].average_time_spent_mapping); + + dataMappedResponse.push(obj); + } + let dataValidatedResponse = []; + for (let i = 0; i < userMetricsStats.length; i++) { + let obj = {}; + obj.id = i + 1; + obj.ProjectName = userMetricsStats[i].project_name; + obj.TasksDone = userMetricsStats[i].tasks_validated; + obj.TotalTaskstime = convertSeconds(userMetricsStats[i].time_spent_validating); + obj.AverageTimePerTask = convertSeconds(userMetricsStats[i].average_time_spent_validating); + + dataValidatedResponse.push(obj); + } + + const columnsForMapped = [ + { + name: 'Project Name', + selector: 'ProjectName', + sortable: true, + grow: 2, + minWidth: '100px', + }, + + { + name: 'Tasks Done ', + selector: 'TasksDone', + sortable: true, + grow: 2, + minWidth: '100px', + }, + { + name: 'Total Tasks time (hh:mm:ss)', + selector: 'TotalTaskstime', + sortable: true, + grow: 2, + minWidth: '100px', + }, + { + name: 'Average time per task(hh:mm:ss)', + selector: 'AverageTimePerTask', + sortable: true, + grow: 2, + minWidth: '200px', + }, + ]; + + function convertArrayOfObjectsToCSV(array) { + let result; + + const columnDelimiter = ','; + const lineDelimiter = '\n'; + const keys = Object.keys(array[0]); + + result = ''; + result += keys.join(columnDelimiter); + result += lineDelimiter; + + array.forEach((item) => { + let ctr = 0; + keys.forEach((key) => { + if (ctr > 0) result += columnDelimiter; + + result += item[key]; + + ctr++; + }); + result += lineDelimiter; + }); + + return result; + } + const state = { + labels: graphDays, + datasets: [ + { + label: 'Mapped', + fill: false, + lineTension: 0.5, + + borderWidth: 2, + data: graphMappedValues, + }, + { + label: 'Validated', + fill: false, + lineTension: 0.5, + backgroundColor: 'rgb(173, 230, 239)', + borderColor: 'rgb(173, 230, 239)', + borderWidth: 2, + data: graphValidationValues, + }, + ], + }; + + const exporttoCsv = (dataArray, fileName) => { + const link = document.createElement('a'); + let csv = convertArrayOfObjectsToCSV(dataArray); + if (csv == null) return; + + const filename = userName + '-' + fileName + 'export.csv'; + + if (!csv.match(/^data:text\/csv/i)) { + csv = `data:text/csv;charset=utf-8,${csv}`; + } + + link.setAttribute('href', encodeURI(csv)); + link.setAttribute('download', filename); + link.click(); + }; + + function submitSelected(Values) { + generateUserMetricsStats(Values.value, value[0], value[1]); + } + var generateUserMetricsStats = (projId, startDate, endDate) => { + var startDateFormatted = moment(startDate).format('YYYY-MM -DD'); + var endDateFormatted = moment(endDate).format('YYYY-MM -DD'); + + let url = ''; + if (projId === 'All') { + url = `users/${userName}/userstaskmapped/?start_date=${startDateFormatted}&end_date=${endDateFormatted}`; + } else { + url = `users/${userName}/userstaskmapped/?project_id=${projId}&start_date=${startDateFormatted}&end_date=${endDateFormatted}`; + } + fetchLocalJSONAPI(url, token) + .then((res) => { + setUserMetricsStats(res.task); + setUserMetricsGraphData(res.day); + }) + .catch((e) => console.log('call back failed in task index file' + e)); + }; + + const customStyles = { + headCells: { + style: { + fontSize: '15px', + fontWeight: 'bold', + }, + }, + + cells: { + style: { + fontSize: '14px', + }, + }, + }; return (
@@ -154,6 +440,137 @@ export const TaskStats = ({ userStats, username }) => {
+ +
+
+
+
+

Your Metrics

+
+ + + + + + + + +
+ + + + + + +
+
+
+ + + Summary + + Mapped + Validated + + + +

+ + +
+
+ + +

+
+ +

+ + + +

+
+ +

+ + + +

+
+
+
+
+
); }; diff --git a/frontend/src/views/teams.js b/frontend/src/views/teams.js index db5fadd73..18e1939c7 100644 --- a/frontend/src/views/teams.js +++ b/frontend/src/views/teams.js @@ -5,12 +5,15 @@ import ReactPlaceholder from 'react-placeholder'; import { TextBlock, RectShape } from 'react-placeholder/lib/placeholders'; import { FormattedMessage } from 'react-intl'; import { Form } from 'react-final-form'; - +import Select from 'react-select'; import messages from './messages'; import { useFetch } from '../hooks/UseFetch'; import { useEditTeamAllowed } from '../hooks/UsePermissions'; import { useSetTitleTag } from '../hooks/UseMetaTags'; import { fetchLocalJSONAPI, pushToLocalJSONAPI } from '../network/genericJSONRequest'; +import DataTable from 'react-data-table-component'; +import { Button } from '../components/button'; +import moment from 'moment'; import { getMembersDiff, filterActiveMembers, @@ -24,18 +27,339 @@ import { TeamForm, TeamsManagement, TeamSideBar, + TeamsStats, } from '../components/teamsAndOrgs/teams'; import { MessageMembers } from '../components/teamsAndOrgs/messageMembers'; import { Projects } from '../components/teamsAndOrgs/projects'; import { FormSubmitButton, CustomButton } from '../components/button'; import { DeleteModal } from '../components/deleteModal'; import { NotFound } from './notFound'; +import { useLocation } from '@reach/router'; +import DateRangePicker from '@wojtekmaj/react-daterange-picker'; +import { isObject } from '@turf/helpers'; export function ManageTeams() { useSetTitleTag('Manage teams'); return ; } +export function MyTeamsUserSatsIndetailed() { + useSetTitleTag('My teams MyTeamsUserSatsIndetailed '); + + useEffect(() => { + getUserNameBasedStats(); + getUserNames(); + }, []); + + const token = useSelector((state) => state.auth.get('token')); + + const [userNames, setUserNames] = useState({}); + + const getUserNames = async () => { + const response = await fetchLocalJSONAPI(`users/`, token); + + const jsonData = await response.users; + //const jsonDataForDays = await response.day; + setUserNames(jsonData); + }; + + const location = useLocation(); + let selectUserStats = []; + for (var i = 0; i < userNames.length; i++) { + var obj = {}; + obj.value = userNames[i].username; + obj.label = userNames[i].username; + selectUserStats.push(obj); + } + + let selectTaskSatus = [ + { value: 'MAPPED', label: 'MAPPED' }, + { value: 'VALIDATED', label: 'VALIDATED' }, + ]; + const maxDateApp = new Date(); + const customStyles = { + headCells: { + style: { + fontSize: '15px', + fontWeight: 'bold', + }, + }, + + cells: { + style: { + fontSize: '14px', + }, + }, + }; + + const popUpTableColumns = [ + { + name: 'Task Url', + selector: 'TaskUrl', + sortable: true, + grow: 2, + minWidth: '100px', + cell: (row) => ( + + Project {row.TaskUrl} - Task {row.TaskId} + + ), + }, + { + name: 'Task', + selector: 'TaskId', + sortable: true, + grow: 2, + minWidth: '100px', + omit: 'yes', + }, + { + name: 'Current State', + selector: 'CurrentState', + sortable: true, + grow: 2, + minWidth: '100px', + }, + + { + name: ' Task Finish time ', + selector: 'TaskFinishTime', + sortable: true, + grow: 2, + minWidth: '100px', + }, + { + name: 'Time spent on task (hh:mm:ss)', + selector: 'TimeSpentOnTask', + sortable: true, + grow: 2, + + minWidth: '100px', + }, + { + name: 'Validator', + selector: 'Reviewer', + sortable: true, + grow: 2, + minWidth: '200px', + }, + ]; + var dateObj = new Date(); + + // subtract one day from current time + dateObj.setDate(dateObj.getDate() - 7); + // const [value, onChange] = useState([new Date(), new Date()]); + let [value, onChange] = useState([dateObj, new Date()]); + let [selectedUserName, setSelectedUserName] = useState(null); + let [selectedTaskStatus, setSelectedTaskStatus] = useState(null); + const [teamMetricsStats, setTeamMetricsStats] = useState({}); + + const params = new URLSearchParams(location.search); + + // You can access specific parameters: + let selectedStringName = params.get('name'); + let selectedStatus = params.get('status'); + + let varSelectedUser = { value: selectedStringName, label: selectedStringName }; + let defaultelectedStatus = { value: selectedStatus, label: selectedStatus }; + let userNameSelected = varSelectedUser.value; + + var convertSeconds = (sec) => { + var hrs = Math.floor(sec / 3600); + var min = Math.floor((sec - hrs * 3600) / 60); + var seconds = sec - hrs * 3600 - min * 60; + seconds = Math.round(seconds * 100) / 100; + + var result = hrs < 10 ? '0' + hrs : hrs; + result += ':' + (min < 10 ? '0' + min : min); + result += ':' + (seconds < 10 ? '0' + seconds : seconds); + return result; + }; + const getUserNameBasedStats = async () => { + var startDateFormatted = moment(value[0]).format('YYYY-MM -DD'); + + var endDateFormatted = moment(value[1]).format('YYYY-MM -DD'); + + const response = await fetchLocalJSONAPI( + `users/${userNameSelected}/tasks/?status=${selectedStatus}&start_date=${startDateFormatted}&end_date=${endDateFormatted}`, + token, + ); + //const response = await fetchLocalJSONAPI(`users/${userName}/tasks/?status=MAPPED`, token); + + const jsonData = await response.tasks; + //const jsonDataForDays = await response.day; + setTeamMetricsStats(jsonData); + }; + let dataUserBasedStats = []; + //totaltime, mappingTotal, ValidationTotal; + + for (let i = 0; i < teamMetricsStats.length; i++) { + let obj = {}; + + obj.TaskUrl = teamMetricsStats[i].project_id; + obj.TaskId = teamMetricsStats[i].tasks_id; + // obj.TimeinOSMTM = convertSeconds(teamMetricsStats[i].time_spent_mapping); + obj.CurrentState = teamMetricsStats[i].task_status; + obj.TaskFinishTime = moment(teamMetricsStats[i].action_date).format('DD-MM-YYYY HH:mm:ss'); + + obj.TimeSpentOnTask = convertSeconds(teamMetricsStats[i].total_time_spent); + obj.Reviewer = teamMetricsStats[i].reviewer; + + dataUserBasedStats.push(obj); + } + const exporttoCsv = (dataArray, fileName) => { + const link = document.createElement('a'); + let csv = convertArrayOfObjectsToCSV(dataArray); + if (csv == null) return; + + const filename = fileName + 'export.csv'; + + if (!csv.match(/^data:text\/csv/i)) { + csv = `data:text/csv;charset=utf-8,${csv}`; + } + + link.setAttribute('href', encodeURI(csv)); + link.setAttribute('download', filename); + link.click(); + }; + function convertArrayOfObjectsToCSV(array) { + let result; + + const columnDelimiter = ','; + const lineDelimiter = '\n'; + const keys = Object.keys(array[0]); + + result = ''; + result += keys.join(columnDelimiter); + result += lineDelimiter; + + array.forEach((item) => { + let ctr = 0; + keys.forEach((key) => { + if (ctr > 0) result += columnDelimiter; + + result += item[key]; + + ctr++; + }); + result += lineDelimiter; + }); + + return result; + } + + function submitUserSelected(Values) { + selectedUserName = Values.value; + let taskStatus = ''; + if (selectedTaskStatus) { + if (isObject(selectedTaskStatus)) { + taskStatus = selectedTaskStatus.value; + } else { + taskStatus = selectedTaskStatus; + } + } else { + taskStatus = 'MAPPED'; + } + generateUserBasedMetricsStats(selectedUserName, taskStatus, value[0], value[1]); + //generateUserBasedMetricsStats(); + } + function submitTaskSelected(Values) { + selectedTaskStatus = Values.value; + let userNameselected = ''; + if (selectedUserName) { + userNameselected = selectedUserName.value; + } else { + userNameselected = userNameSelected; + } + + generateUserBasedMetricsStats(userNameselected, selectedTaskStatus, value[0], value[1]); + } + var generateUserBasedMetricsStats = (userName, taskStatus, startDate, endDate) => { + var startDateFormatted = moment(startDate).format('YYYY-MM -DD'); + + var endDateFormatted = moment(endDate).format('YYYY-MM -DD'); + + let url = `users/${userName}/tasks/?status=${taskStatus}&start_date=${startDateFormatted}&end_date=${endDateFormatted}`; + fetchLocalJSONAPI(url, token) + .then((res) => { + // setTeamMetricsStats(res.team); + const responseData = res.tasks; + setTeamMetricsStats(responseData); + }) + .catch((e) => console.log('call back failed in task index file' + e)); + }; + + return ( +
+
+ + + + + + + + + + +
+ + + + + + + + + + + +
+
+ +
+ ); +} + export function MyTeams() { useSetTitleTag('My teams'); return ( @@ -88,6 +412,7 @@ export function ListTeams({ managementView = false }: Object) { userTeamsOnly={userTeamsOnly} setUserTeamsOnly={setUserTeamsOnly} /> + ); } From 644ed8a5eb0a1b0b7edb340a854a5d7ee643ce7b Mon Sep 17 00:00:00 2001 From: hc00364289 <71371046+hc00364289@users.noreply.github.com> Date: Mon, 14 Dec 2020 17:59:56 +0530 Subject: [PATCH 2/8] removed unnecessary code --- frontend/src/components/teamsAndOrgs/teams.js | 29 ------------------- frontend/src/views/teams.js | 16 ++-------- 2 files changed, 2 insertions(+), 43 deletions(-) diff --git a/frontend/src/components/teamsAndOrgs/teams.js b/frontend/src/components/teamsAndOrgs/teams.js index dc237d394..c6acde633 100644 --- a/frontend/src/components/teamsAndOrgs/teams.js +++ b/frontend/src/components/teamsAndOrgs/teams.js @@ -408,10 +408,7 @@ export function TeamsStats() { const response = await fetchLocalJSONAPI(`teams/?member=${userId}`, token); const jsonData = await response.teams; - //const jsonDataForDays = await response.day; setTeamNames(jsonData); - - console.log('team names are ***', jsonData); }; let selectItems = [{ value: 'All', label: 'All' }]; @@ -431,10 +428,7 @@ export function TeamsStats() { const jsonData = await response.team; //const jsonDataForDays = await response.day; setTeamMetricsStats(jsonData); - - console.log('user metrics stats are ***', jsonData); }; - console.log('team metrics stats are ***', teamMetricsStats); var convertSeconds = (sec) => { var hrs = Math.floor(sec / 3600); var min = Math.floor((sec - hrs * 3600) / 60); @@ -448,7 +442,6 @@ export function TeamsStats() { }; let dataSummaryResponse = []; - //totaltime, mappingTotal, ValidationTotal; for (let i = 0; i < teamMetricsStats.length; i++) { let obj = {}; @@ -524,38 +517,22 @@ export function TeamsStats() { ]; function submitSelected(Values) { - console.log('param sent is', Values.value); - console.log('start time is', value[0]); - console.log('end time is', value[1]); - generateTeamMetricsStats(Values.value, value[0], value[1]); } var generateTeamMetricsStats = (teamId, startDate, endDate) => { - // console.log('select box value inside api call is', selectBoxValue.value); var startDateFormatted = moment(startDate).format('YYYY-MM -DD'); var endDateFormatted = moment(endDate).format('YYYY-MM -DD'); - // const response = await fetchLocalJSONAPI( - // `users/${userName}/userstaskmapped/ ?project_id=6&start_date=${startDateFormatted}&end_date=${endDateFormatted}`, - // token, - // ); - - // const jsonData = await response.task; - //const response = await fetchLocalJSONAPI(`users/HanumanthMapper/usersteamstats/`, token); - let url = ''; if (teamId === 'All') { url = `users/${userName}/usersteamstats/?start_date=${startDateFormatted}&end_date=${endDateFormatted}`; - //url = `users/${userName}/userstaskmapped/?start_date=${startDateFormatted}&end_date=${endDateFormatted}`; } else { url = `users/${userName}/usersteamstats/?team_id=${teamId}&start_date=${startDateFormatted}&end_date=${endDateFormatted}`; } fetchLocalJSONAPI(url, token) .then((res) => { - // setUserMetricsStats(res.team); setTeamMetricsStats(res.team); - //setUserMetricsGraphData(res.day); }) .catch((e) => console.log('call back failed in task index file' + e)); }; @@ -632,10 +609,6 @@ export function TeamsStats() { }, ]; const exporttoCsv = (dataArray, fileName) => { - console.log('array data', dataArray); - console.log('afile name is', fileName); - console.log('Start Date', value[0]); - console.log('End Date is', value[1]); const link = document.createElement('a'); let csv = convertArrayOfObjectsToCSV(dataArray); if (csv == null) return; @@ -677,9 +650,7 @@ export function TeamsStats() { } function handleRowClick(row, event) { - console.log('row event clicked', row.UserName); setSelectedUser(row.UserName); - console.log('inside handle Row click for popup 1112', selectedUser); } const customStyles = { diff --git a/frontend/src/views/teams.js b/frontend/src/views/teams.js index 18e1939c7..6fc5e8ffe 100644 --- a/frontend/src/views/teams.js +++ b/frontend/src/views/teams.js @@ -52,14 +52,12 @@ export function MyTeamsUserSatsIndetailed() { }, []); const token = useSelector((state) => state.auth.get('token')); - const [userNames, setUserNames] = useState({}); - const getUserNames = async () => { const response = await fetchLocalJSONAPI(`users/`, token); const jsonData = await response.users; - //const jsonDataForDays = await response.day; + setUserNames(jsonData); }; @@ -146,9 +144,8 @@ export function MyTeamsUserSatsIndetailed() { ]; var dateObj = new Date(); - // subtract one day from current time + // subtract seven day from current time dateObj.setDate(dateObj.getDate() - 7); - // const [value, onChange] = useState([new Date(), new Date()]); let [value, onChange] = useState([dateObj, new Date()]); let [selectedUserName, setSelectedUserName] = useState(null); let [selectedTaskStatus, setSelectedTaskStatus] = useState(null); @@ -184,24 +181,16 @@ export function MyTeamsUserSatsIndetailed() { `users/${userNameSelected}/tasks/?status=${selectedStatus}&start_date=${startDateFormatted}&end_date=${endDateFormatted}`, token, ); - //const response = await fetchLocalJSONAPI(`users/${userName}/tasks/?status=MAPPED`, token); - const jsonData = await response.tasks; - //const jsonDataForDays = await response.day; setTeamMetricsStats(jsonData); }; let dataUserBasedStats = []; - //totaltime, mappingTotal, ValidationTotal; - for (let i = 0; i < teamMetricsStats.length; i++) { let obj = {}; - obj.TaskUrl = teamMetricsStats[i].project_id; obj.TaskId = teamMetricsStats[i].tasks_id; - // obj.TimeinOSMTM = convertSeconds(teamMetricsStats[i].time_spent_mapping); obj.CurrentState = teamMetricsStats[i].task_status; obj.TaskFinishTime = moment(teamMetricsStats[i].action_date).format('DD-MM-YYYY HH:mm:ss'); - obj.TimeSpentOnTask = convertSeconds(teamMetricsStats[i].total_time_spent); obj.Reviewer = teamMetricsStats[i].reviewer; @@ -282,7 +271,6 @@ export function MyTeamsUserSatsIndetailed() { let url = `users/${userName}/tasks/?status=${taskStatus}&start_date=${startDateFormatted}&end_date=${endDateFormatted}`; fetchLocalJSONAPI(url, token) .then((res) => { - // setTeamMetricsStats(res.team); const responseData = res.tasks; setTeamMetricsStats(responseData); }) From 15f3e1589dbdb1ce7614b8f1f674705a2e02b105 Mon Sep 17 00:00:00 2001 From: hc00364289 <71371046+hc00364289@users.noreply.github.com> Date: Mon, 14 Dec 2020 21:24:05 +0530 Subject: [PATCH 3/8] code formating for csv export --- frontend/src/components/teamsAndOrgs/teams.js | 47 ++---------------- .../components/userDetail/elementsMapped.js | 48 ++----------------- frontend/src/network/genericCSVExport.js | 40 ++++++++++++++++ frontend/src/views/teams.js | 43 +---------------- 4 files changed, 50 insertions(+), 128 deletions(-) create mode 100644 frontend/src/network/genericCSVExport.js diff --git a/frontend/src/components/teamsAndOrgs/teams.js b/frontend/src/components/teamsAndOrgs/teams.js index c6acde633..aae8e657c 100644 --- a/frontend/src/components/teamsAndOrgs/teams.js +++ b/frontend/src/components/teamsAndOrgs/teams.js @@ -5,6 +5,7 @@ import { FormattedMessage } from 'react-intl'; import ReactPlaceholder from 'react-placeholder'; import { Form, Field } from 'react-final-form'; import { fetchLocalJSONAPI } from '../../network/genericJSONRequest'; +import { exporttoCSVFile } from '../../network/genericCSVExport'; import messages from './messages'; import { useEditTeamAllowed } from '../../hooks/UsePermissions'; import { UserAvatar, UserAvatarList } from '../user/avatar'; @@ -608,46 +609,6 @@ export function TeamsStats() { minWidth: '200px', }, ]; - const exporttoCsv = (dataArray, fileName) => { - const link = document.createElement('a'); - let csv = convertArrayOfObjectsToCSV(dataArray); - if (csv == null) return; - - const filename = fileName + 'export.csv'; - - if (!csv.match(/^data:text\/csv/i)) { - csv = `data:text/csv;charset=utf-8,${csv}`; - } - - link.setAttribute('href', encodeURI(csv)); - link.setAttribute('download', filename); - link.click(); - }; - function convertArrayOfObjectsToCSV(array) { - let result; - - const columnDelimiter = ','; - const lineDelimiter = '\n'; - const keys = Object.keys(array[0]); - - result = ''; - result += keys.join(columnDelimiter); - result += lineDelimiter; - - array.forEach((item) => { - let ctr = 0; - keys.forEach((key) => { - if (ctr > 0) result += columnDelimiter; - - result += item[key]; - - ctr++; - }); - result += lineDelimiter; - }); - - return result; - } function handleRowClick(row, event) { setSelectedUser(row.UserName); @@ -720,7 +681,7 @@ export function TeamsStats() {

@@ -743,7 +704,7 @@ export function TeamsStats() {

@@ -763,7 +724,7 @@ export function TeamsStats() {

diff --git a/frontend/src/components/userDetail/elementsMapped.js b/frontend/src/components/userDetail/elementsMapped.js index af1849d1e..35fd3a35a 100644 --- a/frontend/src/components/userDetail/elementsMapped.js +++ b/frontend/src/components/userDetail/elementsMapped.js @@ -12,6 +12,7 @@ import { Button } from '../button'; import { Line } from 'react-chartjs-2'; import Select from 'react-select'; import moment from 'moment'; +import { exporttoCSVFile } from '../../network/genericCSVExport'; import { ClockIcon, RoadIcon, @@ -259,31 +260,6 @@ export const TaskStats = ({ userStats, username }) => { }, ]; - function convertArrayOfObjectsToCSV(array) { - let result; - - const columnDelimiter = ','; - const lineDelimiter = '\n'; - const keys = Object.keys(array[0]); - - result = ''; - result += keys.join(columnDelimiter); - result += lineDelimiter; - - array.forEach((item) => { - let ctr = 0; - keys.forEach((key) => { - if (ctr > 0) result += columnDelimiter; - - result += item[key]; - - ctr++; - }); - result += lineDelimiter; - }); - - return result; - } const state = { labels: graphDays, datasets: [ @@ -307,22 +283,6 @@ export const TaskStats = ({ userStats, username }) => { ], }; - const exporttoCsv = (dataArray, fileName) => { - const link = document.createElement('a'); - let csv = convertArrayOfObjectsToCSV(dataArray); - if (csv == null) return; - - const filename = userName + '-' + fileName + 'export.csv'; - - if (!csv.match(/^data:text\/csv/i)) { - csv = `data:text/csv;charset=utf-8,${csv}`; - } - - link.setAttribute('href', encodeURI(csv)); - link.setAttribute('download', filename); - link.click(); - }; - function submitSelected(Values) { generateUserMetricsStats(Values.value, value[0], value[1]); } @@ -493,7 +453,7 @@ export const TaskStats = ({ userStats, username }) => {

@@ -531,7 +491,7 @@ export const TaskStats = ({ userStats, username }) => {

@@ -551,7 +511,7 @@ export const TaskStats = ({ userStats, username }) => {

diff --git a/frontend/src/network/genericCSVExport.js b/frontend/src/network/genericCSVExport.js new file mode 100644 index 000000000..5e6dd538f --- /dev/null +++ b/frontend/src/network/genericCSVExport.js @@ -0,0 +1,40 @@ +export function exporttoCSVFile(dataArray, fileName) { + const link = document.createElement('a'); + let csv = convertArrayOfObjectsToCSV(dataArray); + if (csv == null) return; + + const filename = fileName + 'export.csv'; + + if (!csv.match(/^data:text\/csv/i)) { + csv = `data:text/csv;charset=utf-8,${csv}`; + } + + link.setAttribute('href', encodeURI(csv)); + link.setAttribute('download', filename); + link.click(); +} +function convertArrayOfObjectsToCSV(array) { + let result; + + const columnDelimiter = ','; + const lineDelimiter = '\n'; + const keys = Object.keys(array[0]); + + result = ''; + result += keys.join(columnDelimiter); + result += lineDelimiter; + + array.forEach((item) => { + let ctr = 0; + keys.forEach((key) => { + if (ctr > 0) result += columnDelimiter; + + result += item[key]; + + ctr++; + }); + result += lineDelimiter; + }); + + return result; +} diff --git a/frontend/src/views/teams.js b/frontend/src/views/teams.js index 6fc5e8ffe..e950e043a 100644 --- a/frontend/src/views/teams.js +++ b/frontend/src/views/teams.js @@ -11,6 +11,7 @@ import { useFetch } from '../hooks/UseFetch'; import { useEditTeamAllowed } from '../hooks/UsePermissions'; import { useSetTitleTag } from '../hooks/UseMetaTags'; import { fetchLocalJSONAPI, pushToLocalJSONAPI } from '../network/genericJSONRequest'; +import { exporttoCSVFile } from '../network/genericCSVExport'; import DataTable from 'react-data-table-component'; import { Button } from '../components/button'; import moment from 'moment'; @@ -196,46 +197,6 @@ export function MyTeamsUserSatsIndetailed() { dataUserBasedStats.push(obj); } - const exporttoCsv = (dataArray, fileName) => { - const link = document.createElement('a'); - let csv = convertArrayOfObjectsToCSV(dataArray); - if (csv == null) return; - - const filename = fileName + 'export.csv'; - - if (!csv.match(/^data:text\/csv/i)) { - csv = `data:text/csv;charset=utf-8,${csv}`; - } - - link.setAttribute('href', encodeURI(csv)); - link.setAttribute('download', filename); - link.click(); - }; - function convertArrayOfObjectsToCSV(array) { - let result; - - const columnDelimiter = ','; - const lineDelimiter = '\n'; - const keys = Object.keys(array[0]); - - result = ''; - result += keys.join(columnDelimiter); - result += lineDelimiter; - - array.forEach((item) => { - let ctr = 0; - keys.forEach((key) => { - if (ctr > 0) result += columnDelimiter; - - result += item[key]; - - ctr++; - }); - result += lineDelimiter; - }); - - return result; - } function submitUserSelected(Values) { selectedUserName = Values.value; @@ -328,7 +289,7 @@ export function MyTeamsUserSatsIndetailed() { From 463bfb668bcec36ab81110e2f8cc78690cd01d40 Mon Sep 17 00:00:00 2001 From: hc00364289 <71371046+hc00364289@users.noreply.github.com> Date: Mon, 21 Dec 2020 16:25:20 +0530 Subject: [PATCH 4/8] Date format changes in metrics --- frontend/src/components/teamsAndOrgs/teams.js | 46 ++++++++++--------- .../components/userDetail/elementsMapped.js | 15 +++--- frontend/src/network/genericCSVExport.js | 41 +++++++++++++---- frontend/src/views/teams.js | 38 +++++++++------ 4 files changed, 89 insertions(+), 51 deletions(-) diff --git a/frontend/src/components/teamsAndOrgs/teams.js b/frontend/src/components/teamsAndOrgs/teams.js index aae8e657c..0e73b732f 100644 --- a/frontend/src/components/teamsAndOrgs/teams.js +++ b/frontend/src/components/teamsAndOrgs/teams.js @@ -5,7 +5,11 @@ import { FormattedMessage } from 'react-intl'; import ReactPlaceholder from 'react-placeholder'; import { Form, Field } from 'react-final-form'; import { fetchLocalJSONAPI } from '../../network/genericJSONRequest'; -import { exporttoCSVFile } from '../../network/genericCSVExport'; +import { + exporttoCSVFile, + convertStartDateTime, + convertEndDateTime, +} from '../../network/genericCSVExport'; import messages from './messages'; import { useEditTeamAllowed } from '../../hooks/UsePermissions'; import { UserAvatar, UserAvatarList } from '../user/avatar'; @@ -19,7 +23,6 @@ import DataTable from 'react-data-table-component'; import DateRangePicker from '@wojtekmaj/react-daterange-picker'; import 'react-calendar/dist/Calendar.css'; import Select from 'react-select'; -import moment from 'moment'; export function TeamsManagement({ teams, @@ -396,15 +399,17 @@ export function TeamsStats() { const [teamMetricsStats, setTeamMetricsStats] = useState({}); const [teamNames, setTeamNames] = useState({}); - const startDate = moment(value[0]).format('YYYY-MM -DD'); - - const endDate = moment(value[1]).format('YYYY-MM -DD'); - - useEffect(() => { - getTeamMetricsStats(); - getTeamNames(); - }, []); + let startDateTime = convertStartDateTime(value[0]); + let endDateTime = convertEndDateTime(value[1]); + const getTeamMetricsStats = async () => { + const response = await fetchLocalJSONAPI( + `users/${userName}/usersteamstats/?start_date=${startDateTime}&end_date=${endDateTime}`, + token, + ); + const jsonData = await response.team; + setTeamMetricsStats(jsonData); + }; const getTeamNames = async () => { const response = await fetchLocalJSONAPI(`teams/?member=${userId}`, token); @@ -412,6 +417,11 @@ export function TeamsStats() { setTeamNames(jsonData); }; + useEffect(() => { + getTeamMetricsStats(); + getTeamNames(); + }, []); + let selectItems = [{ value: 'All', label: 'All' }]; //selectItems for (var i = 0; i < teamNames.length; i++) { @@ -420,16 +430,7 @@ export function TeamsStats() { obj.label = teamNames[i].name; selectItems.push(obj); } - const getTeamMetricsStats = async () => { - const response = await fetchLocalJSONAPI( - `users/${userName}/usersteamstats/?start_date=${startDate}&end_date=${endDate}`, - token, - ); - const jsonData = await response.team; - //const jsonDataForDays = await response.day; - setTeamMetricsStats(jsonData); - }; var convertSeconds = (sec) => { var hrs = Math.floor(sec / 3600); var min = Math.floor((sec - hrs * 3600) / 60); @@ -521,9 +522,12 @@ export function TeamsStats() { generateTeamMetricsStats(Values.value, value[0], value[1]); } var generateTeamMetricsStats = (teamId, startDate, endDate) => { - var startDateFormatted = moment(startDate).format('YYYY-MM -DD'); + // var startDateFormatted = moment(startDate).format('YYYY-MM -DD'); + + // var endDateFormatted = moment(endDate).format('YYYY-MM -DD'); + var startDateFormatted = convertStartDateTime(startDate); - var endDateFormatted = moment(endDate).format('YYYY-MM -DD'); + var endDateFormatted = convertEndDateTime(endDate); let url = ''; if (teamId === 'All') { diff --git a/frontend/src/components/userDetail/elementsMapped.js b/frontend/src/components/userDetail/elementsMapped.js index 35fd3a35a..8ea823d3d 100644 --- a/frontend/src/components/userDetail/elementsMapped.js +++ b/frontend/src/components/userDetail/elementsMapped.js @@ -12,7 +12,11 @@ import { Button } from '../button'; import { Line } from 'react-chartjs-2'; import Select from 'react-select'; import moment from 'moment'; -import { exporttoCSVFile } from '../../network/genericCSVExport'; +import { + exporttoCSVFile, + convertStartDateTime, + convertEndDateTime, +} from '../../network/genericCSVExport'; import { ClockIcon, RoadIcon, @@ -117,8 +121,6 @@ export const TaskStats = ({ userStats, username }) => { dateObj.setDate(dateObj.getDate() - 7); const [value, onChange] = useState([dateObj, new Date()]); - const startDate = moment(value[0]).format('YYYY-MM -DD'); - const endDate = moment(value[1]).format('YYYY-MM -DD'); const getProjectNames = async () => { const response = await fetchLocalJSONAPI(`projects/`, token); const jsonData = await response.results; @@ -131,6 +133,8 @@ export const TaskStats = ({ userStats, username }) => { obj.label = projectNames[i].name; selectItems.push(obj); } + const startDate = convertStartDateTime(value[0]); + const endDate = convertEndDateTime(value[1]); const getUserMetricsStats = async () => { const response = await fetchLocalJSONAPI( @@ -287,9 +291,8 @@ export const TaskStats = ({ userStats, username }) => { generateUserMetricsStats(Values.value, value[0], value[1]); } var generateUserMetricsStats = (projId, startDate, endDate) => { - var startDateFormatted = moment(startDate).format('YYYY-MM -DD'); - var endDateFormatted = moment(endDate).format('YYYY-MM -DD'); - + var startDateFormatted = convertStartDateTime(startDate); + var endDateFormatted = convertEndDateTime(endDate); let url = ''; if (projId === 'All') { url = `users/${userName}/userstaskmapped/?start_date=${startDateFormatted}&end_date=${endDateFormatted}`; diff --git a/frontend/src/network/genericCSVExport.js b/frontend/src/network/genericCSVExport.js index 5e6dd538f..1607c4ca1 100644 --- a/frontend/src/network/genericCSVExport.js +++ b/frontend/src/network/genericCSVExport.js @@ -1,17 +1,20 @@ +import moment from 'moment'; export function exporttoCSVFile(dataArray, fileName) { - const link = document.createElement('a'); - let csv = convertArrayOfObjectsToCSV(dataArray); - if (csv == null) return; + if (dataArray && dataArray.length > 0) { + const link = document.createElement('a'); + let csv = convertArrayOfObjectsToCSV(dataArray); + if (csv == null) return; - const filename = fileName + 'export.csv'; + const filename = fileName + 'export.csv'; - if (!csv.match(/^data:text\/csv/i)) { - csv = `data:text/csv;charset=utf-8,${csv}`; - } + if (!csv.match(/^data:text\/csv/i)) { + csv = `data:text/csv;charset=utf-8,${csv}`; + } - link.setAttribute('href', encodeURI(csv)); - link.setAttribute('download', filename); - link.click(); + link.setAttribute('href', encodeURI(csv)); + link.setAttribute('download', filename); + link.click(); + } } function convertArrayOfObjectsToCSV(array) { let result; @@ -38,3 +41,21 @@ function convertArrayOfObjectsToCSV(array) { return result; } + +export function convertStartDateTime(value) { + let dateTime = new Date(value); + dateTime.setHours(0); + dateTime.setMinutes(0); + dateTime.setSeconds(0); + let result = moment(dateTime).format('YYYY-MM-DD HH:mm:ss'); + return result; +} +export function convertEndDateTime(value) { + let dateTime = new Date(value); + dateTime.setHours(11); + dateTime.setMinutes(59); + dateTime.setSeconds(59); + + let result = moment(dateTime).format('YYYY-MM-DD HH:mm:ss'); + return result; +} diff --git a/frontend/src/views/teams.js b/frontend/src/views/teams.js index e950e043a..1541c705e 100644 --- a/frontend/src/views/teams.js +++ b/frontend/src/views/teams.js @@ -11,7 +11,11 @@ import { useFetch } from '../hooks/UseFetch'; import { useEditTeamAllowed } from '../hooks/UsePermissions'; import { useSetTitleTag } from '../hooks/UseMetaTags'; import { fetchLocalJSONAPI, pushToLocalJSONAPI } from '../network/genericJSONRequest'; -import { exporttoCSVFile } from '../network/genericCSVExport'; +import { + exporttoCSVFile, + convertStartDateTime, + convertEndDateTime, +} from '../network/genericCSVExport'; import DataTable from 'react-data-table-component'; import { Button } from '../components/button'; import moment from 'moment'; @@ -72,8 +76,12 @@ export function MyTeamsUserSatsIndetailed() { } let selectTaskSatus = [ - { value: 'MAPPED', label: 'MAPPED' }, - { value: 'VALIDATED', label: 'VALIDATED' }, + { value: 'MAPPED', label: 'Mapped' }, + { value: 'LOCKED_FOR_MAPPING', label: 'Locked For Mapping ' }, + { value: 'VALIDATED', label: 'Validated' }, + { value: 'LOCKED_FOR_VALIDATION', label: 'Locked For Validation ' }, + { value: 'INVALIDATED', label: 'In Validated' }, + { value: 'BADIMAGERY', label: 'BadImagery' }, ]; const maxDateApp = new Date(); const customStyles = { @@ -121,8 +129,8 @@ export function MyTeamsUserSatsIndetailed() { }, { - name: ' Task Finish time ', - selector: 'TaskFinishTime', + name: ' Status Change Time', + selector: 'StatusChangeTime', sortable: true, grow: 2, minWidth: '100px', @@ -174,9 +182,12 @@ export function MyTeamsUserSatsIndetailed() { return result; }; const getUserNameBasedStats = async () => { - var startDateFormatted = moment(value[0]).format('YYYY-MM -DD'); + // var startDateFormatted = moment(value[0]).format('YYYY-MM -DD'); + + // var endDateFormatted = moment(value[1]).format('YYYY-MM -DD'); + var startDateFormatted = convertStartDateTime(value[0]); - var endDateFormatted = moment(value[1]).format('YYYY-MM -DD'); + var endDateFormatted = convertEndDateTime(value[1]); const response = await fetchLocalJSONAPI( `users/${userNameSelected}/tasks/?status=${selectedStatus}&start_date=${startDateFormatted}&end_date=${endDateFormatted}`, @@ -191,7 +202,8 @@ export function MyTeamsUserSatsIndetailed() { obj.TaskUrl = teamMetricsStats[i].project_id; obj.TaskId = teamMetricsStats[i].tasks_id; obj.CurrentState = teamMetricsStats[i].task_status; - obj.TaskFinishTime = moment(teamMetricsStats[i].action_date).format('DD-MM-YYYY HH:mm:ss'); + + obj.StatusChangeTime = moment(teamMetricsStats[i].action_date).format('DD-MM-YYYY HH:mm:ss'); obj.TimeSpentOnTask = convertSeconds(teamMetricsStats[i].total_time_spent); obj.Reviewer = teamMetricsStats[i].reviewer; @@ -225,10 +237,8 @@ export function MyTeamsUserSatsIndetailed() { generateUserBasedMetricsStats(userNameselected, selectedTaskStatus, value[0], value[1]); } var generateUserBasedMetricsStats = (userName, taskStatus, startDate, endDate) => { - var startDateFormatted = moment(startDate).format('YYYY-MM -DD'); - - var endDateFormatted = moment(endDate).format('YYYY-MM -DD'); - + var startDateFormatted = convertStartDateTime(startDate); + var endDateFormatted = convertEndDateTime(endDate); let url = `users/${userName}/tasks/?status=${taskStatus}&start_date=${startDateFormatted}&end_date=${endDateFormatted}`; fetchLocalJSONAPI(url, token) .then((res) => { @@ -259,7 +269,7 @@ export function MyTeamsUserSatsIndetailed() { /> - +