Unverified Commit cc56383d authored by Jyothish's avatar Jyothish Committed by GitHub
Browse files

Rename bookmarks (#509)

parent 1e17e365
Pipeline #173472 passed with stages
in 6 minutes and 34 seconds
......@@ -33,9 +33,12 @@
font-size: 13px;
}
.previouslyViewedType {
.label {
margin-right: 8px;
}
.type {
color: $dark-grey;
margin-left: 8px;
font-size: 12px;
font-weight: 300;
}
......
......@@ -26,6 +26,7 @@ import { closeTrackPanelModal } from 'src/content/app/browser/track-panel/trackP
import { closeDrawer } from 'src/content/app/browser/drawer/drawerActions';
import { getActiveGenomePreviouslyViewedObjects } from 'src/content/app/browser/track-panel/trackPanelSelectors';
import analyticsTracking from 'src/services/analytics-service';
import { buildFocusIdForUrl } from 'src/shared/state/ens-object/ensObjectHelpers';
import styles from './DrawerBookmarks.scss';
......@@ -36,10 +37,8 @@ export type DrawerBookmarksProps = {
};
const DrawerBookmarks = (props: DrawerBookmarksProps) => {
const limitedPreviouslyViewedObjects = props.previouslyViewedObjects.slice(
0,
props.previouslyViewedObjects.length - 20
);
const limitedPreviouslyViewedObjects =
props.previouslyViewedObjects.slice(20);
const onClickHandler = (objectType: string, index: number) => {
analyticsTracking.trackEvent({
......@@ -58,12 +57,11 @@ const DrawerBookmarks = (props: DrawerBookmarksProps) => {
<div className={styles.drawerTitle}>Previously viewed</div>
<div className={styles.contentWrapper}>
<div className={styles.linksWrapper}>
{[...limitedPreviouslyViewedObjects]
.reverse()
.map((previouslyViewedObject, index) => {
{limitedPreviouslyViewedObjects.map(
(previouslyViewedObject, index) => {
const path = urlFor.browser({
genomeId: previouslyViewedObject.genome_id,
focus: previouslyViewedObject.object_id
focus: buildFocusIdForUrl(previouslyViewedObject.object_id)
});
return (
......@@ -71,17 +69,25 @@ const DrawerBookmarks = (props: DrawerBookmarksProps) => {
<Link
to={path}
onClick={() =>
onClickHandler(previouslyViewedObject.object_type, index)
onClickHandler(previouslyViewedObject.type, index)
}
>
{previouslyViewedObject.label}
<span className={styles.label}>
{previouslyViewedObject.label[0]}
</span>
{previouslyViewedObject.label[1] && (
<span className={styles.label}>
{previouslyViewedObject.label[1]}
</span>
)}
</Link>
<span className={styles.previouslyViewedType}>
{upperFirst(previouslyViewedObject.object_type)}
<span className={styles.type}>
{upperFirst(previouslyViewedObject.type)}
</span>
</span>
);
})}
}
)}
</div>
</div>
</>
......
......@@ -31,9 +31,8 @@ import { DrawerView } from 'src/content/app/browser/drawer/drawerState';
jest.mock(
'src/shared/components/image-button/ImageButton',
() => (props: { description: string; onClick: () => void }) => (
() => (props: { description: string; onClick: () => void }) =>
<button onClick={props.onClick}>{props.description}</button>
)
);
const fakeGenomeId = 'human';
......@@ -88,7 +87,7 @@ describe('<TrackPanelBar />', () => {
)
);
const bookmarksButton = [...container.querySelectorAll('button')].find(
(button) => button.innerHTML === 'Bookmarks'
(button) => button.innerHTML === 'Previously viewed'
) as HTMLButtonElement;
userEvent.click(bookmarksButton);
......@@ -121,7 +120,7 @@ describe('<TrackPanelBar />', () => {
)
);
const bookmarksButton = [...container.querySelectorAll('button')].find(
(button) => button.innerHTML === 'Bookmarks'
(button) => button.innerHTML === 'Previously viewed'
) as HTMLButtonElement;
userEvent.click(bookmarksButton);
......@@ -146,7 +145,7 @@ describe('<TrackPanelBar />', () => {
it('causes track panel modal to close if a pressed button is clicked again', () => {
const { container } = wrapInRedux();
const bookmarksButton = [...container.querySelectorAll('button')].find(
(button) => button.innerHTML === 'Bookmarks'
(button) => button.innerHTML === 'Previously viewed'
) as HTMLButtonElement;
userEvent.click(bookmarksButton);
......@@ -176,7 +175,7 @@ describe('<TrackPanelBar />', () => {
set(`drawer.isDrawerOpened.${fakeGenomeId}`, true, mockState)
);
const bookmarksButton = [...container.querySelectorAll('button')].find(
(button) => button.innerHTML === 'Bookmarks'
(button) => button.innerHTML === 'Previously viewed'
) as HTMLButtonElement;
userEvent.click(bookmarksButton);
......
......@@ -91,7 +91,7 @@ export const TrackPanelBar = () => {
<div className={styles.sidebarIcon} key="bookmarks">
<ImageButton
status={getViewIconStatus('bookmarks')}
description="Bookmarks"
description="Previously viewed"
onClick={() => toggleModalView('bookmarks')}
image={bookmarkIcon}
/>
......
@import 'src/styles/common';
.trackPanelBookmarks {
margin-left: 10px;
}
.linkHolder {
margin: 5px 0 0 20px;
margin-top: 6px;
text-overflow: ellipsis;
overflow: hidden;
a {
......@@ -11,33 +15,29 @@
font-size: 13px;
font-weight: $normal;
}
.label {
margin-right: 8px;
}
}
.previouslyViewedType {
.type {
color: $dark-grey;
margin-left: 8px;
font-size: 12px;
font-weight: 300;
}
.title {
font-size: 14px;
margin: 5px 0 10px 10px;
margin: 5px 0 25px 0;
font-weight: $bold;
}
.sectionTitle {
color: $dark-grey;
font-size: 12px;
border-bottom: 1px solid $grey;
margin-bottom: 15px;
position: relative;
margin-top: 20px;
.ellipsis {
position: absolute;
right: 5px;
top: -2px;
width: 25px;
.more {
margin-top: 25px;
span {
font-size: 12px;
cursor: pointer;
color: $blue;
font-weight: $normal;
}
}
......@@ -40,6 +40,7 @@ jest.mock('react-router-dom', () => ({
const genomeId = 'triticum_aestivum_GCA_900519105_1';
const geneId = 'TraesCS3D02G273600';
const versionedStableId = 'TraesCS3D02G273600.1';
const region = '3D:2585940-2634711';
const geneObjectId = `${genomeId}:gene:${geneId}`;
const regionObjectId = `${genomeId}:region:${region}`;
......@@ -47,22 +48,22 @@ const regionObjectId = `${genomeId}:region:${region}`;
const createRandomPreviouslyViewedObject = (): PreviouslyViewedObject => ({
genome_id: faker.random.word(),
object_id: `${faker.random.word()}:gene:${faker.datatype.uuid()}`,
object_type: 'gene',
label: faker.random.word()
type: 'gene',
label: [faker.random.word(), faker.random.word()]
});
const previouslyViewedObjects = [
{
genome_id: genomeId,
object_id: geneObjectId,
object_type: 'gene',
label: geneId
type: 'gene',
label: [geneId, versionedStableId]
},
{
genome_id: genomeId,
object_id: regionObjectId,
object_type: 'region',
label: region
type: 'region',
label: [region]
}
];
......@@ -158,22 +159,10 @@ describe('<TrackPanelBookmarks />', () => {
jest.resetAllMocks();
});
it('renders example links', () => {
wrapInRedux();
const exampleGeneLink = screen.getByText('Example gene') as HTMLElement;
const exampleRegionLink = screen.getByText('Example region') as HTMLElement;
const expectedGeneHref = `/genome-browser/${genomeId}?focus=gene:${geneId}`;
const expectedRegionHref = `/genome-browser/${genomeId}?focus=region:${region}`;
expect(exampleGeneLink.getAttribute('href')).toBe(expectedGeneHref);
expect(exampleRegionLink.getAttribute('href')).toBe(expectedRegionHref);
});
it('renders previously viewed links', () => {
wrapInRedux();
const geneLink = screen.getByText(geneId) as HTMLElement;
const regionLink = screen.getByText(region) as HTMLElement;
const geneLink = screen.getByText(geneId).closest('a') as HTMLElement;
const regionLink = screen.getByText(region).closest('a') as HTMLElement;
const expectedGeneHref = `/genome-browser/${genomeId}?focus=gene:${geneId}`;
const expectedRegionHref = `/genome-browser/${genomeId}?focus=region:${region}`;
......@@ -194,7 +183,7 @@ describe('<TrackPanelBookmarks />', () => {
(trackPanelActions.closeTrackPanelModal as any).mockRestore();
});
it('shows the ellipsis only when there are more than 20 objects', () => {
it('shows link to view more only when there are more than 20 objects', () => {
let wrapper = wrapInRedux(
set(
`browser.trackPanel.${genomeId}.previouslyViewedObjects`,
......@@ -202,10 +191,9 @@ describe('<TrackPanelBookmarks />', () => {
mockState
)
);
expect(
wrapper.container.querySelector(
'.trackPanelBookmarks .sectionTitle button'
)
wrapper.container.querySelector('.trackPanelBookmarks .more')
).toBeFalsy();
// Add 21 links to see if ellipsis is shown
......@@ -218,13 +206,11 @@ describe('<TrackPanelBookmarks />', () => {
);
expect(
wrapper.container.querySelector(
'.trackPanelBookmarks .sectionTitle button'
)
wrapper.container.querySelector('.trackPanelBookmarks .more')
).toBeTruthy();
});
it('changes drawer view and toggles drawer when the ellipsis is clicked', () => {
it('changes drawer view and toggles drawer when the "more" link is clicked', () => {
const { container } = wrapInRedux(
set(
`browser.trackPanel.${genomeId}.previouslyViewedObjects`,
......@@ -233,11 +219,11 @@ describe('<TrackPanelBookmarks />', () => {
)
);
const ellipsisButton = container.querySelector(
'.sectionTitle button'
const moreLink = container.querySelector(
'.trackPanelBookmarks .more span'
) as HTMLElement;
userEvent.click(ellipsisButton);
userEvent.click(moreLink);
const dispatchedDrawerActions = store.getActions();
......@@ -253,12 +239,4 @@ describe('<TrackPanelBookmarks />', () => {
);
expect(toggleDrawerAction.payload[genomeId]).toEqual(true);
});
it('renders correct number of links to example objects', () => {
const { container } = wrapInRedux();
expect(container.querySelectorAll('.exampleLinks a').length).toBe(
example_objects.length
);
});
});
......@@ -23,48 +23,13 @@ import analyticsTracking from 'src/services/analytics-service';
import * as urlFor from 'src/shared/helpers/urlHelper';
import { buildFocusIdForUrl } from 'src/shared/state/ens-object/ensObjectHelpers';
import { getBrowserActiveGenomeId } from 'src/content/app/browser/browserSelectors';
import { getActiveGenomePreviouslyViewedObjects } from 'src/content/app/browser/track-panel/trackPanelSelectors';
import { getExampleEnsObjects } from 'src/shared/state/ens-object/ensObjectSelectors';
import { closeTrackPanelModal } from '../../trackPanelActions';
import { changeDrawerViewAndOpen } from 'src/content/app/browser/drawer/drawerActions';
import ImageButton from 'src/shared/components/image-button/ImageButton';
import { ReactComponent as EllipsisIcon } from 'static/img/track-panel/ellipsis.svg';
import { Status } from 'src/shared/types/status';
import styles from './TrackPanelBookmarks.scss';
import { DrawerView } from 'src/content/app/browser/drawer/drawerState';
export const ExampleLinks = () => {
const exampleEnsObjects = useSelector(getExampleEnsObjects);
const activeGenomeId = useSelector(getBrowserActiveGenomeId);
const dispatch = useDispatch();
const onLinkClick = () => dispatch(closeTrackPanelModal());
return (
<div data-test-id="example links" className="exampleLinks">
<div className={styles.sectionTitle}>Example links</div>
{exampleEnsObjects.map((exampleObject) => {
const path = urlFor.browser({
genomeId: activeGenomeId,
focus: buildFocusIdForUrl(exampleObject.object_id)
});
return (
<div key={exampleObject.object_id} className={styles.linkHolder}>
<Link to={path} onClick={onLinkClick} replace>
Example {exampleObject.type}
</Link>
</div>
);
})}
</div>
);
};
export const PreviouslyViewedLinks = () => {
const previouslyViewedObjects = useSelector(
getActiveGenomePreviouslyViewedObjects
......@@ -82,36 +47,40 @@ export const PreviouslyViewedLinks = () => {
dispatch(closeTrackPanelModal());
};
const limitedPreviouslyViewedObjects = previouslyViewedObjects.slice(0, 20);
return (
<div data-test-id="previously viewed links">
{[...previouslyViewedObjects]
.reverse()
.map((previouslyViewedObject, index) => {
const path = urlFor.browser({
genomeId: previouslyViewedObject.genome_id,
focus: buildFocusIdForUrl(previouslyViewedObject.object_id)
});
{limitedPreviouslyViewedObjects.map((previouslyViewedObject, index) => {
const path = urlFor.browser({
genomeId: previouslyViewedObject.genome_id,
focus: buildFocusIdForUrl(previouslyViewedObject.object_id)
});
return (
<div
key={previouslyViewedObject.object_id}
className={styles.linkHolder}
return (
<div
key={previouslyViewedObject.object_id}
className={styles.linkHolder}
>
<Link
replace
to={path}
onClick={() => onLinkClick(previouslyViewedObject.type, index)}
>
<Link
replace
to={path}
onClick={() =>
onLinkClick(previouslyViewedObject.object_type, index)
}
>
{previouslyViewedObject.label}
</Link>
<span className={styles.previouslyViewedType}>
{upperFirst(previouslyViewedObject.object_type)}
</span>
</div>
);
})}
{previouslyViewedObject.label.map((label, index) => {
return (
<span key={index} className={styles.label}>
{label}
</span>
);
})}
</Link>
<span className={styles.type}>
{upperFirst(previouslyViewedObject.type)}
</span>
</div>
);
})}
</div>
);
};
......@@ -120,12 +89,9 @@ export const TrackPanelBookmarks = () => {
const previouslyViewedObjects = useSelector(
getActiveGenomePreviouslyViewedObjects
);
const exampleEnsObjects = useSelector(getExampleEnsObjects);
const dispatch = useDispatch();
const limitedPreviouslyViewedObjects = previouslyViewedObjects.slice(-20);
const onEllipsisClick = () => {
const onMoreClick = () => {
analyticsTracking.trackEvent({
category: 'drawer_open',
label: 'recent_bookmarks',
......@@ -137,25 +103,16 @@ export const TrackPanelBookmarks = () => {
};
return (
<section className="trackPanelBookmarks">
<div className={styles.title}>Bookmarks</div>
{exampleEnsObjects.length ? <ExampleLinks /> : null}
{limitedPreviouslyViewedObjects.length ? (
<section className={styles.trackPanelBookmarks}>
<div className={styles.title}>Previously viewed</div>
{previouslyViewedObjects.length ? (
<>
<div data-test-id="previously viewed" className={styles.sectionTitle}>
Previously viewed
{previouslyViewedObjects.length > 20 && (
<span className={styles.ellipsis}>
<ImageButton
status={Status.DEFAULT}
description={'View all'}
image={EllipsisIcon}
onClick={onEllipsisClick}
/>
</span>
)}
</div>
<PreviouslyViewedLinks />
{previouslyViewedObjects.length > 20 && (
<div className={styles.more}>
<span onClick={onMoreClick}>more...</span>
</div>
)}
</>
) : null}
</section>
......
......@@ -51,236 +51,235 @@ export const updateTrackPanelForGenome = createAction(
}
)();
export const toggleTrackPanel = (
isTrackPanelOpened: boolean
): ThunkAction<void, any, null, Action<string>> => (
dispatch,
getState: () => RootState
) => {
const activeGenomeId = getBrowserActiveGenomeId(getState());
if (!activeGenomeId) {
return;
}
dispatch(
updateTrackPanelForGenome({
activeGenomeId,
data: {
...getActiveTrackPanel(getState()),
isTrackPanelOpened
}
})
);
};
export const selectTrackPanelTab = (
selectedTrackPanelTab: TrackSet
): ThunkAction<void, any, null, Action<string>> => (
dispatch,
getState: () => RootState
) => {
const activeGenomeId = getBrowserActiveGenomeId(getState());
if (!activeGenomeId) {
return;
}
analyticsTracking.trackEvent({
category: 'track_panel_tab',
label: selectedTrackPanelTab,
action: 'selected'
});
dispatch(
updateTrackPanelForGenome({
activeGenomeId,
data: {
...getActiveTrackPanel(getState()),
selectedTrackPanelTab,
isTrackPanelModalOpened: false,
trackPanelModalView: ''
}
})
);
};
export const changeTrackPanelModalViewForGenome = (
trackPanelModalView: string
): ThunkAction<void, any, null, Action<string>> => (
dispatch,
getState: () => RootState
) => {
const activeGenomeId = getBrowserActiveGenomeId(getState());
if (!activeGenomeId) {
return;
}
dispatch(
updateTrackPanelForGenome({
activeGenomeId,
data: {
...getActiveTrackPanel(getState()),