filter box in react

This commit is contained in:
Connor Turland 2017-03-15 20:59:10 -04:00
parent 9789e9966b
commit 40c92cd8dc
12 changed files with 214 additions and 335 deletions

View file

@ -20,5 +20,4 @@
<% # for populating the change metacode list on the topic card %> <% # for populating the change metacode list on the topic card %>
<%= render :partial => 'shared/metacodeoptions' %> <%= render :partial => 'shared/metacodeoptions' %>
<% end %> <% end %>
<div class="hidden"><%= render :partial => 'shared/filterBox' %></div>
<%= render :partial => 'layouts/foot' %> <%= render :partial => 'layouts/foot' %>

View file

@ -1,124 +0,0 @@
<%#
# @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
#and metacodes is filled with all the metacodes that are being used on the map.
if @map
@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|
if @synapses.index{|s| s.desc == synapse.desc} == nil
@synapses.push(synapse)
end
end
@allmappings.each_with_index do |mapping, index|
if @mappers.index(mapping.user) == nil
@mappers.push(mapping.user)
end
end
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|
if @synapses.index{|s| s.desc == synapse.desc} == nil
@synapses.push(synapse)
end
if @mappers.index(synapse.user) == nil
@mappers.push(synapse.user)
end
end
end
if @map || @topic
@metacodes.sort! {|x,y|
n1 = x.name || ""
n2 = y.name || ""
n1 <=> n2
}
@synapses.sort! {|x,y|
d1 = x.desc || ""
d2 = y.desc || ""
d1 <=> d2
}
@mappers.sort! {|x,y|
n1 = x.name || ""
n2 = y.name || ""
n1 <=> n2
}
@metacodes.each_with_index do |metacode, index|
@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 += '<p>' + metacode.name.downcase + '</p></li>'
end
@synapses.each_with_index do |synapse, index|
d = synapse.desc || ""
@synapselist += '<li data-id="' + d + '">'
@synapselist += '<img src="' + asset_path('synapse16.png') + '" alt="synapse icon" /><p>' + d
@synapselist += '</p></li>'
end
@mappers.each_with_index do |mapper, index|
@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 += '<p>' + mapper.name + '</p></li>'
end
end
%>
<div class="filterBox">
<h2>FILTER BY</h2>
<div id="filter_by_mapper" class="filterBySection">
<h3><%= @map ? "MAPPERS" : @topic ? "CREATORS" : "" %></h3>
<span class="hideAll hideAllMappers">NONE</span>
<span class="active showAll showAllMappers">ALL</span>
<div class="clearfloat"></div>
<ul>
<%= @mapperlist.html_safe %>
</ul>
<div class="clearfloat"></div>
</div>
<div id="filter_by_metacode" class="filterBySection">
<h3>METACODES</h3>
<span class="hideAll hideAllMetacodes">NONE</span>
<span class="active showAll showAllMetacodes">ALL</span>
<div class="clearfloat"></div>
<ul>
<%= @metacodelist.html_safe %>
</ul>
<div class="clearfloat"></div>
</div>
<div id="filter_by_synapse" class="filterBySection">
<h3>SYNAPSES</h3>
<span class="hideAll hideAllSynapses">NONE</span>
<span class="active showAll showAllSynapses">ALL</span>
<div class="clearfloat"></div>
<ul>
<%= @synapselist.html_safe %>
</ul>
<div class="clearfloat"></div>
</div>
</div> <!-- end .filterBox -->

View file

@ -9,12 +9,12 @@ const Mapper = Backbone.Model.extend({
toJSON: function(options) { toJSON: function(options) {
return _.omit(this.attributes, this.blacklist) return _.omit(this.attributes, this.blacklist)
}, },
prepareLiForFilter: function() { prepareDataForFilter: function() {
return outdent` return {
<li data-id="${this.id}"> id: this.id,
<img src="${this.get('image')}" data-id="${this.id}" alt="${this.get('name')}" /> image: this.get('image'),
<p>${this.get('name')}</p> name: this.get('name')
</li>` }
}, },
followMap: function(id) { followMap: function(id) {
const idIndex = this.get('follows').maps.indexOf(id) const idIndex = this.get('follows').maps.indexOf(id)

View file

@ -9,12 +9,12 @@ const Metacode = Backbone.Model.extend({
image.src = this.get('icon') image.src = this.get('icon')
this.set('image', image) this.set('image', image)
}, },
prepareLiForFilter: function() { prepareDataForFilter: function() {
return outdent` return {
<li data-id="${this.id}"> id: this.id,
<img src="${this.get('icon')}" data-id="${this.id}" alt="${this.get('name')}" /> name: this.get('name'),
<p>${this.get('name').toLowerCase()}</p> icon: this.get('icon')
</li>` }
} }
}) })

