From dc2aeee19ae55910cd19e2cf1148346ff0c12949 Mon Sep 17 00:00:00 2001 From: bartcharbon Date: Fri, 29 Jan 2021 07:57:52 +0100 Subject: [PATCH 1/2] Add checkbox to filter on read depth > 20 --- package-lock.json | 6 +++--- package.json | 2 +- src/components/RecordTable.vue | 20 +++++++++++++++++++- src/components/RecordTableControls.vue | 12 +++++++++--- src/locales/en.json | 1 + src/store/actions.ts | 3 +++ src/store/getters.ts | 13 +++++++++++++ src/store/mutations.ts | 3 +++ src/store/state.ts | 1 + src/types/State.ts | 1 + tests/unit/store/actions.spec.ts | 8 ++++++++ tests/unit/store/getters.spec.ts | 10 ++++++++++ tests/unit/store/mutations.spec.ts | 6 ++++++ 13 files changed, 78 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index dff107ce..2d587030 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1595,9 +1595,9 @@ } }, "@molgenis/vip-report-api": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@molgenis/vip-report-api/-/vip-report-api-0.6.0.tgz", - "integrity": "sha512-m96IKYoqhr9UWeqdDzXmuoFIjkIMA66LK0GMC6MVlvT+e3Ne3rOoVCWQ48OlabAP4fFuqL5w/Wm+Vzy6WXLIfQ==" + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@molgenis/vip-report-api/-/vip-report-api-0.7.0.tgz", + "integrity": "sha512-RQOKZFBjOtikXjMtMNULLzRcOpjjH/BiAD9V9GGIPZzywVFec6bfMZsU4nrRNViUVHGmSveHRUncnvP2DhLPKA==" }, "@mrmlnc/readdir-enhanced": { "version": "2.2.1", diff --git a/package.json b/package.json index 2ba29389..0d2e3e1b 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "i18n:report": "vue-cli-service i18n:report --src './src/**/*.?(js|vue)' --locales './src/locales/**/*.json'" }, "dependencies": { - "@molgenis/vip-report-api": "0.6.0", + "@molgenis/vip-report-api": "0.7.0", "bootstrap-vue": "^2.15.0", "core-js": "^3.6.5", "file-saver": "^2.0.2", diff --git a/src/components/RecordTable.vue b/src/components/RecordTable.vue index 3907c38e..48f9b7d4 100644 --- a/src/components/RecordTable.vue +++ b/src/components/RecordTable.vue @@ -292,6 +292,7 @@ export default Vue.extend({ 'isRecordsContainPhenotypes', 'isSamplesContainInheritance', 'isSamplesContainDenovo', + 'isSamplesContainDepth', 'sampleMaternal', 'samplePaternal' ]), @@ -302,7 +303,8 @@ export default Vue.extend({ 'selectedSamplePhenotypes', 'filterRecordsByPhenotype', 'filterRecordsByInheritance', - 'filterRecordsByDenovo' + 'filterRecordsByDenovo', + 'filterRecordsByDepth' ]), genomeAssembly(): string { return this.metadata.htsFile.genomeAssembly; @@ -392,6 +394,11 @@ export default Vue.extend({ if (this.isSamplesContainDenovo && this.filterRecordsByDenovo) { queries.push(this.createSampleDenovoQuery()); } + if (this.isSamplesContainDepth && this.filterRecordsByDepth) { + queries.push(this.createSampleReadDepthQuery()); + } + + // todo: translate ctx filter param to query let query: Query | ComposedQuery | undefined; @@ -448,6 +455,13 @@ export default Vue.extend({ args: 1 }; }, + createSampleReadDepthQuery(): Query { + return { + selector: ['s', this.sample.index, 'f', 'DP'], + operator: '>=', + args: 20 + }; + }, hasSamplePhenotypes(): boolean { return this.selectedSamplePhenotypes !== null && this.selectedSamplePhenotypes.page.totalElements > 0; }, @@ -575,6 +589,10 @@ export default Vue.extend({ '$store.state.filterRecordsByDenovo'() { this.page.currentPage = 1; (this.$refs.table as BTable).refresh(); + }, + '$store.state.filterRecordsByDepth'() { + this.page.currentPage = 1; + (this.$refs.table as BTable).refresh(); } } }); diff --git a/src/components/RecordTableControls.vue b/src/components/RecordTableControls.vue index 14a12e3a..9b95b3a5 100644 --- a/src/components/RecordTableControls.vue +++ b/src/components/RecordTableControls.vue @@ -18,6 +18,12 @@ @change="this.setFilterRecordsByDenovo" >{{ $t('matchDenovo') }} + {{ $t('matchDepth') }} + @@ -27,11 +33,11 @@ import { mapActions, mapGetters, mapState } from 'vuex'; export default Vue.extend({ computed: { - ...mapGetters(['isRecordsContainPhenotypes', 'isSamplesContainInheritance', 'isSamplesContainDenovo']), - ...mapState(['filterRecordsByPhenotype', 'filterRecordsByInheritance', 'filterRecordsByDenovo']) + ...mapGetters(['isRecordsContainPhenotypes', 'isSamplesContainInheritance', 'isSamplesContainDenovo', 'isSamplesContainDepth']), + ...mapState(['filterRecordsByPhenotype', 'filterRecordsByInheritance', 'filterRecordsByDenovo', 'filterRecordsByDepth']) }, methods: { - ...mapActions(['setFilterRecordsByPhenotype', 'setFilterRecordsByInheritance', 'setFilterRecordsByDenovo']) + ...mapActions(['setFilterRecordsByPhenotype', 'setFilterRecordsByInheritance', 'setFilterRecordsByDenovo', 'setFilterRecordsByDepth']) } }); diff --git a/src/locales/en.json b/src/locales/en.json index 53c31c4b..f55226eb 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -58,6 +58,7 @@ "matchPhenotype": "Only display records that match sample phenotype(s)", "matchInheritance": "Only display records that match inheritance", "matchDenovo": "Only display records that are denovo", + "matchDepth": "Only display records that have a read depth of 20 or higher", "maleAffected": "Male, Affected.", "maleUnaffected": "Male, Unaffected.", "maleUnknown": "Male, Unknown affected status.", diff --git a/src/store/actions.ts b/src/store/actions.ts index 70f51c24..fb07655f 100644 --- a/src/store/actions.ts +++ b/src/store/actions.ts @@ -89,6 +89,9 @@ export default { }, setFilterRecordsByDenovo({ commit }: ActionContext, value: boolean) { commit('setFilterRecordsByDenovo', value); + }, + setFilterRecordsByDepth({ commit }: ActionContext, value: boolean) { + commit('setFilterRecordsByDepth', value); } }; diff --git a/src/store/getters.ts b/src/store/getters.ts index b8a192b5..49e8fdcd 100644 --- a/src/store/getters.ts +++ b/src/store/getters.ts @@ -171,5 +171,18 @@ export default { hasSampleInheritance = vimFormat !== undefined; } return hasSampleInheritance; + }, + /** + * Returns whether records contain read depth information. + */ + isSamplesContainDepth: (state: State): boolean => { + let hasReadDepth; + if (state.metadata === null) { + hasReadDepth = false; + } else { + const dpFormat = state.metadata.records.format.find(item => item.id === 'DP'); + hasReadDepth = dpFormat !== undefined; + } + return hasReadDepth; } }; diff --git a/src/store/mutations.ts b/src/store/mutations.ts index 72441b87..016a1698 100644 --- a/src/store/mutations.ts +++ b/src/store/mutations.ts @@ -38,5 +38,8 @@ export default { }, setFilterRecordsByDenovo(state: State, value: boolean) { state.filterRecordsByDenovo = value; + }, + setFilterRecordsByDepth(state: State, value: boolean) { + state.filterRecordsByDepth = value; } }; diff --git a/src/store/state.ts b/src/store/state.ts index cf2ce17f..ad5349f6 100644 --- a/src/store/state.ts +++ b/src/store/state.ts @@ -10,6 +10,7 @@ const state: State = { filterRecordsByPhenotype: true, filterRecordsByInheritance: false, filterRecordsByDenovo: false, + filterRecordsByDepth: false, annotations: null }; diff --git a/src/types/State.ts b/src/types/State.ts index 4ccf666a..6c05c4bd 100644 --- a/src/types/State.ts +++ b/src/types/State.ts @@ -12,5 +12,6 @@ export type State = { filterRecordsByPhenotype: boolean; filterRecordsByInheritance: boolean; filterRecordsByDenovo: boolean; + filterRecordsByDepth: boolean; annotations: Annotations | null; }; diff --git a/tests/unit/store/actions.spec.ts b/tests/unit/store/actions.spec.ts index 07a03346..5eedc05b 100644 --- a/tests/unit/store/actions.spec.ts +++ b/tests/unit/store/actions.spec.ts @@ -150,3 +150,11 @@ test('set filter records by denovo status', async done => { expect(commit).toHaveBeenCalledWith('setFilterRecordsByDenovo', true); done(); }); + + +test('set filter records by read depth', async done => { + const commit = jest.fn() as Commit; + actions.setFilterRecordsByDepth({ commit } as ActionContext, true); + expect(commit).toHaveBeenCalledWith('setFilterRecordsByDepth', true); + done(); +}); diff --git a/tests/unit/store/getters.spec.ts b/tests/unit/store/getters.spec.ts index a176545e..534ba029 100644 --- a/tests/unit/store/getters.spec.ts +++ b/tests/unit/store/getters.spec.ts @@ -612,3 +612,13 @@ test('whether records contain denovo information. null.', () => { }; expect(getters.isSamplesContainDenovo(testState)).toEqual(false); }); + +test('whether records contain read depth information. null.', () => { + const metadata = null; + + const testState: State = { + ...initialState, + metadata: metadata + }; + expect(getters.isSamplesContainDepth(testState)).toEqual(false); +}); diff --git a/tests/unit/store/mutations.spec.ts b/tests/unit/store/mutations.spec.ts index 38177219..44e5e0fd 100644 --- a/tests/unit/store/mutations.spec.ts +++ b/tests/unit/store/mutations.spec.ts @@ -64,3 +64,9 @@ test('set filter records by denovo', () => { mutations.setFilterRecordsByDenovo(testState, false); expect(testState.filterRecordsByDenovo).toBe(false); }); + +test('set filter records by read depth', () => { + const testState: State = { ...initialState }; + mutations.setFilterRecordsByDepth(testState, false); + expect(testState.filterRecordsByDepth).toBe(false); +}); From 74b5c3b57f97d8bd6bface51f17c6c09f3306105 Mon Sep 17 00:00:00 2001 From: bartcharbon Date: Fri, 29 Jan 2021 07:59:17 +0100 Subject: [PATCH 2/2] Remove non existent state keys from Sample.Vue --- src/views/Samples.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/Samples.vue b/src/views/Samples.vue index 5cd4844b..91548ba1 100644 --- a/src/views/Samples.vue +++ b/src/views/Samples.vue @@ -20,7 +20,7 @@ export default Vue.extend({ components: { SampleNavigation, SampleReport }, computed: { ...mapGetters(['samples', 'getSampleById']), - ...mapState(['selectedSample', 'selectedSamplePhenotypes', 'selectedSampleInheritance', 'selectedSampleDenovo']) + ...mapState(['selectedSample', 'selectedSamplePhenotypes']) }, methods: { ...mapActions(['loadMetadata', 'loadSamples', 'selectSample']),