redo the mobile menu in react

This commit is contained in:
Connor Turland 2017-03-12 03:26:00 -04:00
parent 780217490b
commit 871c491097
9 changed files with 107 additions and 105 deletions

View file

@ -1,7 +1,3 @@
#mobile_header {
display: none;
}
@media only screen and (max-width : 752px) and (min-width : 504px) {
.sidebarSearch .tt-hint, .sidebarSearch .sidebarSearchField {
width: 160px !important;
@ -51,10 +47,6 @@
display: none;
}
#mobile_header {
display: block;
}
.homeWrapper {
width: 96%;
padding: 0 2%;
@ -116,7 +108,7 @@
#exploreMaps > div {
margin-top: 70px;
}
.mapper {
width: 100%;
margin: 0 0 30px 0;
@ -217,6 +209,7 @@
width: 100%;
box-shadow: 0px 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16);
position: fixed;
z-index: 1;
}
#menu_icon {
@ -249,7 +242,6 @@
}
#mobile_menu {
display: none;
background: #EEE;
position: fixed;
top: 50px;
@ -257,6 +249,7 @@
padding: 10px;
width: 200px;
box-shadow: 3px 3px 3px rgba(0,0,0,0.23), 3px 3px 3px rgba(0,0,0,0.16);
z-index: 2;
li {
padding: 10px;
@ -274,16 +267,6 @@
}
}
/*
* the mobile menu, even if it's been opened by a user, should
* not show up if they resize their browser back to full size
*/
@media only screen and (max-width : 504px) {
#mobile_menu.visible {
display: block;
}
}
li.mobileMenuUser {
border-bottom: 1px solid #BBB;
}

View file

@ -1,67 +0,0 @@
<div id="mobile_header">
<div id="header_content">
<%= yield(:mobile_title) %>
</div>
<div id="menu_icon">
<% if user_unread_notification_count > 0 %>
<div class="unread-notifications-dot"></div>
<% end %>
</div>
</div>
<div id="mobile_menu">
<ul>
<% if not current_user %>
<li>
<%= link_to "Home", root_path %>
</li>
<% end %>
<% if current_user %>
<li class="mobileMenuUser">
<%= image_tag current_user.image.url(:sixtyfour), :size => "32x32" %>
<span><%= current_user.name %></span>
</li>
<li>
<%= link_to "New Map", new_map_path %>
</li>
<li>
<%= link_to "My Maps", explore_mine_path, :data => { :router => 'true'} %>
</li>
<li>
<%= link_to "Shared With Me", explore_shared_path, :data => { :router => 'true'} %>
</li>
<li>
<%= link_to "Starred By Me", explore_starred_path, :data => { :router => 'true'} %>
</li>
<% end %>
<li>
<%= link_to "All Maps", explore_active_path, :data => { :router => 'true'} %>
</li>
<% if not current_user %>
<li>
<%= link_to "Featured Maps", explore_featured_path, :data => { :router => 'true'} %>
</li>
<% end %>
<% if not current_user %>
<li>
<%= link_to "Request Invite", request_path %>
</li>
<li>
<%= link_to "Login", sign_in_path %>
</li>
<% end %>
<% if current_user %>
<li>
<%= link_to "Account", edit_user_url(current_user) %>
</li>
<li class="notifications">
<%= link_to "Notifications", notifications_path %>
<% if user_unread_notification_count > 0 %>
<div class="unread-notifications-dot"></div>
<% end %>
</li>
<li>
<%= link_to "Sign Out", "/logout", id: "Logout" %>
</li>
<% end %>
</ul>
</div>

View file

@ -9,7 +9,6 @@
<body class="<%= authenticated? ? "authenticated" : "unauthenticated" %> controller-<%= controller_name %> action-<%= action_name %>">
<%= content_tag :div, class: "main", id: "react-app" do %>
<%= yield %>
<%= render :partial => 'layouts/mobilemenu' %>
<% end %>
<% if devise_error_messages? %>
<%= devise_error_messages! %>
@ -35,6 +34,9 @@
Metamaps.ServerData.mapIsStarred = <%= @map && current_user.starred_map?(@map) ? true : false %>
</script>
<% end %>
<script type="text/javascript">
Metamaps.ServerData.mobileTitle = "<%= yield(:mobile_title) %>"
</script>
<div class="hidden"><%= render :partial => 'shared/filterBox' %></div>
<div id="loading"></div>
<%= render :partial => 'layouts/foot' %>

