Skip to content

Commit 7637c11

Browse files
authored
Merge pull request #281 from bcgsc/release/v6.16.0
Release/v6.16.0
2 parents a9ea350 + a282b62 commit 7637c11

File tree

21 files changed

+404
-303
lines changed

21 files changed

+404
-303
lines changed

app/common.d.ts

Lines changed: 17 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -104,36 +104,15 @@ type GeneType = {
104104
tumourSuppressor: boolean;
105105
};
106106

107-
type KbMatchVariantType = {
108-
gene: GeneType;
109-
transcript: string;
110-
proteinChange: string;
111-
chromosome: string;
112-
startPosition: number;
113-
endPosition: number;
114-
refSeq: string;
115-
altSeq: string;
116-
zygosity: string;
117-
tumourAltCount: number;
118-
tumourRefCount: number;
119-
tumourDepth: number;
120-
rnaAltCount: number;
121-
rnaRefCount: number;
122-
rnaDepth: number;
123-
normalAltCount: number;
124-
normalRefCount: number;
125-
normalDepth: number;
126-
hgvsProtein: string;
127-
hgvsCds: string;
128-
hgvsGenomic: string;
129-
ncbiBuild: string;
130-
germline: boolean;
131-
tumourAltCopies: number;
132-
tumourRefCopies: number;
133-
library: string;
134-
} & RecordDefaults;
107+
type VariantType = keyof VariantMap;
135108

