/** * See the NOTICE file distributed with this work for additional information * regarding copyright ownership. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import React from 'react'; import { useQuery, gql } from '@apollo/client'; import { useParams } from 'react-router'; import sortBy from 'lodash/sortBy'; import { Pick2 } from 'ts-multipick'; import { parseEnsObjectIdFromUrl } from 'src/shared/state/ens-object/ensObjectHelpers'; import { defaultSort } from 'src/content/app/entity-viewer/shared/helpers/transcripts-sorter'; import { Accordion, AccordionItem, AccordionItemHeading, AccordionItemPanel, AccordionItemButton } from 'src/shared/components/accordion'; import ExternalReference from 'src/shared/components/external-reference/ExternalReference'; import { ExternalReference as ExternalReferenceType, ExternalReferencesGroup } from 'src/shared/types/thoas/externalReference'; import { EntityViewerParams } from 'src/content/app/entity-viewer/EntityViewer'; import { Slice } from 'src/shared/types/thoas/slice'; import { FullProductGeneratingContext } from 'src/shared/types/thoas/productGeneratingContext'; import { TranscriptMetadata } from 'ensemblRoot/src/shared/types/thoas/metadata'; import styles from './GeneExternalReferences.scss'; const QUERY = gql` query Gene($stable_id: String!, $genome_id: String!) { gene(byId: { stable_id: $stable_id, genome_id: $genome_id }) { stable_id symbol external_references { accession_id name description url source { id name } } transcripts { stable_id slice { location { length } } external_references { accession_id name description url source { id name } } product_generating_contexts { product_type product { external_references { accession_id name description url source { id name } } } } metadata { canonical { value } mane { value } } } } } `; type Transcript = { stable_id: string; slice: Pick2; product_generating_contexts: Array< Pick & { product: { external_references: ExternalReferenceType[] } | null; } >; external_references: ExternalReferenceType[]; metadata: Pick; }; type Gene = { symbol: string; stable_id: string; transcripts: Transcript[]; external_references: ExternalReferenceType[]; }; const buildExternalReferencesGroups = ( externalReferences: ExternalReferenceType[] ) => { const externalReferencesGroups: { [key: string]: ExternalReferencesGroup; } = {}; const sortedExternalReferences = sortBy( externalReferences, (reference) => reference.source.name ); sortedExternalReferences.forEach((externalReference) => { const sourceId = externalReference.source.id; if (!externalReferencesGroups[sourceId]) { externalReferencesGroups[sourceId] = { source: externalReference.source, references: [] }; } externalReferencesGroups[sourceId].references.push({ accession_id: externalReference.accession_id, url: externalReference.url, name: externalReference.name, description: externalReference.description }); }); // Sort the xrefs within each group based on description (or accession_id when description is empty) Object.keys(externalReferencesGroups).forEach((sourceId) => { externalReferencesGroups[sourceId].references = sortBy( externalReferencesGroups[sourceId].references, (reference) => reference.description || reference.accession_id ); }); return externalReferencesGroups; }; const GeneExternalReferences = () => { const params: EntityViewerParams = useParams(); const { entityId, genomeId } = params; const stableId = entityId ? parseEnsObjectIdFromUrl(entityId).objectId : null; const { data, loading } = useQuery<{ gene: Gene }>(QUERY, { variables: { stable_id: stableId, genome_id: genomeId }, skip: !stableId }); if (loading) { return
Loading...
; } if (!data || !data.gene) { return
No data to display
; } const externalReferencesGroups = buildExternalReferencesGroups( data.gene.external_references ); const { transcripts } = data.gene; const sortedTranscripts = defaultSort(transcripts); return (
{data.gene.symbol} {data.gene.stable_id}
Gene
{data.gene.external_references && renderXrefs(externalReferencesGroups)} {sortedTranscripts.length && (
Transcripts
{sortedTranscripts.map((transcript, key) => { return (
); })}
)}
); }; const TranscriptXrefs = (props: { transcript: Transcript }) => { const { transcript } = props; const unsortedXrefs = [...transcript.external_references]; // Add protein level xrefs transcript.product_generating_contexts.forEach( (product_generating_context) => { product_generating_context.product && unsortedXrefs.push( ...product_generating_context.product.external_references ); } ); const xrefGroups = buildExternalReferencesGroups(unsortedXrefs); return (
{transcript.stable_id}
{transcript.external_references && (
{renderXrefs(xrefGroups)}
)}
); }; const renderXrefs = (xrefGroups: { [key: string]: ExternalReferencesGroup; }) => { return Object.values(xrefGroups).map((externalReferencesGroup, key) => { if (externalReferencesGroup.references.length === 1) { return (
); } else { return renderXrefGroup(externalReferencesGroup, key); } }); }; const renderXrefGroup = ( externalReferencesGroup: ExternalReferencesGroup, key: number ) => { return (
{externalReferencesGroup.source.name}
{externalReferencesGroup.references.map((entry, key) => ( ))}
); }; export default GeneExternalReferences;