Unverified Commit 7ea2128c authored by Manoj Pandian Sakthivel's avatar Manoj Pandian Sakthivel Committed by GitHub
Browse files

Contact us overlay (#536)

parent f21c940e
Pipeline #179568 passed with stages
in 4 minutes and 32 seconds
@import 'src/styles/common';
.browserInnerWrapper {
display: grid;
align-items: start;
grid-template-rows: 80px 1fr;
}
.exampleLinks {
margin-top: 50px;
padding-left: 80px;
......
......@@ -117,7 +117,7 @@ export const Browser = (props: BrowserProps) => {
return (
<ApolloProvider client={client}>
<div className={styles.browserInnerWrapper}>
<div>
<BrowserAppBar onSpeciesSelect={changeGenomeId} />
{props.activeGenomeId && props.browserQueryParams.focus ? (
<StandardAppLayout
......
......@@ -5,10 +5,20 @@
}
.appBar {
display: flex;
display: grid;
align-items: center;
height: 80px;
padding: 0 44px;
height: 86px;
padding-left: 44px;
grid-template-columns: 100px auto;
.conversationIcon{
justify-self: end;
width: 40px;
height: 24px;
margin-right: 20px;
margin-top: 29px;
}
}
.main {
......
......@@ -19,6 +19,7 @@ import { useLocation } from 'react-router';
import useApiService from 'src/shared/hooks/useApiService';
import ConversationIcon from 'ensemblRoot/src/shared/components/communication-framework/ConversationIcon';
import HelpMenu from './components/help-menu/HelpMenu';
import HelpLanding from './components/help-landing/HelpLanding';
import {
......@@ -66,7 +67,14 @@ const Help = () => {
};
const AppBar = () => {
return <div className={styles.appBar}>Help</div>;
return (
<div className={styles.appBar}>
Help
<div className={styles.conversationIcon}>
<ConversationIcon />
</div>
</div>
);
};
const MainContent = (props: { article: ArticleData }) => {
......
......@@ -37,6 +37,11 @@ jest.mock('connected-react-router', () => ({
push: jest.fn(() => ({ type: 'push' }))
}));
jest.mock(
'ensemblRoot/src/shared/components/communication-framework/ConversationIcon',
() => () => <div>ConversationIcon</div>
);
const defaultProps = {
selectedSpecies: times(5, () => createSelectedSpecies()),
push
......
......@@ -84,30 +84,36 @@
.homeTopRight {
position: absolute;
top: 0;
right: 30px;
top: 7px;
right: 20px;
color: $blue;
font-weight: $bold;
display: grid;
grid-template-columns: auto auto;
height: 40px;
cursor: pointer;
height: 28px;
.wrapper {
.howToUse {
display: grid;
grid-template-columns: 130px auto;
}
.text {
margin-top: 10px;
align-self: center;
}
.helpIcon {
width: 32px;
height: 32px;
width: 25px;
height: 22px;
border-radius: 5px;
fill: $white;
background-color: $blue;
}
.conversationIcon {
width: 40px;
margin-left: 15px;
height: 25px;
}
}
.speciesContainer {
......
......@@ -17,6 +17,8 @@
import React from 'react';
import { Link } from 'react-router-dom';
import ConversationIcon from 'ensemblRoot/src/shared/components/communication-framework/ConversationIcon';
import { ReactComponent as Logotype } from 'static/img/brand/logotype.svg';
import { ReactComponent as SpeciesSelectorIcon } from 'static/img/launchbar/species-selector.svg';
import { ReactComponent as BrowserIcon } from 'static/img/launchbar/browser.svg';
......@@ -33,7 +35,7 @@ import styles from './Home.scss';
const Home = () => {
const helpButton = (
<div className={styles.wrapper}>
<div className={styles.howToUse}>
<div className={styles.text}>How to use Ensembl</div>
<HelpIcon className={styles.helpIcon} />
</div>
......@@ -93,6 +95,9 @@ const Home = () => {
<div className={styles.homeTopRight}>
<Link to="/help">{helpButton}</Link>
<div className={styles.conversationIcon}>
<ConversationIcon />
</div>
</div>
</div>
......
......@@ -27,23 +27,19 @@ export const setBreakpointWidth = createAction(
'browser/update-breakpoint-width'
)<BreakpointWidth>();
export const saveScrollPosition = createAction('update-scroll-position')<
ScrollPosition
>();
export const saveScrollPosition = createAction(
'update-scroll-position'
)<ScrollPosition>();
export const updateBreakpointWidth: ActionCreator<ThunkAction<
void,
any,
null,
Action<string>
>> = (viewportWidth: BreakpointWidth) => async (
dispatch,
getState: () => RootState
) => {
export const updateBreakpointWidth: ActionCreator<
ThunkAction<void, any, null, Action<string>>
> =
(viewportWidth: BreakpointWidth) =>
async (dispatch, getState: () => RootState) => {
const state = getState();
const currentBreakpointWidth = getBreakpointWidth(state);
if (viewportWidth !== currentBreakpointWidth) {
dispatch(setBreakpointWidth(viewportWidth));
}
};
};
......@@ -25,6 +25,7 @@ import global from '../global/globalReducer';
import header from '../header/headerReducer';
import ensObjects from '../shared/state/ens-object/ensObjectReducer';
import inAppSearch from '../shared/state/in-app-search/inAppSearchSlice';
import communication from '../shared/state/communication/communicationSlice';
import speciesSelector from '../content/app/species-selector/state/speciesSelectorReducer';
import entityViewer from 'src/content/app/entity-viewer/state/entityViewerReducer';
import speciesPage from 'src/content/app/species/state/index';
......@@ -34,6 +35,7 @@ const createRootReducer = (history: any) =>
browser,
drawer,
customDownload,
communication,
ensObjects,
inAppSearch,
genome,
......
......@@ -3,6 +3,7 @@
.appBar {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(250px, auto);
grid-template-rows: auto 40px;
align-content: start;
grid-template-areas:
'top top'
......@@ -31,12 +32,19 @@
grid-area: main;
margin-left: 2em;
max-width: 100%;
align-self: start;
}
.appBarAside {
grid-area: right;
display: flex;
justify-content: flex-end;
.conversationIcon {
width: 40px;
margin-left: 15px;
height: 25px;
}
}
.helpLink {
......
......@@ -16,6 +16,7 @@
import React from 'react';
import ConversationIcon from 'ensemblRoot/src/shared/components/communication-framework/ConversationIcon';
import Chevron from 'src/shared/components/chevron/Chevron';
import styles from './AppBar.scss';
......@@ -30,7 +31,12 @@ export const AppBar = (props: AppBarProps) => (
<section className={styles.appBar}>
<div className={styles.appBarTop}>{props.appName}</div>
<div className={styles.appBarMain}>{props.mainContent}</div>
<div className={styles.appBarAside}>{props.aside}</div>
<div className={styles.appBarAside}>
{props.aside}
<div className={styles.conversationIcon}>
<ConversationIcon />
</div>
</div>
</section>
);
......
@import 'src/styles/common';
.wrapper {
position: fixed;
width: 100%;
height: 100%;
top: 1px;
z-index: 11; /* Need to go above the top bar */
}
.panelWrapper {
position: fixed;
right: 0;
top: 110px;
z-index: 11; /* Need to go above the top bar */
height: calc(100% - 150px);
max-height: 750px;
animation: .3s ease-out 0s 1 slideInFromRight;
}
.panel {
position: relative;
min-height: 100px;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
max-width: 100%;
background: $white;
box-shadow: 1px 1px 4px $shadow-color;
height: 100%;
z-index: 2;
width: 750px;
}
.panelBody {
position: relative;
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
overflow: auto;
height: 100%;
}
.panelCloseButton {
position: absolute;
right: 25px;
top: 20px;
z-index: 1;
}
.panelContent {
display: grid;
grid-template-columns: 95px auto;
height: 100%;
.conversationIcon {
width: 40px;
margin: 17px 0 0 27px;
}
}
.overlay {
background-color: rgba(0, 0, 0, 0.1);
position: fixed;
}
@keyframes slideInFromRight {
0% {
transform: translateX(100%);
opacity: 0;
}
100% {
transform: translateX(0);
opacity: 1;
}
}
/**
* 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 { useDispatch, useSelector } from 'react-redux';
import Overlay from 'src/shared/components/overlay/Overlay';
import CloseButton from 'src/shared/components/close-button/CloseButton';
import { toggleCommunicationPanel } from 'src/shared/state/communication/communicationSlice';
import { isCommunicationPanelOpen } from 'src/shared/state/communication/communicationSelector';
import { ReactComponent as ConversationIcon } from 'static/img/shared/icon_conversation.svg';
import styles from './CommunicationPanel.scss';
const CommunicationPanel = () => {
const showCommunicationPanel = useSelector(isCommunicationPanelOpen);
const dispatch = useDispatch();
if (!showCommunicationPanel) {
return null;
}
const onClose = () => {
dispatch(toggleCommunicationPanel());
};
return (
<div className={styles.wrapper}>
<Overlay className={styles.overlay} />
<div className={styles.panelWrapper}>
<div className={styles.panel}>
<CloseButton className={styles.panelCloseButton} onClick={onClose} />
<div className={styles.panelBody}>
<div className={styles.panelContent}>
<div className={styles.conversationIcon}>
<ConversationIcon />
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default CommunicationPanel;
/**
* 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 { useDispatch } from 'react-redux';
import { toggleCommunicationPanel } from 'src/shared/state/communication/communicationSlice';
import { ReactComponent as ConversationImageIcon } from 'static/img/shared/icon_conversation.svg';
import CommunicationPanel from 'ensemblRoot/src/shared/components/communication-framework/CommunicationPanel';
import { Environment, isEnvironment } from 'src/shared/helpers/environment';
import styles from './ConversationIcon.scss';
const ConversationIcon = () => {
const dispatch = useDispatch();
if (isEnvironment([Environment.PRODUCTION])) {
return null;
}
const onClick = () => {
dispatch(toggleCommunicationPanel());
};
return (
<>
<CommunicationPanel />
<ConversationImageIcon
onClick={onClick}
className={styles.conversationIcon}
/>
</>
);
};
export default ConversationIcon;
......@@ -14,7 +14,7 @@
display: inline-flex;
align-items: center;
padding: 0 3px;
height: 18px;
height: 22px;
background: $blue;
font-size: 0;
border-radius: 5px;
......
......@@ -7,5 +7,5 @@
left: 0;
right: 0;
background-color: rgba(255, 255, 255, 0.7);
z-index: 1;
z-index: 11; /* Need to go above the top bar */
}
......@@ -20,11 +20,12 @@ import styles from './Overlay.scss';
type OverlayProps = {
className?: string;
onClick?: () => void;
};
const Overlay = (props: OverlayProps) => {
const overlayClassNames = classNames(styles.overlayDefault, props.className);
return <div className={overlayClassNames}></div>;
return <div className={overlayClassNames} onClick={props.onClick}></div>;
};
export default Overlay;
......@@ -105,4 +105,11 @@ describe('<Tabs />', () => {
true
);
});
it('hides the header when there is no header', () => {
const { container } = renderPanel({ header: undefined });
const header = container.querySelector('.header') as HTMLElement;
expect(header).toBeFalsy();
});
});
......@@ -22,7 +22,7 @@ import CloseButton from 'src/shared/components/close-button/CloseButton';
import styles from './Panel.scss';
export type PanelProps = {
header: ReactNode;
header?: ReactNode;
children: ReactNode;
classNames?: {
panel?: string;
......@@ -55,7 +55,7 @@ const Panel = (props: PanelProps) => {
{onClose && (
<CloseButton className={closeButtonClassNames} onClick={onClose} />
)}
<div className={headerClassNames}>{header}</div>
{props.header && <div className={headerClassNames}>{header}</div>}
<div className={bodyClassNames}>
<div>{props.children}</div>
</div>
......
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