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

View file

@ -6,10 +6,10 @@
#%>
<%= 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>
<%= yield %>
<% if authenticated? %>
<% if current_user %>
<% # for creating and pulling in topics and synapses %>
<% if controller_name == 'maps' && action_name == "conversation" %>
<%= 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>
<% end %>
</div>
<%= render partial: 'notifications/header' %>

View file

@ -9,7 +9,7 @@
<h2 class="notification-title">
<% case @notification.notification_code
when MAP_ACCESS_REQUEST
request = @notification.notified_object
request = @notification.notified_object
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>
<% else %>
@ -24,7 +24,7 @@
<% if request.approved %>
You already responded to this access request, and allowed access.
<% 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.
<% end %>
<% else %>
@ -50,5 +50,3 @@
<% end %>
</div>
</div>
<%= render partial: 'notifications/header' %>

View file

@ -25,9 +25,9 @@ module Metamaps
config.encoding = 'utf-8'
config.to_prepare do
Doorkeeper::ApplicationsController.layout 'doorkeeper'
Doorkeeper::AuthorizationsController.layout 'doorkeeper'
Doorkeeper::AuthorizedApplicationsController.layout 'doorkeeper'
Doorkeeper::ApplicationsController.layout 'application'
Doorkeeper::AuthorizationsController.layout 'application'
Doorkeeper::AuthorizedApplicationsController.layout 'application'
Doorkeeper::ApplicationController.helper ApplicationHelper
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}
}
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 () {
const { children, toast, unreadNotificationsCount, openInviteLightbox,
mobile, mobileTitle, mobileTitleWidth, mobileTitleClick, location,
map, userRequested, requestAnswered, requestApproved, serverData,
onRequestAccess, notifications, fetchNotifications,
markAsRead, markAsUnread } = this.props
const { yieldHTML } = this.state
const { pathname } = location || {}
// this fixes a bug that happens otherwise when you logout
const currentUser = this.props.currentUser && this.props.currentUser.id ? this.props.currentUser : null
const unauthedHome = pathname === '/' && !currentUser
return <div className="wrapper" id="wrapper">
{yieldHTML && <div id="yield" dangerouslySetInnerHTML={{__html: yieldHTML}}></div>}
{mobile && <MobileHeader currentUser={currentUser}
unreadNotificationsCount={unreadNotificationsCount}
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 PropTypes from 'prop-types'
import { Link } from 'react-router'
import _ from 'lodash'
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>
)
}
import NavBar from '../App/Navbar'
import NavBarLink from '../App/NavBarLink'
class Header extends Component {
render = () => {
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 mapper = section === 'mapper'
return (
<div id="exploreMapsHeader">
<div className="exploreMapsBar exploreElement">
<div className="exploreMapsMenu">
<div className="exploreMapsCenter">
<MapLink show={explore}
href={signedIn ? '/' : '/explore/active'}
linkClass={activeClass('active')}
text="All Maps"
/>
<MapLink show={signedIn && explore}
href="/explore/mine"
linkClass={activeClass('my')}
text="My Maps"
/>
<MapLink show={signedIn && explore}
href="/explore/shared"
linkClass={activeClass('shared')}
text="Shared With Me"
/>
<MapLink show={signedIn && explore}
href="/explore/starred"
linkClass={activeClass('starred')}
text="Starred By Me"
/>
<MapLink show={!signedIn && explore}
href="/explore/featured"
linkClass={activeClass('featured')}
text="Featured Maps"
/>
{mapper ? (
<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>
<NavBar>
<NavBarLink show={explore}
href={signedIn ? '/' : '/explore/active'}
linkClass="activeMaps"
text="All Maps"
/>
<NavBarLink show={signedIn && explore}
href="/explore/mine"
linkClass="myMaps"
text="My Maps"
/>
<NavBarLink show={signedIn && explore}
href="/explore/shared"
linkClass="sharedMaps"
text="Shared With Me"
/>
<NavBarLink show={signedIn && explore}
href="/explore/starred"
linkClass="starredMaps"
text="Starred By Me"
/>
<NavBarLink show={!signedIn && explore}
href="/explore/featured"
linkClass="featuredMaps"
text="Featured Maps"
/>
{mapper ? (
<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>}
<div className='clearfloat'></div>
</div>
</div>
</div>
) : null }
</NavBar>
)
}
}

View file

@ -6,7 +6,6 @@ import MapperCard from './MapperCard'
import MapCard from './MapCard'
class Maps extends Component {
static propTypes = {
section: PropTypes.string,
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 { Route, IndexRoute } from 'react-router'
import App from './App'
import Apps from './Apps'
import Maps from './Maps'
import MapView from './MapView'
import Notifications from './Notifications'
import TopicView from './TopicView'
function nullComponent(props) {
@ -31,8 +33,8 @@ export default function makeRoutes (currentUser) {
<Route path="join" component={nullComponent} />
<Route path="request" component={nullComponent} />
<Route path="notifications">
<IndexRoute component={nullComponent} />
<Route path=":id" component={nullComponent} />
<IndexRoute component={Notifications} />
<Route path=":id" component={Notifications} />
</Route>
<Route path="users">
<Route path=":id/edit" component={nullComponent} />
@ -50,20 +52,20 @@ export default function makeRoutes (currentUser) {
<Route path=":id/edit" component={nullComponent} />
</Route>
<Route path="oauth">
<Route path="token/info" component={nullComponent} />
<Route path="token/info" component={Apps} />
<Route path="authorize">
<IndexRoute component={nullComponent} />
<Route path=":code" component={nullComponent} />
</Route>
<Route path="authorized_applications">
<IndexRoute component={nullComponent} />
<Route path=":id" component={nullComponent} />
<IndexRoute component={Apps} />
<Route path=":id" component={Apps} />
</Route>
<Route path="applications">
<IndexRoute component={nullComponent} />
<Route path="new" component={nullComponent} />
<Route path=":id" component={nullComponent} />
<Route path=":id/edit" component={nullComponent} />
<IndexRoute component={Apps} />
<Route path="new" component={Apps} />
<Route path=":id" component={Apps} />
<Route path=":id/edit" component={Apps} />
</Route>
</Route>
</Route>