Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions src/components/AdvanceAnalyticsV2.0/AnalyticsFilters.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ const AnalyticsFilters = ({
groupUUID,
setGroupUUID,
currentDate,
data,
groups,
isFetching,
isGroupsLoading,
budgets,
isBudgetsFetching,
Expand Down Expand Up @@ -114,7 +112,6 @@ const AnalyticsFilters = ({
controlClassName="font-weight-normal analytics-filter-form-controls rounded-0"
as="select"
onChange={(e) => handleDateRangeChange(e.target.value)}
disabled={isFetching}
defaultValue={dateRangeValue}
value={dateRangeValue}
>
Expand Down Expand Up @@ -169,9 +166,7 @@ const AnalyticsFilters = ({
controlClassName="font-weight-normal analytics-filter-form-controls rounded-0"
type="date"
value={startDate || get90DayPriorDate()}
min={data?.minEnrollmentDate || ''}
onChange={(e) => handleStartDateChange(e.target.value)}
disabled={isFetching}
/>
</Form.Group>
</div>
Expand All @@ -190,7 +185,6 @@ const AnalyticsFilters = ({
value={endDate || currentDate || ''}
max={currentDate || ''}
onChange={(e) => handleEndDateChange(e.target.value)}
disabled={isFetching}
/>
</Form.Group>
</div>
Expand All @@ -209,7 +203,6 @@ const AnalyticsFilters = ({
as="select"
value={calculation}
onChange={(e) => setCalculation(e.target.value)}
disabled={isFetching}
>
<option value={CALCULATION.TOTAL}>
{intl.formatMessage({
Expand Down Expand Up @@ -256,7 +249,6 @@ const AnalyticsFilters = ({
as="select"
value={granularity}
onChange={(e) => setGranularity(e.target.value)}
disabled={isFetching}
>
<option value={GRANULARITY.DAILY}>
{intl.formatMessage({
Expand Down Expand Up @@ -418,7 +410,6 @@ const AnalyticsFilters = ({
controlClassName="font-weight-normal analytics-filter-form-controls rounded-0"
as="select"
onChange={(e) => setCourseType(e.target.value)}
disabled={isFetching}
defaultValue={COURSE_TYPES.ALL_COURSE_TYPES}
value={courseType}
>
Expand Down Expand Up @@ -470,9 +461,7 @@ AnalyticsFilters.propTypes = {
groupUUID: PropTypes.string,
setGroupUUID: PropTypes.func.isRequired,
currentDate: PropTypes.string.isRequired,
data: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
groups: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
isFetching: PropTypes.bool.isRequired,
isGroupsLoading: PropTypes.bool.isRequired,
activeTab: PropTypes.string.isRequired,
isEnterpriseCoursesFetching: PropTypes.bool,
Expand Down

This file was deleted.

121 changes: 48 additions & 73 deletions src/components/AdvanceAnalyticsV2.0/AnalyticsPage.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useMemo } from 'react';
import React, { useState } from 'react';
import { Tabs, Tab, Stack } from '@openedx/paragon';
import { Helmet } from 'react-helmet';
import PropTypes from 'prop-types';
Expand All @@ -7,96 +7,71 @@ import { useIntl } from '@edx/frontend-platform/i18n';
import Hero from '../Hero';
import Engagements from './tabs/Engagements';
import Progress from './tabs/Progress';
import { GRANULARITY, CALCULATION } from './data/constants';
import { useAllFlexEnterpriseGroups } from '../learner-credit-management/data';
import { AnalyticsFiltersContext } from './AnalyticsFiltersContext';
import Outcomes from './tabs/Outcomes';

const AnalyticsPage = ({ enterpriseId }) => {
const [activeTab, setActiveTab] = useState('engagements');
const [granularity, setGranularity] = useState(GRANULARITY.WEEKLY);
const [calculation, setCalculation] = useState(CALCULATION.TOTAL);
const [groupUUID, setGroupUUID] = useState('');
const intl = useIntl();
const { data: groups, isLoading: isGroupsLoading } = useAllFlexEnterpriseGroups(enterpriseId);

const PAGE_TITLE = intl.formatMessage({
id: 'analytics.page.title.heading',
defaultMessage: 'Analytics',
description: 'Title of the analytics page',
});

const currentDate = new Date().toISOString().split('T')[0];

const filtersContextValue = useMemo(() => ({
currentDate,
granularity,
calculation,
groupUUID,
enterpriseId,
setGranularity,
setCalculation,
setGroupUUID,
groups,
isGroupsLoading,
}), [
currentDate, granularity, calculation,
groupUUID, enterpriseId, groups, isGroupsLoading,
]);

return (
<>
<Helmet title={PAGE_TITLE} />
<Hero title={PAGE_TITLE} />
<Stack className="container-fluid w-100" gap={4}>
<AnalyticsFiltersContext.Provider value={filtersContextValue}>
<div className="tabs-container pt-3">
<Tabs
variant="tabs"
activeKey={activeTab}
onSelect={(tab) => {
setActiveTab(tab);
}}
<div className="tabs-container pt-3">
<Tabs
variant="tabs"
activeKey={activeTab}
onSelect={(tab) => {
setActiveTab(tab);
}}
mountOnEnter
unmountOnExit
>
<Tab
eventKey="engagements"
title={intl.formatMessage({
id: 'analytics.engagement.tab.title.heading',
defaultMessage: 'Engagement',
description: 'Title for the engagements tab in advance analytics.',
})}
>
<Engagements
enterpriseId={enterpriseId}
/>
</Tab>
<Tab
eventKey="Progress"
title={intl.formatMessage({
id: 'advance.analytics.progress.tab.title.heading',
defaultMessage: 'Progress',
description: 'Title for the progress tab in advance analytics.',
})}
>
<Progress
enterpriseId={enterpriseId}
/>
</Tab>
<Tab
eventKey="Outcomes"
title={intl.formatMessage({
id: 'advance.analytics.outcomes.tab.title.heading',
defaultMessage: 'Outcomes',
description: 'Title for the outcomes tab in advance analytics.',
})}
>
<Tab
eventKey="engagements"
title={intl.formatMessage({
id: 'analytics.engagement.tab.title.heading',
defaultMessage: 'Engagement',
description: 'Title for the engagements tab in advance analytics.',
})}
>
<Engagements
enterpriseId={enterpriseId}
/>
</Tab>
<Tab
eventKey="Progress"
title={intl.formatMessage({
id: 'advance.analytics.progress.tab.title.heading',
defaultMessage: 'Progress',
description: 'Title for the progress tab in advance analytics.',
})}
>
<Progress
enterpriseId={enterpriseId}
/>
</Tab>
<Tab
eventKey="Outcomes"
title={intl.formatMessage({
id: 'advance.analytics.outcomes.tab.title.heading',
defaultMessage: 'Outcomes',
description: 'Title for the outcomes tab in advance analytics.',
})}
>
<Outcomes
enterpriseId={enterpriseId}
/>
</Tab>
</Tabs>
</div>
</AnalyticsFiltersContext.Provider>
<Outcomes
enterpriseId={enterpriseId}
/>
</Tab>
</Tabs>
</div>

</Stack>
</>
Expand Down
4 changes: 2 additions & 2 deletions src/components/AdvanceAnalyticsV2.0/data/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ export const advanceAnalyticsQueryKeys = {
leaderboardTable: (enterpriseUUID, requestOptions) => (
generateKey(analyticsDataTableKeys.leaderboard, enterpriseUUID, requestOptions)
),
aggregates: (enterpriseUUID, requestOptions) => (
generateKey('aggregates', enterpriseUUID, requestOptions)
aggregates: (enterpriseUUID, requestOptions, tabKey) => (
generateKey(`aggregates-${tabKey}`, enterpriseUUID, requestOptions)
),
};

Expand Down
5 changes: 3 additions & 2 deletions src/components/AdvanceAnalyticsV2.0/data/constants.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,9 @@ describe('advanceAnalyticsQueryKeys', () => {
});

it('should return correct key for aggregates', () => {
const result = advanceAnalyticsQueryKeys.aggregates(enterpriseId, requestOptions);
expect(result).toEqual(['admin-analytics', 'aggregates', 'ent-001', 'us-east', 'alpha']);
const tabKey = 'engagements';
const result = advanceAnalyticsQueryKeys.aggregates(enterpriseId, requestOptions, tabKey);
expect(result).toEqual(['admin-analytics', 'aggregates-engagements', 'ent-001', 'us-east', 'alpha']);
});
});

Expand Down
36 changes: 36 additions & 0 deletions src/components/AdvanceAnalyticsV2.0/data/hooks.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,42 @@ describe('useEnterpriseAnalyticsAggregatesData', () => {
expect(result.current.isFetching).toBe(false);
});

expect(EnterpriseDataApiService.fetchAdminAggregatesData).toHaveBeenCalledWith(
TEST_ENTERPRISE_ID,
requestOptions,
);
});
it('includes groupUUID in aggregates API request when provided', async () => {
const startDate = '2021-01-01';
const endDate = '2021-12-31';
const groupUUID = 'group-1234';

const requestOptions = {
startDate,
endDate,
groupUUID,
};

const queryParams = new URLSearchParams(snakeCaseObject(requestOptions));
const baseURL = `${EnterpriseDataApiService.enterpriseAdminAnalyticsV2BaseUrl}${TEST_ENTERPRISE_ID}`;
const analyticsURL = `${baseURL}/aggregates/stats?${queryParams.toString()}`;

axiosMock.onGet(analyticsURL).reply(200, {});

const { result } = renderHook(
() => useEnterpriseAnalyticsAggregatesData({
enterpriseCustomerUUID: TEST_ENTERPRISE_ID,
startDate,
endDate,
groupUUID,
}),
{ wrapper },
);

await waitFor(() => {
expect(result.current.isFetching).toBe(false);
});

expect(EnterpriseDataApiService.fetchAdminAggregatesData).toHaveBeenCalledWith(
TEST_ENTERPRISE_ID,
requestOptions,
Expand Down
12 changes: 10 additions & 2 deletions src/components/AdvanceAnalyticsV2.0/data/hooks/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { useMemo } from 'react';
import { useQuery } from '@tanstack/react-query';

import { advanceAnalyticsQueryKeys, COURSE_TYPES, ALL_COURSES } from '../constants';
import {
advanceAnalyticsQueryKeys, COURSE_TYPES, ALL_COURSES,
} from '../constants';

import EnterpriseDataApiService from '../../../../data/services/EnterpriseDataApiService';

Expand Down Expand Up @@ -81,8 +83,10 @@ export const usePaginatedData = (data) => useMemo(() => {

export const useEnterpriseAnalyticsAggregatesData = ({
enterpriseCustomerUUID,
tabKey,
startDate,
endDate,
groupUUID = undefined,
courseType = undefined,
course = undefined,
budgetUUID = undefined,
Expand All @@ -93,6 +97,10 @@ export const useEnterpriseAnalyticsAggregatesData = ({
endDate,
};

if (groupUUID) {
requestOptions.groupUUID = groupUUID;
}

if (courseType && courseType !== COURSE_TYPES.ALL_COURSE_TYPES) {
requestOptions.courseType = courseType;
}
Expand All @@ -106,7 +114,7 @@ export const useEnterpriseAnalyticsAggregatesData = ({
}

return useQuery({
queryKey: advanceAnalyticsQueryKeys.aggregates(enterpriseCustomerUUID, requestOptions),
queryKey: advanceAnalyticsQueryKeys.aggregates(enterpriseCustomerUUID, requestOptions, tabKey),
queryFn: () => EnterpriseDataApiService.fetchAdminAggregatesData(
enterpriseCustomerUUID,
requestOptions,
Expand Down
Loading