make mapsWidth work and add mobile
This commit is contained in:
parent
9013d49ca1
commit
032d0d8f4b
17 changed files with 156 additions and 147 deletions
|
@ -169,9 +169,6 @@
|
||||||
.upperRightMapButtons {
|
.upperRightMapButtons {
|
||||||
right: 134px;
|
right: 134px;
|
||||||
}
|
}
|
||||||
.mapPage .upperRightMapButtons, .topicPage .upperRightMapButtons {
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upperRightIcon {
|
.upperRightIcon {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
|
@ -180,13 +177,7 @@
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.mapPage .mapElement .importDialog {
|
|
||||||
display: none;
|
|
||||||
background-position: 0 0;
|
|
||||||
}
|
|
||||||
.mapPage.canEditMap .mapElement .importDialog {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.sidebarFilterIcon {
|
.sidebarFilterIcon {
|
||||||
background-position: -32px 0;
|
background-position: -32px 0;
|
||||||
}
|
}
|
||||||
|
@ -347,7 +338,7 @@
|
||||||
|
|
||||||
/* infoAndHelp */
|
/* infoAndHelp */
|
||||||
|
|
||||||
.mapPage .openCheatsheet .tooltipsAbove, .topicPage .openCheatsheet .tooltipsAbove {
|
.openCheatsheet .tooltipsAbove {
|
||||||
right: 1px;
|
right: 1px;
|
||||||
left: auto;
|
left: auto;
|
||||||
}
|
}
|
||||||
|
@ -399,9 +390,6 @@
|
||||||
background-position: 0 0;
|
background-position: 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.unauthenticated .mapPage .starMap {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
/* end infoAndHelp */
|
/* end infoAndHelp */
|
||||||
|
|
||||||
|
|
||||||
|
@ -560,10 +548,6 @@
|
||||||
left: -8px;
|
left: -8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.openCheatsheet .tooltipsAbove {
|
|
||||||
left: -4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebarAccountIcon .tooltipsUnder {
|
.sidebarAccountIcon .tooltipsUnder {
|
||||||
margin-left: -12px;
|
margin-left: -12px;
|
||||||
margin-top: 40px;
|
margin-top: 40px;
|
||||||
|
|
|
@ -35,5 +35,6 @@
|
||||||
Metamaps.ServerData.mapIsStarred = <%= @map && current_user.starred_map?(@map) ? true : false %>
|
Metamaps.ServerData.mapIsStarred = <%= @map && current_user.starred_map?(@map) ? true : false %>
|
||||||
</script>
|
</script>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<div class="hidden"><%= render :partial => 'shared/filterBox' %></div>
|
||||||
<div id="loading"></div>
|
<div id="loading"></div>
|
||||||
<%= render :partial => 'layouts/foot' %>
|
<%= render :partial => 'layouts/foot' %>
|
||||||
|
|
|
@ -2,27 +2,27 @@
|
||||||
# @file
|
# @file
|
||||||
# this code generates the list of icons in the filter box in the upper right menu area
|
# this code generates the list of icons in the filter box in the upper right menu area
|
||||||
#%>
|
#%>
|
||||||
|
|
||||||
<%
|
<%
|
||||||
@mappers = []
|
@mappers = []
|
||||||
@synapses = []
|
@synapses = []
|
||||||
@metacodes = []
|
@metacodes = []
|
||||||
@metacodelist = ''
|
@metacodelist = ''
|
||||||
@mapperlist = ''
|
@mapperlist = ''
|
||||||
@synapselist = ''
|
@synapselist = ''
|
||||||
# There are essentially three functions happening here one to fill data to
|
# There are essentially three functions happening here one to fill data to
|
||||||
#@mappers with all people who have mapped on the selected map, which
|
#@mappers with all people who have mapped on the selected map, which
|
||||||
#actually gets checked twice once for topics or within @metacodes and once
|
#actually gets checked twice once for topics or within @metacodes and once
|
||||||
#for synapses on the map. @synapses get filled with all synapses on the map
|
#for synapses on the map. @synapses get filled with all synapses on the map
|
||||||
#and metacodes is filled with all the metacodes that are being used on the map.
|
#and metacodes is filled with all the metacodes that are being used on the map.
|
||||||
|
|
||||||
if @map
|
if @map
|
||||||
@alltopics.each_with_index do |topic, index|
|
@alltopics.each_with_index do |topic, index|
|
||||||
if @metacodes.index(topic.metacode) == nil
|
if @metacodes.index(topic.metacode) == nil
|
||||||
@metacodes.push(topic.metacode)
|
@metacodes.push(topic.metacode)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@allsynapses.each_with_index do |synapse, index|
|
@allsynapses.each_with_index do |synapse, index|
|
||||||
if @synapses.index{|s| s.desc == synapse.desc} == nil
|
if @synapses.index{|s| s.desc == synapse.desc} == nil
|
||||||
@synapses.push(synapse)
|
@synapses.push(synapse)
|
||||||
end
|
end
|
||||||
|
@ -32,16 +32,16 @@
|
||||||
@mappers.push(mapping.user)
|
@mappers.push(mapping.user)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elsif @topic
|
elsif @topic
|
||||||
@alltopics.each_with_index do |topic, index|
|
@alltopics.each_with_index do |topic, index|
|
||||||
if @metacodes.index(topic.metacode) == nil
|
if @metacodes.index(topic.metacode) == nil
|
||||||
@metacodes.push(topic.metacode)
|
@metacodes.push(topic.metacode)
|
||||||
end
|
end
|
||||||
if @mappers.index(topic.user) == nil
|
if @mappers.index(topic.user) == nil
|
||||||
@mappers.push(topic.user)
|
@mappers.push(topic.user)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@allsynapses.each_with_index do |synapse, index|
|
@allsynapses.each_with_index do |synapse, index|
|
||||||
if @synapses.index{|s| s.desc == synapse.desc} == nil
|
if @synapses.index{|s| s.desc == synapse.desc} == nil
|
||||||
@synapses.push(synapse)
|
@synapses.push(synapse)
|
||||||
end
|
end
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
end
|
end
|
||||||
|
|
||||||
if @map || @topic
|
if @map || @topic
|
||||||
@metacodes.sort! {|x,y|
|
@metacodes.sort! {|x,y|
|
||||||
n1 = x.name || ""
|
n1 = x.name || ""
|
||||||
n2 = y.name || ""
|
n2 = y.name || ""
|
||||||
n1 <=> n2
|
n1 <=> n2
|
||||||
|
@ -62,24 +62,24 @@
|
||||||
d2 = y.desc || ""
|
d2 = y.desc || ""
|
||||||
d1 <=> d2
|
d1 <=> d2
|
||||||
}
|
}
|
||||||
@mappers.sort! {|x,y|
|
@mappers.sort! {|x,y|
|
||||||
n1 = x.name || ""
|
n1 = x.name || ""
|
||||||
n2 = y.name || ""
|
n2 = y.name || ""
|
||||||
n1 <=> n2
|
n1 <=> n2
|
||||||
}
|
}
|
||||||
|
|
||||||
@metacodes.each_with_index do |metacode, index|
|
@metacodes.each_with_index do |metacode, index|
|
||||||
@metacodelist += '<li data-id="' + metacode.id.to_s + '">'
|
@metacodelist += '<li data-id="' + metacode.id.to_s + '">'
|
||||||
@metacodelist += '<img src="' + asset_path(metacode.icon) + '" data-id="' + metacode.id.to_s + '" alt="' + metacode.name + '" />'
|
@metacodelist += '<img src="' + asset_path(metacode.icon) + '" data-id="' + metacode.id.to_s + '" alt="' + metacode.name + '" />'
|
||||||
@metacodelist += '<p>' + metacode.name.downcase + '</p></li>'
|
@metacodelist += '<p>' + metacode.name.downcase + '</p></li>'
|
||||||
end
|
end
|
||||||
@synapses.each_with_index do |synapse, index|
|
@synapses.each_with_index do |synapse, index|
|
||||||
d = synapse.desc || ""
|
d = synapse.desc || ""
|
||||||
@synapselist += '<li data-id="' + d + '">'
|
@synapselist += '<li data-id="' + d + '">'
|
||||||
@synapselist += '<img src="' + asset_path('synapse16.png') + '" alt="synapse icon" /><p>' + d
|
@synapselist += '<img src="' + asset_path('synapse16.png') + '" alt="synapse icon" /><p>' + d
|
||||||
@synapselist += '</p></li>'
|
@synapselist += '</p></li>'
|
||||||
end
|
end
|
||||||
@mappers.each_with_index do |mapper, index|
|
@mappers.each_with_index do |mapper, index|
|
||||||
@mapperlist += '<li data-id="' + mapper.id.to_s + '">'
|
@mapperlist += '<li data-id="' + mapper.id.to_s + '">'
|
||||||
@mapperlist += '<img src="' + mapper.image.url(:sixtyfour) + '" data-id="' + mapper.id.to_s + '" alt="' + mapper.name + '" />'
|
@mapperlist += '<img src="' + mapper.image.url(:sixtyfour) + '" data-id="' + mapper.id.to_s + '" alt="' + mapper.name + '" />'
|
||||||
@mapperlist += '<p>' + mapper.name + '</p></li>'
|
@mapperlist += '<p>' + mapper.name + '</p></li>'
|
||||||
|
@ -95,7 +95,7 @@
|
||||||
<div class="clearfloat"></div>
|
<div class="clearfloat"></div>
|
||||||
<ul>
|
<ul>
|
||||||
<%= @mapperlist.html_safe %>
|
<%= @mapperlist.html_safe %>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="clearfloat"></div>
|
<div class="clearfloat"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@
|
||||||
<div class="clearfloat"></div>
|
<div class="clearfloat"></div>
|
||||||
<ul>
|
<ul>
|
||||||
<%= @metacodelist.html_safe %>
|
<%= @metacodelist.html_safe %>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="clearfloat"></div>
|
<div class="clearfloat"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -117,9 +117,8 @@
|
||||||
<div class="clearfloat"></div>
|
<div class="clearfloat"></div>
|
||||||
<ul>
|
<ul>
|
||||||
<%= @synapselist.html_safe %>
|
<%= @synapselist.html_safe %>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="clearfloat"></div>
|
<div class="clearfloat"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div> <!-- end .filterBox -->
|
</div> <!-- end .filterBox -->
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,6 @@ const Filter = {
|
||||||
init: function() {
|
init: function() {
|
||||||
var self = Filter
|
var self = Filter
|
||||||
|
|
||||||
$('.sidebarFilterIcon').click(self.toggleBox)
|
|
||||||
|
|
||||||
$('.sidebarFilterBox .showAllMetacodes').click(self.filterNoMetacodes)
|
$('.sidebarFilterBox .showAllMetacodes').click(self.filterNoMetacodes)
|
||||||
$('.sidebarFilterBox .showAllSynapses').click(self.filterNoSynapses)
|
$('.sidebarFilterBox .showAllSynapses').click(self.filterNoSynapses)
|
||||||
$('.sidebarFilterBox .showAllMappers').click(self.filterNoMappers)
|
$('.sidebarFilterBox .showAllMappers').click(self.filterNoMappers)
|
||||||
|
|
|
@ -19,7 +19,7 @@ const ImportDialog = {
|
||||||
self.closeLightbox = closeLightbox
|
self.closeLightbox = closeLightbox
|
||||||
|
|
||||||
$('#lightbox_content').append($(outdent`
|
$('#lightbox_content').append($(outdent`
|
||||||
<div class="lightboxContent" id="import-dialog-lightbox">
|
<div class="lightboxContent" id="import-dialog">
|
||||||
<div class="importDialogWrapper" />
|
<div class="importDialogWrapper" />
|
||||||
</div>
|
</div>
|
||||||
`))
|
`))
|
||||||
|
|
|
@ -3,30 +3,42 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
import { Router, browserHistory } from 'react-router'
|
import { Router, browserHistory } from 'react-router'
|
||||||
|
|
||||||
import { merge } from 'lodash'
|
import { merge } from 'lodash'
|
||||||
|
|
||||||
import { notifyUser } from './index.js'
|
import { notifyUser } from './index.js'
|
||||||
|
import ImportDialog from './ImportDialog'
|
||||||
import Active from '../Active'
|
import Active from '../Active'
|
||||||
import DataModel from '../DataModel'
|
import DataModel from '../DataModel'
|
||||||
import { ExploreMaps, ChatView, TopicCard } from '../Views'
|
import { ExploreMaps, ChatView, TopicCard } from '../Views'
|
||||||
import Filter from '../Filter'
|
import Filter from '../Filter'
|
||||||
|
import JIT from '../JIT'
|
||||||
import Realtime from '../Realtime'
|
import Realtime from '../Realtime'
|
||||||
import Map, { InfoBox } from '../Map'
|
import Map, { InfoBox } from '../Map'
|
||||||
import Topic from '../Topic'
|
import Topic from '../Topic'
|
||||||
|
import Visualize from '../Visualize'
|
||||||
import makeRoutes from '../../components/makeRoutes'
|
import makeRoutes from '../../components/makeRoutes'
|
||||||
let routes
|
let routes
|
||||||
|
|
||||||
|
// 220 wide + 16 padding on both sides
|
||||||
|
const MAP_WIDTH = 252
|
||||||
|
const MOBILE_VIEW_BREAKPOINT = 504
|
||||||
|
const MOBILE_VIEW_PADDING = 40
|
||||||
|
const MAX_COLUMNS = 4
|
||||||
|
|
||||||
const ReactApp = {
|
const ReactApp = {
|
||||||
mapId: null,
|
mapId: null,
|
||||||
unreadNotificationsCount: 0,
|
unreadNotificationsCount: 0,
|
||||||
mapIsStarred: false,
|
mapsWidth: 0,
|
||||||
init: function(serverData) {
|
mobile: false,
|
||||||
|
init: function(serverData, openLightbox) {
|
||||||
const self = ReactApp
|
const self = ReactApp
|
||||||
self.unreadNotificationsCount = serverData.unreadNotificationsCount
|
self.unreadNotificationsCount = serverData.unreadNotificationsCount
|
||||||
self.mapIsStarred = serverData.mapIsStarred
|
self.openLightbox = openLightbox
|
||||||
routes = makeRoutes()
|
routes = makeRoutes()
|
||||||
|
self.resize()
|
||||||
|
self.setMobile()
|
||||||
self.render()
|
self.render()
|
||||||
|
window && window.addEventListener('resize', self.resize)
|
||||||
},
|
},
|
||||||
handleUpdate: function(location) {
|
handleUpdate: function(location) {
|
||||||
const self = ReactApp
|
const self = ReactApp
|
||||||
|
@ -59,7 +71,8 @@ const ReactApp = {
|
||||||
const self = ReactApp
|
const self = ReactApp
|
||||||
return merge({
|
return merge({
|
||||||
unreadNotificationsCount: self.unreadNotificationsCount,
|
unreadNotificationsCount: self.unreadNotificationsCount,
|
||||||
currentUser: Active.Mapper
|
currentUser: Active.Mapper,
|
||||||
|
mobile: self.mobile
|
||||||
},
|
},
|
||||||
self.getMapProps(),
|
self.getMapProps(),
|
||||||
self.getTopicProps(),
|
self.getTopicProps(),
|
||||||
|
@ -72,13 +85,21 @@ const ReactApp = {
|
||||||
return {
|
return {
|
||||||
mapId: self.mapId,
|
mapId: self.mapId,
|
||||||
map: Active.Map,
|
map: Active.Map,
|
||||||
mapIsStarred: self.mapIsStarred,
|
mapIsStarred: Map.mapIsStarred,
|
||||||
endActiveMap: Map.end,
|
endActiveMap: Map.end,
|
||||||
launchNewMap: Map.launch,
|
launchNewMap: Map.launch,
|
||||||
toggleMapInfoBox: InfoBox.toggleBox,
|
toggleMapInfoBox: InfoBox.toggleBox,
|
||||||
|
infoBoxHtml: InfoBox.html,
|
||||||
toggleFilterBox: Filter.toggleBox,
|
toggleFilterBox: Filter.toggleBox,
|
||||||
infoBoxHtml: InfoBox.html
|
filterBoxHtml: $('.filterBox')[0].outerHTML,
|
||||||
// filters
|
openImportLightbox: () => ImportDialog.show(),
|
||||||
|
forkMap: Map.fork,
|
||||||
|
openHelpLightbox: () => self.openLightbox('cheatsheet'),
|
||||||
|
onMapStar: Map.star,
|
||||||
|
onMapUnstar: Map.unstar,
|
||||||
|
onZoomExtents: event => JIT.zoomExtents(event, Visualize.mGraph.canvas),
|
||||||
|
onZoomIn: JIT.zoomIn,
|
||||||
|
onZoomOut: JIT.zoomOut
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getTopicCardProps: function() {
|
getTopicCardProps: function() {
|
||||||
|
@ -109,7 +130,8 @@ const ReactApp = {
|
||||||
pending: ExploreMaps.pending,
|
pending: ExploreMaps.pending,
|
||||||
onStar: ExploreMaps.onStar,
|
onStar: ExploreMaps.onStar,
|
||||||
onRequest: ExploreMaps.onRequest,
|
onRequest: ExploreMaps.onRequest,
|
||||||
onMapFollow: ExploreMaps.onMapFollow
|
onMapFollow: ExploreMaps.onMapFollow,
|
||||||
|
mapsWidth: ReactApp.mapsWidth
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getChatProps: function() {
|
getChatProps: function() {
|
||||||
|
@ -132,6 +154,24 @@ const ReactApp = {
|
||||||
inputFocus: ChatView.inputFocus,
|
inputFocus: ChatView.inputFocus,
|
||||||
handleInputMessage: ChatView.handleInputMessage
|
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
|
||||||
|
const currentUser = Active.Mapper
|
||||||
|
const user = maps && maps.id === 'mapper' ? ExploreMaps.mapper : null
|
||||||
|
const numCards = (maps ? maps.length : 0) + (user || currentUser ? 1 : 0)
|
||||||
|
const mapSpaces = Math.floor(document.body.clientWidth / MAP_WIDTH)
|
||||||
|
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.render()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ const GlobalUI = {
|
||||||
init: function(serverData) {
|
init: function(serverData) {
|
||||||
const self = GlobalUI
|
const self = GlobalUI
|
||||||
|
|
||||||
self.ReactApp.init(serverData)
|
self.ReactApp.init(serverData, self.openLightbox)
|
||||||
self.Search.init(serverData)
|
self.Search.init(serverData)
|
||||||
self.CreateMap.init(serverData)
|
self.CreateMap.init(serverData)
|
||||||
self.Account.init(serverData)
|
self.Account.init(serverData)
|
||||||
|
|
|
@ -50,15 +50,6 @@ const JIT = {
|
||||||
*/
|
*/
|
||||||
init: function(serverData) {
|
init: function(serverData) {
|
||||||
const self = JIT
|
const self = JIT
|
||||||
|
|
||||||
$('.zoomIn').click(self.zoomIn)
|
|
||||||
$('.zoomOut').click(self.zoomOut)
|
|
||||||
|
|
||||||
const zoomExtents = function(event) {
|
|
||||||
self.zoomExtents(event, Visualize.mGraph.canvas)
|
|
||||||
}
|
|
||||||
$('.zoomExtents').click(zoomExtents)
|
|
||||||
|
|
||||||
self.topicDescImage = new Image()
|
self.topicDescImage = new Image()
|
||||||
self.topicDescImage.src = serverData['topic_description_signifier.png']
|
self.topicDescImage.src = serverData['topic_description_signifier.png']
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import Create from '../Create'
|
||||||
import DataModel from '../DataModel'
|
import DataModel from '../DataModel'
|
||||||
import DataModelMap from '../DataModel/Map'
|
import DataModelMap from '../DataModel/Map'
|
||||||
import Filter from '../Filter'
|
import Filter from '../Filter'
|
||||||
import GlobalUI from '../GlobalUI'
|
import GlobalUI, { ReactApp } from '../GlobalUI'
|
||||||
import JIT from '../JIT'
|
import JIT from '../JIT'
|
||||||
import Loading from '../Loading'
|
import Loading from '../Loading'
|
||||||
import Realtime from '../Realtime'
|
import Realtime from '../Realtime'
|
||||||
|
@ -25,26 +25,18 @@ const Map = {
|
||||||
events: {
|
events: {
|
||||||
editedByActiveMapper: 'Metamaps:Map:events:editedByActiveMapper'
|
editedByActiveMapper: 'Metamaps:Map:events:editedByActiveMapper'
|
||||||
},
|
},
|
||||||
|
mapIsStarred: false,
|
||||||
init: function(serverData) {
|
init: function(serverData) {
|
||||||
var self = Map
|
var self = Map
|
||||||
|
|
||||||
|
self.mapIsStarred = serverData.mapIsStarred
|
||||||
|
|
||||||
$('#wrapper').mousedown(function(e) {
|
$('#wrapper').mousedown(function(e) {
|
||||||
if (e.button === 1) return false
|
if (e.button === 1) return false
|
||||||
})
|
})
|
||||||
|
|
||||||
$('.starMap').click(function() {
|
|
||||||
if ($(this).is('.starred')) self.unstar()
|
|
||||||
else self.star()
|
|
||||||
})
|
|
||||||
|
|
||||||
$('.sidebarFork').click(function() {
|
|
||||||
self.fork()
|
|
||||||
})
|
|
||||||
|
|
||||||
GlobalUI.CreateMap.emptyForkMapForm = $('#fork_map').html()
|
GlobalUI.CreateMap.emptyForkMapForm = $('#fork_map').html()
|
||||||
|
|
||||||
self.updateStar()
|
|
||||||
|
|
||||||
InfoBox.init(serverData, function updateThumbnail() {
|
InfoBox.init(serverData, function updateThumbnail() {
|
||||||
self.uploadMapScreenshot()
|
self.uploadMapScreenshot()
|
||||||
})
|
})
|
||||||
|
@ -102,8 +94,6 @@ const Map = {
|
||||||
$('.wrapper').addClass('commonsMap')
|
$('.wrapper').addClass('commonsMap')
|
||||||
}
|
}
|
||||||
|
|
||||||
Map.updateStar()
|
|
||||||
|
|
||||||
// set filter mapper H3 text
|
// set filter mapper H3 text
|
||||||
$('#filter_by_mapper h3').html('MAPPERS')
|
$('#filter_by_mapper h3').html('MAPPERS')
|
||||||
|
|
||||||
|
@ -153,17 +143,6 @@ const Map = {
|
||||||
$('.viewOnly').removeClass('isViewOnly')
|
$('.viewOnly').removeClass('isViewOnly')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
updateStar: function() {
|
|
||||||
if (!Active.Mapper || !DataModel.Stars) return
|
|
||||||
// update the star/unstar icon
|
|
||||||
if (DataModel.Stars.find(function(s) { return s.user_id === Active.Mapper.id })) {
|
|
||||||
$('.starMap').addClass('starred')
|
|
||||||
$('.starMap .tooltipsAbove').html('Unstar')
|
|
||||||
} else {
|
|
||||||
$('.starMap').removeClass('starred')
|
|
||||||
$('.starMap .tooltipsAbove').html('Star')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
star: function() {
|
star: function() {
|
||||||
var self = Map
|
var self = Map
|
||||||
|
|
||||||
|
@ -172,7 +151,8 @@ const Map = {
|
||||||
DataModel.Stars.push({ user_id: Active.Mapper.id, map_id: Active.Map.id })
|
DataModel.Stars.push({ user_id: Active.Mapper.id, map_id: Active.Map.id })
|
||||||
DataModel.Maps.Starred.add(Active.Map)
|
DataModel.Maps.Starred.add(Active.Map)
|
||||||
GlobalUI.notifyUser('Map is now starred')
|
GlobalUI.notifyUser('Map is now starred')
|
||||||
self.updateStar()
|
self.mapIsStarred = true
|
||||||
|
ReactApp.render()
|
||||||
},
|
},
|
||||||
unstar: function() {
|
unstar: function() {
|
||||||
var self = Map
|
var self = Map
|
||||||
|
@ -181,7 +161,8 @@ const Map = {
|
||||||
$.post('/maps/' + Active.Map.id + '/unstar')
|
$.post('/maps/' + Active.Map.id + '/unstar')
|
||||||
DataModel.Stars = DataModel.Stars.filter(function(s) { return s.user_id !== Active.Mapper.id })
|
DataModel.Stars = DataModel.Stars.filter(function(s) { return s.user_id !== Active.Mapper.id })
|
||||||
DataModel.Maps.Starred.remove(Active.Map)
|
DataModel.Maps.Starred.remove(Active.Map)
|
||||||
self.updateStar()
|
self.mapIsStarred = false
|
||||||
|
ReactApp.render()
|
||||||
},
|
},
|
||||||
fork: function() {
|
fork: function() {
|
||||||
GlobalUI.openLightbox('forkmap')
|
GlobalUI.openLightbox('forkmap')
|
||||||
|
|
|
@ -60,6 +60,7 @@ const ExploreMaps = {
|
||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
var self = ExploreMaps
|
var self = ExploreMaps
|
||||||
|
ReactApp.resize()
|
||||||
ReactApp.render()
|
ReactApp.render()
|
||||||
Loading.hide()
|
Loading.hide()
|
||||||
},
|
},
|
||||||
|
|
|
@ -23,13 +23,13 @@ class App extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { toast, currentUser, unreadNotificationsCount } = this.props
|
const { children, toast, currentUser, unreadNotificationsCount } = this.props
|
||||||
return <div className="wrapper" id="wrapper">
|
return <div className="wrapper" id="wrapper">
|
||||||
<UpperLeftUI currentUser={currentUser} />
|
<UpperLeftUI currentUser={currentUser} />
|
||||||
<UpperRightUI currentUser={currentUser} unreadNotificationsCount={unreadNotificationsCount} />
|
<UpperRightUI currentUser={currentUser} unreadNotificationsCount={unreadNotificationsCount} />
|
||||||
<Toast message={toast} />
|
<Toast message={toast} />
|
||||||
{currentUser && <a className='feedback-icon' target='_blank' href='https://hylo.com/c/metamaps'></a>}
|
{currentUser && <a className='feedback-icon' target='_blank' href='https://hylo.com/c/metamaps'></a>}
|
||||||
{this.props.children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,14 @@ import React, { Component, PropTypes } from 'react'
|
||||||
|
|
||||||
class FilterBox extends Component {
|
class FilterBox extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
isMap: PropTypes.bool,
|
||||||
|
filterBoxHtml: PropTypes.string
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
return null
|
const { filterBoxHtml } = this.props
|
||||||
|
const html = {__html: filterBoxHtml}
|
||||||
|
return <div className="sidebarFilterBox upperRightBox" dangerouslySetInnerHTML={html}></div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,23 +7,28 @@ class InfoAndHelp extends Component {
|
||||||
mapIsStarred: PropTypes.bool,
|
mapIsStarred: PropTypes.bool,
|
||||||
currentUser: PropTypes.object,
|
currentUser: PropTypes.object,
|
||||||
map: PropTypes.object,
|
map: PropTypes.object,
|
||||||
|
onHelpClick: PropTypes.func,
|
||||||
|
onMapStar: PropTypes.func,
|
||||||
|
onMapUnstar: PropTypes.func,
|
||||||
|
|
||||||
onInfoClick: PropTypes.func,
|
onInfoClick: PropTypes.func,
|
||||||
infoBoxhtml: PropTypes.string
|
infoBoxhtml: PropTypes.string
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { mapIsStarred, map, currentUser, onInfoClick, infoBoxHtml } = this.props
|
const { mapIsStarred, map, currentUser, onInfoClick, infoBoxHtml, onMapStar, onMapUnstar, onHelpClick } = this.props
|
||||||
const starclassName = mapIsStarred ? 'starred' : ''
|
const starclassName = mapIsStarred ? 'starred' : ''
|
||||||
const tooltip = mapIsStarred ? 'Star' : 'Unstar'
|
const tooltip = mapIsStarred ? 'Unstar' : 'Star'
|
||||||
|
const onStarClick = mapIsStarred ? onMapUnstar : onMapStar
|
||||||
return <div className="infoAndHelp">
|
return <div className="infoAndHelp">
|
||||||
<MapInfoBox map={map} currentUser={currentUser} infoBoxHtml={infoBoxHtml} />
|
<MapInfoBox map={map} currentUser={currentUser} infoBoxHtml={infoBoxHtml} />
|
||||||
<div className={`starMap infoElement mapElement ${starclassName}`}>
|
<div className={`starMap infoElement mapElement ${starclassName}`} onClick={onStarClick}>
|
||||||
<div className="tooltipsAbove">{tooltip}</div>
|
<div className="tooltipsAbove">{tooltip}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mapInfoIcon infoElement mapElement" onClick={onInfoClick}>
|
<div className="mapInfoIcon infoElement mapElement" onClick={onInfoClick}>
|
||||||
<div className="tooltipsAbove">Map Info</div>
|
<div className="tooltipsAbove">Map Info</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="openCheatsheet openLightbox infoElement mapElement" data-open="cheatsheet">
|
<div className="openCheatsheet infoElement mapElement" onClick={onHelpClick}>
|
||||||
<div className="tooltipsAbove">Help</div>
|
<div className="tooltipsAbove">Help</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="clearfloat"></div>
|
<div className="clearfloat"></div>
|
||||||
|
|
|
@ -5,25 +5,31 @@ import FilterBox from './FilterBox'
|
||||||
class MapButtons extends Component {
|
class MapButtons extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
currentUser: PropTypes.object,
|
currentUser: PropTypes.object,
|
||||||
filterBoxOpen: PropTypes.bool
|
canEditMap: PropTypes.bool,
|
||||||
|
onImportClick: PropTypes.func,
|
||||||
|
onForkClick: PropTypes.func,
|
||||||
|
onFilterClick: PropTypes.func,
|
||||||
|
filterBoxHtml: PropTypes.string
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { currentUser, filterBoxOpen } = this.props
|
const { currentUser, canEditMap, filterBoxHtml, onFilterClick, onImportClick, onForkClick } = this.props
|
||||||
return <div className="mapElement upperRightEl upperRightMapButtons upperRightUI">
|
return <div className="mapElement upperRightEl upperRightMapButtons upperRightUI">
|
||||||
{currentUser && <div className="importDialog upperRightEl upperRightIcon mapElement openLightbox" data-open="import-dialog-lightbox">
|
{canEditMap && <div className="importDialog upperRightEl upperRightIcon mapElement" onClick={onImportClick}>
|
||||||
<div className="tooltipsUnder">
|
<div className="tooltipsUnder">
|
||||||
Import Data
|
Import Data
|
||||||
</div>
|
</div>
|
||||||
</div>}
|
</div>}
|
||||||
<div className="sidebarFilter upperRightEl">
|
<div className="sidebarFilter upperRightEl">
|
||||||
<div className="sidebarFilterIcon upperRightIcon"><div className="tooltipsUnder">Filter</div></div>
|
<div className="sidebarFilterIcon upperRightIcon" onClick={onFilterClick}>
|
||||||
{filterBoxOpen && <div className="sidebarFilterBox upperRightBox">
|
<div className="tooltipsUnder">Filter</div>
|
||||||
<FilterBox />
|
</div>
|
||||||
</div>}
|
<FilterBox filterBoxHtml={filterBoxHtml} />
|
||||||
</div>
|
</div>
|
||||||
{currentUser && <div className="sidebarFork upperRightEl">
|
{currentUser && <div className="sidebarFork upperRightEl">
|
||||||
<div className="sidebarForkIcon upperRightIcon"><div className="tooltipsUnder">Save To New Map</div></div>
|
<div className="sidebarForkIcon upperRightIcon" onClick={onForkClick}>
|
||||||
|
<div className="tooltipsUnder">Save To New Map</div>
|
||||||
|
</div>
|
||||||
</div>}
|
</div>}
|
||||||
<div className="clearfloat"></div>
|
<div className="clearfloat"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,13 +2,23 @@ import React, { Component, PropTypes } from 'react'
|
||||||
|
|
||||||
class MapControls extends Component {
|
class MapControls extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
onClickZoomExtents: PropTypes.func,
|
||||||
|
onClickZoomIn: PropTypes.func,
|
||||||
|
onClickZoomOut: PropTypes.func
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
|
const { onClickZoomExtents, onClickZoomIn, onClickZoomOut } = this.props
|
||||||
return <div className="mapControls mapElement">
|
return <div className="mapControls mapElement">
|
||||||
<div className="zoomExtents mapControl"><div className="tooltips">Center View</div></div>
|
<div className="zoomExtents mapControl" onClick={onClickZoomExtents}>
|
||||||
<div className="zoomIn mapControl"><div className="tooltips">Zoom In</div></div>
|
<div className="tooltips">Center View</div>
|
||||||
<div className="zoomOut mapControl"><div className="tooltips">Zoom Out</div></div>
|
</div>
|
||||||
|
<div className="zoomIn mapControl" onClick={onClickZoomIn}>
|
||||||
|
<div className="tooltips">Zoom In</div>
|
||||||
|
</div>
|
||||||
|
<div className="zoomOut mapControl" onClick={onClickZoomOut}>
|
||||||
|
<div className="tooltips">Zoom Out</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ class MapView extends Component {
|
||||||
map: PropTypes.object,
|
map: PropTypes.object,
|
||||||
mapIsStarred: PropTypes.bool,
|
mapIsStarred: PropTypes.bool,
|
||||||
toggleFilterBox: PropTypes.func,
|
toggleFilterBox: PropTypes.func,
|
||||||
|
filterBoxHtml: PropTypes.string,
|
||||||
toggleMapInfoBox: PropTypes.func,
|
toggleMapInfoBox: PropTypes.func,
|
||||||
infoBoxHtml: PropTypes.string,
|
infoBoxHtml: PropTypes.string,
|
||||||
currentUser: PropTypes.object,
|
currentUser: PropTypes.object,
|
||||||
|
@ -62,7 +63,11 @@ class MapView extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render = () => {
|
render = () => {
|
||||||
const { map, mapIsStarred, currentUser, onOpen, onClose, toggleMapInfoBox, toggleFilterBox, infoBoxHtml } = this.props
|
const { map, currentUser, onOpen, onClose,
|
||||||
|
toggleMapInfoBox, toggleFilterBox, infoBoxHtml, filterBoxHtml,
|
||||||
|
openImportLightbox, forkMap, openHelpLightbox,
|
||||||
|
mapIsStarred, onMapStar, onMapUnstar,
|
||||||
|
onZoomExtents, onZoomIn, onZoomOut } = this.props
|
||||||
const { filterBoxOpen, chatOpen } = this.state
|
const { filterBoxOpen, chatOpen } = this.state
|
||||||
const onChatOpen = () => {
|
const onChatOpen = () => {
|
||||||
this.setState({chatOpen: true})
|
this.setState({chatOpen: true})
|
||||||
|
@ -72,17 +77,28 @@ class MapView extends Component {
|
||||||
this.setState({chatOpen: false})
|
this.setState({chatOpen: false})
|
||||||
onClose()
|
onClose()
|
||||||
}
|
}
|
||||||
|
const canEditMap = map && map.authorizeToEdit(currentUser)
|
||||||
// TODO: stop using {...this.props} and make explicit
|
// TODO: stop using {...this.props} and make explicit
|
||||||
return <div className="mapWrapper">
|
return <div className="mapWrapper">
|
||||||
<MapButtons currentUser={currentUser} onFilterClick={toggleFilterBox} />
|
<MapButtons currentUser={currentUser}
|
||||||
|
onImportClick={openImportLightbox}
|
||||||
|
onFilterClick={toggleFilterBox}
|
||||||
|
onForkClick={forkMap}
|
||||||
|
canEditMap={canEditMap}
|
||||||
|
filterBoxHtml={filterBoxHtml} />
|
||||||
<DataVis />
|
<DataVis />
|
||||||
<TopicCard {...this.props} />
|
<TopicCard {...this.props} />
|
||||||
<MapChat {...this.props} onOpen={onChatOpen} onClose={onChatClose} chatOpen={chatOpen} />
|
<MapChat {...this.props} onOpen={onChatOpen} onClose={onChatClose} chatOpen={chatOpen} />
|
||||||
<MapControls />
|
<MapControls onClickZoomExtents={onZoomExtents}
|
||||||
|
onClickZoomIn={onZoomIn}
|
||||||
|
onClickZoomOut={onZoomOut} />
|
||||||
<InfoAndHelp mapIsStarred={mapIsStarred}
|
<InfoAndHelp mapIsStarred={mapIsStarred}
|
||||||
currentUser={currentUser}
|
currentUser={currentUser}
|
||||||
map={map}
|
map={map}
|
||||||
onInfoClick={toggleMapInfoBox}
|
onInfoClick={toggleMapInfoBox}
|
||||||
|
onMapStar={onMapStar}
|
||||||
|
onMapUnstar={onMapUnstar}
|
||||||
|
onHelpClick={openHelpLightbox}
|
||||||
infoBoxHtml={infoBoxHtml} />
|
infoBoxHtml={infoBoxHtml} />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,6 @@ import Header from './Header'
|
||||||
import MapperCard from './MapperCard'
|
import MapperCard from './MapperCard'
|
||||||
import MapCard from './MapCard'
|
import MapCard from './MapCard'
|
||||||
|
|
||||||
// 220 wide + 16 padding on both sides
|
|
||||||
const MAP_WIDTH = 252
|
|
||||||
const MOBILE_VIEW_BREAKPOINT = 504
|
|
||||||
const MOBILE_VIEW_PADDING = 40
|
|
||||||
const MAX_COLUMNS = 4
|
|
||||||
|
|
||||||
class Maps extends Component {
|
class Maps extends Component {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -23,37 +17,17 @@ class Maps extends Component {
|
||||||
pending: PropTypes.bool,
|
pending: PropTypes.bool,
|
||||||
onStar: PropTypes.func,
|
onStar: PropTypes.func,
|
||||||
onRequest: PropTypes.func,
|
onRequest: PropTypes.func,
|
||||||
onMapFollow: PropTypes.func
|
onMapFollow: PropTypes.func,
|
||||||
|
mapsWidth: PropTypes.number,
|
||||||
|
mobile: PropTypes.bool
|
||||||
}
|
}
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
location: PropTypes.object
|
location: PropTypes.object
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props)
|
|
||||||
this.state = { mapsWidth: 0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
window && window.addEventListener('resize', this.resize)
|
this.maps && this.maps.addEventListener('scroll', throttle(this.scroll, 500, { leading: true, trailing: false }))
|
||||||
this.refs.maps && this.refs.maps.addEventListener('scroll', throttle(this.scroll, 500, { leading: true, trailing: false }))
|
|
||||||
this.resize()
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
window && window.removeEventListener('resize', this.resize)
|
|
||||||
}
|
|
||||||
|
|
||||||
resize = () => {
|
|
||||||
const { maps, user, currentUser } = this.props
|
|
||||||
if (!maps) return
|
|
||||||
const numCards = maps.length + (user || currentUser ? 1 : 0)
|
|
||||||
const mapSpaces = Math.floor(document.body.clientWidth / MAP_WIDTH)
|
|
||||||
const mapsWidth = document.body.clientWidth <= MOBILE_VIEW_BREAKPOINT
|
|
||||||
? document.body.clientWidth - MOBILE_VIEW_PADDING
|
|
||||||
: Math.min(MAX_COLUMNS, Math.min(numCards, mapSpaces)) * MAP_WIDTH
|
|
||||||
this.setState({ mapsWidth })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scroll = () => {
|
scroll = () => {
|
||||||
|
@ -65,15 +39,14 @@ class Maps extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render = () => {
|
render = () => {
|
||||||
const { maps, currentUser, juntoState, pending, section, user, onStar, onRequest, onMapFollow } = this.props
|
const { mobile, maps, mapsWidth, currentUser, juntoState, pending, section, user, onStar, onRequest, onMapFollow } = this.props
|
||||||
const style = { width: this.state.mapsWidth + 'px' }
|
const style = { width: mapsWidth + 'px' }
|
||||||
const mobile = document && document.body.clientWidth <= MOBILE_VIEW_BREAKPOINT
|
|
||||||
|
|
||||||
if (!maps) return null // do loading here instead
|
if (!maps) return null // do loading here instead
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div id='exploreMaps' ref='maps'>
|
<div id='exploreMaps' ref={x => this.maps = x}>
|
||||||
<div style={ style }>
|
<div style={ style }>
|
||||||
{ user ? <MapperCard user={ user } /> : null }
|
{ user ? <MapperCard user={ user } /> : null }
|
||||||
{ currentUser && !user && !(pending && maps.length === 0) ? <div className="map newMap"><a href="/maps/new"><div className="newMapImage"></div><span>Create new map...</span></a></div> : null }
|
{ currentUser && !user && !(pending && maps.length === 0) ? <div className="map newMap"><a href="/maps/new"><div className="newMapImage"></div><span>Create new map...</span></a></div> : null }
|
||||||
|
|
Loading…
Add table
Reference in a new issue