View file

@ -28,12 +28,11 @@ const Synapse = Backbone.Model.extend({
this.on('change', this.updateEdgeView) this.on('change', this.updateEdgeView)
this.on('change:desc', Filter.checkSynapses, this) this.on('change:desc', Filter.checkSynapses, this)
}, },
prepareLiForFilter: function() { prepareDataForFilter: function() {
return outdent` return {
<li data-id="${this.get('desc')}"> desc: this.get('desc'),
<img src="${DataModel.synapseIconUrl}" alt="synapse icon" /> icon: DataModel.synapseIconUrl
<p>${this.get('desc')}</p> }
</li>`
}, },
authorizeToEdit: function(mapper) { authorizeToEdit: function(mapper) {
if (mapper && (this.get('permission') === 'commons' || this.get('collaborator_ids').includes(mapper.get('id')) || this.get('user_id') === mapper.get('id'))) return true if (mapper && (this.get('permission') === 'commons' || this.get('collaborator_ids').includes(mapper.get('id')) || this.get('user_id') === mapper.get('id'))) return true

View file

@ -5,13 +5,17 @@ import _ from 'lodash'
import Active from './Active' import Active from './Active'
import Control from './Control' import Control from './Control'
import DataModel from './DataModel' import DataModel from './DataModel'
import GlobalUI from './GlobalUI' import GlobalUI, { ReactApp } from './GlobalUI'
import Settings from './Settings' import Settings from './Settings'
import Visualize from './Visualize' import Visualize from './Visualize'
const Filter = { const Filter = {
dataForPresentation: {
metacodes: [],
mappers: [],
synapses: []
},
filters: { filters: {
name: '',
metacodes: [], metacodes: [],
mappers: [], mappers: [],
synapses: [] synapses: []
@ -23,19 +27,6 @@ const Filter = {
}, },
isOpen: false, isOpen: false,
changing: false, changing: false,
init: function() {
var self = Filter
$('.sidebarFilterBox .showAllMetacodes').click(self.filterNoMetacodes)
$('.sidebarFilterBox .showAllSynapses').click(self.filterNoSynapses)
$('.sidebarFilterBox .showAllMappers').click(self.filterNoMappers)
$('.sidebarFilterBox .hideAllMetacodes').click(self.filterAllMetacodes)
$('.sidebarFilterBox .hideAllSynapses').click(self.filterAllSynapses)
$('.sidebarFilterBox .hideAllMappers').click(self.filterAllMappers)
self.bindLiClicks()
self.getFilterData()
},
toggleBox: function(event) { toggleBox: function(event) {
var self = Filter var self = Filter
@ -75,65 +66,24 @@ const Filter = {
}, },
reset: function() { reset: function() {
var self = Filter var self = Filter
self.filters.metacodes = [] self.filters.metacodes = []
self.filters.mappers = [] self.filters.mappers = []
self.filters.synapses = [] self.filters.synapses = []
self.visible.metacodes = [] self.visible.metacodes = []
self.visible.mappers = [] self.visible.mappers = []
self.visible.synapses = [] self.visible.synapses = []
self.dataForPresentation.metacodes = []
$('#filter_by_metacode ul').empty() self.dataForPresentation.mappers = []
$('#filter_by_mapper ul').empty() self.dataForPresentation.synapses = []
$('#filter_by_synapse ul').empty() ReactApp.render()
$('.filterBox .showAll').addClass('active')
},
/*
Most of this data essentially depends on the ruby function which are happening for filter inside view filterBox
But what these function do is load this data into three accessible array within java : metacodes, mappers and synapses
*/
getFilterData: function() {
var self = Filter
var metacode, mapper, synapse
$('#filter_by_metacode li').each(function() {
metacode = $(this).attr('data-id')
self.filters.metacodes.push(metacode)
self.visible.metacodes.push(metacode)
})
$('#filter_by_mapper li').each(function() {
mapper = ($(this).attr('data-id'))
self.filters.mappers.push(mapper)
self.visible.mappers.push(mapper)
})
$('#filter_by_synapse li').each(function() {
synapse = ($(this).attr('data-id'))
self.filters.synapses.push(synapse)
self.visible.synapses.push(synapse)
})
},
bindLiClicks: function() {
var self = Filter
$('#filter_by_metacode ul li').unbind().click(self.toggleMetacode)
$('#filter_by_mapper ul li').unbind().click(self.toggleMapper)
$('#filter_by_synapse ul li').unbind().click(self.toggleSynapse)
}, },
// an abstraction function for checkMetacodes, checkMappers, checkSynapses to reduce // an abstraction function for checkMetacodes, checkMappers, checkSynapses to reduce
// code redundancy // code redundancy
/*
@param
*/
updateFilters: function(collection, propertyToCheck, correlatedModel, filtersToUse, listToModify) { updateFilters: function(collection, propertyToCheck, correlatedModel, filtersToUse, listToModify) {
var self = Filter var self = Filter
var newList = [] var newList = []
var removed = [] var removed = []
var added = [] var added = []
// the first option enables us to accept // the first option enables us to accept
// ['Topics', 'Synapses'] as 'collection' // ['Topics', 'Synapses'] as 'collection'
if (typeof collection === 'object') { if (typeof collection === 'object') {
@ -166,41 +116,24 @@ const Filter = {
} }
}) })
} }
removed = _.difference(self.filters[filtersToUse], newList) removed = _.difference(self.filters[filtersToUse], newList)
added = _.difference(newList, self.filters[filtersToUse]) added = _.difference(newList, self.filters[filtersToUse])
// remove the list items for things no longer present on the map
_.each(removed, function(identifier) { _.each(removed, function(identifier) {
$('#filter_by_' + listToModify + ' li[data-id="' + identifier + '"]').fadeOut('fast', function() {
$(this).remove()
})
const index = self.visible[filtersToUse].indexOf(identifier) const index = self.visible[filtersToUse].indexOf(identifier)
self.visible[filtersToUse].splice(index, 1) self.visible[filtersToUse].splice(index, 1)
delete self.dataForPresentation[filtersToUse][identifier]
}) })
var model, li, jQueryLi
function sortAlpha(a, b) {
return a.childNodes[1].innerHTML.toLowerCase() > b.childNodes[1].innerHTML.toLowerCase() ? 1 : -1
}
// for each new filter to be added, create a list item for it and fade it in
_.each(added, function(identifier) { _.each(added, function(identifier) {
model = DataModel[correlatedModel].get(identifier) || const model = DataModel[correlatedModel].get(identifier) ||
DataModel[correlatedModel].find(function(model) { DataModel[correlatedModel].find(function(m) {
return model.get(propertyToCheck) === identifier return m.get(propertyToCheck) === identifier
}) })
li = model.prepareLiForFilter() self.dataForPresentation[filtersToUse][identifier] = model.prepareDataForFilter()
jQueryLi = $(li).hide()
$('li', '#filter_by_' + listToModify + ' ul').add(jQueryLi.fadeIn('fast'))
.sort(sortAlpha).appendTo('#filter_by_' + listToModify + ' ul')
self.visible[filtersToUse].push(identifier) self.visible[filtersToUse].push(identifier)
}) })
// update the list of filters with the new list we just generated // update the list of filters with the new list we just generated
self.filters[filtersToUse] = newList self.filters[filtersToUse] = newList
ReactApp.render()
// make sure clicks on list items still trigger the right events
self.bindLiClicks()
}, },
checkMetacodes: function() { checkMetacodes: function() {
var self = Filter var self = Filter
@ -219,114 +152,49 @@ const Filter = {
var self = Filter var self = Filter
self.updateFilters('Synapses', 'desc', 'Synapses', 'synapses', 'synapse') self.updateFilters('Synapses', 'desc', 'Synapses', 'synapses', 'synapse')
}, },
filterAllMetacodes: function(e) { filterAllMetacodes: function(toVisible) {
var self = Filter var self = Filter
$('#filter_by_metacode ul li').addClass('toggledOff') self.visible.metacodes = toVisible ? self.filters.metacodes.slice() : []
$('.showAllMetacodes').removeClass('active') ReactApp.render()
$('.hideAllMetacodes').addClass('active')
self.visible.metacodes = []
self.passFilters() self.passFilters()
}, },
filterNoMetacodes: function(e) { filterAllMappers: function(toVisible) {
var self = Filter var self = Filter
$('#filter_by_metacode ul li').removeClass('toggledOff') self.visible.mappers = toVisible ? self.filters.mappers.slice() : []
$('.showAllMetacodes').addClass('active') ReactApp.render()
$('.hideAllMetacodes').removeClass('active')
self.visible.metacodes = self.filters.metacodes.slice()
self.passFilters() self.passFilters()
}, },
filterAllMappers: function(e) { filterAllSynapses: function(toVisible) {
var self = Filter var self = Filter
$('#filter_by_mapper ul li').addClass('toggledOff') self.visible.synapses = toVisible ? self.filters.synapses.slice() : []
$('.showAllMappers').removeClass('active') ReactApp.render()
$('.hideAllMappers').addClass('active')
self.visible.mappers = []
self.passFilters()
},
filterNoMappers: function(e) {
var self = Filter
$('#filter_by_mapper ul li').removeClass('toggledOff')
$('.showAllMappers').addClass('active')
$('.hideAllMappers').removeClass('active')
self.visible.mappers = self.filters.mappers.slice()
self.passFilters()
},
filterAllSynapses: function(e) {
var self = Filter
$('#filter_by_synapse ul li').addClass('toggledOff')
$('.showAllSynapses').removeClass('active')
$('.hideAllSynapses').addClass('active')
self.visible.synapses = []
self.passFilters()
},
filterNoSynapses: function(e) {
var self = Filter
$('#filter_by_synapse ul li').removeClass('toggledOff')
$('.showAllSynapses').addClass('active')
$('.hideAllSynapses').removeClass('active')
self.visible.synapses = self.filters.synapses.slice()
self.passFilters() self.passFilters()
}, },
// an abstraction function for toggleMetacode, toggleMapper, toggleSynapse // an abstraction function for toggleMetacode, toggleMapper, toggleSynapse
// to reduce code redundancy // to reduce code redundancy
// gets called in the context of a list item in a filter box // gets called in the context of a list item in a filter box
toggleLi: function(whichToFilter) { toggleLi: function(whichToFilter, id) {
var self = Filter var self = Filter
var id = $(this).attr('data-id')
if (self.visible[whichToFilter].indexOf(id) === -1) { if (self.visible[whichToFilter].indexOf(id) === -1) {
self.visible[whichToFilter].push(id) self.visible[whichToFilter].push(id)
$(this).removeClass('toggledOff')
} else { } else {
const index = self.visible[whichToFilter].indexOf(id) const index = self.visible[whichToFilter].indexOf(id)
self.visible[whichToFilter].splice(index, 1) self.visible[whichToFilter].splice(index, 1)
$(this).addClass('toggledOff')
} }
ReactApp.render()
self.passFilters() self.passFilters()
}, },
toggleMetacode: function() { toggleMetacode: function(id) {
var self = Filter var self = Filter
self.toggleLi.call(this, 'metacodes') self.toggleLi('metacodes', id)
if (self.visible.metacodes.length === self.filters.metacodes.length) {
$('.showAllMetacodes').addClass('active')
$('.hideAllMetacodes').removeClass('active')
} else if (self.visible.metacodes.length === 0) {
$('.showAllMetacodes').removeClass('active')
$('.hideAllMetacodes').addClass('active')
} else {
$('.showAllMetacodes').removeClass('active')
$('.hideAllMetacodes').removeClass('active')
}
}, },
toggleMapper: function() { toggleMapper: function(id) {
var self = Filter var self = Filter
self.toggleLi.call(this, 'mappers') self.toggleLi('mappers', id)
if (self.visible.mappers.length === self.filters.mappers.length) {
$('.showAllMappers').addClass('active')
$('.hideAllMappers').removeClass('active')
} else if (self.visible.mappers.length === 0) {
$('.showAllMappers').removeClass('active')
$('.hideAllMappers').addClass('active')
} else {
$('.showAllMappers').removeClass('active')
$('.hideAllMappers').removeClass('active')
}
}, },
toggleSynapse: function() { toggleSynapse: function(id) {
var self = Filter var self = Filter
self.toggleLi.call(this, 'synapses') self.toggleLi('synapses', id)
if (self.visible.synapses.length === self.filters.synapses.length) {
$('.showAllSynapses').addClass('active')
$('.hideAllSynapses').removeClass('active')
} else if (self.visible.synapses.length === 0) {
$('.showAllSynapses').removeClass('active')
$('.hideAllSynapses').addClass('active')
} else {
$('.showAllSynapses').removeClass('active')
$('.hideAllSynapses').removeClass('active')
}
}, },
passFilters: function() { passFilters: function() {
var self = Filter var self = Filter

View file

@ -102,6 +102,7 @@ const ReactApp = {
}, },
self.getMapProps(), self.getMapProps(),
self.getTopicProps(), self.getTopicProps(),
self.getFilterProps(),
self.getMapsProps(), self.getMapsProps(),
self.getTopicCardProps(), self.getTopicCardProps(),
self.getChatProps()) self.getChatProps())
@ -121,8 +122,6 @@ const ReactApp = {
launchNewMap: Map.launch, launchNewMap: Map.launch,
toggleMapInfoBox: InfoBox.toggleBox, toggleMapInfoBox: InfoBox.toggleBox,
infoBoxHtml: InfoBox.html, infoBoxHtml: InfoBox.html,
toggleFilterBox: Filter.toggleBox,
filterBoxHtml: $('.filterBox')[0] && $('.filterBox')[0].outerHTML,
openImportLightbox: () => ImportDialog.show(), openImportLightbox: () => ImportDialog.show(),
forkMap: Map.fork, forkMap: Map.fork,
openHelpLightbox: () => self.openLightbox('cheatsheet'), openHelpLightbox: () => self.openLightbox('cheatsheet'),
@ -187,6 +186,21 @@ const ReactApp = {
handleInputMessage: ChatView.handleInputMessage handleInputMessage: ChatView.handleInputMessage
} }
}, },
getFilterProps: function() {
const self = ReactApp
return {
filterData: Filter.dataForPresentation,
toggleFilterBox: Filter.toggleBox,
allForFiltering: Filter.filters,
visibleForFiltering: Filter.visible,
toggleMetacode: Filter.toggleMetacode,
toggleMapper: Filter.toggleMapper,
toggleSynapse: Filter.toggleSynapse,
filterAllMetacodes: Filter.filterAllMetacodes,
filterAllMappers: Filter.filterAllMappers,
filterAllSynapses: Filter.filterAllSynapses
}
},
resize: function() { resize: function() {
const self = ReactApp const self = ReactApp
const maps = ExploreMaps.collection const maps = ExploreMaps.collection

View file

@ -92,7 +92,6 @@ const Map = {
const self = Map const self = Map
var start = function() { var start = function() {
Map.setAccessRequest() Map.setAccessRequest()
$('#filter_by_mapper h3').html('MAPPERS') // TODO: rewrite filter box in react
Visualize.type = 'ForceDirected' Visualize.type = 'ForceDirected'
JIT.prepareVizData() JIT.prepareVizData()
Filter.reset() Filter.reset()

View file

@ -1,16 +0,0 @@
import React, { Component, PropTypes } from 'react'
class FilterBox extends Component {
static propTypes = {
isMap: PropTypes.bool,
filterBoxHtml: PropTypes.string
}
render () {
const { filterBoxHtml } = this.props
const html = {__html: filterBoxHtml}
return <div className="sidebarFilterBox upperRightBox" dangerouslySetInnerHTML={html}></div>
}
}
export default FilterBox

View file

@ -1,6 +1,6 @@
import React, { Component, PropTypes } from 'react' import React, { Component, PropTypes } from 'react'
import FilterBox from './FilterBox' import FilterBox from '../common/FilterBox'
class MapButtons extends Component { class MapButtons extends Component {
static propTypes = { static propTypes = {
@ -9,11 +9,20 @@ class MapButtons extends Component {
onImportClick: PropTypes.func, onImportClick: PropTypes.func,
onForkClick: PropTypes.func, onForkClick: PropTypes.func,
onFilterClick: PropTypes.func, onFilterClick: PropTypes.func,
filterBoxHtml: PropTypes.string allForFiltering: PropTypes.object,
visibleForFiltering: PropTypes.object,
toggleMetacode: PropTypes.func,
toggleMapper: PropTypes.func,
toggleSynapse: PropTypes.func,
filterAllMetacodes: PropTypes.func,
filterAllMappers: PropTypes.func,
filterAllSynapses: PropTypes.func,
} }
render () { render () {
const { currentUser, canEditMap, filterBoxHtml, onFilterClick, onImportClick, onForkClick } = this.props const { currentUser, canEditMap, filterBoxHtml, onFilterClick, onImportClick, onForkClick,
filterData, allForFiltering, visibleForFiltering, toggleMetacode, toggleMapper, toggleSynapse,
filterAllMetacodes, filterAllMappers, filterAllSynapses } = this.props
return <div className="mapElement upperRightEl upperRightMapButtons upperRightUI"> return <div className="mapElement upperRightEl upperRightMapButtons upperRightUI">
{canEditMap && <div className="importDialog upperRightEl upperRightIcon mapElement" onClick={onImportClick}> {canEditMap && <div className="importDialog upperRightEl upperRightIcon mapElement" onClick={onImportClick}>
<div className="tooltipsUnder"> <div className="tooltipsUnder">
@ -24,7 +33,15 @@ class MapButtons extends Component {
<div className="sidebarFilterIcon upperRightIcon" onClick={onFilterClick}> <div className="sidebarFilterIcon upperRightIcon" onClick={onFilterClick}>
<div className="tooltipsUnder">Filter</div> <div className="tooltipsUnder">Filter</div>
</div> </div>
<FilterBox filterBoxHtml={filterBoxHtml} /> <FilterBox filterData={filterData}
allForFiltering={allForFiltering}
visibleForFiltering={visibleForFiltering}
toggleMetacode={toggleMetacode}
toggleMapper={toggleMapper}
toggleSynapse={toggleSynapse}
filterAllMetacodes={filterAllMetacodes}
filterAllMappers={filterAllMappers}
filterAllSynapses={filterAllSynapses} />
</div> </div>
{currentUser && <div className="sidebarFork upperRightEl"> {currentUser && <div className="sidebarFork upperRightEl">
<div className="sidebarForkIcon upperRightIcon" onClick={onForkClick}> <div className="sidebarForkIcon upperRightIcon" onClick={onForkClick}>

View file

@ -18,7 +18,15 @@ class MapView extends Component {
onMapStar: PropTypes.func, onMapStar: PropTypes.func,
onMapUnstar: PropTypes.func, onMapUnstar: PropTypes.func,
toggleFilterBox: PropTypes.func, toggleFilterBox: PropTypes.func,
filterBoxHtml: PropTypes.string, 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,
toggleMapInfoBox: PropTypes.func, toggleMapInfoBox: PropTypes.func,
infoBoxHtml: PropTypes.string, infoBoxHtml: PropTypes.string,
currentUser: PropTypes.object, currentUser: PropTypes.object,
@ -61,7 +69,9 @@ class MapView extends Component {
render = () => { render = () => {
const { mobile, map, currentUser, onOpen, onClose, const { mobile, map, currentUser, onOpen, onClose,
toggleMapInfoBox, toggleFilterBox, infoBoxHtml, filterBoxHtml, toggleMapInfoBox, infoBoxHtml, toggleFilterBox, allForFiltering, visibleForFiltering,
toggleMetacode, toggleMapper, toggleSynapse, filterAllMetacodes,
filterAllMappers, filterAllSynapses, filterData,
openImportLightbox, forkMap, openHelpLightbox, openImportLightbox, forkMap, openHelpLightbox,
mapIsStarred, onMapStar, onMapUnstar, mapIsStarred, onMapStar, onMapUnstar,
onZoomExtents, onZoomIn, onZoomOut, hasLearnedTopicCreation } = this.props onZoomExtents, onZoomIn, onZoomOut, hasLearnedTopicCreation } = this.props
@ -79,10 +89,18 @@ class MapView extends Component {
return <div className="mapWrapper"> return <div className="mapWrapper">
<MapButtons currentUser={currentUser} <MapButtons currentUser={currentUser}
onImportClick={openImportLightbox} onImportClick={openImportLightbox}
onFilterClick={toggleFilterBox}
onForkClick={forkMap} onForkClick={forkMap}
canEditMap={canEditMap} canEditMap={canEditMap}
filterBoxHtml={filterBoxHtml} /> onFilterClick={toggleFilterBox}
filterData={filterData}
allForFiltering={allForFiltering}
visibleForFiltering={visibleForFiltering}
toggleMetacode={toggleMetacode}
toggleMapper={toggleMapper}
toggleSynapse={toggleSynapse}
filterAllMetacodes={filterAllMetacodes}
filterAllMappers={filterAllMappers}
filterAllSynapses={filterAllSynapses} />
<DataVis /> <DataVis />
<TopicCard {...this.props} /> <TopicCard {...this.props} />
{currentUser && <Instructions mobile={mobile} hasLearnedTopicCreation={hasLearnedTopicCreation} />} {currentUser && <Instructions mobile={mobile} hasLearnedTopicCreation={hasLearnedTopicCreation} />}

View file

@ -0,0 +1,105 @@
import React, { Component, PropTypes } from 'react'
class FilterBox extends Component {
static propTypes = {
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
}
render () {
const { filterData, allForFiltering, visibleForFiltering, toggleMetacode, toggleMapper, toggleSynapse,
filterAllMetacodes, filterAllMappers, filterAllSynapses } = this.props
const mapperAllClass = "showAll showAllMappers"
+ (allForFiltering.mappers.length === visibleForFiltering.mappers.length ? ' active' : '')
const mapperNoneClass = "hideAll hideAllMappers"
+ (visibleForFiltering.mappers.length === 0 ? ' active' : '')
const metacodeAllClass = "showAll showAllMetacodes"
+ (allForFiltering.metacodes.length === visibleForFiltering.metacodes.length ? ' active' : '')
const metacodeNoneClass = "hideAll hideAllMetacodes"
+ (visibleForFiltering.metacodes.length === 0 ? ' active' : '')
const synapseAllClass = "showAll showAllSynapses"
+ (allForFiltering.synapses.length === visibleForFiltering.synapses.length ? ' active' : '')
const synapseNoneClass = "hideAll hideAllSynapses"
+ (visibleForFiltering.synapses.length === 0 ? ' active' : '')
return <div className="sidebarFilterBox upperRightBox">
<div className="filterBox">
<h2>FILTER BY</h2>
<div id="filter_by_mapper" className="filterBySection">
<h3>MAPPERS</h3>
<span className={mapperNoneClass} onClick={() => filterAllMappers()}>NONE</span>
<span className={mapperAllClass} onClick={() => filterAllMappers(true)}>ALL</span>
<div className="clearfloat"></div>
<ul>
{allForFiltering.mappers.map(m => {
const data = filterData.mappers[m]
const isVisible = visibleForFiltering.mappers.indexOf(m) > -1
return <Mapper visible={isVisible} id={m} image={data.image} name={data.name} toggle={toggleMapper} />
})}
</ul>
<div className="clearfloat"></div>
</div>
<div id="filter_by_metacode" className="filterBySection">
<h3>METACODES</h3>
<span className={metacodeNoneClass} onClick={() => filterAllMetacodes()}>NONE</span>
<span className={metacodeAllClass} onClick={() => filterAllMetacodes(true)}>ALL</span>
<div className="clearfloat"></div>
<ul>
{allForFiltering.metacodes.map(m => {
const data = filterData.metacodes[m]
const isVisible = visibleForFiltering.metacodes.indexOf(m) > -1
return <Metacode visible={isVisible} id={m} icon={data.icon} name={data.name} toggle={toggleMetacode} />
})}
</ul>
<div className="clearfloat"></div>
</div>
<div id="filter_by_synapse" className="filterBySection">
<h3>SYNAPSES</h3>
<span className={synapseNoneClass} onClick={() => filterAllSynapses()}>NONE</span>
<span className={synapseAllClass} onClick={() => filterAllSynapses(true)}>ALL</span>
<div className="clearfloat"></div>
<ul>
{allForFiltering.synapses.map(s => {
const data = filterData.synapses[s]
const isVisible = visibleForFiltering.synapses.indexOf(s) > -1
return <Synapse visible={isVisible} desc={s} icon={data.icon} toggle={toggleSynapse} />
})}
</ul>
<div className="clearfloat"></div>
</div>
</div>
</div>
}
}
function Mapper({ visible, name, id, image, toggle }) {
return <li onClick={() => toggle(id)} key={id} className={visible ? '' : 'toggledOff'}>
<img src={image} alt={name} />
<p>{name}</p>
</li>
}
function Metacode({ visible, name, id, icon, toggle }) {
return <li onClick={() => toggle(id)} key={id} className={visible ? '' : 'toggledOff'}>
<img src={icon} alt={name} />
<p>{name.toLowerCase()}</p>
</li>
}
function Synapse({ visible, desc, icon, toggle }) {
return <li onClick={() => toggle(desc)} key={desc} className={visible ? '' : 'toggledOff'}>
<img src={icon} alt="synapse icon" />
<p>{desc}</p>
</li>
}
export default FilterBox