Skip to content

Commit

Permalink
Improve the CompoundInfoPanel component.
Browse files Browse the repository at this point in the history
  • Loading branch information
yjcyxky committed Apr 4, 2024
1 parent 72dc854 commit 2d3fd27
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 77 deletions.
44 changes: 30 additions & 14 deletions studio/src/NodeInfoPanel/CompoundInfoPanel/InfoPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
import { Empty, Row, Col, Tag, Descriptions, Table, Spin } from "antd";
import React, { useEffect, useState } from "react";
import type { DescriptionsProps } from 'antd';
import { CompoundInfo } from "./index.t";
import { CompoundInfo, Classification } from "./index.t";

import './index.less';

export interface InfoPanelProps {
compoundInfo: CompoundInfo
}

const PubMedLinks = (text: string) => {
const parts = text.split(/(PubMed:\d+)/);

const components = parts.map((part, index) => {
if (/PubMed:\d+/.test(part)) {
// @ts-ignore, Extract the PubMed ID from the part
const pubMedId = part.match(/\d+/)[0];
return <a key={index} href={`https://www.ncbi.nlm.nih.gov/pubmed/${pubMedId}`} target="_blank">{part}</a>;
} else {
return <span key={index}>{part}</span>;
}
});
const formatClassification = (classification: Classification): JSX.Element => {
return <span>
{classification.direct_parent} &gt;
{classification.kingdom} &gt;
{classification.superclass} &gt;
{classification.class} &gt;
{classification.subclass}
</span>
}

return <div>{components}</div>;
const formatSynonyms = (synonyms: string[]): JSX.Element => {
return <span>
{synonyms.map((synonym, index) => {
return <Tag key={index}>{synonym}</Tag>
})}
</span>
}

const BoldTextComponent = ({ text }: { text: string }) => {
Expand Down Expand Up @@ -124,6 +126,16 @@ export const InfoPanel: React.FC<InfoPanelProps> = (props) => {
key: 'updated',
label: 'Updated',
children: compoundInfo.updated
},
{
key: 'classification',
label: 'Classification',
children: compoundInfo.classification ? formatClassification(compoundInfo.classification) : null
},
{
key: 'synonyms',
label: 'Synonyms',
children: compoundInfo.synonyms ? formatSynonyms(compoundInfo.synonyms) : null
}
];

Expand All @@ -139,6 +151,10 @@ export const InfoPanel: React.FC<InfoPanelProps> = (props) => {
metabolism: compoundInfo?.metabolism,
absorption: compoundInfo?.absorption,
half_life: compoundInfo?.half_life,
protein_binding: compoundInfo?.protein_binding,
route_of_elimination: compoundInfo?.route_of_elimination,
volume_of_distribution: compoundInfo?.volume_of_distribution,
clearance: compoundInfo?.clearance,
}

setBackground(background);
Expand Down
49 changes: 49 additions & 0 deletions studio/src/NodeInfoPanel/CompoundInfoPanel/Reference.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Empty, Row, Col, Tag, Descriptions, Table, Spin } from "antd";
import React, { useEffect, useState } from "react";
import { CompoundInfo } from "./index.t";

import './index.less';

export interface InfoPanelProps {
compoundInfo: CompoundInfo
}

const formatPubmedId = (pubmedId: string): string => {
return `https://pubmed.ncbi.nlm.nih.gov/${pubmedId}`;
}

export const Reference: React.FC<InfoPanelProps> = (props) => {
const { compoundInfo } = props;

return (
compoundInfo ?
<Row className="compound-info-panel">
<Col className="article">
{
compoundInfo.general_references?.articles ? (compoundInfo.general_references?.articles.map((article, index) => {
return (
<div key={index}>
<span>{article.citation}</span>
<a href={formatPubmedId(article.pubmed_id)} target="_blank">PubMed</a>
</div>
)
})) : null
}
</Col>
<Col className="link">
{
compoundInfo.general_references?.links ? (compoundInfo.general_references?.links.map((link, index) => {
return (
<div key={index}>
<a href={link.url} target="_blank">{link.title}</a>
</div>
)
})) : null
}
</Col>
</Row>
: null
);
}

export default Reference;
3 changes: 2 additions & 1 deletion studio/src/NodeInfoPanel/CompoundInfoPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react'
import { Empty, Spin, Tabs, Descriptions, Table } from 'antd'
import type { CompoundInfo, Patent } from './index.t';
import InfoPanel from './InfoPanel';
import Reference from './Reference';

