diff --git a/apps/api/src/instrument-records/instrument-records.service.ts b/apps/api/src/instrument-records/instrument-records.service.ts index 2017e3dd1..3c415247e 100644 --- a/apps/api/src/instrument-records/instrument-records.service.ts +++ b/apps/api/src/instrument-records/instrument-records.service.ts @@ -38,6 +38,14 @@ type ExpandDataType = success: false; }; +function afterFirstDollar(str: string) { + if (!str) return str; + const match = /\$(.*)/.exec(str); + if (!match) return str; + if (!match[1]) return str; + return match[1]; +} + @Injectable() export class InstrumentRecordsService { constructor( @@ -180,7 +188,7 @@ export class InstrumentRecordsService { sessionId: record.session.id, sessionType: record.session.type, subjectAge: record.subject.dateOfBirth ? yearsPassed(record.subject.dateOfBirth) : null, - subjectId: record.subject.id, + subjectId: afterFirstDollar(record.subject.id), subjectSex: record.subject.sex, timestamp: record.date.toISOString(), value: measureValue @@ -203,7 +211,7 @@ export class InstrumentRecordsService { sessionId: record.session.id, sessionType: record.session.type, subjectAge: record.subject.dateOfBirth ? yearsPassed(record.subject.dateOfBirth) : null, - subjectId: record.subject.id, + subjectId: afterFirstDollar(record.subject.id), subjectSex: record.subject.sex, timestamp: record.date.toISOString(), value: arrayEntry.measureValue diff --git a/apps/web/src/hooks/__tests__/useInstrumentVisualization.test.ts b/apps/web/src/hooks/__tests__/useInstrumentVisualization.test.ts index 52a6ed7f5..c86bf8190 100644 --- a/apps/web/src/hooks/__tests__/useInstrumentVisualization.test.ts +++ b/apps/web/src/hooks/__tests__/useInstrumentVisualization.test.ts @@ -72,7 +72,9 @@ describe('useInstrumentVisualization', () => { const [filename, getContentFn] = mockDownloadFn.mock.calls[0] ?? []; expect(filename).toContain('.csv'); const csvContents = getContentFn(); - expect(csvContents).toMatch(`subjectId,Date,someValue\r\ntestId,${toBasicISOString(FIXED_TEST_DATE)},abc`); + expect(csvContents).toMatch( + `GroupID,subjectId,Date,someValue\r\ntestGroupId,testId,${toBasicISOString(FIXED_TEST_DATE)},abc` + ); }); }); describe('TSV', () => { @@ -85,7 +87,9 @@ describe('useInstrumentVisualization', () => { const [filename, getContentFn] = mockDownloadFn.mock.calls[0] ?? []; expect(filename).toContain('.tsv'); const tsvContents = getContentFn(); - expect(tsvContents).toMatch(`subjectId\tDate\tsomeValue\r\ntestId\t${toBasicISOString(FIXED_TEST_DATE)}\tabc`); + expect(tsvContents).toMatch( + `GroupID\tsubjectId\tDate\tsomeValue\r\ntestGroupId\ttestId\t${toBasicISOString(FIXED_TEST_DATE)}\tabc` + ); }); }); describe('CSV Long', () => { @@ -100,7 +104,7 @@ describe('useInstrumentVisualization', () => { expect(filename).toContain('.csv'); const csvLongContents = getContentFn(); expect(csvLongContents).toMatch( - `Date,SubjectID,Value,Variable\r\n${toBasicISOString(FIXED_TEST_DATE)},testId,abc,someValue` + `GroupID,Date,SubjectID,Value,Variable\r\ntestGroupId,${toBasicISOString(FIXED_TEST_DATE)},testId,abc,someValue` ); }); }); @@ -116,7 +120,7 @@ describe('useInstrumentVisualization', () => { expect(filename).toMatch('.tsv'); const tsvLongContents = getContentFn(); expect(tsvLongContents).toMatch( - `Date\tSubjectID\tValue\tVariable\r\n${toBasicISOString(FIXED_TEST_DATE)}\ttestId\tabc\tsomeValue` + `GroupID\tDate\tSubjectID\tValue\tVariable\r\ntestGroupId\t${toBasicISOString(FIXED_TEST_DATE)}\ttestId\tabc\tsomeValue` ); }); }); diff --git a/apps/web/src/hooks/useInstrumentVisualization.ts b/apps/web/src/hooks/useInstrumentVisualization.ts index d59d5f4c2..097606668 100644 --- a/apps/web/src/hooks/useInstrumentVisualization.ts +++ b/apps/web/src/hooks/useInstrumentVisualization.ts @@ -36,6 +36,14 @@ export function useInstrumentVisualization({ params }: UseInstrumentVisualizatio const [minDate, setMinDate] = useState(null); const [instrumentId, setInstrumentId] = useState(null); + function afterFirstDollar(str: string) { + if (!str) return str; + const match = /\$(.*)/.exec(str); + if (!match) return str; + if (!match[1]) return str; + return match[1]; + } + const instrument = useInstrument(instrumentId) as AnyUnilingualScalarInstrument; const instrumentInfoQuery = useInstrumentInfoQuery({ @@ -70,7 +78,10 @@ export function useInstrumentVisualization({ params }: UseInstrumentVisualizatio const makeWideRows = () => { const columnNames = Object.keys(exportRecords[0]!); return exportRecords.map((item) => { - const obj: { [key: string]: any } = { subjectId: params.subjectId }; + const obj: { [key: string]: any } = { + GroupID: currentGroup ? currentGroup.id : 'root', + subjectId: afterFirstDollar(params.subjectId) + }; for (const key of columnNames) { const val = item[key]; if (key === '__date__') { @@ -99,8 +110,10 @@ export function useInstrumentVisualization({ params }: UseInstrumentVisualizatio objVal.forEach((arrayItem) => { Object.entries(arrayItem as object).forEach(([arrKey, arrItem]) => { longRecord.push({ + GroupID: currentGroup ? currentGroup.id : 'root', + // eslint-disable-next-line perfectionist/sort-objects Date: toBasicISOString(date), - SubjectID: params.subjectId, + SubjectID: afterFirstDollar(params.subjectId), Variable: `${objKey}-${arrKey}`, // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, perfectionist/sort-objects Value: arrItem @@ -109,8 +122,10 @@ export function useInstrumentVisualization({ params }: UseInstrumentVisualizatio }); } else { longRecord.push({ + GroupID: currentGroup ? currentGroup.id : 'root', + // eslint-disable-next-line perfectionist/sort-objects Date: toBasicISOString(date), - SubjectID: params.subjectId, + SubjectID: afterFirstDollar(params.subjectId), Value: objVal, Variable: objKey });