Unverified Commit cbc8f2ce authored by Imran Salam's avatar Imran Salam Committed by GitHub
Browse files

Blast icon status (#750)

parent 0f53e582
Pipeline #281203 passed with stages
in 4 minutes and 52 seconds
/**
* 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, { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom';
import { useAppSelector } from 'src/store';
import { getUnviewedBlastSubmissions } from 'src/content/app/tools/blast/state/blast-results/blastResultsSelectors';
import LaunchbarButtonWithNotification from './LaunchbarButtonWithNotification';
import { BlastIcon } from 'src/shared/components/app-icon';
import styles from './Launchbar.scss';
const BLAST_APP_ROOT_PATH = '/blast';
const BlastLaunchbarButton = () => {
const unviewedSubmissions = useAppSelector(getUnviewedBlastSubmissions);
const location = useLocation();
const [blastAppPath, setBlastAppPath] = useState(BLAST_APP_ROOT_PATH);
useEffect(() => {
if (location.pathname.startsWith(BLAST_APP_ROOT_PATH)) {
setBlastAppPath(location.pathname);
}
}, [[location.pathname]]);
const getNotification = () => {
if (unviewedSubmissions.length > 0) {
const isAnyJobRunning =
unviewedSubmissions.filter((submission) =>
submission.results.some((job) => job.status === 'RUNNING')
).length > 0;
return isAnyJobRunning ? 'red' : 'green';
} else {
return null;
}
};
return (
<div className={styles.category}>
<LaunchbarButtonWithNotification
path={blastAppPath}
description="BLAST"
icon={BlastIcon}
notification={getNotification()}
/>
</div>
);
};
export default BlastLaunchbarButton;
......@@ -91,3 +91,25 @@
margin-left: 0.5rem;
margin-right: 0.5rem;
}
.toolsIconWrapper {
position: relative;
}
.notification {
border-radius: 10px;
height: var(--launchbar-notification-size, 18px);
width: var(--launchbar-notification-size, 18px);
position: absolute;
top: 0;
right: 0;
transform: translate(50%, -50%);
&Red {
background-color: $red;
}
&Green {
background-color: $green;
}
}
......@@ -16,7 +16,8 @@
import React from 'react';
import { Link } from 'react-router-dom';
import { useSelector } from 'react-redux';
import { useAppSelector } from 'src/store';
import { isEnvironment, Environment } from 'src/shared/helpers/environment';
......@@ -27,11 +28,11 @@ import {
SpeciesSelectorIcon,
GlobalSearchIcon,
EntityViewerIcon,
BlastIcon,
CustomDownloadIcon,
HelpIcon
} from 'src/shared/components/app-icon';
import LaunchbarButton from './LaunchbarButton';
import BlastLaunchbarButton from './BlastLaunchbarButton';
import Logotype from 'static/img/brand/logotype.svg';
......@@ -42,7 +43,7 @@ export const getCategoryClass = (separator: boolean): string => {
};
const Launchbar = () => {
const committedSpecies = useSelector(getEnabledCommittedSpecies);
const committedSpecies = useAppSelector(getEnabledCommittedSpecies);
return (
<div className={styles.launchbar}>
......@@ -50,13 +51,13 @@ const Launchbar = () => {
<div className={styles.categories}>
<div className={styles.category}>
<LaunchbarButton
app="global-search"
path="/global-search"
description="Site search"
icon={GlobalSearchIcon}
enabled={false}
/>
<LaunchbarButton
app="species-selector"
path="/species-selector"
description="Species selector"
icon={SpeciesSelectorIcon}
enabled={true}
......@@ -64,7 +65,7 @@ const Launchbar = () => {
</div>
<div className={styles.category}>
<LaunchbarButton
app="genome-browser"
path="/genome-browser"
description="Genome browser"
icon={GenomeBrowserIcon}
enabled={true}
......@@ -72,7 +73,7 @@ const Launchbar = () => {
</div>
<div className={styles.category}>
<LaunchbarButton
app="entity-viewer"
path="/entity-viewer"
description="Entity Viewer"
icon={EntityViewerIcon}
enabled={true}
......@@ -80,18 +81,13 @@ const Launchbar = () => {
</div>
{isEnvironment([Environment.DEVELOPMENT, Environment.INTERNAL]) && (
<div className={styles.category}>
<LaunchbarButton
app="blast"
description="BLAST"
icon={BlastIcon}
enabled={true}
/>
<BlastLaunchbarButton />
</div>
)}
{isEnvironment([Environment.DEVELOPMENT, Environment.INTERNAL]) && (
<div className={styles.category}>
<LaunchbarButton
app="custom-download"
path="/custom-download"
description="Downloads"
icon={CustomDownloadIcon}
enabled={committedSpecies.length > 0}
......@@ -100,7 +96,7 @@ const Launchbar = () => {
)}
<div className={styles.category}>
<LaunchbarButton
app="help"
path="/help"
description="Help & documentation"
icon={HelpIcon}
enabled={true}
......
......@@ -26,8 +26,8 @@ import { Status } from 'src/shared/types/status';
import styles from './Launchbar.scss';
type LaunchbarButtonProps = {
app: string;
export type LaunchbarButtonProps = {
path: string;
description: string;
icon: FunctionComponent<unknown> | string;
enabled: boolean;
......@@ -37,8 +37,7 @@ const LaunchbarButton: FunctionComponent<LaunchbarButtonProps> = (
props: LaunchbarButtonProps
) => {
const location = useLocation();
const pathTo = `/${props.app}`;
const isActive = new RegExp(`^${pathTo}`).test(location.pathname);
const isActive = new RegExp(`^${props.path}`).test(location.pathname);
const imageButtonStatus = getImageButtonStatus({
isDisabled: !props.enabled,
isActive
......@@ -68,7 +67,7 @@ const LaunchbarButton: FunctionComponent<LaunchbarButtonProps> = (
className={({ isActive }) =>
isActive ? activeButtonClass : styles.launchbarButton
}
to={pathTo}
to={props.path}
>
{imageButton}
</NavLink>
......
/**
* 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 from 'react';
import classNames from 'classnames';
import LaunchbarButton, { LaunchbarButtonProps } from './LaunchbarButton';
import styles from './Launchbar.scss';
type Notification = 'red' | 'green';
type LaunchbarButtonWithNotificationProps = LaunchbarButtonProps & {
notification: Notification | null;
};
const LaunchbarButtonWithNotification = (
props: LaunchbarButtonWithNotificationProps
) => {
const getNotificationClasses = () =>
classNames(styles.notification, {
[styles.notificationRed]: props.notification === 'red',
[styles.notificationGreen]: props.notification === 'green'
});
const WrappedIcon = () => {
const { icon: Icon } = props;
return (
<div className={styles.toolsIconWrapper}>
<Icon />
{props.notification && <div className={getNotificationClasses()}></div>}
</div>
);
};
return <LaunchbarButton {...props} icon={WrappedIcon} />;
};
LaunchbarButtonWithNotification.defaultProps = {
enabled: true
};
export default LaunchbarButtonWithNotification;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment