Merge pull request #1148 from metamaps/feature/refactor.nav.bar

rename exploreMapsBar into reusable navBar
This commit is contained in:
Connor Turland 2017-10-14 12:30:29 -04:00 committed by GitHub
commit 76c727cd61
17 changed files with 223 additions and 154 deletions

View file

@ -826,6 +826,7 @@ label {
font-size: 14px; font-size: 14px;
line-height: 14px; line-height: 14px;
color: #757575; color: #757575;
cursor: pointer;
} }
.accountListItem:hover { .accountListItem:hover {
color: #424242; color: #424242;

View file

@ -668,19 +668,19 @@
box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16); box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16);
} }
#exploreMapsHeader { #navBar {
position: absolute; position: absolute;
width: 100%; width: 100%;
} }
.exploreMapsBar { .navBarContainer {
z-index:2; z-index:2;
background-color:#FAFAFA; background-color:#FAFAFA;
height: 42px; height: 42px;
padding-top: 52px; padding-top: 52px;
} }
.exploreMapsMenu { .navBarMenu {
display: block; display: block;
width: 100%; width: 100%;
height:42px; height:42px;
@ -689,11 +689,11 @@
text-align: center; text-align: center;
} }
.exploreMapsCenter { .navBarCenter {
display: block; display: block;
} }
.exploreMapsButton { .navBarButton {
color: #757575; color: #757575;
cursor: default; cursor: default;
font-weight: normal; font-weight: normal;
@ -706,13 +706,13 @@
cursor: pointer; cursor: pointer;
position:relative; position:relative;
} }
.exploreMapsButton:hover, .exploreMapsButton.active { .navBarButton:hover, .navBarButton.active {
text-decoration: none; text-decoration: none;
color: #424242; color: #424242;
border-bottom: 2px solid #00BCD4; border-bottom: 2px solid #00BCD4;
} }
.exploreMapsButton.mapperButton { .navBarButton.mapperButton {
height: 40px; height: 40px;
padding: 0; padding: 0;
} }
@ -729,7 +729,7 @@
} }
.exploreMapsButton .exploreMapsIcon { .navBarButton .navBarIcon {
background-repeat: no-repeat; background-repeat: no-repeat;
width:32px; width:32px;
height:32px; height:32px;
@ -738,53 +738,53 @@
left:5px; left:5px;
} }
.exploreMapsCenter .authedApps .exploreMapsIcon { .navBarCenter .authedApps .navBarIcon {
background-image: url(<%= asset_path('user_sprite.png') %>); background-image: url(<%= asset_path('user_sprite.png') %>);
background-position: 0 -32px; background-position: 0 -32px;
} }
.exploreMapsCenter .myMaps .exploreMapsIcon { .navBarCenter .myMaps .navBarIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>); background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: -32px 0; background-position: -32px 0;
} }
.exploreMapsCenter .sharedMaps .exploreMapsIcon { .navBarCenter .sharedMaps .navBarIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>); background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: -128px 0; background-position: -128px 0;
} }
.exploreMapsCenter .activeMaps .exploreMapsIcon { .navBarCenter .activeMaps .navBarIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>); background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: 0 0; background-position: 0 0;
} }
.exploreMapsCenter .featuredMaps .exploreMapsIcon { .navBarCenter .featuredMaps .navBarIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>); background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: -96px 0; background-position: -96px 0;
} }
.exploreMapsCenter .starredMaps .exploreMapsIcon { .navBarCenter .starredMaps .navBarIcon {
background-image: url(<%= asset_path 'exploremaps_sprite.png' %>); background-image: url(<%= asset_path 'exploremaps_sprite.png' %>);
background-position: -96px 0; background-position: -96px 0;
} }
.exploreMapsCenter .notificationsLink .exploreMapsIcon { .navBarCenter .notificationsLink .navBarIcon {
background-image: url(<%= asset_path 'topright_sprite.png' %>); background-image: url(<%= asset_path 'topright_sprite.png' %>);
background-position: -128px 0; background-position: -128px 0;
} }
.authedApps:hover .exploreMapsIcon, .authedApps.active .exploreMapsIcon { .authedApps:hover .navBarIcon, .authedApps.active .navBarIcon {
background-position-x: -32px; background-position-x: -32px;
} }
.myMaps:hover .exploreMapsIcon, .myMaps.active .exploreMapsIcon { .myMaps:hover .navBarIcon, .myMaps.active .navBarIcon {
background-position: -32px -32px; background-position: -32px -32px;
} }
.activeMaps:hover .exploreMapsIcon, .activeMaps.active .exploreMapsIcon { .activeMaps:hover .navBarIcon, .activeMaps.active .navBarIcon {
background-position: 0 -32px; background-position: 0 -32px;
} }
.featuredMaps:hover .exploreMapsIcon, .featuredMaps.active .exploreMapsIcon { .featuredMaps:hover .navBarIcon, .featuredMaps.active .navBarIcon {
background-position: -96px -32px; background-position: -96px -32px;
} }
.starredMaps:hover .exploreMapsIcon, .starredMaps.active .exploreMapsIcon { .starredMaps:hover .navBarIcon, .starredMaps.active .navBarIcon {
background-position: -96px -32px; background-position: -96px -32px;
} }
.sharedMaps:hover .exploreMapsIcon, .sharedMaps.active .exploreMapsIcon { .sharedMaps:hover .navBarIcon, .sharedMaps.active .navBarIcon {
background-position: -128px -32px; background-position: -128px -32px;
} }
.notificationsLink:hover .exploreMapsIcon, .notificationsLink.active .exploreMapsIcon { .notificationsLink:hover .navBarIcon, .notificationsLink.active .navBarIcon {
background-position-y: -32px; background-position-y: -32px;
} }

