The profile tab for each of the entities (target, disease, drug and evidence) is broken up into sections. Each of these sections is encapsulated in one directory under src/sections/<entity>/
. To add a new one, follow this structure:
src
└── sections
└── <entity>
└── <sectionId>
├── index.js
├── Summary.js
├── Body.js
└── Description.js
The following describe all the files in detail, following the simple TEP section from the target
entity page as an example.
The index.js
defines the section information as well as exporting its Body
and Summary
components:
export const definition = {
id: 'tep',
name: 'Target Enabling Packages',
// Optional, if not present it will default to the first character of the
// first two words in the name.
shortName: 'TEP',
// hasData takes the data content of the summary query as its parameter, to
// determine if there is data for this section (and therefore whether to
// display its body or not.
hasData: data => !!data.tep,
// Optional, set to true if the section uses an external API instead.
external: false,
};
export { default as Summary } from './Summary';
export { default as Body } from './Body';
This component is in charge of handling the data acquisition for the summary, and must render the contents of the section's summary in the page's table of contents:
If the section uses Open Target's GraphQL API, it must include a fragments
field with the query. This is used to add the data to the context provider used by the profile page:
const TEP_SUMMARY_FRAGMENT = gql`
fragment TepSummaryFragment on Target {
id
tep {
uri
name
}
}
`;
function Summary({ definition }) {
// ...
}
Summary.fragments = {
TepSummaryFragment: TEP_SUMMARY_FRAGMENT,
};
The summary component will be used in the entity's profile page, and will bring the following props:
id
: id of the entity (eg:ENSG00000158578
forALAS2
).label
: label of the entity, in case of a target it will contain theapprovedSymbol
field from the API (ALAS2
).definition
: thedefinition
object exported byindex.js
.
The render must be done in using the render prop renderSummary
of a root SummaryItem
component. It must be passed the definition for the section, and takes a data
parameter, which will contain the request's data
field. It is safe to assume there will be data in there, as the SummaryItem
takes care of the loading and error states.
For this to assumption to work when using custom requests, the SummaryItem
component must be passed an object with the requests' state and data structured as follows:
Field | Type | Description |
---|---|---|
loading | bool |
true for an in-flight request |
error | object | null |
should be null if no error |
data | object | null |
It is also worth noting that the for sections using Open Target's GraphQL API, the summary should use the usePlatformApi
hook to store the summary data in the context provider, which later on can be retrieved from the section's body if it is needed. Passing the query as a parameter is optional, and it filters the object contents to only return the part relevant to this section.
function Summary({ definition }) {
const { loading, error, data } = usePlatformApi(TEP_SUMMARY_FRAGMENT);
return (
<SummaryItem
definition={definition}
request={{ loading, error, data }}
renderSummary={() => 'Available'}
/>
);
}
This is the component in charge of rendering the section's main contents. It is also responsible for acquiring its data.
Just like the in the Summary component, the Body is used in the entity's profile page and brings the same id
, label
and definition
props. It also uses a renderBody
to render its contents. It has the same definition
and request
props, and now includes a renderDescription
prop to take care of the titlebar description.
In this example, it is enough for the body to use the data fetched by the summary, so it uses the usePlatformApi
hook like the summary:
const Section = ({ definition, label: symbol }) => {
const request = usePlatformApi(Summary.fragments.TepSummaryFragment);
return (
<SectionItem
definition={definition}
request={request}
renderDescription={() => <Description symbol={symbol} />}
renderBody={data => (
<>
Learn more about the{' '}
<Link to={data.tep.uri} external>
{data.tep.name} TEP
</Link>
.
</>
)}
/>
);
};
This component contains the description shown in the section's body's title bar:
function Description({ symbol }) {
return (
<>
Critical mass of reagents and knowledge allowing for the rapid biochemical
and chemical exploration of <strong>{symbol}</strong>. Source:{' '}
<Link external to="https://www.thesgc.org/tep">
SGC
</Link>
.
</>
);
}
- Related Diseases: Uses Platform-API with separate queries for summary and body.
- Comparative Genomics: External API.
- Baseline Expression: Platform-API in the summary; both Platform-API and external API in the body, uses a query inside each subcomponent.