Skip to content

Commit

Permalink
[ALS-7889] Smarter sample id checkbox (#318)
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesPeck authored Dec 16, 2024
1 parent 7de0a6f commit 4f347e3
Showing 1 changed file with 93 additions and 54 deletions.
147 changes: 93 additions & 54 deletions src/lib/components/explorer/export/ExportStepper.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import { branding, features, settings, resources } from '$lib/configuration';
import { searchDictionary } from '$lib/services/dictionary';
import type { ExportInterface } from '$lib/models/Export';
import { onMount } from 'svelte';
export let query: QueryRequestInterface;
export let showTreeStep = false;
export let rows: ExportRowInterface[] = [];
Expand All @@ -42,6 +43,7 @@
let sampleIds = false;
let lastExports: ExportRowInterface[] = [];
let loadingSampleIds = false;
let checkingSampleIds = false;
$: datasetId = '';
$: canDownload = true;
$: apiExport = false;
Expand All @@ -51,6 +53,39 @@
{ dataElement: 'type', label: 'Type', sort: true },
];
onMount(async () => {
const exportedSampleIds = $exports.filter((e: ExportInterface) =>
e.conceptPath.includes('SAMPLE_ID'),
);
if (exportedSampleIds.length > 0) {
checkingSampleIds = true;
const genomicConcepts = await getGenomicConcepts();
if (genomicConcepts.length > 0) {
// Find sample IDs that match genomic concepts
const matchingSampleIds = exportedSampleIds.filter((sampleId) =>
genomicConcepts.some((concept) => concept.conceptPath === sampleId.conceptPath),
);
sampleIds = matchingSampleIds.length === genomicConcepts.length;
checkingSampleIds = false;
if (sampleIds) {
lastExports = matchingSampleIds.map((item) => ({
ref: item,
variableId: item.conceptPath,
variableName: item.display,
description: item.searchResult?.description,
type: item.searchResult?.type,
selected: true,
})) as ExportRowInterface[];
}
} else {
sampleIds = false;
checkingSampleIds = false;
}
} else {
sampleIds = false;
}
});
const MAX_DATA_POINTS_FOR_EXPORT = settings.maxDataPointsForExport || 1000000;
function openConfirmationModal() {
Expand Down Expand Up @@ -209,6 +244,40 @@
return totalDataPoints > MAX_DATA_POINTS_FOR_EXPORT;
}
async function getGenomicConcepts() {
const concepts = await searchDictionary(
'',
[
{
name: 'data_source_genomic',
category: 'data_source',
display: 'Genomic',
description: 'Associated with genomic data',
count: 0,
},
],
{ pageNumber: 0, pageSize: 10000 },
);
if (concepts.content.length === 0) {
return [];
}
// Get sample ID counts via cross counts query
const crossCountQuery = new Query(structuredClone(query.query));
crossCountQuery.expectedResultType = 'CROSS_COUNT';
const crossCountFields = concepts.content.map((concept) => concept.conceptPath);
crossCountQuery.setCrossCountFields(crossCountFields);
const crossCountResponse: Record<string, number> = await api.post('picsure/query/sync', {
query: crossCountQuery,
resourceUUID: resources.hpds,
});
// Filter and return only concepts with counts > 0
return concepts.content.filter((concept) => crossCountResponse[concept.conceptPath] > 0);
}
async function toggleSampleIds() {
try {
loadingSampleIds = true;
Expand All @@ -217,56 +286,22 @@
(e) => e.ref,
) as ExportInterface[];
removeExports(exportsToRemove || []);
rows = rows.filter((r) => !lastExports.includes(r));
return;
}
// Get genomic concepts from dictionary
const concepts = await searchDictionary(
'',
[
{
name: 'data_source_genomic',
category: 'data_source',
display: 'Genomic',
description: 'Associated with genomic data',
count: 0,
},
],
{ pageNumber: 0, pageSize: 10000 },
);
if (concepts.content.length === 0) {
rows = rows.filter((r) => !lastExports.some((le) => le.variableId === r.variableId));
return;
}
// Get sample ID counts via cross counts query
const crossCountQuery = new Query(structuredClone(query.query));
crossCountQuery.expectedResultType = 'CROSS_COUNT';
const crossCountFields = concepts.content.map((concept) => concept.conceptPath);
crossCountQuery.setCrossCountFields(crossCountFields);
const genomicConcepts = await getGenomicConcepts();
const crossCountResponse: Record<string, number> = await api.post('picsure/query/sync', {
query: crossCountQuery,
resourceUUID: resources.hpds,
});
// Filter to paths with counts > 0
const conceptPathsToAdd = Object.entries(crossCountResponse)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.filter(([_, count]) => count > 0)
.map(([path]) => path);
// Create new exports for each path
const newExports = conceptPathsToAdd.map((path) => {
const concept = concepts.content.find((c) => c.conceptPath === path);
return {
id: uuidv4(),
searchResult: concept,
display: concept?.display || '',
conceptPath: concept?.conceptPath || '',
} as ExportInterface;
});
// Create new exports for each concept
const newExports = genomicConcepts.map(
(concept) =>
({
id: uuidv4(),
searchResult: concept,
display: concept?.display || '',
conceptPath: concept?.conceptPath || '',
}) as ExportInterface,
);
// Add exports and create corresponding rows
addExports(newExports);
Expand Down Expand Up @@ -361,14 +396,18 @@
class="flex items-center"
data-testid="sample-ids-label"
>
<input
type="checkbox"
class="mr-1 &[aria-disabled=“true”]:opacity-75"
data-testid="sample-ids-checkbox"
id="sample-ids-checkbox"
bind:checked={sampleIds}
on:change={toggleSampleIds}
/>
{#if checkingSampleIds}
<ProgressRadial width="w-4" />
{:else}
<input
type="checkbox"
class="mr-1 &[aria-disabled=“true”]:opacity-75"
data-testid="sample-ids-checkbox"
id="sample-ids-checkbox"
bind:checked={sampleIds}
on:change={toggleSampleIds}
/>
{/if}
<span>Include sample identifiers</span>
</label>
</div>
Expand Down

0 comments on commit 4f347e3

Please sign in to comment.