type CompoundInfoPanelProps = {
rootId?: string,
Expand Down Expand Up @@ -92,7 +93,7 @@ const CompoundInfoPanel: React.FC<CompoundInfoPanelProps> = (props) => {
{
label: 'References',
key: 'references',
children: <Empty description="Coming soon..." />
children: <Reference compoundInfo={compoundInfo} />
},
{
label: 'Drug Interactions',
Expand Down
11 changes: 8 additions & 3 deletions studio/src/NodeInfoPanel/ProteinInfoPanel/InfoPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ export const ProteinInfoPanel: React.FC<ProteinInfoPanelProps> = (props) => {
if (geneInfo && isProteinCoding(geneInfo)) {
const uniprotId = geneInfo.uniprot ? geneInfo.uniprot['Swiss-Prot'] : null;
// @ts-ignore
const generalInfo: DescriptionsProps['items'] = [
const infoItems: DescriptionsProps['items'] = [
{
key: 'official-gene-symbol',
label: 'Official Gene Symbol',
Expand Down Expand Up @@ -207,12 +207,17 @@ export const ProteinInfoPanel: React.FC<ProteinInfoPanelProps> = (props) => {
key: 'species',
label: 'Species',
children: guessSpecies(`${geneInfo.taxid}`)
},
{
key: 'sequence-length',
label: 'Amino acids',
children: proteinInfo?.sequence ? proteinInfo?.sequence?.length : 'Unknown',
}
];

setGeneralInfo(generalInfo);
setGeneralInfo(infoItems);
}
}, [geneInfo]);
}, [geneInfo, proteinInfo]);

return (
<Row className="protein-info-panel">
Expand Down
9 changes: 8 additions & 1 deletion studio/src/NodeInfoPanel/ProteinInfoPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type ComposedProteinPanel = {
}

const fetchProteinInfoByGeneInfo = async (geneInfo: GeneInfo): Promise<UniProtEntry> => {
console.log("Fetching protein info by gene info: ", geneInfo)
const uniprotId = geneInfo.uniprot ? geneInfo.uniprot['Swiss-Prot'] : null;
const uniprotIds = geneInfo.uniprot ? (geneInfo.uniprot.TrEMBL || []) : [];
if (!uniprotId && uniprotIds.length === 0) {
Expand All @@ -23,7 +24,13 @@ const fetchProteinInfoByGeneInfo = async (geneInfo: GeneInfo): Promise<UniProtEn
if (uniprotId) {
return fetchProteinInfo(uniprotId);
} else {
return fetchProteinInfo(uniprotIds[0]);
if (typeof uniprotIds === 'string') {
return fetchProteinInfo(uniprotIds);
} else if (typeof uniprotIds === 'object' && uniprotIds.length > 0) {
return fetchProteinInfo(uniprotIds[0]);
} else {
return {} as UniProtEntry;
}
}
}

Expand Down
38 changes: 28 additions & 10 deletions studio/src/components/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { QuestionCircleOutlined, InfoCircleOutlined, UserOutlined, FieldTimeOutlined } from '@ant-design/icons';
import { QuestionCircleOutlined, InfoCircleOutlined, UserOutlined, FieldTimeOutlined, LogoutOutlined } from '@ant-design/icons';
import { Space, Menu, Button, message, Dropdown } from 'antd';
import React, { useEffect, useState } from 'react';
import { getJwtAccessToken, logoutWithRedirect } from '@/components/util';
Expand Down Expand Up @@ -85,11 +85,11 @@ const GlobalHeaderRight: React.FC<GlobalHeaderRightProps> = (props) => {
}, [props.username, user]);

const directItems: MenuProps['items'] = [
{
label: username,
key: 'user',
icon: <UserOutlined />,
},
// {
// label: username,
// key: 'user',
// icon: <UserOutlined />,
// },
{
label: 'v0.3.1',
key: 'version',
Expand All @@ -115,6 +115,15 @@ const GlobalHeaderRight: React.FC<GlobalHeaderRightProps> = (props) => {
},
]

const userItems: MenuProps['items'] = [
{
label: 'Logout',
key: 'logout',
icon: <LogoutOutlined />,
danger: true,
},
]

const onClick = (item: any) => {
if (item.key === 'about') {
history.push('/about')
Expand All @@ -124,6 +133,8 @@ const GlobalHeaderRight: React.FC<GlobalHeaderRightProps> = (props) => {
history.push('/changelog')
} else if (item.key === 'version') {
window.open('https://github.com/open-prophetdb/biomedgps/releases', '_blank');
} else if (item.key === 'logout') {
logoutWithRedirectRaw();
}
};

Expand All @@ -145,10 +156,17 @@ const GlobalHeaderRight: React.FC<GlobalHeaderRightProps> = (props) => {
<Dropdown menu={{ items, onClick: onClick }} placement="bottomLeft">
<Button type="text" icon={<InfoCircleOutlined />} style={{ height: '40px' }}>About</Button>
</Dropdown>
<Button type={isAuthenticated ? 'default' : 'primary'} danger={isAuthenticated}
onClick={() => isAuthenticated ? logoutWithRedirectRaw() : loginWithRedirect()}>
Sign {isAuthenticated ? 'Out' : 'In'}
</Button>
{
!isAuthenticated ? (
<Button type={isAuthenticated ? 'default' : 'primary'} onClick={() => loginWithRedirect()}>
Sign In / Sign Up
</Button>
) : (
<Dropdown menu={{ items: userItems, onClick: onClick }} placement="bottomLeft">
<Button type="primary" icon={<UserOutlined />}>{username}</Button>
</Dropdown>
)
}
</Space>
);
};
Expand Down
Loading

0 comments on commit 2d3fd27

Please sign in to comment.