View file

@ -32,7 +32,7 @@
/* Smartphones (portrait and landscape) ----------- the minimum space that two map cards can fit side by side */ /* Smartphones (portrait and landscape) ----------- the minimum space that two map cards can fit side by side */
@media only screen and (max-width : 504px) { @media only screen and (max-width : 504px) {
.upperLeftUI, .upperRightUI, .openCheatsheet, .mapInfoIcon, .feedback-icon, .chat-box, #exploreMapsHeader { .upperLeftUI, .upperRightUI, .openCheatsheet, .mapInfoIcon, .feedback-icon, .chat-box, #navBar {
display: none !important; display: none !important;
} }

View file

@ -6,10 +6,10 @@
#%> #%>
<%= render :partial => 'layouts/head' %> <%= render :partial => 'layouts/head' %>
<body class="<%= authenticated? ? "authenticated" : "unauthenticated" %> controller-<%= controller_name %> action-<%= action_name %>"> <body class="<%= current_user ? "authenticated" : "unauthenticated" %> controller-<%= controller_name %> action-<%= action_name %>">
<div class="main" id="react-app"></div> <div class="main" id="react-app"></div>
<%= yield %> <%= yield %>
<% if authenticated? %> <% if current_user %>
<% # for creating and pulling in topics and synapses %> <% # for creating and pulling in topics and synapses %>
<% if controller_name == 'maps' && action_name == "conversation" %> <% if controller_name == 'maps' && action_name == "conversation" %>
<%= render :partial => 'maps/newtopicsecret' %> <%= render :partial => 'maps/newtopicsecret' %>

View file

@ -1,31 +0,0 @@
<%#
# @file
# Main application file. Holds scaffolding present on every page.
# Then a certain non-partial view (no _ preceding filename) will be
# displayed within, based on URL
#%>
<%= render :partial => 'layouts/head' %>
<body class="<%= current_user ? 'authenticated' : 'unauthenticated' %>">
<div class="main" id="react-app"></div>
<%= yield %>
<div id="exploreMapsHeader">
<div class="exploreMapsBar exploreElement">
<div class="exploreMapsMenu">
<div class="exploreMapsCenter">
<% if current_user && current_user.admin %>
<a href="<%= oauth_applications_path %>" class="activeMaps exploreMapsButton <%= params[:controller] == 'doorkeeper/applications' ? 'active' : nil %>">
<div class="exploreMapsIcon"></div>Registered Apps
</a>
<% end %>
<a href="<%= oauth_authorized_applications_path %>" class="authedApps exploreMapsButton <%= params[:controller] == 'doorkeeper/authorized_applications' ? 'active' : nil %>">
<div class="exploreMapsIcon"></div>Authorized Apps
</a>
<a href="/" class="myMaps exploreMapsButton">
<div class="exploreMapsIcon"></div>Maps
</a>
</div>
</div>
</div>
</div>
<%= render :partial => 'layouts/foot' %>

View file

@ -1,14 +0,0 @@
<div id="exploreMapsHeader">
<div class="exploreMapsBar exploreElement">
<div class="exploreMapsMenu">
<div class="exploreMapsCenter">
<a href="<%= notifications_path %>" class="notificationsLink exploreMapsButton active">
<div class="exploreMapsIcon"></div>Notifications
</a>
<a href="/" class="exploreMapsButton myMaps">
<div class="exploreMapsIcon"></div>Maps
</a>
</div>
</div>
</div>
</div>

