Merge remote-tracking branch 'origin/master' into lookup-form-component

This commit is contained in:
kialam
2019-01-07 14:40:35 -05:00
49 changed files with 1971 additions and 1136 deletions

View File

@@ -13,10 +13,8 @@ import heroImg from '@patternfly/patternfly-next/assets/images/pfbg_992.jpg';
import brandImg from '../../images/tower-logo-white.svg';
import logoImg from '../../images/tower-logo-login.svg';
import { ConfigContext } from '../context';
class About extends React.Component {
createSpeechBubble = (version) => {
static createSpeechBubble (version) {
let text = `Tower ${version}`;
let top = '';
let bottom = '';
@@ -33,52 +31,56 @@ class About extends React.Component {
return top + text + bottom;
}
handleModalToggle = () => {
const { onAboutModalClose } = this.props;
onAboutModalClose();
};
constructor (props) {
super(props);
this.createSpeechBubble = this.constructor.createSpeechBubble.bind(this);
}
render () {
const { isOpen } = this.props;
const {
ansible_version,
version,
isOpen,
onClose
} = this.props;
const speechBubble = this.createSpeechBubble(version);
return (
<I18n>
{({ i18n }) => (
<ConfigContext.Consumer>
{({ ansible_version, version }) => (
<AboutModal
isOpen={isOpen}
onClose={this.handleModalToggle}
productName="Ansible Tower"
trademark={i18n._(t`Copyright 2018 Red Hat, Inc.`)}
brandImageSrc={brandImg}
brandImageAlt={i18n._(t`Brand Image`)}
logoImageSrc={logoImg}
logoImageAlt={i18n._(t`AboutModal Logo`)}
heroImageSrc={heroImg}
>
<pre>
{this.createSpeechBubble(version)}
{`
<AboutModal
isOpen={isOpen}
onClose={onClose}
productName="Ansible Tower"
trademark={i18n._(t`Copyright 2018 Red Hat, Inc.`)}
brandImageSrc={brandImg}
brandImageAlt={i18n._(t`Brand Image`)}
logoImageSrc={logoImg}
logoImageAlt={i18n._(t`AboutModal Logo`)}
heroImageSrc={heroImg}
>
<pre>
{ speechBubble }
{`
\\
\\ ^__^
\\ ^__^
(oo)\\_______
(__) A )\\
||----w |
|| ||
`}
</pre>
<TextContent>
<TextList component="dl">
<TextListItem component="dt">
<Trans>Ansible Version</Trans>
</TextListItem>
<TextListItem component="dd">{ansible_version}</TextListItem>
</TextList>
</TextContent>
</AboutModal>
)}
</ConfigContext.Consumer>
</pre>
<TextContent>
<TextList component="dl">
<TextListItem component="dt">
<Trans>Ansible Version</Trans>
</TextListItem>
<TextListItem component="dd">{ ansible_version }</TextListItem>
</TextList>
</TextContent>
</AboutModal>
)}
</I18n>
);

View File

@@ -0,0 +1,25 @@
import React, { Fragment } from 'react';
import {
BackgroundImage,
BackgroundImageSrc,
} from '@patternfly/react-core';
const backgroundImageConfig = {
[BackgroundImageSrc.lg]: '/assets/images/pfbg_1200.jpg',
[BackgroundImageSrc.md]: '/assets/images/pfbg_992.jpg',
[BackgroundImageSrc.md2x]: '/assets/images/pfbg_992@2x.jpg',
[BackgroundImageSrc.sm]: '/assets/images/pfbg_768.jpg',
[BackgroundImageSrc.sm2x]: '/assets/images/pfbg_768@2x.jpg',
[BackgroundImageSrc.xl]: '/assets/images/pfbg_2000.jpg',
[BackgroundImageSrc.xs]: '/assets/images/pfbg_576.jpg',
[BackgroundImageSrc.xs2x]: '/assets/images/pfbg_576@2x.jpg',
[BackgroundImageSrc.filter]: '/assets/images/background-filter.svg',
};
export default ({ children }) => (
<Fragment>
<BackgroundImage src={backgroundImageConfig} />
{ children }
</Fragment>
);

View File

@@ -1,23 +0,0 @@
import React from 'react';
import {
Route,
Redirect
} from 'react-router-dom';
const ConditionalRedirect = ({
component: Component,
shouldRedirect,
redirectPath,
location,
...props
}) => (shouldRedirect() ? (
<Redirect to={{
pathname: redirectPath,
state: { from: location }
}}
/>
) : (
<Route {...props} render={rest => (<Component {...rest} />)} />
));
export default ConditionalRedirect;

View File

@@ -43,47 +43,66 @@ class DataListToolbar extends React.Component {
searchKey: sortedColumnKey,
searchValue: '',
};
this.handleSearchInputChange = this.handleSearchInputChange.bind(this);
this.onSortDropdownToggle = this.onSortDropdownToggle.bind(this);
this.onSortDropdownSelect = this.onSortDropdownSelect.bind(this);
this.onSearchDropdownToggle = this.onSearchDropdownToggle.bind(this);
this.onSearchDropdownSelect = this.onSearchDropdownSelect.bind(this);
this.onSearch = this.onSearch.bind(this);
this.onSort = this.onSort.bind(this);
}
handleSearchInputChange = searchValue => {
handleSearchInputChange (searchValue) {
this.setState({ searchValue });
};
}
onSortDropdownToggle = isSortDropdownOpen => {
onSortDropdownToggle (isSortDropdownOpen) {
this.setState({ isSortDropdownOpen });
};
}
onSortDropdownSelect = ({ target }) => {
onSortDropdownSelect ({ target }) {
const { columns, onSort, sortOrder } = this.props;
const { innerText } = target;
const [{ key }] = columns.filter(({ name }) => name === target.innerText);
const [{ key: searchKey }] = columns.filter(({ name }) => name === innerText);
this.setState({ isSortDropdownOpen: false });
onSort(searchKey, sortOrder);
}
onSort(key, sortOrder);
};
onSearchDropdownToggle = isSearchDropdownOpen => {
onSearchDropdownToggle (isSearchDropdownOpen) {
this.setState({ isSearchDropdownOpen });
};
}
onSearchDropdownSelect = ({ target }) => {
onSearchDropdownSelect ({ target }) {
const { columns } = this.props;
const { innerText } = target;
const targetName = target.innerText;
const [{ key }] = columns.filter(({ name }) => name === targetName);
const [{ key: searchKey }] = columns.filter(({ name }) => name === innerText);
this.setState({ isSearchDropdownOpen: false, searchKey });
}
this.setState({ isSearchDropdownOpen: false, searchKey: key });
};
onSearch () {
const { searchValue } = this.state;
const { onSearch } = this.props;
onSearch(searchValue);
}
onSort () {
const { onSort, sortedColumnKey, sortOrder } = this.props;
const newSortOrder = sortOrder === 'ascending' ? 'descending' : 'ascending';
onSort(sortedColumnKey, newSortOrder);
}
render () {
const { up } = DropdownPosition;
const {
columns,
isAllSelected,
onSearch,
onSelectAll,
onSort,
sortedColumnKey,
sortOrder,
addUrl,
@@ -97,29 +116,15 @@ class DataListToolbar extends React.Component {
searchValue,
} = this.state;
const [searchColumn] = columns
.filter(({ key }) => key === searchKey);
const searchColumnName = searchColumn.name;
const [sortedColumn] = columns
const [{ name: searchColumnName }] = columns.filter(({ key }) => key === searchKey);
const [{ name: sortedColumnName, isNumeric }] = columns
.filter(({ key }) => key === sortedColumnKey);
const sortedColumnName = sortedColumn.name;
const isSortNumeric = sortedColumn.isNumeric;
const displayedSortIcon = () => {
let icon;
if (sortOrder === 'ascending') {
icon = isSortNumeric ? (<SortNumericUpIcon />) : (<SortAlphaUpIcon />);
} else {
icon = isSortNumeric ? (<SortNumericDownIcon />) : (<SortAlphaDownIcon />);
}
return icon;
};
const searchDropdownItems = columns
.filter(({ key }) => key !== searchKey)
.map(({ key, name }) => (
<DropdownItem key={key} component="button">
{ name }
{name}
</DropdownItem>
));
@@ -127,17 +132,26 @@ class DataListToolbar extends React.Component {
.filter(({ key, isSortable }) => isSortable && key !== sortedColumnKey)
.map(({ key, name }) => (
<DropdownItem key={key} component="button">
{ name }
{name}
</DropdownItem>
));
let SortIcon;
if (isNumeric) {
SortIcon = sortOrder === 'ascending' ? SortNumericUpIcon : SortNumericDownIcon;
} else {
SortIcon = sortOrder === 'ascending' ? SortAlphaUpIcon : SortAlphaDownIcon;
}
return (
<I18n>
{({ i18n }) => (
<div className="awx-toolbar">
<Level>
<LevelItem>
<Toolbar style={{ marginLeft: '20px' }}>
<Toolbar
style={{ marginLeft: '20px' }}
>
<ToolbarGroup>
<ToolbarItem>
<Checkbox
@@ -152,6 +166,7 @@ class DataListToolbar extends React.Component {
<ToolbarItem>
<div className="pf-c-input-group">
<Dropdown
className="searchKeyDropdown"
onToggle={this.onSearchDropdownToggle}
onSelect={this.onSearchDropdownSelect}
direction={up}
@@ -160,7 +175,7 @@ class DataListToolbar extends React.Component {
<DropdownToggle
onToggle={this.onSearchDropdownToggle}
>
{ searchColumnName }
{searchColumnName}
</DropdownToggle>
)}
dropdownItems={searchDropdownItems}
@@ -174,14 +189,16 @@ class DataListToolbar extends React.Component {
<Button
variant="tertiary"
aria-label={i18n._(t`Search`)}
onClick={() => onSearch(searchValue)}
onClick={this.onSearch}
>
<i className="fas fa-search" aria-hidden="true" />
</Button>
</div>
</ToolbarItem>
</ToolbarGroup>
<ToolbarGroup>
<ToolbarGroup
className="sortDropdownGroup"
>
<ToolbarItem>
<Dropdown
onToggle={this.onSortDropdownToggle}
@@ -192,7 +209,7 @@ class DataListToolbar extends React.Component {
<DropdownToggle
onToggle={this.onSortDropdownToggle}
>
{ sortedColumnName }
{sortedColumnName}
</DropdownToggle>
)}
dropdownItems={sortDropdownItems}
@@ -200,23 +217,29 @@ class DataListToolbar extends React.Component {
</ToolbarItem>
<ToolbarItem>
<Button
onClick={() => onSort(sortedColumnKey, sortOrder === 'ascending' ? 'descending' : 'ascending')}
onClick={this.onSort}
variant="plain"
aria-label={i18n._(t`Sort`)}
>
{displayedSortIcon()}
<SortIcon/>
</Button>
</ToolbarItem>
</ToolbarGroup>
{ showExpandCollapse && (
{showExpandCollapse && (
<ToolbarGroup>
<ToolbarItem>
<Button variant="plain" aria-label={i18n._(t`Expand`)}>
<Button
variant="plain"
aria-label={i18n._(t`Expand`)}
>
<BarsIcon />
</Button>
</ToolbarItem>
<ToolbarItem>
<Button variant="plain" aria-label={i18n._(t`Collapse`)}>
<Button
variant="plain"
aria-label={i18n._(t`Collapse`)}
>
<EqualsIcon />
</Button>
</ToolbarItem>
@@ -225,14 +248,23 @@ class DataListToolbar extends React.Component {
</Toolbar>
</LevelItem>
<LevelItem>
<Tooltip message={i18n._(t`Delete`)} position="top">
<Button variant="plain" aria-label={i18n._(t`Delete`)}>
<Tooltip
message={i18n._(t`Delete`)}
position="top"
>
<Button
variant="plain"
aria-label={i18n._(t`Delete`)}
>
<TrashAltIcon />
</Button>
</Tooltip>
{addUrl && (
<Link to={addUrl}>
<Button variant="primary" aria-label={i18n._(t`Add`)}>
<Button
variant="primary"
aria-label={i18n._(t`Add`)}
>
<PlusIcon />
</Button>
</Link>

View File

@@ -1,62 +0,0 @@
import React, { Component, Fragment } from 'react';
import { Trans } from '@lingui/macro';
import {
Dropdown,
DropdownItem,
DropdownToggle,
DropdownPosition,
} from '@patternfly/react-core';
import { QuestionCircleIcon } from '@patternfly/react-icons';
import AboutModal from './About';
class HelpDropdown extends Component {
state = {
isOpen: false,
showAboutModal: false
};
render () {
const { isOpen, showAboutModal } = this.state;
const dropdownItems = [
<DropdownItem
href="https://docs.ansible.com/ansible-tower/latest/html/userguide/index.html"
target="_blank"
key="help"
>
<Trans>Help</Trans>
</DropdownItem>,
<DropdownItem
onClick={() => this.setState({ showAboutModal: true })}
key="about"
>
<Trans>About</Trans>
</DropdownItem>
];
return (
<Fragment>
<Dropdown
onSelect={() => this.setState({ isOpen: !isOpen })}
toggle={(
<DropdownToggle onToggle={(isToggleOpen) => this.setState({ isOpen: isToggleOpen })}>
<QuestionCircleIcon />
</DropdownToggle>
)}
isOpen={isOpen}
dropdownItems={dropdownItems}
position={DropdownPosition.right}
/>
{showAboutModal
? (
<AboutModal
isOpen={showAboutModal}
onAboutModalClose={() => this.setState({ showAboutModal: !showAboutModal })}
/>
)
: null }
</Fragment>
);
}
}
export default HelpDropdown;

View File

@@ -1,32 +0,0 @@
import React from 'react';
import { I18n } from '@lingui/react';
import { t } from '@lingui/macro';
import {
Button,
ButtonVariant
} from '@patternfly/react-core';
import { UserIcon } from '@patternfly/react-icons';
const LogoutButton = ({ onDevLogout }) => (
<I18n>
{({ i18n }) => (
<Button
id="button-logout"
aria-label={i18n._(t`Logout`)}
variant={ButtonVariant.plain}
onClick={onDevLogout}
onKeyDown={event => {
if (event.keyCode === 13) {
onDevLogout();
}
}}
>
<UserIcon />
</Button>
)}
</I18n>
);
export default LogoutButton;

View File

@@ -14,18 +14,23 @@ class NavExpandableGroup extends Component {
// Extract a list of paths from the route params and store them for later. This creates
// an array of url paths associated with any NavItem component rendered by this component.
this.navItemPaths = routes.map(({ path }) => path);
this.isActiveGroup = this.isActiveGroup.bind(this);
this.isActivePath = this.isActivePath.bind(this);
}
isActiveGroup = () => this.navItemPaths.some(this.isActivePath);
isActiveGroup () {
return this.navItemPaths.some(this.isActivePath);
}
isActivePath = (path) => {
isActivePath (path) {
const { history } = this.props;
return history.location.pathname.startsWith(path);
};
}
render () {
const { routes, groupId, staticContext, ...rest } = this.props;
const { groupId, groupTitle, routes } = this.props;
const isActive = this.isActiveGroup();
return (
@@ -33,7 +38,7 @@ class NavExpandableGroup extends Component {
isActive={isActive}
isExpanded={isActive}
groupId={groupId}
{...rest}
title={groupTitle}
>
{routes.map(({ path, title }) => (
<NavItem

View File

@@ -0,0 +1,129 @@
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { t } from '@lingui/macro';
import { I18n } from '@lingui/react';
import {
Dropdown,
DropdownItem,
DropdownToggle,
DropdownPosition,
Toolbar,
ToolbarGroup,
ToolbarItem,
} from '@patternfly/react-core';
import {
QuestionCircleIcon,
UserIcon,
} from '@patternfly/react-icons';
const DOCLINK = 'https://docs.ansible.com/ansible-tower/latest/html/userguide/index.html';
class PageHeaderToolbar extends Component {
constructor (props) {
super(props);
this.state = { isHelpOpen: false, isUserOpen: false };
this.onHelpSelect = this.onHelpSelect.bind(this);
this.onHelpToggle = this.onHelpToggle.bind(this);
this.onUserSelect = this.onUserSelect.bind(this);
this.onUserToggle = this.onUserToggle.bind(this);
}
onHelpSelect () {
const { isHelpOpen } = this.state;
this.setState({ isHelpOpen: !isHelpOpen });
}
onUserSelect () {
const { isUserOpen } = this.state;
this.setState({ isUserOpen: !isUserOpen });
}
onHelpToggle (isOpen) {
this.setState({ isHelpOpen: isOpen });
}
onUserToggle (isOpen) {
this.setState({ isUserOpen: isOpen });
}
render () {
const { isHelpOpen, isUserOpen } = this.state;
const { isAboutDisabled, onAboutClick, onLogoutClick } = this.props;
return (
<I18n>
{({ i18n }) => (
<Toolbar>
<ToolbarGroup>
<ToolbarItem>
<Dropdown
isOpen={isHelpOpen}
position={DropdownPosition.right}
onSelect={this.onHelpSelect}
toggle={(
<DropdownToggle
onToggle={this.onHelpToggle}
>
<QuestionCircleIcon />
</DropdownToggle>
)}
dropdownItems={[
<DropdownItem
key="help"
target="_blank"
href={DOCLINK}
>
{i18n._(t`Help`)}
</DropdownItem>,
<DropdownItem
key="about"
component="button"
isDisabled={isAboutDisabled}
onClick={onAboutClick}
>
{i18n._(t`About`)}
</DropdownItem>
]}
/>
</ToolbarItem>
<ToolbarItem>
<Dropdown
isOpen={isUserOpen}
position={DropdownPosition.right}
onSelect={this.onUserSelect}
toggle={(
<DropdownToggle
onToggle={this.onUserToggle}
>
<UserIcon />
</DropdownToggle>
)}
dropdownItems={[
<DropdownItem key="user">
<Link to="/home">
{i18n._(t`User Details`)}
</Link>
</DropdownItem>,
<DropdownItem
key="logout"
component="button"
onClick={onLogoutClick}
>
{i18n._(t`Logout`)}
</DropdownItem>
]}
/>
</ToolbarItem>
</ToolbarGroup>
</Toolbar>
)}
</I18n>
);
}
}
export default PageHeaderToolbar;

View File

@@ -7,14 +7,9 @@ import {
DropdownDirection,
DropdownItem,
DropdownToggle,
Form,
FormGroup,
Level,
LevelItem,
TextInput,
Toolbar,
ToolbarGroup,
ToolbarItem,
Split,
SplitItem,
} from '@patternfly/react-core';
@@ -23,24 +18,32 @@ class Pagination extends Component {
constructor (props) {
super(props);
const { page } = this.props;
const { page } = props;
this.state = { value: page, isOpen: false };
this.onPageChange = this.onPageChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.onFirst = this.onFirst.bind(this);
this.onPrevious = this.onPrevious.bind(this);
this.onNext = this.onNext.bind(this);
this.onLast = this.onLast.bind(this);
this.onTogglePageSize = this.onTogglePageSize.bind(this);
this.onSelectPageSize = this.onSelectPageSize.bind(this);
}
componentDidUpdate (prevProps) {
const { page } = this.props;
if (prevProps.page !== page) {
this.setState({ value: page });
this.onPageChange(page);
}
}
onPageChange = value => {
onPageChange (value) {
this.setState({ value });
};
}
onSubmit = event => {
onSubmit (event) {
const { onSetPage, page, pageCount, page_size } = this.props;
const { value } = this.state;
@@ -51,46 +54,42 @@ class Pagination extends Component {
if (isValid) {
onSetPage(value, page_size);
} else{
} else {
this.setState({ value: page });
}
};
}
onFirst = () => {
const { onSetPage, page_size} = this.props;
onFirst () {
const { onSetPage, page_size } = this.props;
onSetPage(1, page_size);
};
}
onPrevious = () => {
onPrevious () {
const { onSetPage, page, page_size } = this.props;
const previousPage = page - 1;
if (previousPage >= 1) {
onSetPage(previousPage, page_size)
}
};
onSetPage(previousPage, page_size);
}
onNext = () => {
onNext () {
const { onSetPage, page, pageCount, page_size } = this.props;
const nextPage = page + 1;
if (nextPage <= pageCount) {
onSetPage(nextPage, page_size)
}
};
onSetPage(nextPage, page_size);
}
onLast = () => {
onLast () {
const { onSetPage, pageCount, page_size } = this.props;
onSetPage(pageCount, page_size)
};
}
onTogglePageSize = isOpen => {
onTogglePageSize (isOpen) {
this.setState({ isOpen });
};
}
onSelectPageSize = ({ target }) => {
onSelectPageSize ({ target }) {
const { onSetPage } = this.props;
const page = 1;
@@ -99,7 +98,7 @@ class Pagination extends Component {
this.setState({ isOpen: false });
onSetPage(page, page_size);
};
}
render () {
const { up } = DropdownDirection;
@@ -140,22 +139,28 @@ class Pagination extends Component {
isOpen={isOpen}
toggle={(
<DropdownToggle
onToggle={this.onTogglePageSize}>
{ page_size }
className="togglePageSize"
onToggle={this.onTogglePageSize}
>
{page_size}
</DropdownToggle>
)}>
)}
>
{opts.map(option => (
<DropdownItem key={option} component="button">
{ option }
<DropdownItem
key={option}
component="button"
>
{option}
</DropdownItem>
))}
</Dropdown>
<Trans>Per Page</Trans>
<Trans> Per Page</Trans>
</LevelItem>
<LevelItem>
<Split gutter="md" className="pf-u-display-flex pf-u-align-items-center">
<SplitItem>
<Trans>{ itemMin } - { itemMax } of { count }</Trans>
<Trans>{itemMin} - {itemMax} of {count}</Trans>
</SplitItem>
<SplitItem>
<div className="pf-c-input-group">
@@ -196,7 +201,7 @@ class Pagination extends Component {
value={value}
type="text"
onChange={this.onPageChange}
/> of { pageCount }
/> of {pageCount}
</Trans>
</form>
</SplitItem>

View File

@@ -0,0 +1,40 @@
import React from 'react';
import { Link } from 'react-router-dom';
import './tabs.scss';
const Tab = ({ location, match, tab, currentTab, children, breadcrumb }) => {
const tabClasses = () => {
let classes = 'pf-c-tabs__item';
if (tab === currentTab) {
classes += ' pf-m-current';
}
return classes;
};
const tabParams = () => {
const params = new URLSearchParams(location.search);
if (params.get('tab') !== undefined) {
params.set('tab', tab);
} else {
params.append('tab', tab);
}
return `?${params.toString()}`;
};
return (
<li className={tabClasses()}>
<Link
className={'pf-c-tabs__button'}
to={{ pathname: `${match.url}`, search: tabParams(), state: { breadcrumb } }}
replace={tab === currentTab}>
{children}
</Link>
</li>
)
}
export default Tab;

View File

@@ -0,0 +1,13 @@
import React from 'react';
import './tabs.scss';
const Tabs = ({ children, labelText }) => (
<div className="pf-c-tabs" aria-label={labelText}>
<ul className="pf-c-tabs__list">
{children}
</ul>
</div>
);
export default Tabs;

View File

@@ -0,0 +1,50 @@
.at-c-orgPane {
a {
display: block;
}
}
.pf-c-card__header {
--pf-c-card__header--PaddingBottom: 0;
--pf-c-card__header--PaddingX: 0;
--pf-c-card__header--PaddingTop: 0;
}
.pf-c-tabs {
--pf-global--link--Color: #484848;
--pf-global--link--Color--hover: #484848;
--pf-global--link--TextDecoration--hover: none;
&:before {
border-bottom: 1px solid var(--pf-c-tabs__item--BorderColor);
border-top: 1px solid var(--pf-c-tabs__item--BorderColor);
bottom: 0;
content: " ";
left: 0;
position: absolute;
right: 0;
top: 0;
}
.pf-c-tabs__button {
--pf-c-tabs__button--PaddingLeft: 20px;
--pf-c-tabs__button--PaddingRight: 20px;
}
.pf-c-tabs__item.pf-m-current
.pf-c-tabs__button::after {
border-bottom: 3px solid var(--pf-c-tabs__item--m-current--Color);
border-top: none;
}
.pf-c-tabs__item:not(.pf-m-current):hover
.pf-c-tabs__button::after {
border-bottom: 3px solid var(--pf-global--Color--dark-200);
border-top: none;
}
}
.pf-c-breadcrumb__item.heading {
flex: 100%;
font-size: 20px;
}

View File

@@ -12,31 +12,31 @@ class TowerLogo extends Component {
super(props);
this.state = { hover: false };
this.onClick = this.onClick.bind(this);
this.onHover = this.onHover.bind(this);
}
onClick = () => {
const { history, onClick: handleClick } = this.props;
onClick () {
const { history, linkTo } = this.props;
if (!handleClick) return;
if (!linkTo) return;
history.push('/');
history.push(linkTo);
}
handleClick();
};
onHover = () => {
onHover () {
const { hover } = this.state;
this.setState({ hover: !hover });
};
}
render () {
const { hover } = this.state;
const { onClick: handleClick } = this.props;
let src = TowerLogoHeader;
if (hover && handleClick) {
if (hover) {
src = TowerLogoHeaderHover;
}