Skip to content

Commit

Permalink
ASAP-507 Engagement CSV Export (#4357)
Browse files Browse the repository at this point in the history
* ASAP-507 Engagement CSV Export

* fix lint
  • Loading branch information
gabiayako authored Aug 26, 2024
1 parent f4ef1e9 commit 2344489
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 1 deletion.
21 changes: 21 additions & 0 deletions apps/crn-frontend/src/analytics/engagement/Engagement.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import { createCsvFileStream } from '@asap-hub/frontend-utils';
import {
engagementInitialSortingDirection,
EngagementResponse,
EngagementSortingDirection,
SortEngagement,
} from '@asap-hub/model';
import { AnalyticsEngagementPageBody } from '@asap-hub/react-components';
import { useState } from 'react';
import { format } from 'date-fns';

import { usePagination, usePaginationParams, useSearch } from '../../hooks';
import { useAnalyticsAlgolia } from '../../hooks/algolia';
import { algoliaResultsToStream } from '../utils/export';
import { useAnalyticsEngagement } from './state';
import { getEngagement } from './api';
import { engagementToCSV } from './export';

const Engagement = () => {
const { currentPage, pageSize } = usePaginationParams();
Expand All @@ -28,6 +34,20 @@ const Engagement = () => {
});

const { numberOfPages, renderPageHref } = usePagination(total, pageSize);

const exportResults = () =>
algoliaResultsToStream<EngagementResponse>(
createCsvFileStream(`engagement_${format(new Date(), 'MMddyy')}.csv`, {
header: true,
}),
(paginationParams) =>
getEngagement(client, {
tags,
...paginationParams,
}),
engagementToCSV,
);

return (
<AnalyticsEngagementPageBody
tags={tags}
Expand All @@ -44,6 +64,7 @@ const Engagement = () => {
}));
}}
data={data}
exportResults={exportResults}
sort={sort}
setSort={setSort}
sortingDirection={sortingDirection}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { AlgoliaSearchClient, EMPTY_ALGOLIA_RESPONSE } from '@asap-hub/algolia';
import { mockConsoleError } from '@asap-hub/dom-test-utils';
import { createCsvFileStream } from '@asap-hub/frontend-utils';
import { ListEngagementAlgoliaResponse } from '@asap-hub/model';
import { analytics } from '@asap-hub/routing';
import { render, screen, waitFor, within } from '@testing-library/react';
Expand All @@ -9,10 +10,10 @@ import { MemoryRouter, Route } from 'react-router-dom';
import { RecoilRoot } from 'recoil';

import { Auth0Provider, WhenReady } from '../../../auth/test-utils';
import { useAnalyticsAlgolia } from '../../../hooks/algolia';
import { getEngagement } from '../api';
import Engagement from '../Engagement';
import { analyticsEngagementState } from '../state';
import { useAnalyticsAlgolia } from '../../../hooks/algolia';

jest.mock('../api');
mockConsoleError();
Expand All @@ -28,6 +29,16 @@ jest.mock('../../../hooks/algolia', () => ({
useAnalyticsAlgolia: jest.fn(),
}));

jest.mock('@asap-hub/frontend-utils', () => {
const original = jest.requireActual('@asap-hub/frontend-utils');
return {
...original,
createCsvFileStream: jest
.fn()
.mockImplementation(() => ({ write: jest.fn(), end: jest.fn() })),
};
});

afterEach(() => {
jest.clearAllMocks();
});
Expand All @@ -48,6 +59,10 @@ const mockUseAnalyticsAlgolia = useAnalyticsAlgolia as jest.MockedFunction<
typeof useAnalyticsAlgolia
>;

const mockCreateCsvFileStream = createCsvFileStream as jest.MockedFunction<
typeof createCsvFileStream
>;

const data: ListEngagementAlgoliaResponse = {
total: 1,
items: [
Expand Down Expand Up @@ -148,6 +163,16 @@ describe('Engagement', () => {
});
});

it('exports csv when user clicks on CSV button', async () => {
await renderPage(analytics({}).engagement({}).$);

userEvent.click(screen.getByText(/csv/i));
expect(mockCreateCsvFileStream).toHaveBeenCalledWith(
expect.stringMatching(/engagement_\d+\.csv/),
expect.anything(),
);
});

describe('search', () => {
const getSearchBox = () => {
const searchContainer = screen.getByRole('search') as HTMLElement;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { EngagementDataObject } from '@asap-hub/model';
import { engagementToCSV } from '../export';

describe('engagementToCSV', () => {
const data: EngagementDataObject = {
id: '1',
name: 'Test Team',
inactiveSince: null,
memberCount: 1,
eventCount: 4,
totalSpeakerCount: 3,
uniqueAllRolesCount: 3,
uniqueAllRolesCountPercentage: 100,
uniqueKeyPersonnelCount: 2,
uniqueKeyPersonnelCountPercentage: 67,
};

it('exports engagement data', () => {
expect(engagementToCSV(data)).toEqual({
Team: 'Test Team',
'Team Status': 'Active',
'Inactive Since': '',
Members: 1,
Events: 4,
'Total Speakers': 3,
'Unique Speakers (All Roles): Value': 3,
'Unique Speakers (All Roles): Percentage': '100%',
'Unique Speakers (Key Personnel): Value': 2,
'Unique Speakers (Key Personnel): Percentage': '67%',
});
});
});
14 changes: 14 additions & 0 deletions apps/crn-frontend/src/analytics/engagement/export.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { EngagementDataObject } from '@asap-hub/model';

export const engagementToCSV = (data: EngagementDataObject) => ({
Team: data.name,
'Team Status': data.inactiveSince ? 'Inactive' : 'Active',
'Inactive Since': data.inactiveSince ? data.inactiveSince.split('T')[0] : '',
Members: data.memberCount,
Events: data.eventCount,
'Total Speakers': data.totalSpeakerCount,
'Unique Speakers (All Roles): Value': data.uniqueAllRolesCount,
'Unique Speakers (All Roles): Percentage': `${data.uniqueAllRolesCountPercentage}%`,
'Unique Speakers (Key Personnel): Value': data.uniqueKeyPersonnelCount,
'Unique Speakers (Key Personnel): Percentage': `${data.uniqueKeyPersonnelCountPercentage}%`,
});
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ type AnalyticsEngagementPageBodyProps = ComponentProps<typeof PageControls> & {
setSortingDirection: React.Dispatch<
React.SetStateAction<EngagementSortingDirection>
>;
exportResults: () => Promise<void>;
};
const AnalyticsEngagementPageBody: React.FC<
AnalyticsEngagementPageBodyProps
> = ({
data,
exportResults,
tags,
setTags,
loadTags,
Expand All @@ -60,6 +62,7 @@ const AnalyticsEngagementPageBody: React.FC<
tags={tags}
loadTags={loadTags}
setTags={setTags}
exportResults={exportResults}
/>
<EngagementTable
data={data}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ describe('AnalyticsEngagementPageBody', () => {
numberOfPages: 1,
currentPageIndex: 0,
renderPageHref: () => '',
exportResults: () => Promise.resolve(),
sort: 'team_asc',
setSort: jest.fn(),
sortingDirection: engagementInitialSortingDirection,
Expand Down

0 comments on commit 2344489

Please sign in to comment.