View file

@ -30,14 +30,15 @@ const ReactApp = {
unreadNotificationsCount: 0,
mapsWidth: 0,
mobile: false,
mobileTitle: '',
mobileTitleWidth: 0,
init: function(serverData, openLightbox) {
const self = ReactApp
self.unreadNotificationsCount = serverData.unreadNotificationsCount
self.mobileTitle = serverData.mobileTitle
self.openLightbox = openLightbox
routes = makeRoutes()
self.resize()
self.setMobile()
self.render()
window && window.addEventListener('resize', self.resize)
},
handleUpdate: function(location) {
@ -72,7 +73,10 @@ const ReactApp = {
return merge({
unreadNotificationsCount: self.unreadNotificationsCount,
currentUser: Active.Mapper,
mobile: self.mobile
mobile: self.mobile,
mobileTitle: self.mobileTitle,
mobileTitleWidth: self.mobileTitleWidth,
mobileTitleClick: (e) => Active.Map && InfoBox.toggleBox(e)
},
self.getMapProps(),
self.getTopicProps(),
@ -155,11 +159,6 @@ const ReactApp = {
handleInputMessage: ChatView.handleInputMessage
}
},
setMobile: function() {
const self = ReactApp
self.mobile = document && document.body.clientWidth <= MOBILE_VIEW_BREAKPOINT
self.render()
},
resize: function() {
const self = ReactApp
const maps = ExploreMaps.collection
@ -170,7 +169,10 @@ const ReactApp = {
const mapsWidth = document.body.clientWidth <= MOBILE_VIEW_BREAKPOINT
? document.body.clientWidth - MOBILE_VIEW_PADDING
: Math.min(MAX_COLUMNS, Math.min(numCards, mapSpaces)) * MAP_WIDTH
self.mapsWidth = mapsWidth
self.mobileTitleWidth = document ? document.body.clientWidth - 70 : 0
self.mobile = document && document.body.clientWidth <= MOBILE_VIEW_BREAKPOINT
self.render()
}
}

View file

@ -20,7 +20,7 @@ const Listeners = {
if (!(Active.Map || Active.Topic)) return
const onCanvas = e.target.tagName === 'BODY'
switch (e.which) {
case 13: // if enter key is pressed
// prevent topic creation if sending a message
@ -141,7 +141,6 @@ const Listeners = {
}
if (Active.Map && Realtime.inConversation) Realtime.positionVideos()
Mobile.resizeTitle()
})
},
centerAndReveal: function(nodes, opts) {

View file

@ -17,7 +17,6 @@ import Listeners from './Listeners'
import Loading from './Loading'
import Map, { CheatSheet, InfoBox } from './Map'
import Mapper from './Mapper'
import Mobile from './Mobile'
import Mouse from './Mouse'
import Organize from './Organize'
import PasteInput from './PasteInput'
@ -57,7 +56,6 @@ Metamaps.Map.CheatSheet = CheatSheet
Metamaps.Map.InfoBox = InfoBox
Metamaps.Maps = {}
Metamaps.Mapper = Mapper
Metamaps.Mobile = Mobile
Metamaps.Mouse = Mouse
Metamaps.Organize = Organize
Metamaps.PasteInput = PasteInput

View file

@ -0,0 +1,66 @@
import React, { Component, PropTypes } from 'react'
import { Link } from 'react-router'
class MobileHeader extends Component {
static propTypes = {
unreadNotificationsCount: PropTypes.number,
currentUser: PropTypes.object,
mobileTitle: PropTypes.string,
mobileTitleWidth: PropTypes.number,
onTitleClick: PropTypes.func
}
constructor(props) {
super(props)
this.state = {open: false}
}
toggle = () => {
this.setState({open: !this.state.open})
}
render() {
const { unreadNotificationsCount, currentUser, mobileTitle, mobileTitleWidth, onTitleClick } = this.props
const { open } = this.state
return <div>
<div id="mobile_header">
<div id="header_content" style={{width: `${mobileTitleWidth}px`}} onClick={onTitleClick}>
{mobileTitle}
</div>
<div id="menu_icon" onClick={this.toggle}>
{unreadNotificationsCount > 0 && <div className="unread-notifications-dot"></div>}
</div>
</div>
{open && <div id="mobile_menu">
{currentUser && <ul onClick={this.toggle}>
<li className="mobileMenuUser">
<Link to={`/explore/mapper/${currentUser.id}`}>
<img src={currentUser.get('image')} width="32" height="32" />
<span>{currentUser.get('name')}</span>
</Link>
</li>
<li><a href="/maps/new">New Map</a></li>
<li><Link to="/explore/mine">My Maps</Link></li>
<li><Link to="/explore/shared">Shared With Me</Link></li>
<li><Link to="/explore/starred">Starred By Me</Link></li>
<li><Link to="/explore/active">All Maps</Link></li>
<li><a href={`/users/${currentUser.id}/edit`}>Account</a></li>
<li className="notifications">
<a href="/notifications">Notifications</a>
{unreadNotificationsCount > 0 && <div className="unread-notifications-dot"></div>}
</li>
<li><a id="Logout" href="/logout">Sign Out</a></li>
</ul>}
{!currentUser && <ul onClick={this.toggle}>
<li><a href="/">Home</a></li>
<li><Link to="/explore/active">All Maps</Link></li>
<li><Link to="/explore/featured">Featured Maps</Link></li>
<li><a href="/request">Request Invite</a></li>
<li><a href="/login">Login</a></li>
</ul>}
</div>}
</div>
}
}
export default MobileHeader

View file

@ -1,5 +1,6 @@
import React, { Component, PropTypes } from 'react'
import MobileHeader from './MobileHeader'
import Toast from './Toast'
import UpperLeftUI from './UpperLeftUI'
import UpperRightUI from './UpperRightUI'
@ -9,7 +10,11 @@ class App extends Component {
children: PropTypes.object,
toast: PropTypes.string,
unreadNotificationsCount: PropTypes.number,
location: PropTypes.object
location: PropTypes.object,
mobile: PropTypes.bool,
mobileTitle: PropTypes.string,
mobileTitleWidth: PropTypes.number,
mobileTitleClick: PropTypes.func
}
static childContextTypes = {
@ -23,12 +28,18 @@ class App extends Component {
}
render () {
const { children, toast, currentUser, unreadNotificationsCount } = this.props
const { children, toast, currentUser, unreadNotificationsCount,
mobile, mobileTitle, mobileTitleWidth, mobileTitleClick } = this.props
return <div className="wrapper" id="wrapper">
{mobile && <MobileHeader currentUser={currentUser}
unreadNotificationsCount={unreadNotificationsCount}
mobileTitle={mobileTitle}
mobileTitleWidth={mobileTitleWidth}
onTitleClick={mobileTitleClick} />}
<UpperLeftUI currentUser={currentUser} />
<UpperRightUI currentUser={currentUser} unreadNotificationsCount={unreadNotificationsCount} />
{!mobile && <UpperRightUI currentUser={currentUser} unreadNotificationsCount={unreadNotificationsCount} />}
<Toast message={toast} />
{currentUser && <a className='feedback-icon' target='_blank' href='https://hylo.com/c/metamaps'></a>}
{!mobile && currentUser && <a className='feedback-icon' target='_blank' href='https://hylo.com/c/metamaps'></a>}
{children}
</div>
}

View file

@ -10,9 +10,12 @@ import TopicCard from '../TopicCard'
class MapView extends Component {
static propTypes = {
mobile: PropTypes.bool,
mapId: PropTypes.string,
map: PropTypes.object,
mapIsStarred: PropTypes.bool,
onMapStar: PropTypes.func,
onMapUnstar: PropTypes.func,
toggleFilterBox: PropTypes.func,
filterBoxHtml: PropTypes.string,
toggleMapInfoBox: PropTypes.func,
@ -20,6 +23,12 @@ class MapView extends Component {
currentUser: PropTypes.object,
endActiveMap: PropTypes.func,
launchNewMap: PropTypes.func,
openImportLightbox: PropTypes.func,
forkMap: PropTypes.func,
openHelpLightbox: PropTypes.func,
onZoomExtents: PropTypes.func,
onZoomIn: PropTypes.func,
onZoomOut: PropTypes.func
}
constructor(props) {
@ -31,7 +40,6 @@ class MapView extends Component {
endMap() {
this.setState({
filterBoxOpen: false,
chatOpen: false
})
this.props.endActiveMap()