Skip to content

Commit

Permalink
Merge branch 'master' into kiram15/ENT-9431
Browse files Browse the repository at this point in the history
  • Loading branch information
kiram15 authored Sep 24, 2024
2 parents fa3ffdd + b8cd0c7 commit 7339314
Show file tree
Hide file tree
Showing 7 changed files with 304 additions and 79 deletions.
2 changes: 2 additions & 0 deletions src/components/AdvanceAnalyticsV2/data/hooks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { advanceAnalyticsQueryKeys } from '../constants';
import EnterpriseDataApiService from '../../../../data/services/EnterpriseDataApiService';

export { default as useEnterpriseEnrollmentsData } from './useEnterpriseEnrollmentsData';
export { default as useEnterpriseEngagementData } from './useEnterpriseEngagementData';
export { default as useEnterpriseCompletionsData } from './useEnterpriseCompletionsData';

export const useEnterpriseAnalyticsData = ({
enterpriseCustomerUUID,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { useQuery } from '@tanstack/react-query';
import _ from 'lodash';

import { useMemo } from 'react';
import { ANALYTICS_TABS, generateKey } from '../constants';
import { applyGranularity, applyCalculation } from '../utils';
import EnterpriseDataApiService from '../../../../data/services/EnterpriseDataApiService';

/**
Applies data transformations to the response data.
Apply transformations to the response data based on the granularity and calculation. Data transformation is applied
only on the items with the allowed enrollment types.
* @param {object} response - The response data returned from the API.
* @param {OpUnitType} granularity - Granularity of the data. e.g. `day`, `week`, `month`, `quarter`, `year`.
* @param {String} calculation - Calculation to apply on the data. e.g.
* `total`, `running_total`, `moving_average_3_periods`, `moving_average_7_periods`.
* @param {Array} allowedEnrollTypes - Allowed enrollment types to consider. e.g. [`certificate`, `audit`].
*/
const applyDataTransformations = (response, granularity, calculation, allowedEnrollTypes = ['certificate', 'audit']) => {
const modifiedResponse = _.cloneDeep(response);
if (modifiedResponse?.data?.completionsOverTime) {
let completionsOverTime = [];
for (let i = 0; i < allowedEnrollTypes.length; i++) {
const data = applyGranularity(
modifiedResponse.data.completionsOverTime.filter(
completion => completion.enrollType === allowedEnrollTypes[i],
),
'passedDate',
'completionCount',
granularity,
);
completionsOverTime = completionsOverTime.concat(
applyCalculation(data, 'completionCount', calculation),
);
}

modifiedResponse.data.completionsOverTime = completionsOverTime;
}

return modifiedResponse;
};

/**
Fetches enterprise completion data.
* @param {String} enterpriseCustomerUUID - UUID of the enterprise customer.
* @param {Date} startDate - Start date for the data.
* @param {Date} endDate - End date for the data.
* @param {OpUnitType} granularity - Granularity of the data. e.g. `day`, `week`, `month`, `quarter`, `year`.
* @param {String} calculation - Calculation to apply on the data. e.g.
* `total`, `running_total`, `moving_average_3_periods`, `moving_average_7_periods`.
* @param {object} queryOptions - Additional options for the query.
*/
const useEnterpriseCompletionsData = ({
enterpriseCustomerUUID,
startDate,
endDate,
granularity = undefined,
calculation = undefined,
queryOptions = {},
}) => {
const requestOptions = { startDate, endDate };
const response = useQuery({
queryKey: generateKey('completions', enterpriseCustomerUUID, requestOptions),
queryFn: () => EnterpriseDataApiService.fetchAdminAnalyticsData(
enterpriseCustomerUUID,
ANALYTICS_TABS.COMPLETIONS,
requestOptions,
),
staleTime: 0.5 * (1000 * 60 * 60), // 30 minutes. The time in milliseconds after data is considered stale.
cacheTime: 0.75 * (1000 * 60 * 60), // 45 minutes. Cache data will be garbage collected after this duration.
keepPreviousData: true,
...queryOptions,
});

return useMemo(() => applyDataTransformations(
response,
granularity,
calculation,
), [response, granularity, calculation]);
};

export default useEnterpriseCompletionsData;
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { useQuery } from '@tanstack/react-query';
import _ from 'lodash';

import { useMemo } from 'react';
import { ANALYTICS_TABS, generateKey } from '../constants';
import { applyGranularity, applyCalculation } from '../utils';
import EnterpriseDataApiService from '../../../../data/services/EnterpriseDataApiService';

/**
Applies data transformations to the response data.
Apply transformations to the response data based on the granularity and calculation. Data transformation is applied
only on the items with the allowed enrollment types.
* @param {object} response - The response data returned from the API.
* @param {OpUnitType} granularity - Granularity of the data. e.g. `day`, `week`, `month`, `quarter`, `year`.
* @param {String} calculation - Calculation to apply on the data. e.g.
* `total`, `running_total`, `moving_average_3_periods`, `moving_average_7_periods`.
* @param {Array} allowedEnrollTypes - Allowed enrollment types to consider. e.g. [`certificate`, `audit`].
*/
const applyDataTransformations = (response, granularity, calculation, allowedEnrollTypes = ['certificate', 'audit']) => {
const modifiedResponse = _.cloneDeep(response);
if (modifiedResponse?.data?.engagementOverTime) {
let engagementOverTime = [];
for (let i = 0; i < allowedEnrollTypes.length; i++) {
const data = applyGranularity(
modifiedResponse.data.engagementOverTime.filter(
engagement => engagement.enrollType === allowedEnrollTypes[i],
),
'activityDate',
'learningTimeHours',
granularity,
);
engagementOverTime = engagementOverTime.concat(
applyCalculation(data, 'learningTimeHours', calculation),
);
}

modifiedResponse.data.engagementOverTime = engagementOverTime;
}

return modifiedResponse;
};

/**
Fetches enterprise engagement data.
* @param {String} enterpriseCustomerUUID - UUID of the enterprise customer.
* @param {Date} startDate - Start date for the data.
* @param {Date} endDate - End date for the data.
* @param {OpUnitType} granularity - Granularity of the data. e.g. `day`, `week`, `month`, `quarter`, `year`.
* @param {String} calculation - Calculation to apply on the data. e.g.
* `total`, `running_total`, `moving_average_3_periods`, `moving_average_7_periods`.
* @param {object} queryOptions - Additional options for the query.
*/
const useEnterpriseEngagementData = ({
enterpriseCustomerUUID,
startDate,
endDate,
granularity = undefined,
calculation = undefined,
queryOptions = {},
}) => {
const requestOptions = { startDate, endDate };
const response = useQuery({
queryKey: generateKey('engagements', enterpriseCustomerUUID, requestOptions),
queryFn: () => EnterpriseDataApiService.fetchAdminAnalyticsData(
enterpriseCustomerUUID,
ANALYTICS_TABS.ENGAGEMENTS,
requestOptions,
),
staleTime: 0.5 * (1000 * 60 * 60), // 30 minutes. The time in milliseconds after data is considered stale.
cacheTime: 0.75 * (1000 * 60 * 60), // 45 minutes. Cache data will be garbage collected after this duration.
keepPreviousData: true,
...queryOptions,
});

return useMemo(() => applyDataTransformations(
response,
granularity,
calculation,
), [response, granularity, calculation]);
};

export default useEnterpriseEngagementData;
94 changes: 61 additions & 33 deletions src/components/AdvanceAnalyticsV2/tabs/Completions.jsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import React from 'react';
import React, { useMemo } from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';
import PropTypes from 'prop-types';
import dayjs from 'dayjs';
import Header from '../Header';
import { ANALYTICS_TABS, CHART_TYPES, chartColorMap } from '../data/constants';
import { ANALYTICS_TABS, chartColorMap } from '../data/constants';
import AnalyticsTable from './AnalyticsTable';
import ChartWrapper from '../charts/ChartWrapper';
import { useEnterpriseAnalyticsData } from '../data/hooks';
import DownloadCSV from '../DownloadCSV';
import { constructChartHoverTemplate } from '../data/utils';
import { useEnterpriseCompletionsData } from '../data/hooks';
import DownloadCSVButton from '../DownloadCSVButton';
import { constructChartHoverTemplate, modifyDataToIntroduceEnrollTypeCount } from '../data/utils';

const Completions = ({
startDate, endDate, granularity, calculation, enterpriseId,
Expand All @@ -16,7 +17,7 @@ const Completions = ({

const {
isFetching, isError, data,
} = useEnterpriseAnalyticsData({
} = useEnterpriseCompletionsData({
enterpriseCustomerUUID: enterpriseId,
key: ANALYTICS_TABS.COMPLETIONS,
startDate,
Expand All @@ -25,6 +26,48 @@ const Completions = ({
calculation,
});

const completionsOverTimeForCSV = useMemo(() => {
const completionsOverTime = modifyDataToIntroduceEnrollTypeCount(
data?.completionsOverTime,
'passedDate',
'completionCount',
);
return completionsOverTime.map(({ activityDate, certificate, audit }) => ({
activity_date: dayjs.utc(activityDate).toISOString().split('T')[0],
certificate,
audit,
}));
}, [data]);

const topCoursesByCompletionForCSV = useMemo(() => {
const topCoursesByCompletions = modifyDataToIntroduceEnrollTypeCount(
data?.topCoursesByCompletions,
'courseKey',
'completionCount',
);
return topCoursesByCompletions.map(({
courseKey, courseTitle, certificate, audit,
}) => ({
course_key: courseKey,
course_title: courseTitle,
certificate,
audit,
}));
}, [data]);

const topSubjectsByCompletionsForCSV = useMemo(() => {
const topSubjectsByCompletions = modifyDataToIntroduceEnrollTypeCount(
data?.topSubjectsByCompletions,
'courseSubject',
'completionCount',
);
return topSubjectsByCompletions.map(({ courseSubject, certificate, audit }) => ({
course_subject: courseSubject,
certificate,
audit,
}));
}, [data]);

return (
<div className="tab-completions mt-4">
<div className="completions-over-time-chart-container mb-4">
Expand All @@ -40,14 +83,9 @@ const Completions = ({
description: 'Subtitle for the completions over time chart.',
})}
DownloadCSVComponent={(
<DownloadCSV
enterpriseId={enterpriseId}
startDate={startDate}
endDate={endDate}
activeTab={ANALYTICS_TABS.COMPLETIONS}
granularity={granularity}
calculation={calculation}
chartType={CHART_TYPES.COMPLETIONS_OVER_TIME}
<DownloadCSVButton
jsonData={completionsOverTimeForCSV}
csvFileName={`Completions over time - ${startDate} - ${endDate} (${granularity} ${calculation})`}
/>
)}
/>
Expand All @@ -58,7 +96,7 @@ const Completions = ({
chartProps={{
data: data?.completionsOverTime,
xKey: 'passedDate',
yKey: 'count',
yKey: 'completionCount',
colorKey: 'enrollType',
colorMap: chartColorMap,
xAxisTitle: '',
Expand Down Expand Up @@ -88,14 +126,9 @@ const Completions = ({
description: 'Subtitle for the top 10 courses by completions chart.',
})}
DownloadCSVComponent={(
<DownloadCSV
enterpriseId={enterpriseId}
startDate={startDate}
endDate={endDate}
activeTab={ANALYTICS_TABS.COMPLETIONS}
granularity={granularity}
calculation={calculation}
chartType={CHART_TYPES.TOP_COURSES_BY_COMPLETIONS}
<DownloadCSVButton
jsonData={topCoursesByCompletionForCSV}
csvFileName={`Top Courses by Completion - ${startDate} - ${endDate} (${granularity} ${calculation})`}
/>
)}
/>
Expand All @@ -106,7 +139,7 @@ const Completions = ({
chartProps={{
data: data?.topCoursesByCompletions,
xKey: 'courseKey',
yKey: 'count',
yKey: 'completionCount',
colorKey: 'enrollType',
colorMap: chartColorMap,
yAxisTitle: intl.formatMessage({
Expand Down Expand Up @@ -139,14 +172,9 @@ const Completions = ({
description: 'Subtitle for the top 10 subjects by completion chart.',
})}
DownloadCSVComponent={(
<DownloadCSV
enterpriseId={enterpriseId}
startDate={startDate}
endDate={endDate}
activeTab={ANALYTICS_TABS.COMPLETIONS}
granularity={granularity}
calculation={calculation}
chartType={CHART_TYPES.TOP_SUBJECTS_BY_COMPLETIONS}
<DownloadCSVButton
jsonData={topSubjectsByCompletionsForCSV}
csvFileName={`Top Subjects by Completion - ${startDate} - ${endDate} (${granularity} ${calculation})`}
/>
)}
/>
Expand All @@ -157,7 +185,7 @@ const Completions = ({
chartProps={{
data: data?.topSubjectsByCompletions,
xKey: 'courseSubject',
yKey: 'count',
yKey: 'completionCount',
colorKey: 'enrollType',
colorMap: chartColorMap,
yAxisTitle: intl.formatMessage({
Expand Down
Loading

0 comments on commit 7339314

Please sign in to comment.