136-
type KbMatchType = {
109+
type VariantMap = {
110+
'cnv': CopyNumberType
111+
'mut': SmallMutationType
112+
'sv': StructuralVariantType
113+
};
114+
115+
type KbMatchType<T extends VariantType = VariantType> = {
137116
category: string;
138117
approvedTherapy: boolean;
139118
kbVariant: string;
@@ -148,7 +127,7 @@ type KbMatchType = {
148127
iprEvidenceLevel: string;
149128
matchedCancer: boolean;
150129
pmidRef: string;
151-
variantType: string;
130+
variantType: T;
152131
kbVariantId: string;
153132
kbStatementId: string;
154133
kbData: {
@@ -157,7 +136,7 @@ type KbMatchType = {
157136
externalSource: string;
158137
externalStatementId: string;
159138
reviewStatus: string;
160-
variant: KbMatchVariantType;
139+
variant: VariantMap[T];
161140
} & RecordDefaults;
162141

163142
type CopyNumberType = {
@@ -185,8 +164,8 @@ type StructuralVariantType = {
185164
exon1: string | null;
186165
exon2: string | null;
187166
frame: string | null;
188-
gene1: Record<string, unknown> | null;
189-
gene2: Record<string, unknown> | null;
167+
gene1: GeneType | null;
168+
gene2: GeneType | null;
190169
highQuality: boolean;
191170
kbMatches: null | KbMatchType[];
192171
mavis_product_id: number | null;
@@ -202,11 +181,13 @@ type SmallMutationType = {
202181
altSeq: string | null;
203182
chromosome: number | null;
204183
endPosition: number | null;
205-
gene: Record<string, unknown>;
184+
gene: GeneType;
206185
germline: string | null;
207186
hgvsCds: string | null;
187+
hgvsGenomic: string | null;
208188
hgvsProtein: string | null;
209189
kbMatches: KbMatchType[];
190+
library: string | null;
210191
ncbiBuild: string | null;
211192
normalAltCount: number | null;
212193
normalDepth: number | null;
@@ -218,8 +199,10 @@ type SmallMutationType = {
218199
rnaRefCount: number | null;
219200
startPosition: number | null;
220201
transcript: string | null;
202+
tumourAltCopies: number | null;
221203
tumourAltCount: number | null;
222204
tumourDepth: number | null;
205+
tumourRefCopies: number | null;
223206
tumourRefCount: number | null;
224207
zygosity: string | null;
225208
} & RecordDefaults;

app/components/PrintTable/index.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
border-collapse: collapse;
55
margin: 8px;
66

7+
&--full-width {
8+
width: 100%;
9+
}
10+
711
&__header {
812
font-size: 9pt;
913
text-align: left;

app/components/PrintTable/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export type PrintTableProps = {
1515
/* string of fieldNames for columns to be collapsed */
1616
collapseableCols?: string[];
1717
noRowsText?: string;
18+
fullWidth?: boolean;
1819
};
1920

2021
/**
@@ -27,6 +28,7 @@ const PrintTable = ({
2728
order = [],
2829
noRowsText = '',
2930
collapseableCols = null,
31+
fullWidth = false,
3032
}: PrintTableProps): JSX.Element => {
3133
const sortedColDefs = useMemo(() => columnDefs
3234
.filter((col) => (col.headerName && col.hide !== true && col.headerName !== 'Actions'))
@@ -177,7 +179,7 @@ const PrintTable = ({
177179
return (
178180
<div className="table-container">
179181
{Boolean(columnDefs.length) && (
180-
<table className="table">
182+
<table className={`table ${fullWidth ? 'table--full-width' : ''}`}>
181183
<thead className="table__header">
182184
<tr>
183185
{sortedColDefs.map((col) => (

app/services/api/ApiCallSet.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ class ApiCallSet {
1919
this.calls.forEach((controller) => controller.abort());
2020
}
2121

22-
async request(): Promise<RequestReturnType[]> {
22+
async request(settled = false): Promise<PromiseSettledResult<RequestReturnType>[] | RequestReturnType[]> {
23+
if (settled) {
24+
return Promise.allSettled(this.calls.map((call) => call.request()));
25+
}
2326
return Promise.all(this.calls.map((call) => call.request()));
2427
}
2528
}

app/views/AdminView/components/Users/components/AddEditUserDialog/index.tsx

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
import { useForm, Controller } from 'react-hook-form';
1919
import api, { ApiCallSet } from '@/services/api';
2020
import { UserType, GroupType } from '@/common';
21+
import snackbar from '@/services/SnackbarUtils';
2122
import {
2223
ProjectType,
2324
} from '../../../../types';
@@ -124,43 +125,62 @@ const AddEditUserDialog = ({
124125
username,
125126
type,
126127
};
127-
// User Section
128-
const addEditResp = editData
129-
? await api.put(`/user/${editData.ident}`, userReq).request()
130-
: await api.post('/user', userReq).request();
131128

132-
// Project Section
133-
if (dirtyFields.projects) {
134-
const existingProjects = editData.projects.map(({ ident }) => ident);
129+
try {
130+
const addEditResp = editData
131+
? await api.put(`/user/${editData.ident}`, userReq).request()
132+
: await api.post('/user', userReq).request();
135133

136-
const toAddProjs = projects.filter((projectId) => !existingProjects.includes(projectId));
137-
const toRemoveProjs = existingProjects.filter((projectId) => !projects.includes(projectId));
134+
// Project Section
135+
if (dirtyFields.projects && editData) {
136+
const existingProjects = editData.projects.map(({ ident }) => ident);
138137

139-
const callSet = new ApiCallSet([
140-
...toAddProjs.map((projectId) => api.post(`/project/${projectId}/user`, { user: addEditResp.ident }, {})),
141-
...toRemoveProjs.map((projectId) => api.del(`/project/${projectId}/user`, { user: addEditResp.ident }, {})),
142-
]);
143-
await callSet.request();
144-
}
138+
const toAddProjs = projects.filter((projectId) => !existingProjects.includes(projectId));
139+
const toRemoveProjs = existingProjects.filter((projectId) => !projects.includes(projectId));
140+
141+
const callSet = new ApiCallSet([
142+
...toAddProjs.map((projectId) => api.post(`/project/${projectId}/user`, { user: addEditResp.ident }, {})),
143+
...toRemoveProjs.map((projectId) => api.del(`/project/${projectId}/user`, { user: addEditResp.ident }, {})),
144+
]);
145+
try {
146+
await callSet.request();
147+
} catch (e) {
148+
throw { ...e, errorType: 'project' };
149+
}
150+
}
145151

146-
// Groups Section
147-
if (dirtyFields.groups) {
148-
const existingGroups = editData.groups.map(({ ident }) => ident);
152+
// Groups Section
153+
if (dirtyFields.groups && editData) {
154+
const existingGroups = editData.groups.map(({ ident }) => ident);
149155

150-
const toAddGroups = groups.filter((groupId) => !existingGroups.includes(groupId));
151-
const toRemoveGroups = existingGroups.filter((groupId) => !groups.includes(groupId));
156+
const toAddGroups = groups.filter((groupId) => !existingGroups.includes(groupId));
157+
const toRemoveGroups = existingGroups.filter((groupId) => !groups.includes(groupId));
152158

153-
const callSet = new ApiCallSet([
154-
...toAddGroups.map((groupId) => api.post(`/user/group/${groupId}/member`, { user: addEditResp.ident }, {})),
155-
...toRemoveGroups.map((groupId) => api.del(`/user/group/${groupId}/member`, { user: addEditResp.ident }, {})),
156-
]);
157-
await callSet.request();
158-
}
159+
const callSet = new ApiCallSet([
160+
...toAddGroups.map((groupId) => api.post(`/user/group/${groupId}/member`, { user: addEditResp.ident }, {})),
161+
...toRemoveGroups.map((groupId) => api.del(`/user/group/${groupId}/member`, { user: addEditResp.ident }, {})),
162+
]);
163+
try {
164+
await callSet.request();
165+
} catch (e) {
166+
throw { ...e, errorType: 'group' };
167+
}
168+
}
169+
addEditResp.projects = projectOptions.filter(({ ident }) => projects.includes(ident));
170+
addEditResp.groups = groupOptions.filter(({ ident }) => groups.includes(ident));
159171

160-
addEditResp.projects = projectOptions.filter(({ ident }) => projects.includes(ident));
161-
addEditResp.groups = groupOptions.filter(({ ident }) => groups.includes(ident));
162-
onClose(addEditResp);
172+
snackbar.success(`User successfully ${editData ? 'updated' : 'created'}`);
173+
onClose(addEditResp);
174+
} catch (e) {
175+
if (e.errorType) {
176+
snackbar.error(`Error setting ${e.errorType}s related to user`);
177+
} else {
178+
snackbar.error(`Error ${editData ? 'editing' : 'creating'} user`);
179+
}
180+
console.error(e);
181+
}
163182
}
183+
164184
onClose(null);
165185
}, [dirtyFields, editData, onClose, projectOptions, groupOptions]);
166186

app/views/AdminView/components/Users/index.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,11 @@ const Users = (): JSX.Element => {
5656
const newUsers = [...users];
5757
newUsers[userIndex] = newData;
5858
setUsers(newUsers);
59-
snackbar.enqueueSnackbar('User edited');
6059
} else {
6160
setUsers((prevVal) => [...prevVal, newData]);
62-
snackbar.enqueueSnackbar('User added');
6361
}
6462
}
65-
}, [snackbar, users]);
63+
}, [users]);
6664

6765
return (
6866
<div className="admin-table__container">

app/views/PrintView/index.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ const reducer = (state, action) => {
3333
switch (action.type) {
3434
case 'summary':
3535
return { ...state, summary: true };
36-
case 'analyst':
37-
return { ...state, analyst: true };
36+
case 'analyst-comments':
37+
return { ...state, 'analyst-comments': true };
3838
case 'pathway':
3939
return { ...state, pathway: true };
4040
case 'therapeutic':
@@ -46,7 +46,7 @@ const reducer = (state, action) => {
4646
default:
4747
return {
4848
summary: false,
49-
analyst: false,
49+
'analyst-comments': false,
5050
pathway: false,
5151
therapeutic: false,
5252
slides: false,
@@ -63,7 +63,7 @@ const Print = (): JSX.Element => {
6363
const [report, setReport] = useState<ReportType>(null);
6464
const [reportSectionsLoaded, dispatch] = useReducer(reducer, {
6565
summary: false,
66-
analyst: false,
66+
'analyst-comments': false,
6767
pathway: false,
6868
therapeutic: false,
6969
slides: false,

app/views/ReportView/components/AnalystComments/index.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,15 @@ import './index.scss';
2525
type AnalystCommentsProps = {
2626
isPrint?: boolean;
2727
isSigned?: boolean;
28+
loadedDispatch?: (type: Record<'type', string>) => void;
2829
} & WithLoadingInjectedProps;
2930

3031
const AnalystComments = ({
3132
isPrint = false,
3233
isLoading,
3334
isSigned,
3435
setIsLoading,
36+
loadedDispatch,
3537
}: AnalystCommentsProps): JSX.Element => {
3638
const { report } = useContext(ReportContext);
3739
const { setIsSigned } = useContext(ConfirmContext);
@@ -64,11 +66,14 @@ const AnalystComments = ({
6466
snackbar.error(`Network error: ${err}`);
6567
} finally {
6668
setIsLoading(false);
69+
if (loadedDispatch) {
70+
loadedDispatch({ type: 'analyst-comments' });
71+
}
6772
}
6873
};
6974
getData();
7075
}
71-
}, [report, setIsLoading]);
76+
}, [report, setIsLoading, loadedDispatch]);
7277

7378
const handleSign = useCallback(async (signed: boolean, role: SignatureUserType) => {
7479
let newSignature;
Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,18 @@
1-
.genomic-summary {
2-
margin: 20px auto;
3-
padding: 0 20px;
4-
5-
@media print {
6-
margin: 0 auto;
7-
}
8-
1+
// Shared styling between both versions
2+
.genomic-summary, .genomic-summary--print {
93
&__patient-information {
104
margin: 0 0 32px 0;
115

12-
&-title {
13-
@media print {
14-
margin: 0 0 8px;
15-
}
16-
}
17-
186
&-content {
197
padding: 0 16px;
208
}
219
}
2210

23-
&__analysis-summary {
11+
&__tumour-summary, &__alterations {
2412
margin: 0 0 32px 0;
13+
}
2514

26-
@media print {
27-
margin: 32px 0;
28-
}
29-
15+
&__analysis-summary {
3016
&-title {
3117
margin: 8px 0;
3218
}
@@ -35,12 +21,20 @@
3521
padding: 0 16px;
3622
}
3723
}
24+
}
3825

39-
&__tumour-summary {
40-
margin: 0 0 32px 0;
41-
}
26+
.genomic-summary {
27+
margin: 20px auto;
28+
padding: 0 20px;
29+
}
4230

43-
&__alterations {
44-
margin: 0 0 32px 0;
31+
.genomic-summary--print {
32+
margin: 0 auto;
33+
padding: 0 20px;
34+
35+
&__patient-information {
36+
&-title {
37+
margin: 0 0 8px;
38+
}
4539
}
46-
}
40+
}

0 commit comments

Comments
 (0)