Unverified Commit 27ad268b authored by Manoj Pandian Sakthivel's avatar Manoj Pandian Sakthivel Committed by GitHub
Browse files

Track descriptions (#435)

parent 0050ba95
Pipeline #128507 passed with stages
in 3 minutes and 9 seconds
......@@ -15,36 +15,23 @@
*/
import React from 'react';
import { connect } from 'react-redux';
import { useSelector } from 'react-redux';
import TrackDetails from './drawer-views/track-details/TrackDetails';
import DrawerBookmarks from './drawer-views/DrawerBookmarks';
import GeneSummary from './drawer-views/gene-summary/GeneSummary';
import TranscriptSummary from './drawer-views/transcript-summary/TranscriptSummary';
import { RootState } from 'src/store';
import { closeDrawer } from './drawerActions';
import { getDrawerView } from './drawerSelectors';
import { getBrowserActiveEnsObject } from '../browserSelectors';
import DrawerGene from './drawer-views/DrawerGene';
import DrawerTranscript from './drawer-views/DrawerTranscript';
import ProteinCodingGenes from './drawer-views/ProteinCodingGenes';
import OtherGenes from './drawer-views/OtherGenes';
import DrawerContigs from './drawer-views/DrawerContigs';
import DrawerGC from './drawer-views/DrawerGC';
import DrawerBookmarks from './drawer-views/DrawerBookmarks';
import { DrawerView } from 'src/content/app/browser/drawer/drawerState';
import styles from './Drawer.scss';
import SnpIndels from './drawer-views/SnpIndels';
import {
EnsObject,
EnsObjectGene
} from 'src/shared/state/ens-object/ensObjectTypes';
export type DrawerProps = {
drawerView: string;
ensObject: EnsObject | null;
};
export const Drawer = (props: DrawerProps) => {
const { ensObject, drawerView } = props;
export const Drawer = () => {
const drawerView = useSelector(getDrawerView);
const ensObject = useSelector(getBrowserActiveEnsObject);
if (!ensObject) {
return null;
......@@ -52,25 +39,13 @@ export const Drawer = (props: DrawerProps) => {
const getDrawerViewComponent = () => {
switch (drawerView) {
case 'track:gene-feat':
return <DrawerGene ensObject={ensObject as EnsObjectGene} />;
case 'track:gene-feat-1':
return <DrawerTranscript ensObject={ensObject as EnsObjectGene} />;
case 'track:gene-pc-fwd':
return <ProteinCodingGenes forwardStrand={true} />;
case 'track:gene-other-fwd':
return <OtherGenes forwardStrand={true} />;
case 'track:gene-pc-rev':
return <ProteinCodingGenes forwardStrand={false} />;
case 'track:gene-other-rev':
return <OtherGenes forwardStrand={false} />;
case 'track:contig':
return <DrawerContigs />;
case 'track:gc':
return <DrawerGC />;
case 'track:variant':
return <SnpIndels />;
case 'bookmarks':
case DrawerView.TRACK_DETAILS:
return <TrackDetails />;
case DrawerView.GENE_SUMMARY:
return <GeneSummary />;
case DrawerView.TRANSCRIPT_SUMMARY:
return <TranscriptSummary />;
case DrawerView.BOOKMARKS:
return <DrawerBookmarks />;
}
};
......@@ -80,13 +55,4 @@ export const Drawer = (props: DrawerProps) => {
);
};
const mapStateToProps = (state: RootState) => ({
drawerView: getDrawerView(state),
ensObject: getBrowserActiveEnsObject(state)
});
const mapDispatchToProps = {
closeDrawer
};
export default connect(mapStateToProps, mapDispatchToProps)(Drawer);
export default Drawer;
/**
* 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, { FunctionComponent } from 'react';
import styles from '../Drawer.scss';
const DrawerContigs: FunctionComponent = () => {
return (
<div className={styles.drawerView}>
<div className={styles.container}>
<div className={styles.label}>Track name</div>
<div className={styles.details}>Contigs</div>
<div className={styles.label}>Description</div>
<div className={styles.details}>
Shows a contiguous stretch of DNA sequence without gaps that has been
assembled solely based on direct sequencing information.
</div>
</div>
</div>
);
};
export default DrawerContigs;
/**
* 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, { FunctionComponent } from 'react';
import styles from '../Drawer.scss';
const DrawerGC: FunctionComponent = () => {
return (
<div className={styles.drawerView}>
<div className={styles.container}>
<div className={styles.label}>Track name</div>
<div className={styles.details}>%GC</div>
<div className={styles.label}>Description</div>
<div className={styles.details}>
Shows the percentage of Gs and Cs in a region.
</div>
</div>
</div>
);
};
export default DrawerGC;
/**
* 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, { FunctionComponent } from 'react';
import styles from '../Drawer.scss';
type OtherGenesProps = {
forwardStrand: boolean;
};
const OtherGenes: FunctionComponent<OtherGenesProps> = (
props: OtherGenesProps
) => {
const { forwardStrand } = props;
return (
<div className={styles.drawerView}>
<div className={styles.container}>
<div className={styles.label}>Track name</div>
<div className={styles.details}>Other genes</div>
<div className={styles.label}>Description</div>
<div className={styles.details}>
<p>
<span className={styles.nextLine}>
Shows all non-coding genes on the{' '}
{forwardStrand ? 'forward' : 'reverse'} strand of this chromosome.
Part of the GENCODE comprehensive gene set.
</span>
<a href="https://www.gencodegenes.org">
https://www.gencodegenes.org/
</a>
</p>
</div>
</div>
</div>
);
};
export default OtherGenes;
/**
* 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, { FunctionComponent } from 'react';
import styles from '../Drawer.scss';
const SnpIndels: FunctionComponent = () => {
return (
<div className={styles.drawerView}>
<div className={styles.container}>
<div className={styles.label}>Track name</div>
<div className={styles.details}>1000 Genomes all SNPs &amp; indels</div>
<div className={styles.label}>Description</div>
<div className={styles.details}>
The 1000 Genomes Project has found the most genetic variants (SNPs,
CNVs, indels) with frequencies of at least 1% in the human populations
studied.
</div>
</div>
</div>
);
};
export default SnpIndels;
......@@ -14,22 +14,18 @@
* limitations under the License.
*/
import React, { FunctionComponent } from 'react';
import React from 'react';
import { useSelector } from 'react-redux';
import { getDisplayStableId } from 'src/shared/state/ens-object/ensObjectHelpers';
import { getBrowserActiveEnsObject } from 'src/content/app/browser/browserSelectors';
import { EnsObjectGene } from 'src/shared/state/ens-object/ensObjectTypes';
import styles from '../Drawer.scss';
import styles from 'src/content/app/browser/drawer/Drawer.scss';
type DrawerGeneProps = {
ensObject: EnsObjectGene;
};
const DrawerGene: FunctionComponent<DrawerGeneProps> = (
props: DrawerGeneProps
) => {
const { ensObject } = props;
const GeneSummary = () => {
const ensObject = useSelector(getBrowserActiveEnsObject) as EnsObjectGene;
return (
<div className={styles.drawerView}>
......@@ -49,4 +45,4 @@ const DrawerGene: FunctionComponent<DrawerGeneProps> = (
);
};
export default DrawerGene;
export default GeneSummary;
@import 'src/styles/common';
.trackName {
font-weight: $bold;
display: inline-block;
}
.strand {
margin-left: 50px;
color: $dark-grey;
}
.standardLabelValue {
display: grid;
grid-template-columns: [label] 120px 10px [value] auto;
margin-bottom: 15px;
.label {
grid-column: label;
color: $dark-grey;
text-align: right;
}
.value {
grid-column: value;
}
}
.featureDetails {
display: flex;
align-items: center;
white-space: nowrap;
flex-wrap: nowrap;
overflow: hidden;
& > div:not(:first-child) {
margin-left: 30px;
}
}
.featureSymbol {
font-weight: $bold;
}
.stableId {
font-weight: $bold;
}
.featureSymbol + .stableId {
margin-left: 12px;
color: $dark-grey;
font-weight: $light;
}
......@@ -14,43 +14,67 @@
* limitations under the License.
*/
import React, { FunctionComponent } from 'react';
import React from 'react';
import { useSelector } from 'react-redux';
import styles from '../Drawer.scss';
import { getActiveDrawerTrackId } from 'src/content/app/browser/drawer/drawerSelectors';
import { getBrowserActiveGenomeId } from 'src/content/app/browser/browserSelectors';
type ProteinCodingGenesProps = {
forwardStrand: boolean;
};
import ExternalLink from 'src/shared/components/external-link/ExternalLink';
import { trackDetailsSampleData } from '../../sampleData';
import styles from './TrackDetails.scss';
const TrackDetails = () => {
const activeGenomeId = useSelector(getBrowserActiveGenomeId);
const trackId = useSelector(getActiveDrawerTrackId);
if (!activeGenomeId || !trackId) {
return null;
}
const trackDetails = trackDetailsSampleData[activeGenomeId][trackId] || null;
const ProteinCodingGenes: FunctionComponent<ProteinCodingGenesProps> = (
props: ProteinCodingGenesProps
) => {
const { forwardStrand } = props;
if (!trackDetails) {
return null;
}
return (
<div className={styles.drawerView}>
<div className={styles.container}>
<div className={styles.label}>Track name</div>
<div className={styles.details}>
<p>Protein coding genes</p>
</div>
<div className={styles.container}>
<div className={styles.standardLabelValue}>
<div className={styles.value}>
<span className={styles.trackName}>{trackDetails.track_name}</span>
<div className={styles.label}>Description</div>
<div className={styles.details}>
<p>
<span className={styles.nextLine}>
Shows all protein coding genes on the{' '}
{forwardStrand ? 'forward' : 'reverse'} strand of this chromosome.
Part of the GENCODE comprehensive gene set.
</span>
<a href="https://www.gencodegenes.org">
https://www.gencodegenes.org/
</a>
</p>
{trackDetails.strand && (
<span className={styles.strand}>{trackDetails.strand} strand</span>
)}
</div>
</div>
{trackDetails.description && (
<div className={styles.standardLabelValue}>
<div className={styles.label}>Description</div>
<div className={styles.value}>
<div>{trackDetails.description || null}</div>
</div>
</div>
)}
{trackDetails.source && (
<div className={styles.standardLabelValue}>
<div className={styles.value}>
<div>
<ExternalLink
to={trackDetails.source.url}
linkText={trackDetails.source.name}
/>
</div>
</div>
</div>
)}
</div>
);
};
export default ProteinCodingGenes;
export default TrackDetails;
......@@ -14,27 +14,23 @@
* limitations under the License.
*/
import React, { FunctionComponent } from 'react';
import React from 'react';
import get from 'lodash/get';
import find from 'lodash/find';
import { useSelector } from 'react-redux';
import { getDisplayStableId } from 'src/shared/state/ens-object/ensObjectHelpers';
import { getBrowserActiveEnsObject } from 'src/content/app/browser/browserSelectors';
import { EnsObjectGene } from 'src/shared/state/ens-object/ensObjectTypes';
import styles from '../Drawer.scss';
type DrawerTranscriptProps = {
ensObject: EnsObjectGene;
};
import styles from 'src/content/app/browser/drawer/Drawer.scss';
// TODO: Once we start supporting multiple transcripts, we need to either remove this constant or move it to trackConfig
const TRANSCRIPT_GENE_NAME = 'track:gene-feat-1';
const DrawerTranscript: FunctionComponent<DrawerTranscriptProps> = (
props: DrawerTranscriptProps
) => {
const { ensObject } = props;
const TranscriptSummary = () => {
const ensObject = useSelector(getBrowserActiveEnsObject) as EnsObjectGene;
if (!ensObject.track) {
return null;
......@@ -88,4 +84,4 @@ const DrawerTranscript: FunctionComponent<DrawerTranscriptProps> = (
);
};
export default DrawerTranscript;
export default TranscriptSummary;
......@@ -16,23 +16,26 @@
import { createAction } from 'typesafe-actions';
import { batch } from 'react-redux';
import { ActionCreator, Action } from 'redux';
import { Action } from 'redux';
import { ThunkAction } from 'redux-thunk';
import { RootState } from 'src/store';
import { getBrowserActiveGenomeId } from '../browserSelectors';
import { RootState } from 'src/store';
import { DrawerView } from 'src/content/app/browser/drawer/drawerState';
export const changeDrawerViewForGenome = createAction(
'drawer/update-drawer-view',
(drawerViewForGenome: { [genomeId: string]: string }) => drawerViewForGenome
(drawerViewForGenome: { [genomeId: string]: DrawerView | null }) =>
drawerViewForGenome
)();
export const changeDrawerView: ActionCreator<ThunkAction<
void,
any,
null,
Action<string>
>> = (drawerView: string) => (dispatch, getState: () => RootState) => {
export const changeDrawerView = (
drawerView: DrawerView
): ThunkAction<void, any, null, Action<string>> => (
dispatch,
getState: () => RootState
) => {
const activeGenomeId = getBrowserActiveGenomeId(getState());
if (!activeGenomeId) {
......@@ -46,12 +49,12 @@ export const changeDrawerView: ActionCreator<ThunkAction<
);
};
export const changeDrawerViewAndOpen: ActionCreator<ThunkAction<
void,
any,
null,
Action<string>
>> = (drawerView: string) => (dispatch, getState: () => RootState) => {
export const changeDrawerViewAndOpen = (
drawerView: DrawerView
): ThunkAction<void, any, null, Action<string>> => (
dispatch,
getState: () => RootState
) => {
const activeGenomeId = getBrowserActiveGenomeId(getState());
if (!activeGenomeId) {
......@@ -74,12 +77,12 @@ export const toggleDrawerForGenome = createAction(
isDrawerOpenedForGenome
)();
export const toggleDrawer: ActionCreator<ThunkAction<
void,
any,
null,
Action<string>
>> = (isDrawerOpened: boolean) => (dispatch, getState: () => RootState) => {
export const toggleDrawer = (
isDrawerOpened: boolean
): ThunkAction<void, any, null, Action<string>> => (
dispatch,
getState: () => RootState
) => {
const activeGenomeId = getBrowserActiveGenomeId(getState());
if (!activeGenomeId) {
......@@ -93,12 +96,10 @@ export const toggleDrawer: ActionCreator<ThunkAction<
);
};