diff --git a/frontend/src/Metamaps/GlobalUI/CreateMap.js b/frontend/src/Metamaps/GlobalUI/CreateMap.js index a92e1836..c0c2868b 100644 --- a/frontend/src/Metamaps/GlobalUI/CreateMap.js +++ b/frontend/src/Metamaps/GlobalUI/CreateMap.js @@ -61,7 +61,7 @@ const CreateMap = { if (GlobalUI.lightbox === 'forkmap') { self.newMap.set('topicsToMap', self.topicsToMap) self.newMap.set('synapsesToMap', self.synapsesToMap) - self.newMap.set('source_id', Active.Map.id) + if (Active.Map) self.newMap.set('source_id', Active.Map.id) } var formId = GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map' diff --git a/frontend/src/Metamaps/GlobalUI/ReactApp.js b/frontend/src/Metamaps/GlobalUI/ReactApp.js index d75d505f..95ce91a3 100644 --- a/frontend/src/Metamaps/GlobalUI/ReactApp.js +++ b/frontend/src/Metamaps/GlobalUI/ReactApp.js @@ -28,6 +28,7 @@ const MAX_COLUMNS = 4 const ReactApp = { mapId: null, + topicId: null, unreadNotificationsCount: 0, mapsWidth: 0, toast: '', @@ -60,15 +61,21 @@ const ReactApp = { $('#yield').hide() ExploreMaps.updateFromPath(pathname) self.mapId = null + self.topicId = null Active.Map = null Active.Topic = null break case 'topics': $('#yield').hide() + Active.Map = null + self.mapId = null + self.topicId = pathname.split('/')[2] break case 'maps': if (!pathname.includes('request_access')) { $('#yield').hide() + Active.Topic = null + self.topicId = null self.mapId = pathname.split('/')[2] } break @@ -101,6 +108,7 @@ const ReactApp = { self.getMapProps(), self.getTopicProps(), self.getFilterProps(), + self.getCommonProps(), self.getMapsProps(), self.getTopicCardProps(), self.getChatProps()) @@ -122,9 +130,14 @@ const ReactApp = { infoBoxHtml: InfoBox.html, openImportLightbox: () => ImportDialog.show(), forkMap: Map.fork, - openHelpLightbox: () => self.openLightbox('cheatsheet'), onMapStar: Map.star, - onMapUnstar: Map.unstar, + onMapUnstar: Map.unstar + } + }, + getCommonProps: function() { + const self = ReactApp + return { + openHelpLightbox: () => self.openLightbox('cheatsheet'), onZoomExtents: event => JIT.zoomExtents(event, Visualize.mGraph.canvas), onZoomIn: JIT.zoomIn, onZoomOut: JIT.zoomOut @@ -143,7 +156,10 @@ const ReactApp = { getTopicProps: function() { const self = ReactApp return { - topic: Active.Topic + topicId: self.topicId, + topic: Active.Topic, + endActiveTopic: Topic.end, + launchNewTopic: Topic.launch } }, getMapsProps: function() { diff --git a/frontend/src/Metamaps/Map/index.js b/frontend/src/Metamaps/Map/index.js index 7eff2db4..595ec206 100644 --- a/frontend/src/Metamaps/Map/index.js +++ b/frontend/src/Metamaps/Map/index.js @@ -94,9 +94,9 @@ const Map = { Map.setAccessRequest() Visualize.type = 'ForceDirected' JIT.prepareVizData() - Filter.reset() Selected.reset() InfoBox.load() + Filter.reset() Filter.checkMetacodes() Filter.checkSynapses() Filter.checkMappers() @@ -110,7 +110,7 @@ const Map = { if (InfoBox.generateBoxHTML) start() else setTimeout(() => isLoaded(), 50) } - if (Active.Map && Active.Map.id == id) { + if (Active.Map && Active.Map.id === id) { isLoaded() } else { diff --git a/frontend/src/Metamaps/Topic.js b/frontend/src/Metamaps/Topic.js index df5789c8..10d1da81 100644 --- a/frontend/src/Metamaps/Topic.js +++ b/frontend/src/Metamaps/Topic.js @@ -7,8 +7,9 @@ import AutoLayout from './AutoLayout' import Create from './Create' import DataModel from './DataModel' import Filter from './Filter' -import GlobalUI from './GlobalUI' +import GlobalUI, { ReactApp } from './GlobalUI' import JIT from './JIT' +import Loading from './Loading' import Map from './Map' import Selected from './Selected' import Settings from './Settings' @@ -35,41 +36,35 @@ const Topic = { } else callback(DataModel.Topics.get(id)) }, launch: function(id) { - var start = function(data) { - Active.Topic = new DataModel.Topic(data.topic) - DataModel.Creators = new DataModel.MapperCollection(data.creators) - DataModel.Topics = new DataModel.TopicCollection([data.topic].concat(data.relatives)) - DataModel.Synapses = new DataModel.SynapseCollection(data.synapses) - DataModel.attachCollectionEvents() - - document.title = Active.Topic.get('name') + ' | Metamaps' - - // set filter mapper H3 text - $('#filter_by_mapper h3').html('CREATORS') - - // build and render the visualization + var start = function() { Visualize.type = 'RGraph' JIT.prepareVizData() - - // update filters - Filter.reset() - - // reset selected arrays Selected.reset() - - // these three update the actual filter box with the right list items + Filter.reset() Filter.checkMetacodes() Filter.checkSynapses() Filter.checkMappers() - - // for mobile - $('#header_content').html(Active.Topic.get('name')) + document.title = Active.Topic.get('name') + ' | Metamaps' + ReactApp.mobileTitle = Active.Topic.get('name') + ReactApp.render() + } + if (Active.Topic && Active.Topic.id === id) { + start() + } + else { + Loading.show() + $.ajax({ + url: '/topics/' + id + '/network.json', + success: function(data) { + Active.Topic = new DataModel.Topic(data.topic) + DataModel.Creators = new DataModel.MapperCollection(data.creators) + DataModel.Topics = new DataModel.TopicCollection([data.topic].concat(data.relatives)) + DataModel.Synapses = new DataModel.SynapseCollection(data.synapses) + DataModel.attachCollectionEvents() + start() + } + }) } - - $.ajax({ - url: '/topics/' + id + '/network.json', - success: start - }) }, end: function() { if (Active.Topic) { diff --git a/frontend/src/components/MapView/index.js b/frontend/src/components/MapView/index.js index b78ddeb5..342da793 100644 --- a/frontend/src/components/MapView/index.js +++ b/frontend/src/components/MapView/index.js @@ -1,14 +1,14 @@ import React, { Component, PropTypes } from 'react' -import DataVis from './DataVis' -import MapButtons from './MapButtons' -import InfoAndHelp from './InfoAndHelp' +import DataVis from '../common/DataVis' +import UpperOptions from '../common/UpperOptions' +import InfoAndHelp from '../common/InfoAndHelp' import Instructions from './Instructions' -import MapControls from './MapControls' +import VisualizationControls from '../common/VisualizationControls' import MapChat from './MapChat' import TopicCard from '../TopicCard' -class MapView extends Component { +export default class MapView extends Component { static propTypes = { mobile: PropTypes.bool, @@ -52,7 +52,7 @@ class MapView extends Component { chatOpen: false }) this.mapChat.reset() - this.mapButtons.reset() + this.upperOptions.reset() this.props.endActiveMap() } @@ -87,27 +87,29 @@ class MapView extends Component { const canEditMap = map && map.authorizeToEdit(currentUser) // TODO: stop using {...this.props} and make explicit return
- this.mapButtons = x} - currentUser={currentUser} - onImportClick={openImportLightbox} - onForkClick={forkMap} - canEditMap={canEditMap} - filterData={filterData} - allForFiltering={allForFiltering} - visibleForFiltering={visibleForFiltering} - toggleMetacode={toggleMetacode} - toggleMapper={toggleMapper} - toggleSynapse={toggleSynapse} - filterAllMetacodes={filterAllMetacodes} - filterAllMappers={filterAllMappers} - filterAllSynapses={filterAllSynapses} /> + this.upperOptions = x} + map={map} + currentUser={currentUser} + onImportClick={openImportLightbox} + onForkClick={forkMap} + canEditMap={canEditMap} + filterData={filterData} + allForFiltering={allForFiltering} + visibleForFiltering={visibleForFiltering} + toggleMetacode={toggleMetacode} + toggleMapper={toggleMapper} + toggleSynapse={toggleSynapse} + filterAllMetacodes={filterAllMetacodes} + filterAllMappers={filterAllMappers} + filterAllSynapses={filterAllSynapses} /> {currentUser && } {currentUser && this.mapChat = x} />} - + } } - -export default MapView diff --git a/frontend/src/components/TopicCard/Links.js b/frontend/src/components/TopicCard/Links.js index ad1758d3..401fb565 100644 --- a/frontend/src/components/TopicCard/Links.js +++ b/frontend/src/components/TopicCard/Links.js @@ -1,6 +1,7 @@ /* global $ */ import React, { PropTypes, Component } from 'react' +import { Link } from 'react-router' import MetacodeSelect from '../MetacodeSelect' import Permission from './Permission' @@ -52,21 +53,21 @@ class Links extends Component { } let output = [] - + firstFiveLinks.forEach(obj => { - output.push(
  • {obj.mapName}
  • ) + output.push(
  • {obj.mapName}
  • ) }) if (extraLinks.length > 0) { if (this.state.showMoreMaps) { extraLinks.forEach(obj => { - output.push(
  • {obj.mapName}
  • ) + output.push(
  • {obj.mapName}
  • ) }) } const text = this.state.showMoreMaps ? 'See less...' : `See ${extraLinks.length} more...` output.push(
  • {text}
  • ) } - + return output } diff --git a/frontend/src/components/TopicView/index.js b/frontend/src/components/TopicView/index.js index 5c30dfee..07450769 100644 --- a/frontend/src/components/TopicView/index.js +++ b/frontend/src/components/TopicView/index.js @@ -1,9 +1,77 @@ -import React, { PropTypes, Component } from 'react' +import React, { Component, PropTypes } from 'react' -class TopicView extends Component { - render() { - return null +import DataVis from '../common/DataVis' +import UpperOptions from '../common/UpperOptions' +import InfoAndHelp from '../common/InfoAndHelp' +import VisualizationControls from '../common/VisualizationControls' +import TopicCard from '../TopicCard' + +export default class TopicView extends Component { + + static propTypes = { + mobile: PropTypes.bool, + topicId: PropTypes.string, + topic: PropTypes.object, + filterData: PropTypes.object, + allForFiltering: PropTypes.object, + visibleForFiltering: PropTypes.object, + toggleMetacode: PropTypes.func, + toggleMapper: PropTypes.func, + toggleSynapse: PropTypes.func, + filterAllMetacodes: PropTypes.func, + filterAllMappers: PropTypes.func, + filterAllSynapses: PropTypes.func, + currentUser: PropTypes.object, + endActiveTopic: PropTypes.func, + launchNewTopic: PropTypes.func, + openHelpLightbox: PropTypes.func, + forkMap: PropTypes.func, + onZoomIn: PropTypes.func, + onZoomOut: PropTypes.func + } + + endTopic() { + this.upperOptions.reset() + this.props.endActiveTopic() + } + + componentDidUpdate(prevProps) { + const oldTopicId = prevProps.topicId + const { topicId, launchNewTopic } = this.props + if (!oldTopicId && topicId) launchNewTopic(topicId) + else if (oldTopicId && topicId && oldTopicId !== topicId) { + this.endTopic() + launchNewTopic(topicId) + } + else if (oldTopicId && !topicId) this.endTopic() + } + + render = () => { + const { mobile, topic, currentUser, allForFiltering, visibleForFiltering, + toggleMetacode, toggleMapper, toggleSynapse, filterAllMetacodes, + filterAllMappers, filterAllSynapses, filterData, forkMap, + openHelpLightbox, onZoomIn, onZoomOut } = this.props + // TODO: stop using {...this.props} and make explicit + return
    + this.upperOptions = x} + currentUser={currentUser} + topic={topic} + onForkClick={forkMap} + filterData={filterData} + allForFiltering={allForFiltering} + visibleForFiltering={visibleForFiltering} + toggleMetacode={toggleMetacode} + toggleMapper={toggleMapper} + toggleSynapse={toggleSynapse} + filterAllMetacodes={filterAllMetacodes} + filterAllMappers={filterAllMappers} + filterAllSynapses={filterAllSynapses} /> + + + + +
    } } - -export default TopicView diff --git a/frontend/src/components/MapView/DataVis.js b/frontend/src/components/common/DataVis.js similarity index 100% rename from frontend/src/components/MapView/DataVis.js rename to frontend/src/components/common/DataVis.js diff --git a/frontend/src/components/common/FilterBox.js b/frontend/src/components/common/FilterBox.js index b5a5275b..fbab1111 100644 --- a/frontend/src/components/common/FilterBox.js +++ b/frontend/src/components/common/FilterBox.js @@ -4,6 +4,8 @@ import onClickOutsideAddon from 'react-onclickoutside' class FilterBox extends Component { static propTypes = { + topic: PropTypes.object, + map: PropTypes.object, filterData: PropTypes.object, allForFiltering: PropTypes.object, visibleForFiltering: PropTypes.object, @@ -21,8 +23,9 @@ class FilterBox extends Component { } render () { - const { filterData, allForFiltering, visibleForFiltering, toggleMetacode, toggleMapper, toggleSynapse, - filterAllMetacodes, filterAllMappers, filterAllSynapses } = this.props + const { topic, map, filterData, allForFiltering, visibleForFiltering, toggleMetacode, + toggleMapper, toggleSynapse, filterAllMetacodes, + filterAllMappers, filterAllSynapses } = this.props const style = { maxHeight: document.body.clientHeight - 108 + 'px' } @@ -42,7 +45,8 @@ class FilterBox extends Component {

    FILTER BY

    -

    MAPPERS

    + {map &&

    MAPPERS

    } + {topic &&

    CREATORS

    } filterAllMappers()}>NONE filterAllMappers(true)}>ALL
    diff --git a/frontend/src/components/MapView/InfoAndHelp.js b/frontend/src/components/common/InfoAndHelp.js similarity index 75% rename from frontend/src/components/MapView/InfoAndHelp.js rename to frontend/src/components/common/InfoAndHelp.js index ec1abbd7..fe298691 100644 --- a/frontend/src/components/MapView/InfoAndHelp.js +++ b/frontend/src/components/common/InfoAndHelp.js @@ -1,6 +1,6 @@ import React, { Component, PropTypes } from 'react' -import MapInfoBox from './MapInfoBox' +import MapInfoBox from '../MapView/MapInfoBox' class InfoAndHelp extends Component { static propTypes = { @@ -20,13 +20,13 @@ class InfoAndHelp extends Component { const tooltip = mapIsStarred ? 'Unstar' : 'Star' const onStarClick = mapIsStarred ? onMapUnstar : onMapStar return
    - - {currentUser &&
    + {map && } + {map && currentUser &&
    {tooltip}
    } -
    + {map &&
    Map Info
    -
    +
    }
    Help
    diff --git a/frontend/src/components/MapView/MapButtons.js b/frontend/src/components/common/UpperOptions.js similarity index 63% rename from frontend/src/components/MapView/MapButtons.js rename to frontend/src/components/common/UpperOptions.js index 670e5ddd..d17214ee 100644 --- a/frontend/src/components/MapView/MapButtons.js +++ b/frontend/src/components/common/UpperOptions.js @@ -2,9 +2,11 @@ import React, { Component, PropTypes } from 'react' import FilterBox from '../common/FilterBox' -class MapButtons extends Component { +export default class UpperOptions extends Component { static propTypes = { currentUser: PropTypes.object, + map: PropTypes.object, + topic: PropTypes.object, canEditMap: PropTypes.bool, onImportClick: PropTypes.func, onForkClick: PropTypes.func, @@ -33,12 +35,12 @@ class MapButtons extends Component { } render () { - const { currentUser, canEditMap, filterBoxHtml, onFilterClick, onImportClick, onForkClick, + const { currentUser, map, topic, canEditMap, filterBoxHtml, onFilterClick, onImportClick, onForkClick, filterData, allForFiltering, visibleForFiltering, toggleMetacode, toggleMapper, toggleSynapse, filterAllMetacodes, filterAllMappers, filterAllSynapses } = this.props const { filterBoxOpen } = this.state return
    - {canEditMap &&
    + {map && canEditMap &&
    Import Data
    @@ -48,15 +50,17 @@ class MapButtons extends Component {
    Filter
    {filterBoxOpen && this.reset()} />} + map={map} + topic={topic} + allForFiltering={allForFiltering} + visibleForFiltering={visibleForFiltering} + toggleMetacode={toggleMetacode} + toggleMapper={toggleMapper} + toggleSynapse={toggleSynapse} + filterAllMetacodes={filterAllMetacodes} + filterAllMappers={filterAllMappers} + filterAllSynapses={filterAllSynapses} + closeBox={() => this.reset()} />}
    {currentUser &&
    @@ -67,5 +71,3 @@ class MapButtons extends Component {
    } } - -export default MapButtons diff --git a/frontend/src/components/MapView/MapControls.js b/frontend/src/components/common/VisualizationControls.js similarity index 68% rename from frontend/src/components/MapView/MapControls.js rename to frontend/src/components/common/VisualizationControls.js index cf61feea..0b45f827 100644 --- a/frontend/src/components/MapView/MapControls.js +++ b/frontend/src/components/common/VisualizationControls.js @@ -1,18 +1,19 @@ import React, { Component, PropTypes } from 'react' -class MapControls extends Component { +export default class VisualizationControls extends Component { static propTypes = { + map: PropTypes.object, onClickZoomExtents: PropTypes.func, onClickZoomIn: PropTypes.func, onClickZoomOut: PropTypes.func } render () { - const { onClickZoomExtents, onClickZoomIn, onClickZoomOut } = this.props + const { map, onClickZoomExtents, onClickZoomIn, onClickZoomOut } = this.props return
    -
    + {map &&
    Center View
    -
    +
    }
    Zoom In
    @@ -22,5 +23,3 @@ class MapControls extends Component {
    } } - -export default MapControls