Skip to content

Commit

Permalink
Merge pull request #526 from ProteinsWebTeam/dev
Browse files Browse the repository at this point in the history
Release 97.0
  • Loading branch information
matthiasblum authored Nov 8, 2023
2 parents dcc6399 + 08014f2 commit 3b05af0
Show file tree
Hide file tree
Showing 21 changed files with 405 additions and 182 deletions.
19 changes: 11 additions & 8 deletions src/components/BreadCrumbs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,7 @@ const locationType = T.shape({
other: T.arrayOf(T.string),
});
const BreadCrumb = (
{
to,
children,
} /*: {
{ to, children } /*: {
children: any,
to?: function | {description: Object}} */,
) => {
Expand Down Expand Up @@ -107,7 +104,8 @@ const BreadCrumbsForSearchOrResult = (
{ location } /*: {location: Location} */,
) => {
if (!['search', 'result'].includes(location?.main?.key)) return null;
const key /*: 'search' | 'result' */ = (location.main.key /*: any */);
//$FlowFixMe[incompatible-type]
const key /*: 'search' | 'result' */ = location.main.key;
const { type, value, accession } = location[key];
return (
<>
Expand Down Expand Up @@ -224,10 +222,12 @@ BreadCrumbForEntityDetail.propTypes = {
const BreadCrumbForSecondPart = ({ location } /*: {location: Location} */) => {
const { accession, detail } = location[location.main.key];
const filters = Object.keys(location)
.filter((ep) => (location[ep] /*: any */)?.isFilter)
//$FlowFixMe[prop-missing]
.filter((ep) => location[ep]?.isFilter)
.sort(
(ep1, ep2) =>
(location[ep1] /*: any */)?.order - (location[ep2] /*: any */).order,
//$FlowFixMe[prop-missing]
location[ep1]?.order - location[ep2].order,
);
return (
<section className={f('secondary')}>
Expand Down Expand Up @@ -266,7 +266,10 @@ const BreadCrumbsForBrowse = ({ location } /*: {location: Location} */) => {
description: { main: { key: endpoint }, [endpoint]: { db } },
}}
>
By {endpoint}{' '}
By{' '}
{db && db.toLowerCase() === 'pfam' && endpoint.toLowerCase() === 'set'
? 'clan'
: endpoint}{' '}
</BreadCrumb>
<BreadCrumb
to={{
Expand Down
2 changes: 1 addition & 1 deletion src/components/BrowseTabs/__snapshots__/test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ exports[`<BrowseTabsWithoutData /> should render 1`] = `
}
}
isFirstLevel={true}
name="By Set"
name="By Clan/Set"
to={[Function]}
/>
</li>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const css = cssBinder(ipro, local, fonts);
const ImportedTag = ({ accession }: { accession: string }) => {
return (
<Tooltip
title={`The member database didn't provide a description for this signature.
title={`The member database didn't provide a description for this signature.
The description displayed has been imported from ${accession}, the InterPro entry in which the signature is integrated.`}
>
<span className={css('tag')}>
Expand Down Expand Up @@ -57,6 +57,7 @@ const ImportedTag = ({ accession }: { accession: string }) => {
type Props = {
integrated: string | null;
setIntegratedCitations?: (citations: string[]) => void;
headerText?: string;
};

interface IntegratedProps
Expand All @@ -67,6 +68,7 @@ const DescriptionFromIntegrated = ({
integrated,
data,
setIntegratedCitations = (_: string[]) => null,
headerText,
}: IntegratedProps) => {
const { loading, payload } = data || {};
useEffect(() => {
Expand All @@ -87,7 +89,7 @@ const DescriptionFromIntegrated = ({
return (
<>
<h4>
Description <ImportedTag accession={integrated} />
{headerText || 'Description'} <ImportedTag accession={integrated} />
</h4>
<Description
textBlocks={payload.metadata.description}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<DescriptionLLM /> should render 1`] = `
<React.Fragment>
<div
className="row"
>
<div
className="columns large-12"
>
<div
className="callout warning"
style={
{
"alignItems": "center",
"display": "flex",
}
}
>
<span
className="small icon icon-common icon-exclamation-triangle"
style={
{
"color": "#664d03",
"fontSize": "2em",
"paddingRight": "1rem",
}
}
/>
<p>
This description has been automatically generated using
<Memo(Connect(Link))
href="https://openai.com/research/gpt-4"
target="_blank"
>
GPT-4
</Memo(Connect(Link))>
, an AI language model, and is based on data extracted from
<Memo(Connect(Link))
href="https://www.uniprot.org"
target="_blank"
>
UniProtKB/Swiss-Prot
</Memo(Connect(Link))>
. It has not undergone a thorough review by curators. Please exercise discretion when interpreting the information provided and consider it as preliminary.
<br />
<Memo(Connect(Link))
href="https://interpro-documentation.readthedocs.io/en/latest/llm_descriptions.html"
target="_blank"
>
Read more on description generation
</Memo(Connect(Link))>
</p>
</div>
</div>
</div>
<Description
textBlocks={
[
"<p>The function of the family is not clear.</p>",
]
}
/>
</React.Fragment>
`;
75 changes: 75 additions & 0 deletions src/components/Description/DescriptionLLM/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import React, { PureComponent } from 'react';

import cssBinder from 'styles/cssBinder';
import globalStyles from 'styles/interpro-vf.css';
import fonts from 'EBI-Icon-fonts/fonts.css';
import Link from 'components/generic/Link';

import Description from '..';
import config from 'config';

const css = cssBinder(globalStyles, fonts);

type Props = {
text: string;
};

class DescriptionLLM extends PureComponent<Props> {
render() {
const text = this.props.text || '';
if (text.length === 0) return null;

return (
<>
<div className={css('row')}>
<div className={css('columns', 'large-12')}>
<div
className={css('callout', 'warning')}
style={{
display: 'flex',
alignItems: 'center',
}}
>
<span
style={{
fontSize: '2em',
color: '#664d03',
paddingRight: '1rem',
}}
className={css(
'small',
'icon',
'icon-common',
'icon-exclamation-triangle'
)}
/>{' '}
<p>
This description has been automatically generated using{' '}
<Link href="https://openai.com/research/gpt-4" target="_blank">
GPT-4
</Link>
, an AI language model, and is based on data extracted from{' '}
<Link href="https://www.uniprot.org" target="_blank">
UniProtKB/Swiss-Prot
</Link>
. It has not undergone a thorough review by curators. Please
exercise discretion when interpreting the information provided
and consider it as preliminary.
<br />
<Link
href={`${config.root.readthedocs.href}llm_descriptions.html`}
target="_blank"
>
Read more on description generation
</Link>
</p>
</div>
</div>
</div>
<Description textBlocks={[text]} />
</>
);
}
}

export default DescriptionLLM;
14 changes: 14 additions & 0 deletions src/components/Description/DescriptionLLM/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';
import ShallowRenderer from 'react-test-renderer/shallow';

import DescriptionLLM from '.';

const renderer = new ShallowRenderer();
const description = '<p>The function of the family is not clear.</p>';

describe('<DescriptionLLM />', () => {
test('should render', () => {
renderer.render(<DescriptionLLM text={description} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
});
55 changes: 39 additions & 16 deletions src/components/Entry/RemovedEntrySummary/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,47 @@ import ebiGlobalStyles from 'ebi-framework/css/ebi-global.css';

const f = foundationPartial(ebiGlobalStyles, fonts);

const RemovedEntrySummary = ({ detail, accession, date, history, dbInfo }) => {
const RemovedEntrySummary = ({
accession,
source_database,
type,
name,
short_name,
deletion_date,
history,
dbInfo,
}) => {
const allNames = (history?.names || []).concat(history?.short_names || []);
const formerNames = allNames.filter((n) => n !== name && n !== short_name);
const listWrap = (n) => `<li>${n}</li>`;
const metadata = {
accession: accession.toUpperCase(),
name: { name: history?.names?.[0] || '???' },
source_database: 'Removed',
type: 'unknown',
name: {
name: name,
short: short_name,
},
source_database: source_database,
type: type,
member_databases: history?.signatures,
description: [
`<b>Removed</b>: ${date}`,
'<b>Used names</b>:',
...(history?.names || []).map((n) => ` * ${n}`),
],
description:
formerNames.length !== 0
? [`<ul>${formerNames.map(listWrap).join('')}</ul>`]
: [],
is_removed: true,
};
const regex = /ipr[0-9]{6}/gi;
const detailF = (detail || '').replace(regex, accession.toUpperCase());
const date = new Date(deletion_date).toLocaleDateString('en-GB', {
month: 'long',
year: 'numeric',
});
const message = `${metadata.accession} is obsolete since ${date}.`;
return (
<div className={f('row')}>
<div className={f('medium-12', 'large-12', 'columns')}>
<EdgeCase text={detailF} status={410} shouldRedirect={false} />
<EdgeCase text={message} status={410} shouldRedirect={false} />
<Title metadata={metadata} mainType="entry" />
<SummaryEntry
data={{ metadata: { ...metadata, source_database: 'interpro' } }}
data={{ metadata: metadata }}
headerText={'Former names'}
loading={false}
dbInfo={dbInfo}
/>
Expand All @@ -42,12 +61,16 @@ const RemovedEntrySummary = ({ detail, accession, date, history, dbInfo }) => {
};

RemovedEntrySummary.propTypes = {
detail: T.string,
accession: T.string,
date: T.string,
source_database: T.string,
type: T.string,
name: T.string,
short_name: T.string,
deletion_date: T.string,
history: T.shape({
signatures: T.arrayOf(T.object),
names: T.arrayOf(T.string),
short_names: T.arrayOf(T.string),
signatures: T.object,
}),
dbInfo: T.object,
};
Expand Down
6 changes: 5 additions & 1 deletion src/components/Entry/Summary/MemberDBSubtitle/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,11 @@ const MemberDBSubtitle = ({
)}
{metadata?.counters?.sets ? (
<tr>
<td>Set</td>
<td>
{metadata.source_database.toLowerCase() === 'pfam'
? 'Clan'
: 'Set'}
</td>
<td>
{metadata.set_info ? (
<Link
Expand Down
Loading

0 comments on commit 3b05af0

Please sign in to comment.