View file

@ -76,5 +76,3 @@
</div> </div>
<% end %> <% end %>
</div> </div>
<%= render partial: 'notifications/header' %>

View file

@ -9,7 +9,7 @@
<h2 class="notification-title"> <h2 class="notification-title">
<% case @notification.notification_code <% case @notification.notification_code
when MAP_ACCESS_REQUEST when MAP_ACCESS_REQUEST
request = @notification.notified_object request = @notification.notified_object
map = request.map %> map = request.map %>
<%= image_tag @notification.sender.image(:thirtytwo), class: 'thirty-two-avatar' %> <span style='font-weight:bold;' class='requesterName'><%= request.user.name %></span> wants to collaborate on map <span style='font-weight:bold;'><%= map.name %></span> <%= image_tag @notification.sender.image(:thirtytwo), class: 'thirty-two-avatar' %> <span style='font-weight:bold;' class='requesterName'><%= request.user.name %></span> wants to collaborate on map <span style='font-weight:bold;'><%= map.name %></span>
<% else %> <% else %>
@ -24,7 +24,7 @@
<% if request.approved %> <% if request.approved %>
You already responded to this access request, and allowed access. You already responded to this access request, and allowed access.
<% elsif !request.approved %> <% elsif !request.approved %>
You already responded to this access request, and declined access. If you changed your mind, you can still grant You already responded to this access request, and declined access. If you changed your mind, you can still grant
them access by going to the map and adding them as a collaborator. them access by going to the map and adding them as a collaborator.
<% end %> <% end %>
<% else %> <% else %>
@ -50,5 +50,3 @@
<% end %> <% end %>
</div> </div>
</div> </div>
<%= render partial: 'notifications/header' %>

View file

@ -25,9 +25,9 @@ module Metamaps
config.encoding = 'utf-8' config.encoding = 'utf-8'
config.to_prepare do config.to_prepare do
Doorkeeper::ApplicationsController.layout 'doorkeeper' Doorkeeper::ApplicationsController.layout 'application'
Doorkeeper::AuthorizationsController.layout 'doorkeeper' Doorkeeper::AuthorizationsController.layout 'application'
Doorkeeper::AuthorizedApplicationsController.layout 'doorkeeper' Doorkeeper::AuthorizedApplicationsController.layout 'application'
Doorkeeper::ApplicationController.helper ApplicationHelper Doorkeeper::ApplicationController.helper ApplicationHelper
end end

View file

@ -0,0 +1,19 @@
import React, { Component } from 'react'
class NavBar extends Component {
render() {
return (
<div id="navBar">
<div className="navBarContainer">
<div className="navBarMenu">
<div className="navBarCenter">
{this.props.children}
</div>
</div>
</div>
</div>
)
}
}
export default NavBar

View file

@ -0,0 +1,65 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Link } from 'react-router'
import _ from 'lodash'
const PROP_LIST = [
'matchChildRoutes',
'hardReload',
'show',
'text',
'href',
'linkClass'
]
class NavBarLink extends Component {
static propTypes = {
matchChildRoutes: PropTypes.bool,
hardReload: PropTypes.bool,
show: PropTypes.bool,
text: PropTypes.string,
href: PropTypes.string,
linkClass: PropTypes.string
}
static contextTypes = {
location: PropTypes.object
}
render = () => {
const {
matchChildRoutes,
hardReload,
show,
text,
href,
linkClass
} = this.props
const { location } = this.context
const otherProps = _.omit(this.props, PROP_LIST)
const classes = ['navBarButton', linkClass]
const active = matchChildRoutes ?
location.pathname.startsWith(href) :
location.pathname === href
if (active) classes.push('active')
if (!show) {
return null
}
if (hardReload) {
return (
<a { ...otherProps } href={href} className={classes.join(' ')}>
<div className="navBarIcon"></div>
{text}
</a>
)
}
return (
<Link { ...otherProps } to={href} className={classes.join(' ')}>
<div className="navBarIcon"></div>
{text}
</Link>
)
}
}
export default NavBarLink

View file

