From ae395d3d1e22b4010fb27e2b250e14ff5b7d1b63 Mon Sep 17 00:00:00 2001 From: Justin McDavid Date: Thu, 28 Jul 2016 11:25:04 -0700 Subject: [PATCH 01/19] NavBar: Rework NavBar Justin & I cleaned the Navbar up and changed the styling a bit. Big internal refactor of the codebase. --- app/addons/auth/base.js | 49 ++--- app/addons/fauxton/appwrapper.js | 2 +- app/addons/fauxton/assets/less/fauxton.less | 1 + app/addons/fauxton/assets/less/navigation.less | 172 ++++++++++++++++ app/addons/fauxton/base.js | 3 +- .../navigation/__tests__/login-logout-test.js | 80 ++++++++ app/addons/fauxton/navigation/actiontypes.js | 6 +- app/addons/fauxton/navigation/components.react.jsx | 161 --------------- app/addons/fauxton/navigation/components/Brand.js | 36 ++++ app/addons/fauxton/navigation/components/Burger.js | 43 ++++ app/addons/fauxton/navigation/components/Footer.js | 33 +++ .../fauxton/navigation/components/LoginButton.js | 42 ++++ .../fauxton/navigation/components/LogoutButton.js | 46 +++++ app/addons/fauxton/navigation/components/NavBar.js | 109 ++++++++++ .../fauxton/navigation/components/NavLink.js | 51 +++++ app/addons/fauxton/navigation/container/NavBar.js | 79 ++++++++ app/addons/fauxton/navigation/stores.js | 29 ++- app/addons/setup/route.js | 2 + app/app.js | 19 ++ assets/less/fauxton.less | 5 +- assets/less/templates.less | 221 --------------------- package.json | 1 + 22 files changed, 770 insertions(+), 420 deletions(-) create mode 100644 app/addons/fauxton/assets/less/navigation.less create mode 100644 app/addons/fauxton/navigation/__tests__/login-logout-test.js delete mode 100644 app/addons/fauxton/navigation/components.react.jsx create mode 100644 app/addons/fauxton/navigation/components/Brand.js create mode 100644 app/addons/fauxton/navigation/components/Burger.js create mode 100644 app/addons/fauxton/navigation/components/Footer.js create mode 100644 app/addons/fauxton/navigation/components/LoginButton.js create mode 100644 app/addons/fauxton/navigation/components/LogoutButton.js create mode 100644 app/addons/fauxton/navigation/components/NavBar.js create mode 100644 app/addons/fauxton/navigation/components/NavLink.js create mode 100644 app/addons/fauxton/navigation/container/NavBar.js diff --git a/app/addons/auth/base.js b/app/addons/auth/base.js index 237a45065..b0c2808f9 100644 --- a/app/addons/auth/base.js +++ b/app/addons/auth/base.js @@ -14,35 +14,39 @@ import app from "../../app"; import FauxtonAPI from "../../core/api"; import Auth from "./routes"; import "./assets/less/auth.less"; +import Actions from './actions'; Auth.session = new Auth.Session(); FauxtonAPI.setSession(Auth.session); app.session = Auth.session; -Auth.initialize = function () { - FauxtonAPI.addHeaderLink({ - id: 'auth', - title: 'Login', - href: '#/login', - icon: 'fonticon-user', - bottomNav: true - }); +function cleanupAuthSection () { + FauxtonAPI.removeHeaderLink({ id: 'auth', footerNav: true }); +} + +Auth.initialize = function () { Auth.session.on('change', function () { var session = Auth.session; var link = {}; if (session.isAdminParty()) { - link = { + const link = { id: 'auth', title: 'Admin Party!', href: '#/createAdmin', icon: 'fonticon-user', bottomNav: true }; + + cleanupAuthSection(); + FauxtonAPI.addHeaderLink(link); + FauxtonAPI.hideLogin(); + } else if (session.isLoggedIn()) { - link = { + + const link = { id: 'auth', title: session.user().name, href: '#/changePassword', @@ -50,27 +54,14 @@ Auth.initialize = function () { bottomNav: true }; - // ensure the footer link is removed before adding it - FauxtonAPI.removeHeaderLink({ id: 'logout', footerNav: true }); - FauxtonAPI.addHeaderLink({ - id: 'logout', - footerNav: true, - href: '#logout', - title: 'Logout', - icon: '', - className: 'logout' - }); + cleanupAuthSection(); + FauxtonAPI.addHeaderLink(link); + FauxtonAPI.showLogout(); } else { - link = { - id: 'auth', - title: 'Login', - href: '#/login', - icon: 'fonticon-user', - bottomNav: true - }; - FauxtonAPI.removeHeaderLink({ id: 'logout', footerNav: true }); + cleanupAuthSection(); + FauxtonAPI.showLogin(); } - FauxtonAPI.updateHeaderLink(link); + }); Auth.session.fetchUser().then(function () { diff --git a/app/addons/fauxton/appwrapper.js b/app/addons/fauxton/appwrapper.js index b2cd9fcab..6056e38c1 100644 --- a/app/addons/fauxton/appwrapper.js +++ b/app/addons/fauxton/appwrapper.js @@ -14,7 +14,7 @@ import React from 'react'; import FauxtonAPI from '../../core/api'; import ComponentActions from '../components/actions'; import {NotificationController} from "./notifications/notifications.react"; -import {NavBar} from './navigation/components.react'; +import NavBar from './navigation/container/NavBar'; import NavbarActions from './navigation/actions'; class ContentWrapper extends React.Component { diff --git a/app/addons/fauxton/assets/less/fauxton.less b/app/addons/fauxton/assets/less/fauxton.less index 255589d52..c248f69c9 100644 --- a/app/addons/fauxton/assets/less/fauxton.less +++ b/app/addons/fauxton/assets/less/fauxton.less @@ -1 +1,2 @@ @import "components.less"; +@import "navigation.less"; diff --git a/app/addons/fauxton/assets/less/navigation.less b/app/addons/fauxton/assets/less/navigation.less new file mode 100644 index 000000000..f8b1b510b --- /dev/null +++ b/app/addons/fauxton/assets/less/navigation.less @@ -0,0 +1,172 @@ +.faux-navbar { + margin-top: 64px; + background-color: #3A2C2B; + + position: absolute; + left: 0; + top: 0; + bottom: 0; + z-index: 5; + +} + +.faux-navbar__itemarea { + .box-sizing(border-box); + border-bottom: 1px solid #3A2C2B; + height: 48px; + padding: 10px 20px; + line-height: 24px; +} + +.faux-navbar__version-footer { + color: #fff; + font-size: 10px; + text-align: center; + background-color: @brown; +} + +.faux-navbar__burger { + background-color: @primaryNav; + padding: 22px 0 22px 18px; + position: fixed; + z-index: 100; + top: 0; +} + +.faux-navbar--narrow { + width: @collapsedNavWidth; +} + +.faux-navbar--wide { + width: @navWidth; +} + +.faux-navbar__burger:hover .faux-navbar__burger__stripe { + background-color: #fff; +} + +.faux-navbar__burger__stripe { + height: 4px; + width: 24px; + .border-radius(2); + background-color: #B3B4B4; + margin: 2px 0px; +} + +.faux-navbar__link, .faux-logout__link, .faux-login__link { + display: block; + text-decoration: none; + cursor: pointer; +} + +.faux-navbar__link--active { + background-color: #AF2D24; + text-decoration: none; +} + +.faux-navbar__link--inactive { + background-color: #564E4C; +} + +.faux-navbar__link:hover, .faux-logout__link:hover, .faux-login__link:hover { + background-color: #E73D34; + text-decoration: none; +} + +.faux-navbar__link:active { + text-decoration: none; +} + +.faux-navbar__link:hover .faux-navbar__icon:before { + color: #fff; +} + +.faux-navbar__link--active .faux-navbar__icon:before { + color: #fff; +} + +.faux-navbar__icon { + margin-right: 14px; + color: #B3B4B4; + font-size: 24px; + vertical-align: middle; +} + +.faux-navbar__text { + margin: 0; + color: #fff; + vertical-align: middle; + font-size: 16px; + font-weight: normal; + font-family: Helvetica,sans-serif; + font-weight: 400; +} + +.faux-navbar__logout__text { + font-size: 12px; + color: #fff; +} + +.faux-navbar__logout__textcontainer { + text-align: center; + color: #fff; +} + +.faux-navbar__logout__textcontainer--narrow { + padding-bottom: 4px; + padding: 20px 0; +} + +.faux-navbar__logout__textcontainer--wide { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + padding: 20px; +} + +.faux-navbar__login__textcontainer { + text-align: center; + color: #fff; +} + +.faux-navbar__login__textcontainer--narrow { + padding-bottom: 4px; + padding: 20px 0; +} + +.faux-navbar__login__textcontainer--wide { + padding: 20px; +} + +.faux-navbar__brand { + margin: 20px 0 20px 0; + height: 50px; + padding: 10px 10px 10px 10px; + float: none; + background: #3a2c2b; +} + +.faux-navbar__brand-logo { + display: block; + height: 100%; + margin-top: 10px; +} + +.faux-navbar__brand-logo--wide { + background: url(../../../../../assets/img/CouchDB-negative-logo.png) no-repeat 23px 0px; + background-size: 150px; + width: 200px; +} + +.faux-navbar__brand-logo--narrow { + width: 43px; + height: 40px; + background: url(../../../../../assets/img/couchdb-logo.png) no-repeat 3px 0; + background-size: 40px; +} + +.faux-navbar__footer { + position: absolute; + bottom: 0; + width:100%; +} diff --git a/app/addons/fauxton/base.js b/app/addons/fauxton/base.js index 0509717f9..7440f612f 100644 --- a/app/addons/fauxton/base.js +++ b/app/addons/fauxton/base.js @@ -15,7 +15,7 @@ import FauxtonAPI from "../../core/api"; import React from "react"; import NotificationComponents from "./notifications/notifications.react"; import Actions from "./notifications/actions"; -import NavbarReactComponents from "./navigation/components.react"; + import NavigationActions from "./navigation/actions"; import ReactComponents from "../components/react-components.react"; import ComponentActions from "../components/actions"; @@ -26,7 +26,6 @@ import "./assets/less/fauxton.less"; const Fauxton = FauxtonAPI.addon(); Fauxton.initialize = () => { - const versionInfo = new Fauxton.VersionInfo(); versionInfo.fetch().then(function () { NavigationActions.setNavbarVersionInfo(versionInfo.get("version")); diff --git a/app/addons/fauxton/navigation/__tests__/login-logout-test.js b/app/addons/fauxton/navigation/__tests__/login-logout-test.js new file mode 100644 index 000000000..c7e161a5e --- /dev/null +++ b/app/addons/fauxton/navigation/__tests__/login-logout-test.js @@ -0,0 +1,80 @@ +// 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 { mount } from 'enzyme'; + +import NavBar from '../components/NavBar'; + +describe('Navigation Bar', () => { + + it('renders with login button when logged out', () => { + const props = { + activeLink: '', + isMinimized: false, + version: '42', + navLinks: [], + bottomNavLinks: [], + footerNavLinks: [], + + isLoginSectionVisible: true, + isLoginVisibleInsteadOfLogout: true + }; + + const navBar = mount(); + + const button = navBar.find('[href="#/login"]'); + expect(button.text()).toContain('Login'); + }); + + it('renders with logout button when logged in', () => { + const props = { + activeLink: '', + isMinimized: false, + version: '42', + navLinks: [], + bottomNavLinks: [], + footerNavLinks: [], + username: 'Rocko', + + isLoginSectionVisible: true, + isLoginVisibleInsteadOfLogout: false + }; + + const navBar = mount(); + + const button = navBar.find('[href="#/logout"]'); + expect(button.text()).toContain('Log Out'); + }); + + it('Admin Party has no Logout button and no Login button', () => { + const props = { + activeLink: '', + isMinimized: false, + version: '42', + navLinks: [], + bottomNavLinks: [], + footerNavLinks: [], + username: 'Rocko', + + isLoginSectionVisible: false, + isLoginVisibleInsteadOfLogout: false + }; + + const navBar = mount(); + + expect(/Login/.test(navBar.text())).toBe(false); + expect(/Log Out/.test(navBar.text())).toBe(false); + }); + +}); diff --git a/app/addons/fauxton/navigation/actiontypes.js b/app/addons/fauxton/navigation/actiontypes.js index b5515bdcd..3f1971016 100644 --- a/app/addons/fauxton/navigation/actiontypes.js +++ b/app/addons/fauxton/navigation/actiontypes.js @@ -19,5 +19,9 @@ export default { NAVBAR_SET_VERSION_INFO: 'NAVBAR_SET_VERSION_INFO', NAVBAR_ACTIVE_LINK: 'NAVBAR_ACTIVE_LINK', NAVBAR_HIDE: 'NAVBAR_HIDE', - NAVBAR_SHOW: 'NAVBAR_SHOW' + NAVBAR_SHOW: 'NAVBAR_SHOW', + + NAVBAR_SHOW_HIDE_LOGIN_LOGOUT_SECTION: 'NAVBAR_SHOW_HIDE_LOGIN_LOGOUT_SECTION', + NAVBAR_SHOW_LOGIN_BUTTON: 'NAVBAR_SHOW_LOGIN_BUTTON', + NAVBAR_SHOW_LOGOUT_BUTTON: 'NAVBAR_SHOW_LOGOUT_BUTTON' }; diff --git a/app/addons/fauxton/navigation/components.react.jsx b/app/addons/fauxton/navigation/components.react.jsx deleted file mode 100644 index 6e6101598..000000000 --- a/app/addons/fauxton/navigation/components.react.jsx +++ /dev/null @@ -1,161 +0,0 @@ -// 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 app from "../../../app"; -import FauxtonAPI from "../../../core/api"; -import React from "react"; -import ReactDOM from "react-dom"; -import Stores from "./stores"; -import Actions from "./actions"; -const navBarStore = Stores.navBarStore; - -const Footer = React.createClass({ - render () { - const version = this.props.version; - - if (!version) { return null; } - return ( -
- Fauxton on {" "} - Apache CouchDB - {" "} v. {version} -
- ); - } -}); - -const Burger = React.createClass({ - render () { - return ( -
-
-
-
-
- ); - } -}); - -const NavLink = React.createClass({ - render () { - const link = this.props.link; - const liClassName = this.props.active === link.title ? 'active' : ''; - - return ( -
  • - - - - -
  • - ); - } -}); - -export const NavBar = React.createClass({ - getStoreState () { - return { - navLinks: navBarStore.getNavLinks(), - bottomNavLinks: navBarStore.getBottomNavLinks(), - footerNavLinks: navBarStore.getFooterNavLinks(), - activeLink: navBarStore.getActiveLink(), - version: navBarStore.getVersion(), - isMinimized: navBarStore.isMinimized(), - isNavBarVisible: navBarStore.isNavBarVisible() - }; - }, - - getInitialState () { - return this.getStoreState(); - }, - - createLinks (links) { - return _.map(links, function (link, i) { - return ; - }, this); - }, - - onChange () { - this.setState(this.getStoreState()); - }, - - setMenuState () { - $('body').toggleClass('closeMenu', this.state.isMinimized); - FauxtonAPI.Events.trigger(FauxtonAPI.constants.EVENTS.NAVBAR_SIZE_CHANGED, this.state.isMinimized); - }, - - componentDidMount () { - navBarStore.on('change', this.onChange, this); - this.setMenuState(); - }, - - componentDidUpdate () { - this.setMenuState(); - }, - - componentWillUnmount () { - navBarStore.off('change', this.onChange); - }, - - toggleMenu () { - Actions.toggleNavbarMenu(); - }, - - render () { - //YUCK!! but we can only really fix this once we have removed all backbone - if (!this.state.isNavBarVisible) { - $('#primary-navbar').hide(); - return null; - } - - $('#primary-navbar').show(); - - const navLinks = this.createLinks(this.state.navLinks); - const bottomNavLinks = this.createLinks(this.state.bottomNavLinks); - const footerNavLinks = this.createLinks(this.state.footerNavLinks); - - return ( -
    - - -
    - -
    -
    -
    Apache Fauxton
    -
    - -
    - -
    -
    - ); - } -}); - -export default { - NavBar: NavBar, - Burger: Burger -}; diff --git a/app/addons/fauxton/navigation/components/Brand.js b/app/addons/fauxton/navigation/components/Brand.js new file mode 100644 index 000000000..158c04a0c --- /dev/null +++ b/app/addons/fauxton/navigation/components/Brand.js @@ -0,0 +1,36 @@ +// 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, { PropTypes } from 'react'; + +import classNames from 'classnames'; + +const Brand = ({toggleMenu, isMinimized}) => { + + const burgerClasses = classNames( + 'faux-navbar__brand-logo', + {'faux-navbar__brand-logo--wide': !isMinimized}, + {'faux-navbar__brand-logo--narrow': isMinimized} + ); + + return ( +
    +
    +
    + ); +}; + +Brand.propTypes = { + isMinimized: React.PropTypes.bool.isRequired +}; + +export default Brand; diff --git a/app/addons/fauxton/navigation/components/Burger.js b/app/addons/fauxton/navigation/components/Burger.js new file mode 100644 index 000000000..98742de14 --- /dev/null +++ b/app/addons/fauxton/navigation/components/Burger.js @@ -0,0 +1,43 @@ +// 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, { PropTypes } from 'react'; + +import classNames from 'classnames'; + +const Burger = ({toggleMenu, isMinimized}) => { + + const burgerClasses = classNames( + 'faux-navbar__burger', + {'faux-navbar--wide': !isMinimized}, + {'faux-navbar--narrow': isMinimized} + ); + + return ( +
    + + + +
    + ); +}; + +Burger.propTypes = { + toggleMenu: React.PropTypes.func.isRequired, + isMinimized: React.PropTypes.bool.isRequired +}; + +const Stripe = () => { + return
    ; +}; + +export default Burger; diff --git a/app/addons/fauxton/navigation/components/Footer.js b/app/addons/fauxton/navigation/components/Footer.js new file mode 100644 index 000000000..73a64a400 --- /dev/null +++ b/app/addons/fauxton/navigation/components/Footer.js @@ -0,0 +1,33 @@ +// 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, { PropTypes } from 'react'; + +const Footer = ({version}) => { + + if (!version) { return null; } + + return ( +
    + Fauxton on   + Apache CouchDB +   v. {version} +
    + ); + +}; + +Footer.propTypes = { + version: React.PropTypes.string +}; + +export default Footer; diff --git a/app/addons/fauxton/navigation/components/LoginButton.js b/app/addons/fauxton/navigation/components/LoginButton.js new file mode 100644 index 000000000..a11bdce9b --- /dev/null +++ b/app/addons/fauxton/navigation/components/LoginButton.js @@ -0,0 +1,42 @@ +// 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, { PropTypes } from 'react'; + +import classNames from 'classnames'; + +const LoginButton = ({isMinimized}) => { + + const containerClasses = classNames( + 'faux-navbar__login__textcontainer', + {'faux-navbar__login__textcontainer--narrow': isMinimized}, + {'faux-navbar__login__textcontainer--wide': !isMinimized} + ); + + return ( + + +
    + + Login + +
    + +
    + ); +}; + +LoginButton.propTypes = { + isMinimized: React.PropTypes.bool.isRequired +}; + +export default LoginButton; diff --git a/app/addons/fauxton/navigation/components/LogoutButton.js b/app/addons/fauxton/navigation/components/LogoutButton.js new file mode 100644 index 000000000..b324da5f0 --- /dev/null +++ b/app/addons/fauxton/navigation/components/LogoutButton.js @@ -0,0 +1,46 @@ +// 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, { PropTypes } from 'react'; + +import classNames from 'classnames'; +import _ from 'lodash'; + +const LogoutButton = ({username, isMinimized}) => { + + const containerClasses = classNames( + 'faux-navbar__logout__textcontainer', + {'faux-navbar__logout__textcontainer--narrow': isMinimized}, + {'faux-navbar__logout__textcontainer--wide': !isMinimized} + ); + + return ( + +
    + + Log Out + +   + + {isMinimized ? null : _.escape(username)} + +
    +
    + ); +}; + +LogoutButton.propTypes = { + username: React.PropTypes.string, + isMinimized: React.PropTypes.bool.isRequired +}; + +export default LogoutButton; diff --git a/app/addons/fauxton/navigation/components/NavBar.js b/app/addons/fauxton/navigation/components/NavBar.js new file mode 100644 index 000000000..6ce36d9bd --- /dev/null +++ b/app/addons/fauxton/navigation/components/NavBar.js @@ -0,0 +1,109 @@ +// 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, { Component, PropTypes } from 'react'; + +import FauxtonAPI from "../../../../core/api"; + +import Footer from './Footer'; +import Burger from './Burger'; +import NavLink from './NavLink'; +import Brand from './Brand'; +import LogoutButton from './LogoutButton'; +import LoginButton from './LoginButton'; + +import Actions from "../actions"; + +import classNames from 'classnames'; +import _ from 'lodash'; + +class NavBar extends Component { + + createLinks (links) { + const { activeLink, isMinimized } = this.props; + + return _.map(links, function (link, i) { + return ; + }, this); + } + + toggleMenu () { + Actions.toggleNavbarMenu(); + } + + render () { + const { + isMinimized, + version, + isLoginSectionVisible, + isLoginVisibleInsteadOfLogout, + activeLink, + username + } = this.props; + + const navLinks = this.createLinks(this.props.navLinks); + const bottomNavLinks = this.createLinks(this.props.bottomNavLinks); + const footerNavLinks = this.createLinks(this.props.footerNavLinks); + + const navClasses = classNames( + 'faux-navbar', + {'faux-navbar--wide': !isMinimized}, + {'faux-navbar--narrow': isMinimized} + ); + + const loginSection = isLoginVisibleInsteadOfLogout ? + : + ; + + return ( +
    + +
    +
    + ); + } +} + +NavBar.propTypes = { + activeLink: React.PropTypes.string, + isMinimized: React.PropTypes.bool.isRequired, + version: React.PropTypes.string, + username: React.PropTypes.string, + navLinks: React.PropTypes.array, + bottomNavLinks: React.PropTypes.array, + footerNavLinks: React.PropTypes.array, + isLoginSectionVisible: React.PropTypes.bool.isRequired, + isLoginVisibleInsteadOfLogout: React.PropTypes.bool.isRequired +}; + +export default NavBar; diff --git a/app/addons/fauxton/navigation/components/NavLink.js b/app/addons/fauxton/navigation/components/NavLink.js new file mode 100644 index 000000000..1c41b9a19 --- /dev/null +++ b/app/addons/fauxton/navigation/components/NavLink.js @@ -0,0 +1,51 @@ +// 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, { PropTypes } from 'react'; +import classNames from 'classnames'; + + +const NavLink = ({link, active, isMinimized}) => { + + const linkClass = classNames( + 'faux-navbar__link', + {'faux-navbar__link--active': active === link.title}, + {'faux-navbar__link--inactive': active !== link.title}, + {'faux-navbar--wide': !isMinimized}, + {'faux-navbar--narrow': isMinimized} + ); + + return ( + +
    + + {!!link.icon ? + : + null + } + {isMinimized ? + null : + {link.title} + } +
    +
    + ); +}; + +NavLink.propTypes = { + link: React.PropTypes.object.isRequired, + active: React.PropTypes.string, + isMinimized: React.PropTypes.bool.isRequired, +}; + + +export default NavLink; diff --git a/app/addons/fauxton/navigation/container/NavBar.js b/app/addons/fauxton/navigation/container/NavBar.js new file mode 100644 index 000000000..0aa3d0584 --- /dev/null +++ b/app/addons/fauxton/navigation/container/NavBar.js @@ -0,0 +1,79 @@ +// 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 app from "../../../../app"; +import FauxtonAPI from "../../../../core/api"; +import React from "react"; + +import ReactDOM from "react-dom"; +import Stores from "../stores"; + +import NavBar from '../components/NavBar'; + +const navBarStore = Stores.navBarStore; + +const NavBarContainer = React.createClass({ + + getStoreState () { + return { + navLinks: navBarStore.getNavLinks(), + bottomNavLinks: navBarStore.getBottomNavLinks(), + footerNavLinks: navBarStore.getFooterNavLinks(), + activeLink: navBarStore.getActiveLink(), + version: navBarStore.getVersion(), + isMinimized: navBarStore.isMinimized(), + isNavBarVisible: navBarStore.isNavBarVisible(), + + isLoginSectionVisible: navBarStore.getIsLoginSectionVisible(), + isLoginVisibleInsteadOfLogout: navBarStore.getIsLoginVisibleInsteadOfLogout() + }; + }, + + getInitialState () { + return this.getStoreState(); + }, + + onChange () { + this.setState(this.getStoreState()); + }, + + setMenuState () { + $('body').toggleClass('closeMenu', this.state.isMinimized); + FauxtonAPI.Events.trigger(FauxtonAPI.constants.EVENTS.NAVBAR_SIZE_CHANGED, this.state.isMinimized); + }, + + componentDidMount () { + navBarStore.on('change', this.onChange, this); + this.setMenuState(); + }, + + componentDidUpdate () { + this.setMenuState(); + }, + + componentWillUnmount () { + navBarStore.off('change', this.onChange); + }, + + render () { + const user = FauxtonAPI.session.user(); + + const username = user ? user.name : ''; + return ( + + ); + } + +}); + + +export default NavBarContainer; diff --git a/app/addons/fauxton/navigation/stores.js b/app/addons/fauxton/navigation/stores.js index 5e781a8f6..350feb7c3 100644 --- a/app/addons/fauxton/navigation/stores.js +++ b/app/addons/fauxton/navigation/stores.js @@ -13,8 +13,10 @@ import app from "../../../app"; import FauxtonAPI from "../../../core/api"; import ActionTypes from "./actiontypes"; -const Stores = {}; +import _ from 'lodash'; + +const Stores = {}; Stores.NavBarStore = FauxtonAPI.Store.extend({ initialize () { @@ -28,6 +30,17 @@ Stores.NavBarStore = FauxtonAPI.Store.extend({ this._footerNavLinks = []; this._bottomNavLinks = []; this._navBarVisible = true; + + this._loginSectionVisible = false; + this._loginVisibleInsteadOfLogout = true; + }, + + getIsLoginSectionVisible () { + return this._loginSectionVisible; + }, + + getIsLoginVisibleInsteadOfLogout () { + return this._loginVisibleInsteadOfLogout; }, isNavBarVisible () { @@ -185,6 +198,20 @@ Stores.NavBarStore = FauxtonAPI.Store.extend({ this.showNavBar(); break; + case ActionTypes.NAVBAR_SHOW_HIDE_LOGIN_LOGOUT_SECTION: + this._loginSectionVisible = action.visible; + break; + + case ActionTypes.NAVBAR_SHOW_LOGIN_BUTTON: + this._loginSectionVisible = true; + this._loginVisibleInsteadOfLogout = true; + break; + + case ActionTypes.NAVBAR_SHOW_LOGOUT_BUTTON: + this._loginSectionVisible = true; + this._loginVisibleInsteadOfLogout = false; + break; + default: return; // do nothing diff --git a/app/addons/setup/route.js b/app/addons/setup/route.js index b601abaf9..ccdb14fe7 100644 --- a/app/addons/setup/route.js +++ b/app/addons/setup/route.js @@ -22,6 +22,8 @@ import {OnePaneSimpleLayout} from '../components/layouts'; var RouteObject = FauxtonAPI.RouteObject.extend({ roles: ['_admin'], + selectedHeader: 'Setup', + routes: { 'setup': 'setupInitView', 'setup/finish': 'finishView', diff --git a/app/app.js b/app/app.js index 939418c29..120ff05ce 100644 --- a/app/app.js +++ b/app/app.js @@ -74,6 +74,25 @@ FauxtonAPI.config({ type: 'REMOVE_NAVBAR_LINK', link: link }); + }, + + hideLogin: function () { + FauxtonAPI.dispatch({ + type: 'NAVBAR_SHOW_HIDE_LOGIN_LOGOUT_SECTION', + visible: false + }); + }, + + showLogout: function () { + FauxtonAPI.dispatch({ + type: 'NAVBAR_SHOW_LOGOUT_BUTTON' + }); + }, + + showLogin: function () { + FauxtonAPI.dispatch({ + type: 'NAVBAR_SHOW_LOGIN_BUTTON' + }); } }); diff --git a/assets/less/fauxton.less b/assets/less/fauxton.less index fbdf0db77..24c4a524f 100644 --- a/assets/less/fauxton.less +++ b/assets/less/fauxton.less @@ -60,10 +60,6 @@ body { h2,h3,h4 {font-weight: 600;} -a { - .transition(all .25s linear); -} - // remove blue borders from clicked elements button:focus, a:focus { outline: 0; @@ -77,6 +73,7 @@ a, a:visited, a:active { color: @linkColor; + text-decoration: none; } a:hover { diff --git a/assets/less/templates.less b/assets/less/templates.less index a56434ded..bbe95d0b1 100644 --- a/assets/less/templates.less +++ b/assets/less/templates.less @@ -50,227 +50,6 @@ } } -/* Fixed side navigation */ -#primary-navbar { - z-index: 5; - height: 100%; - left: 0; - top: 0; - bottom: 0; - position: absolute; - width: @navWidth; - .closeMenu & { - width: @collapsedNavWidth; - overflow-x: hidden; - } - background-color: @primaryNav; - .version-footer { - color: #fff; - font-size: 10px; - text-align: center; - background-color: @brown; - } - .closeMenu & { - .version-footer { - display: none; - } - } - #user-create-admin { - font-size: 12px - } - .navbar { - .closeMenu & { - width: @collapsedNavWidth; - } - .burger { - padding: 22px 0 22px 18px; - position: fixed; - z-index: 100; - top: 0; - background-color: @primaryNav; - width: @navWidth; - .closeMenu & { - width: @collapsedNavWidth; - } - div { - height: 4px; - width: 24px; - .border-radius(2); - background-color: @navBG; - margin: 2px 0px; - } - &:hover div { - background-color: @navBGHover; - } - } - .bottom-container { - position: fixed; - bottom: 10px; - .brand { - .box-sizing(content-box); - .hide-text; - margin: 20px 0 0px 0; - width: 199px; - height: 50px; - padding: 10px 10px 10px 10px; - float: none; - background: #3a2c2b; - .icon { - .box-sizing(content-box); - background: url(../img/CouchDB-negative-logo.png) no-repeat 23px 0px; - background-size: 150px; - display: block; - height: 100%; - width: 100%; - margin-top: 10px; - } - .closeMenu & { - width: 43px; - - .icon { - background: url(../img/couchdb-logo.png) no-repeat 3px 0; - background-size: 40px; - - } - } - } - - #footer-nav-links { - width: 100%; - margin: 0; - background: @brown; - - li { - width: 100%; - text-align: center; - - a { - font-size: 10px; - color: @linkColor; - padding: 0px; - text-shadow: none; - width: 100%; - } - - &.active, &:hover { - a { - text-decoration: underline; - color: @darkRed; - } - } - } - } - } - nav { - margin-top: 64px; - .nav { - margin: 0; - li { - padding: 0; - font-size: 16px; - letter-spacing: 1px; - line-height: 24px; - width: @navWidth; - .closeMenu & { - width: @collapsedNavWidth; - } - font-weight: normal; - font-family: helvetica; - .box-sizing(border-box); - background-color: @navBG; - border-bottom: 1px solid @primaryNav; - height: 48px; - min-height: 48px; - position: relative; - - &.active, &:hover { - a { - .box-shadow(none); - } - background-color: @navBGHover; - } - &:hover .fonticon:before { - color: @white; - } - &.active .fonticon:before, - &:hover .fonticon:before, - { - text-shadow: @boxShadow; - color: @NavIconActive; - } - a { - padding: 12px 25px 12px 60px; - background-color: transparent; - color: #fff; - text-shadow: @textShadowOff; - height: 48px; - display: flex; - - .fonticon { - position: relative; - - &:before { - position: absolute; - left: -41px; - font-size: 24px; - color: @NavIcon; - text-shadow: @boxShadowOff; - } - } - .closeMenu & { - color: transparent; - span { - display: none; - } - } - } - } - } - ul#footer-nav-links { - li { - background-color: @primaryNav; - border-top: 1px solid @linkColor; - border-bottom: none; - &.active, &:hover { - background-color: @navBGHover; - border-top: 1px solid @linkColor; - a { - color: white; - } - } - a { - color: @linkColor; - } - } - - } - ul#bottom-nav-links { - margin-top: 0; - padding-bottom: 136px; - li { - background-color: @bottomNav; - &.active { - background-color:@navBGHover; - } - &:hover { - background-color: @navBGHover; - } - a { - &.fonticon { - position: relative; - &:before { - top: -5px; - left: -40px; - font-size: 22px; - } - } - } - } - } - } - } -} - .bottom-shadow-border { border-bottom: 1px solid #999; .box-shadow(0px 6px 0 0 rgba(0, 0, 0, 0.1)); diff --git a/package.json b/package.json index 4be555070..d1bac4e0b 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "bluebird": "^3.4.6", "brace": "^0.7.0", "chai": "^3.5.0", + "classnames": "^2.2.5", "clean-css": "^3.4.9", "clipboard": "^1.5.16", "couchapp": "~0.11.0", From 000e41d461950e33184d23604bbeaa7a7f63416d Mon Sep 17 00:00:00 2001 From: Robert Kowalski Date: Wed, 28 Dec 2016 11:29:07 +0100 Subject: [PATCH 02/19] the death of the burger + minimized by defualt --- app/addons/fauxton/assets/less/navigation.less | 23 +++++++++++++--------- app/addons/fauxton/navigation/components/Burger.js | 8 +++++--- app/addons/fauxton/navigation/stores.js | 7 +++---- app/constants.js | 4 ---- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/app/addons/fauxton/assets/less/navigation.less b/app/addons/fauxton/assets/less/navigation.less index f8b1b510b..637ab4022 100644 --- a/app/addons/fauxton/assets/less/navigation.less +++ b/app/addons/fauxton/assets/less/navigation.less @@ -27,7 +27,7 @@ .faux-navbar__burger { background-color: @primaryNav; - padding: 22px 0 22px 18px; + padding: 19px 0 18px 18px; position: fixed; z-index: 100; top: 0; @@ -41,16 +41,21 @@ width: @navWidth; } -.faux-navbar__burger:hover .faux-navbar__burger__stripe { - background-color: #fff; +.faux-navbar__burger:hover .faux-navbar__burger__icon { + color: #fff; +} + +.faux-navbar__burger__icon { + color: #B3B4B4; + font-size: 27px; } -.faux-navbar__burger__stripe { - height: 4px; - width: 24px; - .border-radius(2); - background-color: #B3B4B4; - margin: 2px 0px; +.faux-navbar__burger__icon--flipped:before{ + -moz-transform: scale(-1, 1); + -webkit-transform: scale(-1, 1); + -o-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + transform: scale(-1, 1); } .faux-navbar__link, .faux-logout__link, .faux-login__link { diff --git a/app/addons/fauxton/navigation/components/Burger.js b/app/addons/fauxton/navigation/components/Burger.js index 98742de14..17549ad03 100644 --- a/app/addons/fauxton/navigation/components/Burger.js +++ b/app/addons/fauxton/navigation/components/Burger.js @@ -22,11 +22,13 @@ const Burger = ({toggleMenu, isMinimized}) => { {'faux-navbar--narrow': isMinimized} ); + const icon = isMinimized ? + 'icon-resize-horizontal' : + 'icon-signin faux-navbar__burger__icon--flipped'; + return (
    - - - +
    ); }; diff --git a/app/addons/fauxton/navigation/stores.js b/app/addons/fauxton/navigation/stores.js index 350feb7c3..dfdcb6d72 100644 --- a/app/addons/fauxton/navigation/stores.js +++ b/app/addons/fauxton/navigation/stores.js @@ -24,6 +24,7 @@ Stores.NavBarStore = FauxtonAPI.Store.extend({ }, reset () { + this._isMinimized = true; this._activeLink = null; this._version = null; this._navLinks = []; @@ -107,8 +108,7 @@ Stores.NavBarStore = FauxtonAPI.Store.extend({ }, toggleMenu () { - app.utils.localStorageSet(FauxtonAPI.constants.LOCAL_STORAGE.SIDEBAR_MINIMIZED, - !this.isMinimized()); + this._isMinimized = !this._isMinimized; }, getLinkSection (link) { @@ -156,8 +156,7 @@ Stores.NavBarStore = FauxtonAPI.Store.extend({ }, isMinimized () { - const isMinimized = app.utils.localStorageGet(FauxtonAPI.constants.LOCAL_STORAGE.SIDEBAR_MINIMIZED); - return (_.isUndefined(isMinimized)) ? false : isMinimized; + return this._isMinimized; }, dispatch (action) { diff --git a/app/constants.js b/app/constants.js index a967db4c9..e93709446 100644 --- a/app/constants.js +++ b/app/constants.js @@ -47,9 +47,5 @@ export default { MANGO_INDEX: '/_utils/docs/intro/api.html#documents', MANGO_SEARCH: '/_utils/docs/intro/api.html#documents', CHANGES: '/_utils/docs/api/database/changes.html?highlight=changes#post--db-_changes' - }, - - LOCAL_STORAGE: { - SIDEBAR_MINIMIZED: 'sidebar-minimized' } }; From 27c29670c424fd75073657009abc18ee4ec822bc Mon Sep 17 00:00:00 2001 From: Ryan Millay Date: Thu, 2 Mar 2017 09:42:09 -0500 Subject: [PATCH 03/19] placing on back burner --- .../navigation/__tests__/login-logout-test.js | 4 +-- .../navigation/tests/componentsSpec.react.jsx | 7 ++-- app/addons/fauxton/navigation/tests/storeSpec.js | 40 ---------------------- 3 files changed, 6 insertions(+), 45 deletions(-) diff --git a/app/addons/fauxton/navigation/__tests__/login-logout-test.js b/app/addons/fauxton/navigation/__tests__/login-logout-test.js index c7e161a5e..afe139183 100644 --- a/app/addons/fauxton/navigation/__tests__/login-logout-test.js +++ b/app/addons/fauxton/navigation/__tests__/login-logout-test.js @@ -73,8 +73,8 @@ describe('Navigation Bar', () => { const navBar = mount(); - expect(/Login/.test(navBar.text())).toBe(false); - expect(/Log Out/.test(navBar.text())).toBe(false); + expect(navBar.text()).not.toMatch(/Login/); + expect(navBar.text()).not.toMatch(/Log Out/); }); }); diff --git a/app/addons/fauxton/navigation/tests/componentsSpec.react.jsx b/app/addons/fauxton/navigation/tests/componentsSpec.react.jsx index fc8d349a2..36bc1a5b8 100644 --- a/app/addons/fauxton/navigation/tests/componentsSpec.react.jsx +++ b/app/addons/fauxton/navigation/tests/componentsSpec.react.jsx @@ -10,7 +10,8 @@ // License for the specific language governing permissions and limitations under // the License. import FauxtonAPI from "../../../../core/api"; -import Views from "../components.react"; +import Burger from "../components/Burger"; +import NavBar from "../components/NavBar"; import Actions from "../actions"; import Auth from "../../../../core/auth"; import BaseAuth from "../../../auth/base"; @@ -28,7 +29,7 @@ describe('NavBar', function () { describe('burger', function () { it('dispatch TOGGLE_NAVBAR_MENU on click', function () { const toggleMenu = sinon.spy(); - const burgerEl = mount(); + const burgerEl = mount(); burgerEl.simulate('click'); assert.ok(toggleMenu.calledOnce); }); @@ -42,7 +43,7 @@ describe('NavBar', function () { sinon.stub(FauxtonAPI.session, 'user').returns({ name: 'test-user' }); BaseAuth.initialize(); - const el = mount(); + const el = mount(); FauxtonAPI.session.trigger('change'); diff --git a/app/addons/fauxton/navigation/tests/storeSpec.js b/app/addons/fauxton/navigation/tests/storeSpec.js index 778dac149..e36375413 100644 --- a/app/addons/fauxton/navigation/tests/storeSpec.js +++ b/app/addons/fauxton/navigation/tests/storeSpec.js @@ -221,44 +221,4 @@ describe('NavBarStore', function () { }); }); - - describe('is Minimized', function () { - - it('returns true if localstorage is true', function () { - app.utils.localStorageSet(FauxtonAPI.constants.LOCAL_STORAGE.SIDEBAR_MINIMIZED, true); - assert.ok(navBarStore.isMinimized()); - }); - - it('returns false if localstorage is false', function () { - app.utils.localStorageSet(FauxtonAPI.constants.LOCAL_STORAGE.SIDEBAR_MINIMIZED, false); - assert.notOk(navBarStore.isMinimized(), false); - }); - - it('returns false if localstorage is undefined', function () { - window.localStorage.removeItem(FauxtonAPI.constants.LOCAL_STORAGE.SIDEBAR_MINIMIZED); - assert.notOk(navBarStore.isMinimized(), false); - }); - }); - - describe('toggleMenu', function () { - - it('that is minimized changes to false', function () { - app.utils.localStorageSet(FauxtonAPI.constants.LOCAL_STORAGE.SIDEBAR_MINIMIZED, true); - navBarStore.toggleMenu(); - assert.notOk(navBarStore.isMinimized()); - }); - - it('that is not minimized changes to true', function () { - app.utils.localStorageSet(FauxtonAPI.constants.LOCAL_STORAGE.SIDEBAR_MINIMIZED, false); - navBarStore.toggleMenu(); - assert.ok(navBarStore.isMinimized()); - }); - - it('that is undefined changes to true', function () { - window.localStorage.removeItem(FauxtonAPI.constants.LOCAL_STORAGE.SIDEBAR_MINIMIZED); - navBarStore.toggleMenu(); - assert.ok(navBarStore.isMinimized()); - }); - - }); }); From 15f236d515dbe3da7551db5d1256d2dbec658c2e Mon Sep 17 00:00:00 2001 From: Ryan Millay Date: Fri, 24 Mar 2017 15:38:33 -0400 Subject: [PATCH 04/19] Removed jquery dependency from navbar and repaired bugs --- app/addons/auth/base.js | 5 +- app/addons/auth/routes.js | 5 +- app/addons/cluster/routes.js | 2 + app/addons/config/routes.js | 1 + app/addons/fauxton/appwrapper.js | 63 +++++++++++++++++------ app/addons/fauxton/navigation/container/NavBar.js | 1 - app/addons/setup/route.js | 2 - assets/less/fauxton.less | 12 ++--- assets/less/templates.less | 3 -- 9 files changed, 58 insertions(+), 36 deletions(-) diff --git a/app/addons/auth/base.js b/app/addons/auth/base.js index 2bcfab208..c07a04651 100644 --- a/app/addons/auth/base.js +++ b/app/addons/auth/base.js @@ -21,7 +21,7 @@ app.session = Auth.session; function cleanupAuthSection () { - FauxtonAPI.removeHeaderLink({ id: 'auth', footerNav: true }); + FauxtonAPI.removeHeaderLink({ id: 'auth', bottomNav: true }); } Auth.initialize = function () { @@ -43,10 +43,9 @@ Auth.initialize = function () { FauxtonAPI.hideLogin(); } else if (session.isLoggedIn()) { - const link = { id: 'auth', - title: session.user().name, + title: 'Your Account', href: '#/changePassword', icon: 'fonticon-user', bottomNav: true diff --git a/app/addons/auth/routes.js b/app/addons/auth/routes.js index b4a0e6837..12256197e 100644 --- a/app/addons/auth/routes.js +++ b/app/addons/auth/routes.js @@ -65,6 +65,7 @@ var AuthRouteObject = FauxtonAPI.RouteObject.extend({ var UserRouteObject = FauxtonAPI.RouteObject.extend({ hideNotificationCenter: true, hideApiBar: true, + selectedHeader: 'Your Account', routes: { 'changePassword': { @@ -93,10 +94,6 @@ var UserRouteObject = FauxtonAPI.RouteObject.extend({ ClusterActions.navigateToNodeBasedOnNodeCount('/addAdmin/'); }, - selectedHeader: function () { - return FauxtonAPI.session.user().name; - }, - changePassword: function () { ClusterActions.fetchNodes(); AuthActions.selectPage('changePassword'); diff --git a/app/addons/cluster/routes.js b/app/addons/cluster/routes.js index 591541f51..c4b924d56 100644 --- a/app/addons/cluster/routes.js +++ b/app/addons/cluster/routes.js @@ -19,6 +19,8 @@ import {OnePaneSimpleLayout} from '../components/layouts'; var ConfigDisabledRouteObject = FauxtonAPI.RouteObject.extend({ + selectedHeader: 'Configuration', + routes: { 'cluster/disabled': 'showDisabledFeatureScreen' }, diff --git a/app/addons/config/routes.js b/app/addons/config/routes.js index e1dadb769..370d126fc 100644 --- a/app/addons/config/routes.js +++ b/app/addons/config/routes.js @@ -20,6 +20,7 @@ import Layout from './layout'; var ConfigDisabledRouteObject = FauxtonAPI.RouteObject.extend({ + selectedHeader: 'Configuration', routes: { '_config': 'checkNodes', diff --git a/app/addons/fauxton/appwrapper.js b/app/addons/fauxton/appwrapper.js index 4603686f8..573521baf 100644 --- a/app/addons/fauxton/appwrapper.js +++ b/app/addons/fauxton/appwrapper.js @@ -14,6 +14,10 @@ import React from 'react'; import {NotificationController, PermanentNotification} from "./notifications/notifications.react"; import NavBar from './navigation/container/NavBar'; import NavbarActions from './navigation/actions'; +import Stores from './navigation/stores'; +import classNames from 'classnames'; + +const navBarStore = Stores.navBarStore; class ContentWrapper extends React.Component { constructor(props) { @@ -49,27 +53,52 @@ class ContentWrapper extends React.Component { } } -const App = ({router}) => { - return ( -
    - -
    - -
    -
    -
    -
    -
    - -
    -
    - +class App extends React.Component { + constructor (props) { + super(props); + this.state = this.getStoreState(); + } + + getStoreState () { + return { + isPrimaryNavMinimized: navBarStore.isMinimized() + }; + } + + componentDidMount () { + navBarStore.on('change', this.onChange, this); + } + + onChange () { + this.setState(this.getStoreState()); + } + + render () { + const mainClass = classNames( + {'closeMenu': this.state.isPrimaryNavMinimized} + ); + + return ( +
    + +
    + +
    +
    +
    +
    +
    + +
    +
    + +
    -
    - ); + ); + } }; export default App; diff --git a/app/addons/fauxton/navigation/container/NavBar.js b/app/addons/fauxton/navigation/container/NavBar.js index 959c94701..0be0c5cd1 100644 --- a/app/addons/fauxton/navigation/container/NavBar.js +++ b/app/addons/fauxton/navigation/container/NavBar.js @@ -46,7 +46,6 @@ const NavBarContainer = React.createClass({ }, setMenuState () { - $('body').toggleClass('closeMenu', this.state.isMinimized); FauxtonAPI.Events.trigger(FauxtonAPI.constants.EVENTS.NAVBAR_SIZE_CHANGED, this.state.isMinimized); }, diff --git a/app/addons/setup/route.js b/app/addons/setup/route.js index 0c04f274e..1549bdc1f 100644 --- a/app/addons/setup/route.js +++ b/app/addons/setup/route.js @@ -23,8 +23,6 @@ var RouteObject = FauxtonAPI.RouteObject.extend({ roles: ['_admin'], selectedHeader: 'Setup', - selectedHeader: 'Setup', - routes: { 'setup': 'setupInitView', 'setup/finish': 'finishView', diff --git a/assets/less/fauxton.less b/assets/less/fauxton.less index 24c4a524f..9346a3ea4 100644 --- a/assets/less/fauxton.less +++ b/assets/less/fauxton.less @@ -553,7 +553,7 @@ footer.pagination-footer { // left navigationbar is closed @media (max-width: 875px) { - body:not(.closeMenu) { + #main:not(.closeMenu) { .one-pane { .faux-header__searchboxwrapper { display: none; @@ -563,7 +563,7 @@ footer.pagination-footer { } @media (max-width: 1285px) { - body:not(.closeMenu) { + #main:not(.closeMenu) { .with-sidebar { .faux-header__searchboxwrapper { display: none; @@ -580,7 +580,7 @@ body .control-toggle-include-docs span { } @media (max-width: 1177px) { - body.closeMenu { + #main.closeMenu { .with-sidebar { .two-panel-header { .control-toggle-include-docs span::before { @@ -596,7 +596,7 @@ body .control-toggle-include-docs span { @media (max-width: 1120px) { - body.closeMenu { + #main.closeMenu { .with-sidebar { .two-panel-header { .control-toggle-include-docs span::before { @@ -623,7 +623,7 @@ body .control-toggle-include-docs span { } @media (max-width: 1339px) { - body:not(.closeMenu) { + #main:not(.closeMenu) { .with-sidebar { .two-panel-header { .control-toggle-include-docs span::before { @@ -638,7 +638,7 @@ body .control-toggle-include-docs span { } @media (max-width: 1090px) { - body:not(.closeMenu) { + #main:not(.closeMenu) { .with-sidebar { .two-panel-header { .control-toggle-include-docs span::before { diff --git a/assets/less/templates.less b/assets/less/templates.less index 1e2644414..5dcc5c87a 100644 --- a/assets/less/templates.less +++ b/assets/less/templates.less @@ -204,9 +204,6 @@ left: @sidebarWidth; right: 0; .box-sizing(border-box); - .closeMenu & { - left: @sidebarWidth+@collapsedNavWidth; - } } .with-tabs-sidebar & { overflow: hidden; From 257e17f31fdf6e14eb064b56bd6d82a3ad5233b9 Mon Sep 17 00:00:00 2001 From: Ryan Millay Date: Mon, 27 Mar 2017 11:33:52 -0400 Subject: [PATCH 05/19] fixed and refactored auth jest test --- app/addons/auth/__tests__/base.test.js | 83 +++++++++++++++++ app/addons/auth/base.js | 2 +- app/addons/auth/test/baseSpec.js | 100 --------------------- .../navigation/tests/componentsSpec.react.jsx | 1 - app/addons/fauxton/navigation/tests/storeSpec.js | 1 - 5 files changed, 84 insertions(+), 103 deletions(-) create mode 100644 app/addons/auth/__tests__/base.test.js delete mode 100644 app/addons/auth/test/baseSpec.js diff --git a/app/addons/auth/__tests__/base.test.js b/app/addons/auth/__tests__/base.test.js new file mode 100644 index 000000000..ae56b1668 --- /dev/null +++ b/app/addons/auth/__tests__/base.test.js @@ -0,0 +1,83 @@ +// 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 FauxtonAPI from "../../../core/api"; +import Auth from "../../../core/auth"; +import Base from "../base"; +import sinon from "sinon"; + + +describe("Auth", function () { + FauxtonAPI.auth = new Auth(); + Base.initialize(); + + describe("failed login", function () { + + it("redirects with replace: true set", function () { + const navigateSpy = sinon.spy(FauxtonAPI, 'navigate'); + FauxtonAPI.router.trigger = () => {}; + FauxtonAPI.session.isLoggedIn = function () { return false; }; + FauxtonAPI.auth.authDeniedCb(); + expect(navigateSpy.withArgs('/login?urlback=', {replace: true}).calledOnce).toBeTruthy(); + FauxtonAPI.navigate.restore(); + }); + }); + + describe('auth session change', function () { + + afterEach(function () { + FauxtonAPI.addHeaderLink.restore && FauxtonAPI.addHeaderLink.restore(); + FauxtonAPI.session.isLoggedIn.restore && FauxtonAPI.session.isLoggedIn.restore(); + FauxtonAPI.session.isAdminParty.restore(); + }); + + it('for admin party changes title to admin party', function () { + const spy = sinon.spy(FauxtonAPI, 'addHeaderLink'); + sinon.stub(FauxtonAPI.session, 'isAdminParty').returns(true); + FauxtonAPI.session.trigger('change'); + + expect(spy.calledOnce).toBeTruthy(); + const args = spy.getCall(0).args[0]; + expect(args.title).toMatch("Admin Party!"); + }); + + it('for login changes title to Your Account', function () { + var spy = sinon.spy(FauxtonAPI, 'addHeaderLink'); + sinon.stub(FauxtonAPI.session, 'isAdminParty').returns(false); + sinon.stub(FauxtonAPI.session, 'isLoggedIn').returns(true); + FauxtonAPI.session.trigger('change'); + + expect(spy.calledOnce).toBeTruthy(); + var args = spy.getCall(0).args[0]; + expect(args.title).toMatch("Your Account"); + }); + + it('for login adds logout link', function () { + var spy = sinon.spy(FauxtonAPI, 'showLogout'); + sinon.stub(FauxtonAPI.session, 'isAdminParty').returns(false); + sinon.stub(FauxtonAPI.session, 'isLoggedIn').returns(true); + FauxtonAPI.session.trigger('change'); + + expect(spy.calledOnce).toBeTruthy(); + FauxtonAPI.showLogout.restore(); + }); + + it('for logout, removes logout link', function () { + var spy = sinon.spy(FauxtonAPI, 'showLogin'); + sinon.stub(FauxtonAPI.session, 'isAdminParty').returns(false); + sinon.stub(FauxtonAPI.session, 'isLoggedIn').returns(false); + FauxtonAPI.session.trigger('change'); + + expect(spy.calledOnce).toBeTruthy(); + FauxtonAPI.showLogin.restore(); + }); + }); +}); diff --git a/app/addons/auth/base.js b/app/addons/auth/base.js index c07a04651..563f722a5 100644 --- a/app/addons/auth/base.js +++ b/app/addons/auth/base.js @@ -27,7 +27,7 @@ function cleanupAuthSection () { Auth.initialize = function () { Auth.session.on('change', function () { - var session = Auth.session; + const session = Auth.session; if (session.isAdminParty()) { const link = { diff --git a/app/addons/auth/test/baseSpec.js b/app/addons/auth/test/baseSpec.js deleted file mode 100644 index c56628775..000000000 --- a/app/addons/auth/test/baseSpec.js +++ /dev/null @@ -1,100 +0,0 @@ -// 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 FauxtonAPI from "../../../core/api"; -import Base from "../base"; -import Auth from "../../../core/auth"; -import testUtils from "../../../../test/mocha/testUtils"; -import sinon from "sinon"; -var assert = testUtils.assert; - -describe("Auth: Login", function () { - - describe("failed login", function () { - - it("redirects with replace: true set", function () { - var navigateSpy = sinon.spy(FauxtonAPI, 'navigate'); - FauxtonAPI.auth = new Auth(); - FauxtonAPI.session.isLoggedIn = function () { return false; }; - Base.initialize(); - FauxtonAPI.auth.authDeniedCb(); - assert.ok(navigateSpy.withArgs('/login?urlback=', {replace: true}).calledOnce); - }); - }); -}); - -describe('auth session change', function () { - - afterEach(function () { - FauxtonAPI.updateHeaderLink.restore && FauxtonAPI.updateHeaderLink.restore(); - FauxtonAPI.session.isAdminParty.restore && FauxtonAPI.session.isAdminParty.restore(); - }); - - it('for admin party changes title to admin party', function () { - var spy = sinon.spy(FauxtonAPI, 'updateHeaderLink'); - var stub = sinon.stub(FauxtonAPI.session, 'isAdminParty').returns(true); - FauxtonAPI.session.trigger('change'); - - assert.ok(spy.calledOnce); - var args = spy.getCall(0).args[0]; - - assert.ok(args.title.match(/Admin Party/)); - FauxtonAPI.session.isAdminParty.restore(); - }); - - it('for login changes title to login', function () { - var spy = sinon.spy(FauxtonAPI, 'updateHeaderLink'); - var stub = sinon.stub(FauxtonAPI.session, 'isAdminParty').returns(false); - sinon.stub(FauxtonAPI.session, 'user').returns({name: 'test-user'}); - sinon.stub(FauxtonAPI.session, 'isLoggedIn').returns(true); - FauxtonAPI.session.trigger('change'); - - assert.ok(spy.calledOnce); - var args = spy.getCall(0).args[0]; - - assert.equal(args.title, 'test-user'); - FauxtonAPI.session.isLoggedIn.restore(); - FauxtonAPI.session.user.restore(); - FauxtonAPI.session.isAdminParty.restore(); - }); - - it('for login adds logout link', function () { - var spy = sinon.spy(FauxtonAPI, 'addHeaderLink'); - var stub = sinon.stub(FauxtonAPI.session, 'isAdminParty').returns(false); - sinon.stub(FauxtonAPI.session, 'user').returns({name: 'test-user'}); - sinon.stub(FauxtonAPI.session, 'isLoggedIn').returns(true); - FauxtonAPI.session.trigger('change'); - - assert.ok(spy.calledOnce); - var args = spy.getCall(0).args[0]; - - assert.equal(args.title, 'Logout'); - FauxtonAPI.session.isLoggedIn.restore(); - FauxtonAPI.session.user.restore(); - FauxtonAPI.session.isAdminParty.restore(); - }); - - it('for logout, removes logout link', function () { - var spy = sinon.spy(FauxtonAPI, 'removeHeaderLink'); - var stub = sinon.stub(FauxtonAPI.session, 'isAdminParty').returns(false); - sinon.stub(FauxtonAPI.session, 'isLoggedIn').returns(false); - FauxtonAPI.session.trigger('change'); - - assert.ok(spy.calledOnce); - var args = spy.getCall(0).args[0]; - - assert.equal(args.id, 'logout'); - FauxtonAPI.session.isLoggedIn.restore(); - FauxtonAPI.session.isAdminParty.restore(); - }); - - -}); diff --git a/app/addons/fauxton/navigation/tests/componentsSpec.react.jsx b/app/addons/fauxton/navigation/tests/componentsSpec.react.jsx index 824f98c47..8b046742f 100644 --- a/app/addons/fauxton/navigation/tests/componentsSpec.react.jsx +++ b/app/addons/fauxton/navigation/tests/componentsSpec.react.jsx @@ -12,7 +12,6 @@ import FauxtonAPI from "../../../../core/api"; import Burger from "../components/Burger"; import NavBar from "../components/NavBar"; -import Actions from "../actions"; import Auth from "../../../../core/auth"; import BaseAuth from "../../../auth/base"; import utils from "../../../../../test/mocha/testUtils"; diff --git a/app/addons/fauxton/navigation/tests/storeSpec.js b/app/addons/fauxton/navigation/tests/storeSpec.js index e36375413..a491c3a54 100644 --- a/app/addons/fauxton/navigation/tests/storeSpec.js +++ b/app/addons/fauxton/navigation/tests/storeSpec.js @@ -9,7 +9,6 @@ // 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 app from "../../../../app"; import testUtils from "../../../../../test/mocha/testUtils"; import FauxtonAPI from "../../../../core/api"; import Stores from "../stores"; From 77cccacdd8e499bf4c830637f6f5da1f7f558821 Mon Sep 17 00:00:00 2001 From: Ryan Millay Date: Mon, 27 Mar 2017 14:11:38 -0400 Subject: [PATCH 06/19] converting and removing mocha test --- .../fauxton/navigation/__tests__/burger-test.js | 29 ++++++++++ .../navigation/tests/componentsSpec.react.jsx | 62 ---------------------- 2 files changed, 29 insertions(+), 62 deletions(-) create mode 100644 app/addons/fauxton/navigation/__tests__/burger-test.js delete mode 100644 app/addons/fauxton/navigation/tests/componentsSpec.react.jsx diff --git a/app/addons/fauxton/navigation/__tests__/burger-test.js b/app/addons/fauxton/navigation/__tests__/burger-test.js new file mode 100644 index 000000000..a05bfdce8 --- /dev/null +++ b/app/addons/fauxton/navigation/__tests__/burger-test.js @@ -0,0 +1,29 @@ +// 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 Burger from "../components/Burger"; +import React from "react"; +import ReactDOM from "react-dom"; +import sinon from "sinon"; +import {mount} from 'enzyme'; + +describe('Navigation Bar', function () { + + describe('Burger', function () { + it('dispatch TOGGLE_NAVBAR_MENU on click', function () { + const toggleMenu = sinon.spy(); + const burgerEl = mount(); + burgerEl.simulate('click'); + expect(toggleMenu.calledOnce).toBeTruthy(); + }); + + }); +}); \ No newline at end of file diff --git a/app/addons/fauxton/navigation/tests/componentsSpec.react.jsx b/app/addons/fauxton/navigation/tests/componentsSpec.react.jsx deleted file mode 100644 index 8b046742f..000000000 --- a/app/addons/fauxton/navigation/tests/componentsSpec.react.jsx +++ /dev/null @@ -1,62 +0,0 @@ -// 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 FauxtonAPI from "../../../../core/api"; -import Burger from "../components/Burger"; -import NavBar from "../components/NavBar"; -import Auth from "../../../../core/auth"; -import BaseAuth from "../../../auth/base"; -import utils from "../../../../../test/mocha/testUtils"; -import React from "react"; -import ReactDOM from "react-dom"; -import sinon from "sinon"; -import {mount} from 'enzyme'; - -var assert = utils.assert; - -describe('NavBar', function () { - - describe('burger', function () { - it('dispatch TOGGLE_NAVBAR_MENU on click', function () { - const toggleMenu = sinon.spy(); - const burgerEl = mount(); - burgerEl.simulate('click'); - assert.ok(toggleMenu.calledOnce); - }); - - }); - - it('logout link only ever appears once', function () { - FauxtonAPI.auth = new Auth(); - sinon.stub(FauxtonAPI.session, 'isLoggedIn').returns(true); - sinon.stub(FauxtonAPI.session, 'isAdminParty').returns(false); - sinon.stub(FauxtonAPI.session, 'user').returns({ name: 'test-user' }); - BaseAuth.initialize(); - - const el = mount(); - - FauxtonAPI.session.trigger('change'); - - // confirm the logout link is present - let matches = el.text().match(/Logout/); - assert.equal(matches.length, 1); - - // now confirm there's still only a single logout link after publishing multiple - FauxtonAPI.session.trigger('change'); - FauxtonAPI.session.trigger('change'); - matches = el.text().match(/Logout/); - assert.equal(matches.length, 1); - - FauxtonAPI.session.isLoggedIn.restore(); - FauxtonAPI.session.user.restore(); - FauxtonAPI.session.isAdminParty.restore(); - }); -}); From fb7ce41ea0aae6762abad8f6f2a3e5bc3f8a0c14 Mon Sep 17 00:00:00 2001 From: Ryan Millay Date: Mon, 27 Mar 2017 15:11:03 -0400 Subject: [PATCH 07/19] added new test and converted mocha test to jest --- .../fauxton/navigation/__tests__/burger-test.js | 6 +- .../navigation-store-test.js} | 68 +++++++++++----------- .../fauxton/navigation/__tests__/navlink-test.js | 49 ++++++++++++++++ app/addons/fauxton/navigation/components/NavBar.js | 2 +- 4 files changed, 86 insertions(+), 39 deletions(-) rename app/addons/fauxton/navigation/{tests/storeSpec.js => __tests__/navigation-store-test.js} (68%) create mode 100644 app/addons/fauxton/navigation/__tests__/navlink-test.js diff --git a/app/addons/fauxton/navigation/__tests__/burger-test.js b/app/addons/fauxton/navigation/__tests__/burger-test.js index a05bfdce8..b689df9af 100644 --- a/app/addons/fauxton/navigation/__tests__/burger-test.js +++ b/app/addons/fauxton/navigation/__tests__/burger-test.js @@ -15,10 +15,10 @@ import ReactDOM from "react-dom"; import sinon from "sinon"; import {mount} from 'enzyme'; -describe('Navigation Bar', function () { +describe('Navigation Bar', () => { - describe('Burger', function () { - it('dispatch TOGGLE_NAVBAR_MENU on click', function () { + describe('Burger', () => { + it('dispatch TOGGLE_NAVBAR_MENU on click', () => { const toggleMenu = sinon.spy(); const burgerEl = mount(); burgerEl.simulate('click'); diff --git a/app/addons/fauxton/navigation/tests/storeSpec.js b/app/addons/fauxton/navigation/__tests__/navigation-store-test.js similarity index 68% rename from app/addons/fauxton/navigation/tests/storeSpec.js rename to app/addons/fauxton/navigation/__tests__/navigation-store-test.js index a491c3a54..c664dceec 100644 --- a/app/addons/fauxton/navigation/tests/storeSpec.js +++ b/app/addons/fauxton/navigation/__tests__/navigation-store-test.js @@ -9,23 +9,21 @@ // 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 testUtils from "../../../../../test/mocha/testUtils"; import FauxtonAPI from "../../../../core/api"; import Stores from "../stores"; -var assert = testUtils.assert; -var navBarStore = Stores.navBarStore; +const navBarStore = Stores.navBarStore; -describe('NavBarStore', function () { - beforeEach(function () { +describe('NavBarStore', () => { + beforeEach(() => { FauxtonAPI.dispatch({ type: 'CLEAR_NAVBAR_LINK', }); }); - describe('add links', function () { + describe('add links', () => { - it('to nav links', function () { + it('to nav links', () => { var link = { id: 'mylink' }; @@ -34,10 +32,10 @@ describe('NavBarStore', function () { link: link }); - assert.equal(navBarStore.getNavLinks()[0].id, link.id); + expect(navBarStore.getNavLinks()[0].id).toMatch(link.id); }); - it('to top nav links', function () { + it('to top nav links', () => { var link1 = { id: 'mylink1' }; @@ -57,10 +55,10 @@ describe('NavBarStore', function () { link: link2 }); - assert.equal(navBarStore.getNavLinks()[0].id, link2.id); + expect(navBarStore.getNavLinks()[0].id).toMatch(link2.id); }); - it('to bottom nav', function () { + it('to bottom nav', () => { var link = { id: 'bottomNav', bottomNav: true @@ -70,10 +68,10 @@ describe('NavBarStore', function () { link: link }); - assert.equal(navBarStore.getBottomNavLinks()[0].id, link.id); + expect(navBarStore.getBottomNavLinks()[0].id).toMatch(link.id); }); - it('to top of bottom nav', function () { + it('to top of bottom nav', () => { var link = { id: 'bottomNav', bottomNav: true, @@ -84,10 +82,10 @@ describe('NavBarStore', function () { link: link }); - assert.equal(navBarStore.getBottomNavLinks()[0].id, link.id); + expect(navBarStore.getBottomNavLinks()[0].id).toMatch(link.id); }); - it('to footer nav', function () { + it('to footer nav', () => { var link = { id: 'footerNav', footerNav: true @@ -97,12 +95,12 @@ describe('NavBarStore', function () { link: link }); - assert.equal(navBarStore.getFooterNavLinks()[0].id, link.id); + expect(navBarStore.getFooterNavLinks()[0].id).toMatch(link.id); }); }); - describe('remove link', function () { - it('from nav links', function () { + describe('remove link', () => { + it('from nav links', () => { var link = { id: 'remove_link', }; @@ -116,11 +114,11 @@ describe('NavBarStore', function () { link: link }); - assert.equal(navBarStore.getNavLinks().length, 0); + expect(navBarStore.getNavLinks().length).toBe(0); }); - it('remove link from list', function () { - function addLink (id) { + it('remove link from list', () => { + const addLink = (id) => { FauxtonAPI.dispatch({ type: 'ADD_NAVBAR_LINK', link: { @@ -128,8 +126,8 @@ describe('NavBarStore', function () { footerNav: true } }); - } - function removeLink () { + }; + const removeLink = () => { FauxtonAPI.dispatch({ type: 'REMOVE_NAVBAR_LINK', link: { @@ -137,7 +135,7 @@ describe('NavBarStore', function () { footerNav: true } }); - } + }; addLink('remove_link1'); addLink('remove_link2'); addLink('remove_link3'); @@ -146,10 +144,10 @@ describe('NavBarStore', function () { removeLink(); removeLink(); - assert.equal(navBarStore.getFooterNavLinks().length, 2); + expect(navBarStore.getFooterNavLinks().length).toBe(2); }); - it('from bottom nav links', function () { + it('from bottom nav links', () => { var link = { id: 'remove_link', bottomNav: true @@ -164,10 +162,10 @@ describe('NavBarStore', function () { link: link }); - assert.equal(navBarStore.getBottomNavLinks().length, 0); + expect(navBarStore.getBottomNavLinks().length).toBe(0); }); - it('from footer nav links', function () { + it('from footer nav links', () => { var link = { id: 'remove_link', footerNav: true @@ -182,12 +180,12 @@ describe('NavBarStore', function () { link: link }); - assert.equal(navBarStore.getFooterNavLinks().length, 0); + expect(navBarStore.getFooterNavLinks().length).toBe(0); }); }); - describe('update link', function () { - it('for nav links', function () { + describe('update link', () => { + it('for nav links', () => { var link = { id: 'update-link', title: 'first' @@ -204,19 +202,19 @@ describe('NavBarStore', function () { link: link }); - assert.equal(navBarStore.getNavLinks()[0].title, 'second'); + expect(navBarStore.getNavLinks()[0].title).toMatch('second'); }); }); - describe('set version', function () { - it('stores version number', function () { + describe('set version', () => { + it('stores version number', () => { FauxtonAPI.dispatch({ type: 'NAVBAR_SET_VERSION_INFO', version: 1234 }); - assert.equal(navBarStore.getVersion(), 1234); + expect(navBarStore.getVersion()).toBe(1234); }); }); diff --git a/app/addons/fauxton/navigation/__tests__/navlink-test.js b/app/addons/fauxton/navigation/__tests__/navlink-test.js new file mode 100644 index 000000000..980e11882 --- /dev/null +++ b/app/addons/fauxton/navigation/__tests__/navlink-test.js @@ -0,0 +1,49 @@ +// 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 NavLink from "../components/NavLink"; +import React from "react"; +import ReactDOM from "react-dom"; +import sinon from "sinon"; +import {mount} from 'enzyme'; + +describe('Navigation Bar', () => { + const dbLink = { + href: "#/_all_dbs", + title: "Databases", + icon: "fonticon-database", + className: 'databases' + } + + describe('Active Link', () => { + it('matching title sets active css class', () => { + const linkEl = mount(); + expect(linkEl.find('a.faux-navbar__link--active').length).toBe(1); + }); + + it('different title sets inactive css class', () => { + const linkEl = mount(); + expect(linkEl.find('a.faux-navbar__link--inactive').length).toBe(1); + }); + }); + + describe('Minimized Link', () => { + it('shows title when not minimized', () => { + const linkEl = mount(); + expect(linkEl.text()).toMatch("Databases"); + }); + + it('does not show title when minimized', () => { + const linkEl = mount(); + expect(linkEl.find('span.faux-navbar__text').length).toBe(0); + }); + }); +}); \ No newline at end of file diff --git a/app/addons/fauxton/navigation/components/NavBar.js b/app/addons/fauxton/navigation/components/NavBar.js index 26050070e..c7583c83e 100644 --- a/app/addons/fauxton/navigation/components/NavBar.js +++ b/app/addons/fauxton/navigation/components/NavBar.js @@ -29,7 +29,7 @@ class NavBar extends Component { createLinks (links) { const { activeLink, isMinimized } = this.props; - return _.map(links, function (link, i) { + return _.map(links, (link, i) => { return Date: Mon, 27 Mar 2017 15:40:42 -0400 Subject: [PATCH 08/19] repairing lost less variables --- app/addons/fauxton/assets/less/navigation.less | 36 +++++++++++++------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/app/addons/fauxton/assets/less/navigation.less b/app/addons/fauxton/assets/less/navigation.less index 637ab4022..cb09a8f6e 100644 --- a/app/addons/fauxton/assets/less/navigation.less +++ b/app/addons/fauxton/assets/less/navigation.less @@ -1,6 +1,6 @@ .faux-navbar { margin-top: 64px; - background-color: #3A2C2B; + background-color: @brandDark2; position: absolute; left: 0; @@ -12,21 +12,21 @@ .faux-navbar__itemarea { .box-sizing(border-box); - border-bottom: 1px solid #3A2C2B; + border-bottom: 1px solid @brandDark2; height: 48px; padding: 10px 20px; line-height: 24px; } .faux-navbar__version-footer { - color: #fff; + color: @buttonText; font-size: 10px; text-align: center; - background-color: @brown; + background-color: @brandDark2; } .faux-navbar__burger { - background-color: @primaryNav; + background-color: @brandDark2; padding: 19px 0 18px 18px; position: fixed; z-index: 100; @@ -42,11 +42,11 @@ } .faux-navbar__burger:hover .faux-navbar__burger__icon { - color: #fff; + color: @navIconActive; } .faux-navbar__burger__icon { - color: #B3B4B4; + color: @navIconColor; font-size: 27px; } @@ -65,16 +65,16 @@ } .faux-navbar__link--active { - background-color: #AF2D24; + background-color: @brandHighlight; text-decoration: none; } .faux-navbar__link--inactive { - background-color: #564E4C; + background-color: @brandDark1; } .faux-navbar__link:hover, .faux-logout__link:hover, .faux-login__link:hover { - background-color: #E73D34; + background-color: @hoverHighlight; text-decoration: none; } @@ -83,23 +83,23 @@ } .faux-navbar__link:hover .faux-navbar__icon:before { - color: #fff; + color: @navIconActive; } .faux-navbar__link--active .faux-navbar__icon:before { - color: #fff; + color: @navIconActive; } .faux-navbar__icon { margin-right: 14px; - color: #B3B4B4; + color: @navIconColor; font-size: 24px; vertical-align: middle; } .faux-navbar__text { margin: 0; - color: #fff; + color: @buttonText; vertical-align: middle; font-size: 16px; font-weight: normal; @@ -109,12 +109,12 @@ .faux-navbar__logout__text { font-size: 12px; - color: #fff; + color: @buttonText; } .faux-navbar__logout__textcontainer { text-align: center; - color: #fff; + color: @buttonText; } .faux-navbar__logout__textcontainer--narrow { @@ -131,7 +131,7 @@ .faux-navbar__login__textcontainer { text-align: center; - color: #fff; + color: @buttonText; } .faux-navbar__login__textcontainer--narrow { @@ -148,7 +148,7 @@ height: 50px; padding: 10px 10px 10px 10px; float: none; - background: #3a2c2b; + background: @brandDark2; } .faux-navbar__brand-logo { From 6478e35e643ebb62d4167e1e8f83149d6028617d Mon Sep 17 00:00:00 2001 From: Ryan Millay Date: Mon, 27 Mar 2017 15:58:15 -0400 Subject: [PATCH 09/19] fixing linting errors --- app/addons/fauxton/navigation/__tests__/burger-test.js | 2 +- app/addons/fauxton/navigation/__tests__/navlink-test.js | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/app/addons/fauxton/navigation/__tests__/burger-test.js b/app/addons/fauxton/navigation/__tests__/burger-test.js index b689df9af..5f9640ff6 100644 --- a/app/addons/fauxton/navigation/__tests__/burger-test.js +++ b/app/addons/fauxton/navigation/__tests__/burger-test.js @@ -26,4 +26,4 @@ describe('Navigation Bar', () => { }); }); -}); \ No newline at end of file +}); diff --git a/app/addons/fauxton/navigation/__tests__/navlink-test.js b/app/addons/fauxton/navigation/__tests__/navlink-test.js index 980e11882..8201f4e4a 100644 --- a/app/addons/fauxton/navigation/__tests__/navlink-test.js +++ b/app/addons/fauxton/navigation/__tests__/navlink-test.js @@ -12,7 +12,6 @@ import NavLink from "../components/NavLink"; import React from "react"; import ReactDOM from "react-dom"; -import sinon from "sinon"; import {mount} from 'enzyme'; describe('Navigation Bar', () => { @@ -21,7 +20,7 @@ describe('Navigation Bar', () => { title: "Databases", icon: "fonticon-database", className: 'databases' - } + }; describe('Active Link', () => { it('matching title sets active css class', () => { @@ -32,7 +31,7 @@ describe('Navigation Bar', () => { it('different title sets inactive css class', () => { const linkEl = mount(); expect(linkEl.find('a.faux-navbar__link--inactive').length).toBe(1); - }); + }); }); describe('Minimized Link', () => { @@ -46,4 +45,4 @@ describe('Navigation Bar', () => { expect(linkEl.find('span.faux-navbar__text').length).toBe(0); }); }); -}); \ No newline at end of file +}); From a0c94874f7ec05bb05eff40ac6e42ca903959d1a Mon Sep 17 00:00:00 2001 From: Ryan Millay Date: Mon, 27 Mar 2017 23:18:20 -0400 Subject: [PATCH 10/19] repairing old css selectors in nightwatch tests --- app/addons/databases/tests/nightwatch/checkDatabaseTooltip.js | 2 +- app/addons/documents/tests/nightwatch/selectDocViaTypeahead.js | 2 -- app/addons/fauxton/tests/nightwatch/highlightsidebar.js | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/addons/databases/tests/nightwatch/checkDatabaseTooltip.js b/app/addons/databases/tests/nightwatch/checkDatabaseTooltip.js index d2c6606a7..e5b0353d5 100644 --- a/app/addons/databases/tests/nightwatch/checkDatabaseTooltip.js +++ b/app/addons/databases/tests/nightwatch/checkDatabaseTooltip.js @@ -38,7 +38,7 @@ module.exports = { .checkForStringPresent(newDatabaseName, '"doc_del_count":1') - .clickWhenVisible('#nav-links a[href="#/_all_dbs"]') + .clickWhenVisible('#primary-navbar a[href="#/_all_dbs"]') // now let's look at the actual UI to confirm the tooltip appears .waitForElementPresent('.js-db-graveyard', waitTime, false) .moveToElement('.js-db-graveyard', 1, 1) diff --git a/app/addons/documents/tests/nightwatch/selectDocViaTypeahead.js b/app/addons/documents/tests/nightwatch/selectDocViaTypeahead.js index b96940e42..0a083f206 100644 --- a/app/addons/documents/tests/nightwatch/selectDocViaTypeahead.js +++ b/app/addons/documents/tests/nightwatch/selectDocViaTypeahead.js @@ -27,7 +27,6 @@ module.exports = { .keys(['\uE00C']) .waitForElementPresent('.prettyprint', waitTime, false) .waitForElementPresent('.documents-pagination', waitTime, false) - .click('.burger') // we need to explicitly show the doc field because it's hidden on Travis due to screen width .execute("$('.searchbox-wrapper').show();") .setValue('.jump-to-doc .Select-input input', ['_des']) @@ -50,7 +49,6 @@ module.exports = { .keys(['\uE00C']) .waitForElementPresent('.prettyprint', waitTime, false) .waitForElementPresent('.documents-pagination', waitTime, false) - .click('.burger') // we need to explicitly show the doc field because it's hidden on Travis due to screen width .execute("$('.searchbox-wrapper').show();") .setValue('.jump-to-doc .Select-input input', ['MY_CAP']) diff --git a/app/addons/fauxton/tests/nightwatch/highlightsidebar.js b/app/addons/fauxton/tests/nightwatch/highlightsidebar.js index def0e2327..daa4c5900 100644 --- a/app/addons/fauxton/tests/nightwatch/highlightsidebar.js +++ b/app/addons/fauxton/tests/nightwatch/highlightsidebar.js @@ -24,7 +24,7 @@ module.exports = { .click('a[href="#/replication"]') .pause(1000) .waitForElementVisible('.replication__activity_header-btn', waitTime, false) - .assert.cssClassPresent('li[data-nav-name="Replication"]', 'active') + .assert.cssClassPresent('a[href="#/replication"]', 'faux-navbar__link--active') .end(); } }; From 99ffb0c0a0fd51a6abab5e65e35d93d363be75e7 Mon Sep 17 00:00:00 2001 From: Ryan Millay Date: Tue, 28 Mar 2017 14:54:12 -0400 Subject: [PATCH 11/19] first wave of review fixes --- app/addons/auth/base.js | 5 +++-- app/addons/fauxton/navigation/actiontypes.js | 1 - app/addons/fauxton/navigation/components/Footer.js | 2 +- app/addons/fauxton/navigation/components/NavBar.js | 5 ++--- app/addons/fauxton/navigation/container/NavBar.js | 9 --------- app/addons/fauxton/navigation/stores.js | 4 +--- 6 files changed, 7 insertions(+), 19 deletions(-) diff --git a/app/addons/auth/base.js b/app/addons/auth/base.js index 563f722a5..c7c32c7ca 100644 --- a/app/addons/auth/base.js +++ b/app/addons/auth/base.js @@ -28,9 +28,10 @@ Auth.initialize = function () { Auth.session.on('change', function () { const session = Auth.session; + let link; if (session.isAdminParty()) { - const link = { + link = { id: 'auth', title: 'Admin Party!', href: '#/createAdmin', @@ -43,7 +44,7 @@ Auth.initialize = function () { FauxtonAPI.hideLogin(); } else if (session.isLoggedIn()) { - const link = { + link = { id: 'auth', title: 'Your Account', href: '#/changePassword', diff --git a/app/addons/fauxton/navigation/actiontypes.js b/app/addons/fauxton/navigation/actiontypes.js index 3f1971016..e5f685f33 100644 --- a/app/addons/fauxton/navigation/actiontypes.js +++ b/app/addons/fauxton/navigation/actiontypes.js @@ -20,7 +20,6 @@ export default { NAVBAR_ACTIVE_LINK: 'NAVBAR_ACTIVE_LINK', NAVBAR_HIDE: 'NAVBAR_HIDE', NAVBAR_SHOW: 'NAVBAR_SHOW', - NAVBAR_SHOW_HIDE_LOGIN_LOGOUT_SECTION: 'NAVBAR_SHOW_HIDE_LOGIN_LOGOUT_SECTION', NAVBAR_SHOW_LOGIN_BUTTON: 'NAVBAR_SHOW_LOGIN_BUTTON', NAVBAR_SHOW_LOGOUT_BUTTON: 'NAVBAR_SHOW_LOGOUT_BUTTON' diff --git a/app/addons/fauxton/navigation/components/Footer.js b/app/addons/fauxton/navigation/components/Footer.js index 3735c1405..72ddd012c 100644 --- a/app/addons/fauxton/navigation/components/Footer.js +++ b/app/addons/fauxton/navigation/components/Footer.js @@ -20,7 +20,7 @@ const Footer = ({version}) => {
    Fauxton on   Apache CouchDB -   v. {version} +
    v. {version}
    ); diff --git a/app/addons/fauxton/navigation/components/NavBar.js b/app/addons/fauxton/navigation/components/NavBar.js index c7583c83e..f98076d87 100644 --- a/app/addons/fauxton/navigation/components/NavBar.js +++ b/app/addons/fauxton/navigation/components/NavBar.js @@ -22,20 +22,19 @@ import LoginButton from './LoginButton'; import Actions from "../actions"; import classNames from 'classnames'; -import _ from 'lodash'; class NavBar extends Component { createLinks (links) { const { activeLink, isMinimized } = this.props; - return _.map(links, (link, i) => { + return links.map((link, i) => { return ; - }, this); + }); } toggleMenu () { diff --git a/app/addons/fauxton/navigation/container/NavBar.js b/app/addons/fauxton/navigation/container/NavBar.js index 0be0c5cd1..537f0da1a 100644 --- a/app/addons/fauxton/navigation/container/NavBar.js +++ b/app/addons/fauxton/navigation/container/NavBar.js @@ -45,17 +45,8 @@ const NavBarContainer = React.createClass({ this.setState(this.getStoreState()); }, - setMenuState () { - FauxtonAPI.Events.trigger(FauxtonAPI.constants.EVENTS.NAVBAR_SIZE_CHANGED, this.state.isMinimized); - }, - componentDidMount () { navBarStore.on('change', this.onChange, this); - this.setMenuState(); - }, - - componentDidUpdate () { - this.setMenuState(); }, componentWillUnmount () { diff --git a/app/addons/fauxton/navigation/stores.js b/app/addons/fauxton/navigation/stores.js index 9153b2577..777f09796 100644 --- a/app/addons/fauxton/navigation/stores.js +++ b/app/addons/fauxton/navigation/stores.js @@ -13,8 +13,6 @@ import FauxtonAPI from "../../../core/api"; import ActionTypes from "./actiontypes"; -import _ from 'lodash'; - const Stores = {}; Stores.NavBarStore = FauxtonAPI.Store.extend({ @@ -80,7 +78,7 @@ Stores.NavBarStore = FauxtonAPI.Store.extend({ const links = this.getLinkSection(removeLink); let indexOf = 0; - const res = _.filter(links, function (link) { + const res = links.filter((link) => { if (link.id === removeLink.id) { return true; } From e28dfef970380b6bfd83c866bc7ec1963fcbe267 Mon Sep 17 00:00:00 2001 From: Ryan Millay Date: Fri, 31 Mar 2017 12:17:00 -0400 Subject: [PATCH 12/19] dynamic image paths and hardening a stubborn test --- app/addons/fauxton/assets/less/navigation.less | 4 ++-- app/addons/fauxton/tests/nightwatch/notificationCenter.js | 2 ++ assets/less/variables.less | 7 +++++++ package.json | 6 +++--- settings.json.default.json | 12 +++++++++--- webpack.config.dev.js | 10 +++++++++- webpack.config.release.js | 10 +++++++++- 7 files changed, 41 insertions(+), 10 deletions(-) diff --git a/app/addons/fauxton/assets/less/navigation.less b/app/addons/fauxton/assets/less/navigation.less index cb09a8f6e..8273aa8ee 100644 --- a/app/addons/fauxton/assets/less/navigation.less +++ b/app/addons/fauxton/assets/less/navigation.less @@ -158,7 +158,7 @@ } .faux-navbar__brand-logo--wide { - background: url(../../../../../assets/img/CouchDB-negative-logo.png) no-repeat 23px 0px; + background: url(@largeLogoPath) no-repeat 23px 0px; background-size: 150px; width: 200px; } @@ -166,7 +166,7 @@ .faux-navbar__brand-logo--narrow { width: 43px; height: 40px; - background: url(../../../../../assets/img/couchdb-logo.png) no-repeat 3px 0; + background: url(@smallLogoPath) no-repeat 3px 0; background-size: 40px; } diff --git a/app/addons/fauxton/tests/nightwatch/notificationCenter.js b/app/addons/fauxton/tests/nightwatch/notificationCenter.js index b81d86064..6dd4a5750 100644 --- a/app/addons/fauxton/tests/nightwatch/notificationCenter.js +++ b/app/addons/fauxton/tests/nightwatch/notificationCenter.js @@ -26,9 +26,11 @@ module.exports = { .loginToGUI() .waitForElementPresent('#notification-center-btn', waitTime, false) + .clickWhenVisible('.global-notification .fonticon-cancel', waitTime, false) .assert.cssClassNotPresent('.notification-center-panel', 'visible') .clickWhenVisible('#notification-center-btn', waitTime, false) .waitForElementPresent('.notification-center-panel.visible', waitTime, false) + .waitForElementPresent('.notification-list div.flex-layout', waitTime, false) .getText('.notification-center-panel', function (result) { var content = result.value; diff --git a/assets/less/variables.less b/assets/less/variables.less index a33f43f19..47d9b76a7 100644 --- a/assets/less/variables.less +++ b/assets/less/variables.less @@ -115,3 +115,10 @@ @infoAlertColor: #329898; @successAlertColor: #448c11; @errorAlertColor: #c45b55; + +/* + -- logo image paths -- + These are set during webpack bundle through your settings.json file. +*/ +@largeLogoPath: ""; +@smallLogoPath: ""; diff --git a/package.json b/package.json index 23eb3b7d9..3d4d985f3 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "fetch-mock": "^5.9.3", "jest": "^18.1.0", "less": "^2.7.2", - "less-loader": "^2.2.3", + "less-loader": "^4.0.3", "mocha": "~3.1.2", "mocha-loader": "^1.1.0", "mocha-phantomjs": "git+https://github.com/garrensmith/mocha-phantomjs.git", @@ -78,8 +78,8 @@ "imports-loader": "^0.7.0", "jquery": "^2.2.0", "jsondiffpatch": "^0.1.41", - "less": "^2.3.1", - "less-loader": "^2.2.3", + "less": "^2.7.2", + "less-loader": "^4.0.3", "lodash": "^3.10.1", "mkdirp": "^0.5.1", "moment": "^2.17.1", diff --git a/settings.json.default.json b/settings.json.default.json index fde5dada0..d474c1b5b 100644 --- a/settings.json.default.json +++ b/settings.json.default.json @@ -21,7 +21,9 @@ "dest": "dist/debug/index.html", "variables": { "title": "Project Fauxton", - "generationLabel": "Fauxton Dev" + "generationLabel": "Fauxton Dev", + "largeLogoPath": "../../../../../assets/img/CouchDB-negative-logo.png", + "smallLogoPath": "../../../../../assets/img/couchdb-logo.png" }, "app": { "root": "/", @@ -34,7 +36,9 @@ "dest": "dist/debug/index.html", "variables": { "title": "Project Fauxton", - "generationLabel": "Fauxton Release" + "generationLabel": "Fauxton Release", + "largeLogoPath": "../../../../../assets/img/CouchDB-negative-logo.png", + "smallLogoPath": "../../../../../assets/img/couchdb-logo.png" }, "app": { "root": "/", @@ -47,7 +51,9 @@ "dest": "dist/debug/index.html", "variables": { "title": "Project Fauxton", - "generationLabel": "Fauxton Couchapp" + "generationLabel": "Fauxton Couchapp", + "largeLogoPath": "../../../../../assets/img/CouchDB-negative-logo.png", + "smallLogoPath": "../../../../../assets/img/couchdb-logo.png" }, "app": { "root": "/", diff --git a/webpack.config.dev.js b/webpack.config.dev.js index 89d3dbd55..54f09f407 100644 --- a/webpack.config.dev.js +++ b/webpack.config.dev.js @@ -74,7 +74,15 @@ module.exports = { use: [ "style-loader", "css-loader", - "less-loader" + { + loader: "less-loader", + options: { + modifyVars: { + largeLogoPath: "\'" + settings.variables.largeLogoPath + "\'", + smallLogoPath: "\'" + settings.variables.smallLogoPath + "\'" + } + } + } ] }, { diff --git a/webpack.config.release.js b/webpack.config.release.js index 99316c93a..522095281 100644 --- a/webpack.config.release.js +++ b/webpack.config.release.js @@ -109,7 +109,15 @@ module.exports = { fallback: "style-loader", use: [ "css-loader", - "less-loader" + { + loader: "less-loader", + options: { + modifyVars: { + largeLogoPath: "\'" + settings.variables.largeLogoPath + "\'", + smallLogoPath: "\'" + settings.variables.smallLogoPath + "\'" + } + } + } ], publicPath: '../../' }), From a44fb29a246f1fdb4a0a489f19a6511cfd2c0249 Mon Sep 17 00:00:00 2001 From: Ryan Millay Date: Fri, 31 Mar 2017 13:50:00 -0400 Subject: [PATCH 13/19] restoring isNavBarVisible functionality --- .../navigation/__tests__/login-logout-test.js | 6 +-- .../fauxton/navigation/__tests__/navbar-test.js | 44 ++++++++++++++++++++++ app/addons/fauxton/navigation/components/NavBar.js | 8 +++- 3 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 app/addons/fauxton/navigation/__tests__/navbar-test.js diff --git a/app/addons/fauxton/navigation/__tests__/login-logout-test.js b/app/addons/fauxton/navigation/__tests__/login-logout-test.js index afe139183..097e4952f 100644 --- a/app/addons/fauxton/navigation/__tests__/login-logout-test.js +++ b/app/addons/fauxton/navigation/__tests__/login-logout-test.js @@ -26,7 +26,7 @@ describe('Navigation Bar', () => { navLinks: [], bottomNavLinks: [], footerNavLinks: [], - + isNavBarVisible: true, isLoginSectionVisible: true, isLoginVisibleInsteadOfLogout: true }; @@ -46,7 +46,7 @@ describe('Navigation Bar', () => { bottomNavLinks: [], footerNavLinks: [], username: 'Rocko', - + isNavBarVisible: true, isLoginSectionVisible: true, isLoginVisibleInsteadOfLogout: false }; @@ -66,7 +66,7 @@ describe('Navigation Bar', () => { bottomNavLinks: [], footerNavLinks: [], username: 'Rocko', - + isNavBarVisible: true, isLoginSectionVisible: false, isLoginVisibleInsteadOfLogout: false }; diff --git a/app/addons/fauxton/navigation/__tests__/navbar-test.js b/app/addons/fauxton/navigation/__tests__/navbar-test.js new file mode 100644 index 000000000..59d9ed668 --- /dev/null +++ b/app/addons/fauxton/navigation/__tests__/navbar-test.js @@ -0,0 +1,44 @@ +// 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 NavBarContainer from "../container/NavBar"; +import FauxtonAPI from "../../../../core/api"; +import ActionTypes from "../actiontypes"; +import React from "react"; +import ReactDOM from "react-dom"; +import sinon from "sinon"; +import {mount} from 'enzyme'; + +describe('Navigation Bar', () => { + FauxtonAPI.session = { + user: () => {} + }; + + it('is displayed by default', () => { + const NavBar = mount(); + expect(NavBar.find('.faux-navbar').length).toBe(1); + }); + + it('is dynamically displayed by isNavBarVisible', () => { + const NavBar = mount(); + + FauxtonAPI.dispatch({ + type: ActionTypes.NAVBAR_HIDE + }); + expect(NavBar.find('.faux-navbar').length).toBe(0); + + FauxtonAPI.dispatch({ + type: ActionTypes.NAVBAR_SHOW + }); + expect(NavBar.find('.faux-navbar').length).toBe(1); + }); + +}); diff --git a/app/addons/fauxton/navigation/components/NavBar.js b/app/addons/fauxton/navigation/components/NavBar.js index f98076d87..2e6dc3026 100644 --- a/app/addons/fauxton/navigation/components/NavBar.js +++ b/app/addons/fauxton/navigation/components/NavBar.js @@ -48,9 +48,14 @@ class NavBar extends Component { isLoginSectionVisible, isLoginVisibleInsteadOfLogout, activeLink, - username + username, + isNavBarVisible } = this.props; + if (!isNavBarVisible) { + return null; + } + const navLinks = this.createLinks(this.props.navLinks); const bottomNavLinks = this.createLinks(this.props.bottomNavLinks); const footerNavLinks = this.createLinks(this.props.footerNavLinks); @@ -99,6 +104,7 @@ NavBar.propTypes = { navLinks: React.PropTypes.array, bottomNavLinks: React.PropTypes.array, footerNavLinks: React.PropTypes.array, + isNavBarVisible: React.PropTypes.bool, isLoginSectionVisible: React.PropTypes.bool.isRequired, isLoginVisibleInsteadOfLogout: React.PropTypes.bool.isRequired }; From 0b39f621e55d165e0048eccb139e0ed9b7e0db97 Mon Sep 17 00:00:00 2001 From: Ryan Millay Date: Fri, 31 Mar 2017 14:25:17 -0400 Subject: [PATCH 14/19] fixing linting error --- app/addons/fauxton/navigation/__tests__/navbar-test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app/addons/fauxton/navigation/__tests__/navbar-test.js b/app/addons/fauxton/navigation/__tests__/navbar-test.js index 59d9ed668..7a6331ebb 100644 --- a/app/addons/fauxton/navigation/__tests__/navbar-test.js +++ b/app/addons/fauxton/navigation/__tests__/navbar-test.js @@ -14,7 +14,6 @@ import FauxtonAPI from "../../../../core/api"; import ActionTypes from "../actiontypes"; import React from "react"; import ReactDOM from "react-dom"; -import sinon from "sinon"; import {mount} from 'enzyme'; describe('Navigation Bar', () => { From 35f644abef3e9e64d0815328028814f38a083a2b Mon Sep 17 00:00:00 2001 From: Ryan Millay Date: Fri, 31 Mar 2017 16:02:59 -0400 Subject: [PATCH 15/19] tweaking style and behavior of logout button --- app/addons/fauxton/assets/less/navigation.less | 13 +++++++++++++ app/addons/fauxton/navigation/components/LogoutButton.js | 7 ++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/app/addons/fauxton/assets/less/navigation.less b/app/addons/fauxton/assets/less/navigation.less index 8273aa8ee..f9d8345c5 100644 --- a/app/addons/fauxton/assets/less/navigation.less +++ b/app/addons/fauxton/assets/less/navigation.less @@ -175,3 +175,16 @@ bottom: 0; width:100%; } + +.faux-navbar__logout__username { + color: @buttonText; + overflow: hidden; + text-overflow: ellipsis; + max-width: 150px; + display: inline-block; + white-space: nowrap; + vertical-align: bottom; + padding-right: 5px; + padding-left: 10px; + font-size: 12px; +} diff --git a/app/addons/fauxton/navigation/components/LogoutButton.js b/app/addons/fauxton/navigation/components/LogoutButton.js index 7ef1621ed..037f172be 100644 --- a/app/addons/fauxton/navigation/components/LogoutButton.js +++ b/app/addons/fauxton/navigation/components/LogoutButton.js @@ -30,9 +30,10 @@ const LogoutButton = ({username, isMinimized}) => { Log Out   - - {isMinimized ? null : _.escape(username)} - + {isMinimized ? + null : + {_.escape(username)} + }
    ); From 83c1ae3569c5f478e339f6ca1ed4f7757b87fa12 Mon Sep 17 00:00:00 2001 From: Ryan Millay Date: Fri, 31 Mar 2017 16:31:30 -0400 Subject: [PATCH 16/19] further styling and alignment --- app/addons/fauxton/assets/less/navigation.less | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/app/addons/fauxton/assets/less/navigation.less b/app/addons/fauxton/assets/less/navigation.less index f9d8345c5..5eb905919 100644 --- a/app/addons/fauxton/assets/less/navigation.less +++ b/app/addons/fauxton/assets/less/navigation.less @@ -23,6 +23,7 @@ font-size: 10px; text-align: center; background-color: @brandDark2; + padding-bottom: 10px; } .faux-navbar__burger { @@ -119,14 +120,14 @@ .faux-navbar__logout__textcontainer--narrow { padding-bottom: 4px; - padding: 20px 0; + padding: 15px 0; } .faux-navbar__logout__textcontainer--wide { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - padding: 20px; + padding: 15px; } .faux-navbar__login__textcontainer { @@ -136,11 +137,11 @@ .faux-navbar__login__textcontainer--narrow { padding-bottom: 4px; - padding: 20px 0; + padding: 15px 0; } .faux-navbar__login__textcontainer--wide { - padding: 20px; + padding: 15px; } .faux-navbar__brand { @@ -181,9 +182,7 @@ overflow: hidden; text-overflow: ellipsis; max-width: 150px; - display: inline-block; white-space: nowrap; - vertical-align: bottom; padding-right: 5px; padding-left: 10px; font-size: 12px; From b6c394499e9a217458c45c454fd9a28775a5c0e8 Mon Sep 17 00:00:00 2001 From: Ryan Millay Date: Fri, 31 Mar 2017 22:51:39 -0400 Subject: [PATCH 17/19] stubborn test fix a.k.a. i hate you nightwatch --- app/addons/fauxton/tests/nightwatch/notificationCenter.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app/addons/fauxton/tests/nightwatch/notificationCenter.js b/app/addons/fauxton/tests/nightwatch/notificationCenter.js index 6dd4a5750..0c192bd0f 100644 --- a/app/addons/fauxton/tests/nightwatch/notificationCenter.js +++ b/app/addons/fauxton/tests/nightwatch/notificationCenter.js @@ -26,7 +26,6 @@ module.exports = { .loginToGUI() .waitForElementPresent('#notification-center-btn', waitTime, false) - .clickWhenVisible('.global-notification .fonticon-cancel', waitTime, false) .assert.cssClassNotPresent('.notification-center-panel', 'visible') .clickWhenVisible('#notification-center-btn', waitTime, false) .waitForElementPresent('.notification-center-panel.visible', waitTime, false) From d90077127b1a3ff5521d6a16d9e32ef946eb2505 Mon Sep 17 00:00:00 2001 From: Ryan Millay Date: Mon, 3 Apr 2017 13:15:21 -0400 Subject: [PATCH 18/19] addressing review comments by introducing flexbox --- app/addons/fauxton/assets/less/navigation.less | 21 ++++++++++++++++---- app/addons/fauxton/navigation/components/NavBar.js | 23 ++++++++++++---------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/app/addons/fauxton/assets/less/navigation.less b/app/addons/fauxton/assets/less/navigation.less index 5eb905919..d6697089d 100644 --- a/app/addons/fauxton/assets/less/navigation.less +++ b/app/addons/fauxton/assets/less/navigation.less @@ -1,13 +1,23 @@ .faux-navbar { margin-top: 64px; background-color: @brandDark2; - position: absolute; left: 0; top: 0; bottom: 0; z-index: 5; + overflow: scroll; +} +.faux-navbar nav { + height: 100%; +} + +.faux-navbar__flex { + display: flex; + flex-direction: column; + justify-content: space-between; + height: 100%; } .faux-navbar__itemarea { @@ -172,9 +182,12 @@ } .faux-navbar__footer { - position: absolute; - bottom: 0; - width:100%; + display: flex; + flex-direction: column; + justify-content: flex-end; + height: 100%; + min-height: 200px; + width: 100%; } .faux-navbar__logout__username { diff --git a/app/addons/fauxton/navigation/components/NavBar.js b/app/addons/fauxton/navigation/components/NavBar.js index 2e6dc3026..1a6a56928 100644 --- a/app/addons/fauxton/navigation/components/NavBar.js +++ b/app/addons/fauxton/navigation/components/NavBar.js @@ -74,20 +74,23 @@ class NavBar extends Component {
    From 687a52c825f0a913cdd23ac535c32ac496aaaf21 Mon Sep 17 00:00:00 2001 From: Ryan Millay Date: Wed, 5 Apr 2017 10:07:23 -0400 Subject: [PATCH 19/19] renaming css class per review --- app/addons/fauxton/assets/less/navigation.less | 2 +- app/addons/fauxton/navigation/components/NavBar.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/addons/fauxton/assets/less/navigation.less b/app/addons/fauxton/assets/less/navigation.less index d6697089d..1493c6272 100644 --- a/app/addons/fauxton/assets/less/navigation.less +++ b/app/addons/fauxton/assets/less/navigation.less @@ -13,7 +13,7 @@ height: 100%; } -.faux-navbar__flex { +.faux-navbar__linkcontainer { display: flex; flex-direction: column; justify-content: space-between; diff --git a/app/addons/fauxton/navigation/components/NavBar.js b/app/addons/fauxton/navigation/components/NavBar.js index 1a6a56928..3a83a1158 100644 --- a/app/addons/fauxton/navigation/components/NavBar.js +++ b/app/addons/fauxton/navigation/components/NavBar.js @@ -74,7 +74,7 @@ class NavBar extends Component {