Skip to content

Commit 2aa4ee1

Browse files
authored
Merge pull request #1238 from david-roper/add-username-to-export
Refactors of useFindSessionQuery, useEffect, and nullable subject in $Session schema
2 parents adf6df7 + 7e71a32 commit 2aa4ee1

File tree

9 files changed

+44
-84
lines changed

9 files changed

+44
-84
lines changed

apps/api/src/sessions/sessions.controller.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { CurrentUser } from '@douglasneuroinformatics/libnest';
22
import { Body, Controller, Get, Param, Post, Query } from '@nestjs/common';
33
import { ApiOperation } from '@nestjs/swagger';
4+
import type { SessionWithUser } from '@opendatacapture/schemas/session';
45
import type { Session } from '@prisma/client';
56

67
import type { AppAbility } from '@/auth/auth.types';
78
import { RouteAccess } from '@/core/decorators/route-access.decorator';
89

910
import { CreateSessionDto } from './dto/create-session.dto';
1011
import { SessionsService } from './sessions.service';
11-
import type { SessionWithUser } from '@opendatacapture/schemas/session';
1212

1313
@Controller('sessions')
1414
export class SessionsController {

apps/api/src/sessions/sessions.service.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ export class SessionsService {
4646
let group: Group | null = null;
4747
if (groupId && !subject.groupIds.includes(groupId)) {
4848
group = await this.groupsService.findById(groupId);
49-
await this.subjectsService.addGroupForSubject(subject.id, group.id);
49+
if (group) {
50+
await this.subjectsService.addGroupForSubject(subject.id, group.id);
51+
}
5052
}
5153

5254
const { id } = await this.sessionModel.create({
@@ -97,12 +99,12 @@ export class SessionsService {
9799
async findAllIncludeUsernames(groupId?: string, { ability }: EntityOperationOptions = {}) {
98100
const sessionsWithUsers = await this.sessionModel.findMany({
99101
include: {
102+
subject: true,
100103
user: {
101104
select: {
102105
username: true
103106
}
104-
},
105-
subject: true
107+
}
106108
},
107109
where: {
108110
AND: [accessibleQuery(ability, 'read', 'Session'), { groupId }]

apps/web/src/components/Sidebar/Sidebar.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ export const Sidebar = () => {
8888
>
8989
<h5 className="text-sm font-medium">{t('common.sessionInProgress')}</h5>
9090
<hr className="my-1.5 h-[1px] border-none bg-slate-700" />
91-
{isSubjectWithPersonalInfo(currentSession.subject) ? (
91+
{isSubjectWithPersonalInfo(currentSession.subject!) ? (
9292
<div data-testid="current-session-info">
9393
<p>{`${t('core.fullName')}: ${currentSession.subject.firstName} ${currentSession.subject.lastName}`}</p>
9494
<p>
@@ -100,7 +100,7 @@ export const Sidebar = () => {
100100
</div>
101101
) : (
102102
<div data-testid="current-session-info">
103-
<p>ID: {removeSubjectIdScope(currentSession.subject.id)}</p>
103+
<p>ID: {removeSubjectIdScope(currentSession.subject!.id)}</p>
104104
</div>
105105
)}
106106
</motion.div>

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

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,15 @@ const mockInstrumentRecords = {
3838
]
3939
};
4040

41-
const mockSession = {
42-
userId: '111'
43-
};
44-
45-
const mockUser = {
46-
id: '111',
47-
username: 'testusername'
41+
const mockSessionWithUsername = {
42+
data: [
43+
{
44+
id: '123',
45+
user: {
46+
username: 'testusername'
47+
}
48+
}
49+
]
4850
};
4951

5052
vi.mock('@/hooks/useInstrument', () => ({
@@ -73,12 +75,8 @@ vi.mock('@/hooks/useInstrumentRecords', () => ({
7375
useInstrumentRecords: () => mockInstrumentRecords
7476
}));
7577

76-
vi.mock('@/hooks/useFindSession', () => ({
77-
sessionInfo: () => Promise.resolve(mockSession)
78-
}));
79-
80-
vi.mock('@/hooks/useFindUser', () => ({
81-
userInfo: () => Promise.resolve(mockUser)
78+
vi.mock('@/hooks/useFindSessionQuery', () => ({
79+
useFindSessionQuery: () => mockSessionWithUsername
8280
}));
8381

8482
describe('useInstrumentVisualization', () => {

apps/web/src/hooks/useFindSessionQuery.ts

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { $SessionWithUser } from '@opendatacapture/schemas/session';
2-
import type { Session, SessionWithUserQueryParams } from '@opendatacapture/schemas/session';
2+
import type { SessionWithUserQueryParams } from '@opendatacapture/schemas/session';
33
import { useQuery } from '@tanstack/react-query';
44
import axios from 'axios';
55

@@ -14,19 +14,6 @@ type UseSessionOptions = {
1414
params: SessionWithUserQueryParams;
1515
};
1616

17-
export const sessionInfo = async (sessionId: string): Promise<Session> => {
18-
try {
19-
const response = await axios.get(`/v1/sessions/${encodeURIComponent(sessionId)}`);
20-
if (!response.data) {
21-
throw new Error('Session data does not exist');
22-
}
23-
return response.data as Session;
24-
} catch (error) {
25-
console.error('Error fetching session:', error);
26-
throw error;
27-
}
28-
};
29-
3017
export const useFindSessionQuery = (
3118
{ enabled, params }: UseSessionOptions = {
3219
enabled: true,
@@ -36,7 +23,7 @@ export const useFindSessionQuery = (
3623
return useQuery({
3724
enabled,
3825
queryFn: async () => {
39-
const response = await axios.get('/v1/sessions/', {
26+
const response = await axios.get('/v1/sessions', {
4027
params
4128
});
4229
return $SessionWithUser.array().parseAsync(response.data);

apps/web/src/hooks/useFindUser.ts

Lines changed: 0 additions & 14 deletions
This file was deleted.

apps/web/src/hooks/useInstrumentVisualization.ts

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ import { useInstrumentRecords } from '@/hooks/useInstrumentRecords';
1313
import { useAppStore } from '@/store';
1414
import { downloadSubjectTableExcel } from '@/utils/excel';
1515

16-
import { sessionInfo, useFindSessionQuery } from './useFindSessionQuery';
17-
import { userInfo } from './useFindUser';
16+
import { useFindSessionQuery } from './useFindSessionQuery';
1817

1918
type InstrumentVisualizationRecord = {
2019
[key: string]: unknown;
@@ -57,12 +56,12 @@ export function useInstrumentVisualization({ params }: UseInstrumentVisualizatio
5756
}
5857
});
5958

60-
// const sessionsUsernameQuery = useFindSessionQuery({
61-
// enabled: instrumentId !== null,
62-
// params: {
63-
// groupId: currentGroup?.id
64-
// }
65-
// });
59+
const sessionsUsernameQuery = useFindSessionQuery({
60+
enabled: instrumentId !== null,
61+
params: {
62+
groupId: currentGroup?.id
63+
}
64+
});
6665

6766
// Create a new sessionsUsernameQuery which uses the useFindSessionQuery hook
6867
// have use a different return type with
@@ -219,27 +218,18 @@ export function useInstrumentVisualization({ params }: UseInstrumentVisualizatio
219218
};
220219

221220
useEffect(() => {
222-
let cancelled = false;
223-
const fetchRecords = async () => {
221+
const fetchRecords = () => {
224222
try {
225-
if (recordsQuery.data) {
223+
const sessions = sessionsUsernameQuery.data;
224+
if (recordsQuery.data && sessions) {
226225
// Fetch all sessions in parallel
227-
const sessionPromises = recordsQuery.data.map((record) => sessionInfo(record.sessionId));
228-
const sessions = await Promise.all(sessionPromises);
229-
230-
// Extract unique userIds and fetch users in parallel
231-
const userIds = [...new Set(sessions.filter((s) => s?.userId).map((s) => s.userId))];
232-
233-
//assume userId exists in userId set as we already filtered out the non-existing userIds
234-
const userPromises = userIds.map((userId) => userInfo(userId!).catch(() => null));
235-
const users = await Promise.all(userPromises);
236-
const userMap = new Map(users.filter((u) => u).map((u) => [u!.id, u!.username]));
237226

238227
// Build records with looked-up data
239-
const records: InstrumentVisualizationRecord[] = recordsQuery.data.map((record, i) => {
228+
const records: InstrumentVisualizationRecord[] = recordsQuery.data.map((record) => {
240229
const props = record.data && typeof record.data === 'object' ? record.data : {};
241-
const session = sessions[i];
242-
const username = session?.userId ? (userMap.get(session.userId) ?? 'N/A') : 'N/A';
230+
const usersSession = sessions.find((s) => s.id === record.sessionId);
231+
232+
const username = usersSession?.user?.username ?? 'N/A';
243233

244234
return {
245235
__date__: record.date,
@@ -250,9 +240,7 @@ export function useInstrumentVisualization({ params }: UseInstrumentVisualizatio
250240
};
251241
});
252242

253-
if (!cancelled) {
254-
setRecords(records);
255-
}
243+
setRecords(records);
256244
}
257245
} catch (error) {
258246
console.error('Error occurred: ', error);
@@ -266,9 +254,6 @@ export function useInstrumentVisualization({ params }: UseInstrumentVisualizatio
266254
}
267255
};
268256
void fetchRecords();
269-
return () => {
270-
cancelled = true;
271-
};
272257
}, [recordsQuery.data]);
273258

274259
const instrumentOptions: { [key: string]: string } = useMemo(() => {

apps/web/src/routes/_app/instruments/render/$id.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ const RouteComponent = () => {
4242
groupId: currentGroup?.id,
4343
instrumentId,
4444
sessionId: currentSession!.id,
45-
subjectId: currentSession!.subject.id
45+
subjectId: currentSession!.subject!.id
4646
} satisfies CreateInstrumentRecordData);
4747
notifications.addNotification({ type: 'success' });
4848
};
@@ -61,7 +61,7 @@ const RouteComponent = () => {
6161
<div className="grow">
6262
<InstrumentRenderer
6363
className="mx-auto max-w-3xl"
64-
subject={currentSession?.subject}
64+
subject={currentSession?.subject ?? undefined}
6565
target={instrumentBundleQuery.data}
6666
onSubmit={handleSubmit}
6767
/>

packages/schemas/src/session/session.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export type Session = z.infer<typeof $Session>;
1010
export const $Session = $BaseModel.extend({
1111
date: z.coerce.date(),
1212
groupId: z.string().nullable(),
13-
subject: $Subject,
13+
subject: $Subject.nullable(),
1414
subjectId: z.string(),
1515
type: $SessionType,
1616
userId: z.string().nullish()
@@ -27,9 +27,11 @@ export const $CreateSessionData = z.object({
2727

2828
export type SessionWithUser = z.infer<typeof $SessionWithUser>;
2929
export const $SessionWithUser = $Session.extend({
30-
user: z.object({
31-
username: z.string().nullish()
32-
})
30+
user: z
31+
.object({
32+
username: z.string().nullish()
33+
})
34+
.nullable()
3335
});
3436

3537
export type SessionWithUserQueryParams = {

0 commit comments

Comments
 (0)