@ -38,17 +38,38 @@ class App extends Component {
return {location} return {location}
} }
constructor (props) {
super(props)
this.state = {
yieldHTML: null
}
}
componentDidMount () {
this.setYield()
}
setYield () {
const yieldHTML = document.getElementById('yield')
if (yieldHTML) {
this.setState({yieldHTML: yieldHTML.innerHTML})
document.body.removeChild(yieldHTML)
}
}
render () { render () {
const { children, toast, unreadNotificationsCount, openInviteLightbox, const { children, toast, unreadNotificationsCount, openInviteLightbox,
mobile, mobileTitle, mobileTitleWidth, mobileTitleClick, location, mobile, mobileTitle, mobileTitleWidth, mobileTitleClick, location,
map, userRequested, requestAnswered, requestApproved, serverData, map, userRequested, requestAnswered, requestApproved, serverData,
onRequestAccess, notifications, fetchNotifications, onRequestAccess, notifications, fetchNotifications,
markAsRead, markAsUnread } = this.props markAsRead, markAsUnread } = this.props
const { yieldHTML } = this.state
const { pathname } = location || {} const { pathname } = location || {}
// this fixes a bug that happens otherwise when you logout // this fixes a bug that happens otherwise when you logout
const currentUser = this.props.currentUser && this.props.currentUser.id ? this.props.currentUser : null const currentUser = this.props.currentUser && this.props.currentUser.id ? this.props.currentUser : null
const unauthedHome = pathname === '/' && !currentUser const unauthedHome = pathname === '/' && !currentUser
return <div className="wrapper" id="wrapper"> return <div className="wrapper" id="wrapper">
{yieldHTML && <div id="yield" dangerouslySetInnerHTML={{__html: yieldHTML}}></div>}
{mobile && <MobileHeader currentUser={currentUser} {mobile && <MobileHeader currentUser={currentUser}
unreadNotificationsCount={unreadNotificationsCount} unreadNotificationsCount={unreadNotificationsCount}
mobileTitle={mobileTitle} mobileTitle={mobileTitle}

View file

@ -0,0 +1,24 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import NavBar from '../App/Navbar'
import NavBarLink from '../App/NavBarLink'
class Apps extends Component {
render = () => {
const { currentUser } = this.props
return (
<NavBar>
{currentUser && currentUser.get('admin') && <NavBarLink show hardReload
matchChildRoutes href="/oauth/applications" linkClass="activeMaps"
text="Registered Apps" />}
<NavBarLink show hardReload matchChildRoutes
href="/oauth/authorized_applications"
linkClass="authedApps" text="Authorized Apps" />
<NavBarLink show href="/" linkClass="myMaps" text="Maps" />
</NavBar>
)
}
}
export default Apps

View file

@ -1,80 +1,50 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { Link } from 'react-router' import NavBar from '../App/Navbar'
import _ from 'lodash' import NavBarLink from '../App/NavBarLink'
const MapLink = props => {
const { show, text, href, linkClass } = props
const otherProps = _.omit(props, ['show', 'text', 'href', 'linkClass'])
if (!show) {
return null
}
return (
<Link { ...otherProps } to={href} className={linkClass}>
<div className="exploreMapsIcon"></div>
{text}
</Link>
)
}
class Header extends Component { class Header extends Component {
render = () => { render = () => {
const { signedIn, section, user } = this.props const { signedIn, section, user } = this.props
const activeClass = (title) => {
let forClass = 'exploreMapsButton'
forClass += ' ' + title + 'Maps'
if (title === 'my' && section === 'mine' ||
title === section) forClass += ' active'
return forClass
}
const explore = section === 'mine' || section === 'active' || section === 'starred' || section === 'shared' || section === 'featured' const explore = section === 'mine' || section === 'active' || section === 'starred' || section === 'shared' || section === 'featured'
const mapper = section === 'mapper' const mapper = section === 'mapper'
return ( return (
<div id="exploreMapsHeader"> <NavBar>
<div className="exploreMapsBar exploreElement"> <NavBarLink show={explore}
<div className="exploreMapsMenu"> href={signedIn ? '/' : '/explore/active'}
<div className="exploreMapsCenter"> linkClass="activeMaps"
<MapLink show={explore} text="All Maps"
href={signedIn ? '/' : '/explore/active'} />
linkClass={activeClass('active')} <NavBarLink show={signedIn && explore}
text="All Maps" href="/explore/mine"
/> linkClass="myMaps"
<MapLink show={signedIn && explore} text="My Maps"
href="/explore/mine" />
linkClass={activeClass('my')} <NavBarLink show={signedIn && explore}
text="My Maps" href="/explore/shared"
/> linkClass="sharedMaps"
<MapLink show={signedIn && explore} text="Shared With Me"
href="/explore/shared" />
linkClass={activeClass('shared')} <NavBarLink show={signedIn && explore}
text="Shared With Me" href="/explore/starred"
/> linkClass="starredMaps"
<MapLink show={signedIn && explore} text="Starred By Me"
href="/explore/starred" />
linkClass={activeClass('starred')} <NavBarLink show={!signedIn && explore}
text="Starred By Me" href="/explore/featured"
/> linkClass="featuredMaps"
<MapLink show={!signedIn && explore} text="Featured Maps"
href="/explore/featured" />
linkClass={activeClass('featured')} {mapper ? (
text="Featured Maps" <div className='navBarButton active mapperButton'>
/> {user && <img className='exploreMapperImage' width='24' height='24' src={user.image} />}
{user && <div className='exploreMapperName'>{user.name}&rsquo;s Maps</div>}
{mapper ? ( <div className='clearfloat'></div>
<div className='exploreMapsButton active mapperButton'>
{user && <img className='exploreMapperImage' width='24' height='24' src={user.image} />}
{user && <div className='exploreMapperName'>{user.name}&rsquo;s Maps</div>}
<div className='clearfloat'></div>
</div>
) : null }
</div>
</div> </div>
</div> ) : null }
</div> </NavBar>
) )
} }
} }

View file

@ -6,7 +6,6 @@ import MapperCard from './MapperCard'
import MapCard from './MapCard' import MapCard from './MapCard'
class Maps extends Component { class Maps extends Component {
static propTypes = { static propTypes = {
section: PropTypes.string, section: PropTypes.string,
maps: PropTypes.object, maps: PropTypes.object,

View file

@ -0,0 +1,17 @@
import React, { Component } from 'react'
import NavBar from '../App/Navbar'
import NavBarLink from '../App/NavBarLink'
class Notifications extends Component {
render = () => {
return (
<NavBar>
<NavBarLink show matchChildRoutes href="/notifications"
linkClass="notificationsLink" text="Notifications" />
<NavBarLink show href="/" linkClass="myMaps" text="Maps" />
</NavBar>
)
}
}
export default Notifications

View file

@ -1,8 +1,10 @@
import React from 'react' import React from 'react'
import { Route, IndexRoute } from 'react-router' import { Route, IndexRoute } from 'react-router'
import App from './App' import App from './App'
import Apps from './Apps'
import Maps from './Maps' import Maps from './Maps'
import MapView from './MapView' import MapView from './MapView'
import Notifications from './Notifications'
import TopicView from './TopicView' import TopicView from './TopicView'
function nullComponent(props) { function nullComponent(props) {
@ -31,8 +33,8 @@ export default function makeRoutes (currentUser) {
<Route path="join" component={nullComponent} /> <Route path="join" component={nullComponent} />
<Route path="request" component={nullComponent} /> <Route path="request" component={nullComponent} />
<Route path="notifications"> <Route path="notifications">
<IndexRoute component={nullComponent} /> <IndexRoute component={Notifications} />
<Route path=":id" component={nullComponent} /> <Route path=":id" component={Notifications} />
</Route> </Route>
<Route path="users"> <Route path="users">
<Route path=":id/edit" component={nullComponent} /> <Route path=":id/edit" component={nullComponent} />
@ -50,20 +52,20 @@ export default function makeRoutes (currentUser) {
<Route path=":id/edit" component={nullComponent} /> <Route path=":id/edit" component={nullComponent} />
</Route> </Route>
<Route path="oauth"> <Route path="oauth">
<Route path="token/info" component={nullComponent} /> <Route path="token/info" component={Apps} />
<Route path="authorize"> <Route path="authorize">
<IndexRoute component={nullComponent} /> <IndexRoute component={nullComponent} />
<Route path=":code" component={nullComponent} /> <Route path=":code" component={nullComponent} />
</Route> </Route>
<Route path="authorized_applications"> <Route path="authorized_applications">
<IndexRoute component={nullComponent} /> <IndexRoute component={Apps} />
<Route path=":id" component={nullComponent} /> <Route path=":id" component={Apps} />
</Route> </Route>
<Route path="applications"> <Route path="applications">
<IndexRoute component={nullComponent} /> <IndexRoute component={Apps} />
<Route path="new" component={nullComponent} /> <Route path="new" component={Apps} />
<Route path=":id" component={nullComponent} /> <Route path=":id" component={Apps} />
<Route path=":id/edit" component={nullComponent} /> <Route path=":id/edit" component={Apps} />
</Route> </Route>
</Route> </Route>
</Route> </Route>