Skip to content

Commit 47b7479

Browse files
authored
Merge pull request #1218 from david-roper/add-group-column
Add excel options to subject table download
2 parents bfe3f6b + c7c5af6 commit 47b7479

File tree

5 files changed

+77
-3
lines changed

5 files changed

+77
-3
lines changed

apps/web/src/hooks/__tests__/useInstrumentVisualization.test.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ const mockStore = {
2020

2121
const mockDownloadFn = vi.fn();
2222

23+
const mockExcelDownloadFn = vi.hoisted(() => vi.fn());
24+
2325
const mockInfoQuery = {
2426
data: []
2527
};
@@ -53,6 +55,10 @@ vi.mock('@/hooks/useInstrumentInfoQuery', () => ({
5355
useInstrumentInfoQuery: () => mockInfoQuery
5456
}));
5557

58+
vi.mock('@/utils/excel', () => ({
59+
downloadSubjectTableExcel: mockExcelDownloadFn
60+
}));
61+
5662
vi.mock('@/hooks/useInstrumentRecords', () => ({
5763
useInstrumentRecords: () => mockInstrumentRecords
5864
}));
@@ -124,6 +130,51 @@ describe('useInstrumentVisualization', () => {
124130
);
125131
});
126132
});
133+
describe('Excel', () => {
134+
it('Should download', () => {
135+
const { result } = renderHook(() => useInstrumentVisualization({ params: { subjectId: 'testId' } }));
136+
const { dl, records } = result.current;
137+
act(() => dl('Excel'));
138+
expect(records).toBeDefined();
139+
expect(mockExcelDownloadFn).toHaveBeenCalledTimes(1);
140+
const [filename, getContentFn] = mockExcelDownloadFn.mock.calls[0] ?? [];
141+
expect(filename).toMatch('.xlsx');
142+
const excelContents = getContentFn;
143+
144+
expect(excelContents).toEqual([
145+
{
146+
GroupID: 'testGroupId',
147+
subjectId: 'testId',
148+
// eslint-disable-next-line perfectionist/sort-objects
149+
Date: '2025-04-30',
150+
someValue: 'abc'
151+
}
152+
]);
153+
});
154+
});
155+
describe('Excel Long', () => {
156+
it('Should download', () => {
157+
const { result } = renderHook(() => useInstrumentVisualization({ params: { subjectId: 'testId' } }));
158+
const { dl, records } = result.current;
159+
act(() => dl('Excel Long'));
160+
expect(records).toBeDefined();
161+
expect(mockExcelDownloadFn).toHaveBeenCalledTimes(1);
162+
163+
const [filename, getContentFn] = mockExcelDownloadFn.mock.calls[0] ?? [];
164+
expect(filename).toMatch('.xlsx');
165+
const excelContents = getContentFn;
166+
167+
expect(excelContents).toEqual([
168+
{
169+
Date: '2025-04-30',
170+
GroupID: 'testGroupId',
171+
SubjectID: 'testId',
172+
Value: 'abc',
173+
Variable: 'someValue'
174+
}
175+
]);
176+
});
177+
});
127178
describe('JSON', () => {
128179
it('Should download', async () => {
129180
const { result } = renderHook(() => useInstrumentVisualization({ params: { subjectId: 'testId' } }));

apps/web/src/hooks/useInstrumentVisualization.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { useInstrument } from '@/hooks/useInstrument';
1111
import { useInstrumentInfoQuery } from '@/hooks/useInstrumentInfoQuery';
1212
import { useInstrumentRecords } from '@/hooks/useInstrumentRecords';
1313
import { useAppStore } from '@/store';
14+
import { downloadSubjectTableExcel } from '@/utils/excel';
1415

1516
type InstrumentVisualizationRecord = {
1617
[key: string]: unknown;
@@ -53,7 +54,7 @@ export function useInstrumentVisualization({ params }: UseInstrumentVisualizatio
5354
}
5455
});
5556

56-
const dl = (option: 'CSV' | 'CSV Long' | 'JSON' | 'TSV' | 'TSV Long') => {
57+
const dl = (option: 'CSV' | 'CSV Long' | 'Excel' | 'Excel Long' | 'JSON' | 'TSV' | 'TSV Long') => {
5758
if (!instrument) {
5859
notifications.addNotification({ message: t('errors.noInstrumentSelected'), type: 'error' });
5960
return;
@@ -157,6 +158,16 @@ export function useInstrumentVisualization({ params }: UseInstrumentVisualizatio
157158
});
158159
break;
159160
}
161+
case 'Excel': {
162+
const rows = makeWideRows();
163+
downloadSubjectTableExcel(`${baseFilename}.xlsx`, rows);
164+
break;
165+
}
166+
case 'Excel Long': {
167+
const rows = makeLongRows();
168+
downloadSubjectTableExcel(`${baseFilename}.xlsx`, rows);
169+
break;
170+
}
160171
case 'JSON': {
161172
exportRecords.map((item) => {
162173
item.subjectID = params.subjectId;

apps/web/src/routes/_app/datahub/$subjectId/table.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const RouteComponent = () => {
3838
widthFull
3939
data-spotlight-type="export-data-dropdown"
4040
disabled={!instrumentId}
41-
options={['TSV', 'TSV Long', 'JSON', 'CSV', 'CSV Long']}
41+
options={['TSV', 'TSV Long', 'JSON', 'CSV', 'CSV Long', 'Excel', 'Excel Long']}
4242
title={t('core.download')}
4343
triggerClassName="min-w-32"
4444
onSelection={dl}
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
import { describe, expect, it } from 'vitest';
22

3-
import { downloadExcel } from '../excel';
3+
import { downloadExcel, downloadSubjectTableExcel } from '../excel';
44

55
describe('downloadExcel', () => {
66
it('should be defined', () => {
77
expect(downloadExcel).toBeDefined();
88
});
99
});
10+
11+
describe('downloadSujectTableExcel', () => {
12+
it('should be defined', () => {
13+
expect(downloadSubjectTableExcel).toBeDefined();
14+
});
15+
});

apps/web/src/utils/excel.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,9 @@ export function downloadExcel(filename: string, recordsExport: InstrumentRecords
66
utils.book_append_sheet(workbook, utils.json_to_sheet(recordsExport), 'ULTRA_LONG');
77
writeFileXLSX(workbook, filename);
88
}
9+
10+
export function downloadSubjectTableExcel(filename: string, records: { [key: string]: any }[]) {
11+
const workbook = utils.book_new();
12+
utils.book_append_sheet(workbook, utils.json_to_sheet(records), 'ULTRA_LONG');
13+
writeFileXLSX(workbook, filename);
14+
}

0 commit comments

Comments
 (0)