diff --git a/app/assets/stylesheets/clean.css.erb b/app/assets/stylesheets/clean.css.erb index dc576800..bc94a6f7 100644 --- a/app/assets/stylesheets/clean.css.erb +++ b/app/assets/stylesheets/clean.css.erb @@ -169,9 +169,6 @@ .upperRightMapButtons { right: 134px; } -.mapPage .upperRightMapButtons, .topicPage .upperRightMapButtons { - top: 0; -} .upperRightIcon { width: 32px; @@ -180,13 +177,7 @@ background-repeat: no-repeat; cursor: pointer; } -.mapPage .mapElement .importDialog { - display: none; - background-position: 0 0; -} -.mapPage.canEditMap .mapElement .importDialog { - display: block; -} + .sidebarFilterIcon { background-position: -32px 0; } @@ -347,7 +338,7 @@ /* infoAndHelp */ -.mapPage .openCheatsheet .tooltipsAbove, .topicPage .openCheatsheet .tooltipsAbove { +.openCheatsheet .tooltipsAbove { right: 1px; left: auto; } @@ -399,9 +390,6 @@ background-position: 0 0; } -.unauthenticated .mapPage .starMap { - display: none; -} /* end infoAndHelp */ @@ -560,10 +548,6 @@ left: -8px; } -.openCheatsheet .tooltipsAbove { - left: -4px; -} - .sidebarAccountIcon .tooltipsUnder { margin-left: -12px; margin-top: 40px; diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index a7641fe0..34e0a479 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -35,5 +35,6 @@ Metamaps.ServerData.mapIsStarred = <%= @map && current_user.starred_map?(@map) ? true : false %> <% end %> +
<%= render :partial => 'layouts/foot' %> diff --git a/app/views/shared/_filterBox.html.erb b/app/views/shared/_filterBox.html.erb index 9ea4926b..6698e64d 100644 --- a/app/views/shared/_filterBox.html.erb +++ b/app/views/shared/_filterBox.html.erb @@ -2,27 +2,27 @@ # @file # this code generates the list of icons in the filter box in the upper right menu area #%> - -<% + +<% @mappers = [] @synapses = [] @metacodes = [] @metacodelist = '' @mapperlist = '' @synapselist = '' -# There are essentially three functions happening here one to fill data to -#@mappers with all people who have mapped on the selected map, which -#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 +# There are essentially three functions happening here one to fill data to +#@mappers with all people who have mapped on the selected map, which +#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 #and metacodes is filled with all the metacodes that are being used on the map. if @map - @alltopics.each_with_index do |topic, index| + @alltopics.each_with_index do |topic, index| if @metacodes.index(topic.metacode) == nil @metacodes.push(topic.metacode) end - end - @allsynapses.each_with_index do |synapse, index| + end + @allsynapses.each_with_index do |synapse, index| if @synapses.index{|s| s.desc == synapse.desc} == nil @synapses.push(synapse) end @@ -32,16 +32,16 @@ @mappers.push(mapping.user) end end - elsif @topic - @alltopics.each_with_index do |topic, index| + elsif @topic + @alltopics.each_with_index do |topic, index| if @metacodes.index(topic.metacode) == nil @metacodes.push(topic.metacode) end if @mappers.index(topic.user) == nil @mappers.push(topic.user) end - end - @allsynapses.each_with_index do |synapse, index| + end + @allsynapses.each_with_index do |synapse, index| if @synapses.index{|s| s.desc == synapse.desc} == nil @synapses.push(synapse) end @@ -52,7 +52,7 @@ end if @map || @topic - @metacodes.sort! {|x,y| + @metacodes.sort! {|x,y| n1 = x.name || "" n2 = y.name || "" n1 <=> n2 @@ -62,24 +62,24 @@ d2 = y.desc || "" d1 <=> d2 } - @mappers.sort! {|x,y| + @mappers.sort! {|x,y| n1 = x.name || "" n2 = y.name || "" - n1 <=> n2 + n1 <=> n2 } - - @metacodes.each_with_index do |metacode, index| + + @metacodes.each_with_index do |metacode, index| @metacodelist += '
  • ' @metacodelist += '' + metacode.name + '' @metacodelist += '

    ' + metacode.name.downcase + '

  • ' end - @synapses.each_with_index do |synapse, index| + @synapses.each_with_index do |synapse, index| d = synapse.desc || "" @synapselist += '
  • ' @synapselist += 'synapse icon

    ' + d @synapselist += '

  • ' - end - @mappers.each_with_index do |mapper, index| + end + @mappers.each_with_index do |mapper, index| @mapperlist += '
  • ' @mapperlist += '' + mapper.name + '' @mapperlist += '

    ' + mapper.name + '

  • ' @@ -95,7 +95,7 @@
    +
    @@ -106,7 +106,7 @@
    +
    @@ -117,9 +117,8 @@
    +
    - diff --git a/frontend/src/Metamaps/Filter.js b/frontend/src/Metamaps/Filter.js index 8f45423e..f617c05c 100644 --- a/frontend/src/Metamaps/Filter.js +++ b/frontend/src/Metamaps/Filter.js @@ -26,8 +26,6 @@ const Filter = { init: function() { var self = Filter - $('.sidebarFilterIcon').click(self.toggleBox) - $('.sidebarFilterBox .showAllMetacodes').click(self.filterNoMetacodes) $('.sidebarFilterBox .showAllSynapses').click(self.filterNoSynapses) $('.sidebarFilterBox .showAllMappers').click(self.filterNoMappers) diff --git a/frontend/src/Metamaps/GlobalUI/ImportDialog.js b/frontend/src/Metamaps/GlobalUI/ImportDialog.js index 774c2190..63c47491 100644 --- a/frontend/src/Metamaps/GlobalUI/ImportDialog.js +++ b/frontend/src/Metamaps/GlobalUI/ImportDialog.js @@ -19,7 +19,7 @@ const ImportDialog = { self.closeLightbox = closeLightbox $('#lightbox_content').append($(outdent` -
    +
    `)) diff --git a/frontend/src/Metamaps/GlobalUI/ReactApp.js b/frontend/src/Metamaps/GlobalUI/ReactApp.js index f224e206..d317d4c8 100644 --- a/frontend/src/Metamaps/GlobalUI/ReactApp.js +++ b/frontend/src/Metamaps/GlobalUI/ReactApp.js @@ -3,30 +3,42 @@ import React from 'react' import ReactDOM from 'react-dom' import { Router, browserHistory } from 'react-router' - import { merge } from 'lodash' import { notifyUser } from './index.js' +import ImportDialog from './ImportDialog' import Active from '../Active' import DataModel from '../DataModel' import { ExploreMaps, ChatView, TopicCard } from '../Views' import Filter from '../Filter' +import JIT from '../JIT' import Realtime from '../Realtime' import Map, { InfoBox } from '../Map' import Topic from '../Topic' +import Visualize from '../Visualize' import makeRoutes from '../../components/makeRoutes' 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 = { mapId: null, unreadNotificationsCount: 0, - mapIsStarred: false, - init: function(serverData) { + mapsWidth: 0, + mobile: false, + init: function(serverData, openLightbox) { const self = ReactApp self.unreadNotificationsCount = serverData.unreadNotificationsCount - self.mapIsStarred = serverData.mapIsStarred + self.openLightbox = openLightbox routes = makeRoutes() + self.resize() + self.setMobile() self.render() + window && window.addEventListener('resize', self.resize) }, handleUpdate: function(location) { const self = ReactApp @@ -59,7 +71,8 @@ const ReactApp = { const self = ReactApp return merge({ unreadNotificationsCount: self.unreadNotificationsCount, - currentUser: Active.Mapper + currentUser: Active.Mapper, + mobile: self.mobile }, self.getMapProps(), self.getTopicProps(), @@ -72,13 +85,21 @@ const ReactApp = { return { mapId: self.mapId, map: Active.Map, - mapIsStarred: self.mapIsStarred, + mapIsStarred: Map.mapIsStarred, endActiveMap: Map.end, launchNewMap: Map.launch, toggleMapInfoBox: InfoBox.toggleBox, + infoBoxHtml: InfoBox.html, toggleFilterBox: Filter.toggleBox, - infoBoxHtml: InfoBox.html - // filters + filterBoxHtml: $('.filterBox')[0].outerHTML, + 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() { @@ -109,7 +130,8 @@ const ReactApp = { pending: ExploreMaps.pending, onStar: ExploreMaps.onStar, onRequest: ExploreMaps.onRequest, - onMapFollow: ExploreMaps.onMapFollow + onMapFollow: ExploreMaps.onMapFollow, + mapsWidth: ReactApp.mapsWidth } }, getChatProps: function() { @@ -132,6 +154,24 @@ const ReactApp = { inputFocus: ChatView.inputFocus, 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() } } diff --git a/frontend/src/Metamaps/GlobalUI/index.js b/frontend/src/Metamaps/GlobalUI/index.js index 14185abf..a766140e 100644 --- a/frontend/src/Metamaps/GlobalUI/index.js +++ b/frontend/src/Metamaps/GlobalUI/index.js @@ -18,7 +18,7 @@ const GlobalUI = { init: function(serverData) { const self = GlobalUI - self.ReactApp.init(serverData) + self.ReactApp.init(serverData, self.openLightbox) self.Search.init(serverData) self.CreateMap.init(serverData) self.Account.init(serverData) diff --git a/frontend/src/Metamaps/JIT.js b/frontend/src/Metamaps/JIT.js index eb023fe8..cc1ff467 100644 --- a/frontend/src/Metamaps/JIT.js +++ b/frontend/src/Metamaps/JIT.js @@ -50,15 +50,6 @@ const JIT = { */ init: function(serverData) { 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.src = serverData['topic_description_signifier.png'] diff --git a/frontend/src/Metamaps/Map/index.js b/frontend/src/Metamaps/Map/index.js index 94a749c1..0b64a0b0 100644 --- a/frontend/src/Metamaps/Map/index.js +++ b/frontend/src/Metamaps/Map/index.js @@ -9,7 +9,7 @@ import Create from '../Create' import DataModel from '../DataModel' import DataModelMap from '../DataModel/Map' import Filter from '../Filter' -import GlobalUI from '../GlobalUI' +import GlobalUI, { ReactApp } from '../GlobalUI' import JIT from '../JIT' import Loading from '../Loading' import Realtime from '../Realtime' @@ -25,26 +25,18 @@ const Map = { events: { editedByActiveMapper: 'Metamaps:Map:events:editedByActiveMapper' }, + mapIsStarred: false, init: function(serverData) { var self = Map + self.mapIsStarred = serverData.mapIsStarred + $('#wrapper').mousedown(function(e) { 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() - self.updateStar() - InfoBox.init(serverData, function updateThumbnail() { self.uploadMapScreenshot() }) @@ -102,8 +94,6 @@ const Map = { $('.wrapper').addClass('commonsMap') } - Map.updateStar() - // set filter mapper H3 text $('#filter_by_mapper h3').html('MAPPERS') @@ -153,17 +143,6 @@ const Map = { $('.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() { var self = Map @@ -172,7 +151,8 @@ const Map = { DataModel.Stars.push({ user_id: Active.Mapper.id, map_id: Active.Map.id }) DataModel.Maps.Starred.add(Active.Map) GlobalUI.notifyUser('Map is now starred') - self.updateStar() + self.mapIsStarred = true + ReactApp.render() }, unstar: function() { var self = Map @@ -181,7 +161,8 @@ const Map = { $.post('/maps/' + Active.Map.id + '/unstar') DataModel.Stars = DataModel.Stars.filter(function(s) { return s.user_id !== Active.Mapper.id }) DataModel.Maps.Starred.remove(Active.Map) - self.updateStar() + self.mapIsStarred = false + ReactApp.render() }, fork: function() { GlobalUI.openLightbox('forkmap') diff --git a/frontend/src/Metamaps/Views/ExploreMaps.js b/frontend/src/Metamaps/Views/ExploreMaps.js index 5d332390..506fb041 100644 --- a/frontend/src/Metamaps/Views/ExploreMaps.js +++ b/frontend/src/Metamaps/Views/ExploreMaps.js @@ -60,6 +60,7 @@ const ExploreMaps = { }, render: function() { var self = ExploreMaps + ReactApp.resize() ReactApp.render() Loading.hide() }, diff --git a/frontend/src/components/App/index.js b/frontend/src/components/App/index.js index 9a8e6204..9424052a 100644 --- a/frontend/src/components/App/index.js +++ b/frontend/src/components/App/index.js @@ -23,13 +23,13 @@ class App extends Component { } render () { - const { toast, currentUser, unreadNotificationsCount } = this.props + const { children, toast, currentUser, unreadNotificationsCount } = this.props return
    {currentUser && } - {this.props.children} + {children}
    } } diff --git a/frontend/src/components/MapView/FilterBox.js b/frontend/src/components/MapView/FilterBox.js index 3ea1a614..6b6fdd34 100644 --- a/frontend/src/components/MapView/FilterBox.js +++ b/frontend/src/components/MapView/FilterBox.js @@ -2,10 +2,14 @@ import React, { Component, PropTypes } from 'react' class FilterBox extends Component { static propTypes = { + isMap: PropTypes.bool, + filterBoxHtml: PropTypes.string } render () { - return null + const { filterBoxHtml } = this.props + const html = {__html: filterBoxHtml} + return
    } } diff --git a/frontend/src/components/MapView/InfoAndHelp.js b/frontend/src/components/MapView/InfoAndHelp.js index 3e86c5fd..578f4b71 100644 --- a/frontend/src/components/MapView/InfoAndHelp.js +++ b/frontend/src/components/MapView/InfoAndHelp.js @@ -7,23 +7,28 @@ class InfoAndHelp extends Component { mapIsStarred: PropTypes.bool, currentUser: PropTypes.object, map: PropTypes.object, + onHelpClick: PropTypes.func, + onMapStar: PropTypes.func, + onMapUnstar: PropTypes.func, + onInfoClick: PropTypes.func, infoBoxhtml: PropTypes.string } 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 tooltip = mapIsStarred ? 'Star' : 'Unstar' + const tooltip = mapIsStarred ? 'Unstar' : 'Star' + const onStarClick = mapIsStarred ? onMapUnstar : onMapStar return
    -
    +
    {tooltip}
    Map Info
    -
    +
    Help
    diff --git a/frontend/src/components/MapView/MapButtons.js b/frontend/src/components/MapView/MapButtons.js index c15960a1..c4b3c4d2 100644 --- a/frontend/src/components/MapView/MapButtons.js +++ b/frontend/src/components/MapView/MapButtons.js @@ -5,25 +5,31 @@ import FilterBox from './FilterBox' class MapButtons extends Component { static propTypes = { currentUser: PropTypes.object, - filterBoxOpen: PropTypes.bool + canEditMap: PropTypes.bool, + onImportClick: PropTypes.func, + onForkClick: PropTypes.func, + onFilterClick: PropTypes.func, + filterBoxHtml: PropTypes.string } render () { - const { currentUser, filterBoxOpen } = this.props + const { currentUser, canEditMap, filterBoxHtml, onFilterClick, onImportClick, onForkClick } = this.props return
    - {currentUser &&
    + {canEditMap &&
    Import Data
    }
    -
    Filter
    - {filterBoxOpen &&
    - -
    } +
    +
    Filter
    +
    +
    {currentUser &&
    -
    Save To New Map
    +
    +
    Save To New Map
    +
    }
    diff --git a/frontend/src/components/MapView/MapControls.js b/frontend/src/components/MapView/MapControls.js index 8d9831ee..cf61feea 100644 --- a/frontend/src/components/MapView/MapControls.js +++ b/frontend/src/components/MapView/MapControls.js @@ -2,13 +2,23 @@ import React, { Component, PropTypes } from 'react' class MapControls extends Component { static propTypes = { + onClickZoomExtents: PropTypes.func, + onClickZoomIn: PropTypes.func, + onClickZoomOut: PropTypes.func } render () { + const { onClickZoomExtents, onClickZoomIn, onClickZoomOut } = this.props return
    -
    Center View
    -
    Zoom In
    -
    Zoom Out
    +
    +
    Center View
    +
    +
    +
    Zoom In
    +
    +
    +
    Zoom Out
    +
    } } diff --git a/frontend/src/components/MapView/index.js b/frontend/src/components/MapView/index.js index ef9222e4..4ac1c99a 100644 --- a/frontend/src/components/MapView/index.js +++ b/frontend/src/components/MapView/index.js @@ -14,6 +14,7 @@ class MapView extends Component { map: PropTypes.object, mapIsStarred: PropTypes.bool, toggleFilterBox: PropTypes.func, + filterBoxHtml: PropTypes.string, toggleMapInfoBox: PropTypes.func, infoBoxHtml: PropTypes.string, currentUser: PropTypes.object, @@ -62,7 +63,11 @@ class MapView extends Component { } 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 onChatOpen = () => { this.setState({chatOpen: true}) @@ -72,17 +77,28 @@ class MapView extends Component { this.setState({chatOpen: false}) onClose() } + const canEditMap = map && map.authorizeToEdit(currentUser) // TODO: stop using {...this.props} and make explicit return
    - + - +
    } diff --git a/frontend/src/components/Maps/index.js b/frontend/src/components/Maps/index.js index 607282e2..21fa82ed 100644 --- a/frontend/src/components/Maps/index.js +++ b/frontend/src/components/Maps/index.js @@ -4,12 +4,6 @@ import Header from './Header' import MapperCard from './MapperCard' 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 { static propTypes = { @@ -23,37 +17,17 @@ class Maps extends Component { pending: PropTypes.bool, onStar: PropTypes.func, onRequest: PropTypes.func, - onMapFollow: PropTypes.func + onMapFollow: PropTypes.func, + mapsWidth: PropTypes.number, + mobile: PropTypes.bool } static contextTypes = { location: PropTypes.object } - constructor(props) { - super(props) - this.state = { mapsWidth: 0 } - } - componentDidMount() { - window && window.addEventListener('resize', this.resize) - 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 }) + this.maps && this.maps.addEventListener('scroll', throttle(this.scroll, 500, { leading: true, trailing: false })) } scroll = () => { @@ -65,15 +39,14 @@ class Maps extends Component { } render = () => { - const { maps, currentUser, juntoState, pending, section, user, onStar, onRequest, onMapFollow } = this.props - const style = { width: this.state.mapsWidth + 'px' } - const mobile = document && document.body.clientWidth <= MOBILE_VIEW_BREAKPOINT + const { mobile, maps, mapsWidth, currentUser, juntoState, pending, section, user, onStar, onRequest, onMapFollow } = this.props + const style = { width: mapsWidth + 'px' } if (!maps) return null // do loading here instead return (
    -
    +
    this.maps = x}>
    { user ? : null } { currentUser && !user && !(pending && maps.length === 0) ? : null }