move infobox template into react
Co-authored-by: Connor Turland <connorturland@gmail.com> Co-authored-by: Robert Best <chessscholar@gmail.com>
This commit is contained in:
parent
f941c1c362
commit
4cab56d653
8 changed files with 127 additions and 188 deletions
|
@ -125,53 +125,6 @@
|
|||
</script>
|
||||
|
||||
<div class="templates">
|
||||
<script type="text/template" id="mapInfoBoxTemplate">
|
||||
<div class="requestTitle">Click here to name this map</div>
|
||||
<div class="mapInfoName" id="mapInfoName">{{{name}}}</div>
|
||||
|
||||
<div class="mapInfoStat">
|
||||
<div class="infoStatIcon mapContributors hoverForTip">
|
||||
<img id="mapContribs" class="{{contributors_class}}"
|
||||
width="25" height="25" src="{{contributor_image}}" />
|
||||
<span class="count">{{contributor_count}}</span>
|
||||
<div class="tip">{{{contributor_list}}}</div>
|
||||
</div>
|
||||
<div class="infoStatIcon mapTopics">
|
||||
{{topic_count}}
|
||||
</div>
|
||||
<div class="infoStatIcon mapSynapses">
|
||||
{{synapse_count}}
|
||||
</div>
|
||||
<div class="infoStatIcon mapPermission {{permission}} hoverForTip">
|
||||
{{{map_creator_tip}}}
|
||||
</div>
|
||||
<div class="clearfloat"></div>
|
||||
</div>
|
||||
<div class="mapInfoDesc" id="mapInfoDesc">
|
||||
{{{desc}}}
|
||||
</div>
|
||||
|
||||
<div class="mapInfoMeta">
|
||||
<p class="mapCreatedAt"><span>Created by:</span> {{user_name}} on {{created_at}}</p>
|
||||
<p class="mapEditedAt"><span>Last edited:</span> {{updated_at}}</p>
|
||||
<div class="mapInfoButtonsWrapper">
|
||||
<div class="mapInfoThumbnail">
|
||||
<div class="thumbnail"></div>
|
||||
<div class="tooltip">Update Thumbnail</div>
|
||||
<span>Thumb</span>
|
||||
</div>
|
||||
<div class="mapInfoDelete">
|
||||
<div class="deleteMap"></div>
|
||||
<span>Delete</span>
|
||||
</div>
|
||||
<div class="mapInfoShare">
|
||||
<div class="mapInfoShareIcon"></div>
|
||||
<span>Share</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="topicSearchTemplate">
|
||||
<div class="result{{rtype}}">
|
||||
<div class="topicMetacode searchResIconWrapper">
|
||||
|
|
|
@ -29,7 +29,7 @@ const Cable = {
|
|||
},
|
||||
unsubscribeFromMap: () => {
|
||||
let self = Cable
|
||||
self.sub.unsubscribe()
|
||||
if (self.sub) self.sub.unsubscribe()
|
||||
delete self.sub
|
||||
},
|
||||
synapseAdded: event => {
|
||||
|
|
|
@ -140,7 +140,6 @@ const ReactApp = {
|
|||
endActiveMap: Map.end,
|
||||
launchNewMap: Map.launch,
|
||||
toggleMapInfoBox: InfoBox.toggleBox,
|
||||
infoBoxHtml: InfoBox.html,
|
||||
openImportLightbox: () => ImportDialog.show(),
|
||||
openMetacodeSwitcher: () => self.openLightbox('metacodeSwitcher'),
|
||||
forkMap: Map.fork,
|
||||
|
|
|
@ -11,46 +11,13 @@ import Util from '../Util'
|
|||
const InfoBox = {
|
||||
isOpen: false,
|
||||
selectingPermission: false,
|
||||
changePermissionText: "<div class='tooltips'>As the creator, you can change the permission of this map, and the permission of all the topics and synapses you have authority to change will change as well.</div>",
|
||||
nameHTML: outdent`
|
||||
<span class="best_in_place best_in_place_name"
|
||||
id="best_in_place_map_{{id}}_name"
|
||||
data-bip-url="/maps/{{id}}"
|
||||
data-bip-object="map"
|
||||
data-bip-attribute="name"
|
||||
data-bip-type="textarea"
|
||||
data-bip-activator="#mapInfoName"
|
||||
data-bip-value="{{name}}"
|
||||
>{{name}}</span>`,
|
||||
descHTML: outdent`
|
||||
<span class="best_in_place best_in_place_desc"
|
||||
id="best_in_place_map_{{id}}_desc"
|
||||
data-bip-url="/maps/{{id}}"
|
||||
data-bip-object="map"
|
||||
data-bip-attribute="desc"
|
||||
data-bip-nil="Click to add description..."
|
||||
data-bip-type="textarea"
|
||||
data-bip-activator="#mapInfoDesc"
|
||||
data-bip-value="{{desc}}"
|
||||
>{{desc}}</span>`,
|
||||
userImageUrl: '',
|
||||
html: '',
|
||||
init: function(serverData, updateThumbnail) {
|
||||
var self = InfoBox
|
||||
|
||||
self.updateThumbnail = updateThumbnail
|
||||
|
||||
$('.mapInfoBox').click(function(event) {
|
||||
event.stopPropagation()
|
||||
})
|
||||
$('body').click(self.close)
|
||||
|
||||
self.attachEventListeners()
|
||||
|
||||
self.generateBoxHTML = Hogan.compile($('#mapInfoBoxTemplate').html())
|
||||
|
||||
self.userImageUrl = serverData['user.png']
|
||||
|
||||
var querystring = window.location.search.replace(/^\?/, '')
|
||||
if (querystring === 'new') {
|
||||
self.open()
|
||||
|
@ -85,34 +52,7 @@ const InfoBox = {
|
|||
})
|
||||
},
|
||||
load: function() {
|
||||
var self = InfoBox
|
||||
|
||||
var map = Active.Map
|
||||
|
||||
var obj = map.pick('permission', 'topic_count', 'synapse_count')
|
||||
|
||||
var isCreator = map.authorizePermissionChange(Active.Mapper)
|
||||
var canEdit = map.authorizeToEdit(Active.Mapper)
|
||||
var relevantPeople = map.get('permission') === 'commons' ? DataModel.Mappers : DataModel.Collaborators
|
||||
var shareable = map.get('permission') !== 'private'
|
||||
|
||||
obj['name'] = canEdit ? Hogan.compile(self.nameHTML).render({id: map.id, name: map.get('name')}) : map.get('name')
|
||||
obj['desc'] = canEdit ? Hogan.compile(self.descHTML).render({id: map.id, desc: map.get('desc')}) : map.get('desc')
|
||||
obj['map_creator_tip'] = isCreator ? self.changePermissionText : ''
|
||||
|
||||
obj['contributor_count'] = relevantPeople.length
|
||||
obj['contributors_class'] = relevantPeople.length > 1 ? 'multiple' : ''
|
||||
obj['contributors_class'] += relevantPeople.length === 2 ? ' mTwo' : ''
|
||||
obj['contributor_image'] = relevantPeople.length > 0 ? relevantPeople.models[0].get('image') : self.userImageUrl
|
||||
obj['contributor_list'] = self.createContributorList()
|
||||
|
||||
obj['user_name'] = isCreator ? 'You' : map.get('user_name')
|
||||
obj['created_at'] = map.get('created_at_clean')
|
||||
obj['updated_at'] = map.get('updated_at_clean')
|
||||
|
||||
self.html = self.generateBoxHTML.render(obj)
|
||||
ReactApp.render()
|
||||
self.attachEventListeners()
|
||||
InfoBox.attachEventListeners()
|
||||
},
|
||||
attachEventListeners: function() {
|
||||
var self = InfoBox
|
||||
|
@ -238,7 +178,6 @@ const InfoBox = {
|
|||
DataModel.Collaborators.remove(DataModel.Collaborators.get(collaboratorId))
|
||||
var mapperIds = DataModel.Collaborators.models.map(function(mapper) { return mapper.id })
|
||||
$.post('/maps/' + Active.Map.id + '/access', { access: mapperIds })
|
||||
self.updateNumbers()
|
||||
},
|
||||
addCollaborator: function(newCollaboratorId) {
|
||||
var self = InfoBox
|
||||
|
@ -254,7 +193,6 @@ const InfoBox = {
|
|||
$.post('/maps/' + Active.Map.id + '/access', { access: mapperIds })
|
||||
var name = DataModel.Collaborators.get(newCollaboratorId).get('name')
|
||||
GlobalUI.notifyUser(name + ' will be notified')
|
||||
self.updateNumbers()
|
||||
}
|
||||
|
||||
$.getJSON('/users/' + newCollaboratorId + '.json', callback)
|
||||
|
@ -271,59 +209,6 @@ const InfoBox = {
|
|||
$('.mapInfoDesc .best_in_place_desc').html(desc)
|
||||
$('.mapInfoBox .mapPermission').removeClass('commons public private').addClass(perm)
|
||||
},
|
||||
createContributorList: function() {
|
||||
var relevantPeople = Active.Map.get('permission') === 'commons' ? DataModel.Mappers : DataModel.Collaborators
|
||||
var activeMapperIsCreator = Active.Mapper && Active.Mapper.id === Active.Map.get('user_id')
|
||||
var string = ''
|
||||
string += '<ul>'
|
||||
|
||||
relevantPeople.each(function(m) {
|
||||
var isCreator = Active.Map.get('user_id') === m.get('id')
|
||||
string += '<li><a href="/explore/mapper/' + m.get('id') + '">' + '<img class="rtUserImage" width="25" height="25" src="' + m.get('image') + '" />' + m.get('name')
|
||||
if (isCreator) string += ' (creator)'
|
||||
string += '</a>'
|
||||
if (activeMapperIsCreator && !isCreator) string += '<span class="removeCollaborator" data-id="' + m.get('id') + '"></span>'
|
||||
string += '</li>'
|
||||
})
|
||||
|
||||
string += '</ul>'
|
||||
|
||||
if (activeMapperIsCreator) {
|
||||
string += '<div class="collabSearchField"><span class="addCollab"></span><input class="collaboratorSearchField" placeholder="Add a collaborator"></input></div>'
|
||||
}
|
||||
return string
|
||||
},
|
||||
updateNumbers: function() {
|
||||
if (!Active.Map) return
|
||||
|
||||
const self = InfoBox
|
||||
|
||||
var relevantPeople = Active.Map.get('permission') === 'commons' ? DataModel.Mappers : DataModel.Collaborators
|
||||
|
||||
let contributorsClass = ''
|
||||
if (relevantPeople.length === 2) {
|
||||
contributorsClass = 'multiple mTwo'
|
||||
} else if (relevantPeople.length > 2) {
|
||||
contributorsClass = 'multiple'
|
||||
}
|
||||
|
||||
let contributorsImage = self.userImageUrl
|
||||
if (relevantPeople.length > 0) {
|
||||
// get the first contributor and use their image
|
||||
contributorsImage = relevantPeople.models[0].get('image')
|
||||
}
|
||||
$('.mapContributors img').attr('src', contributorsImage).removeClass('multiple mTwo').addClass(contributorsClass)
|
||||
$('.mapContributors span').text(relevantPeople.length)
|
||||
$('.mapContributors .tip').html(self.createContributorList())
|
||||
self.addTypeahead()
|
||||
$('.mapContributors .tip').unbind().click(function(event) {
|
||||
event.stopPropagation()
|
||||
})
|
||||
$('.mapTopics').text(DataModel.Topics.length)
|
||||
$('.mapSynapses').text(DataModel.Synapses.length)
|
||||
|
||||
$('.mapEditedAt').html('<span>Last edited: </span>' + Util.nowDateFormatted())
|
||||
},
|
||||
onPermissionClick: function(event) {
|
||||
var self = InfoBox
|
||||
|
||||
|
|
|
@ -94,7 +94,6 @@ const Map = {
|
|||
Visualize.type = 'ForceDirected'
|
||||
JIT.prepareVizData()
|
||||
Selected.reset()
|
||||
InfoBox.load()
|
||||
Filter.reset()
|
||||
Filter.checkMetacodes()
|
||||
Filter.checkSynapses()
|
||||
|
@ -104,13 +103,10 @@ const Map = {
|
|||
document.title = Active.Map.get('name') + ' | Metamaps'
|
||||
ReactApp.mobileTitle = Active.Map.get('name')
|
||||
ReactApp.render()
|
||||
}
|
||||
function isLoaded() {
|
||||
if (InfoBox.generateBoxHTML) dataIsReadySetupMap()
|
||||
else setTimeout(() => isLoaded(), 50)
|
||||
InfoBox.load()
|
||||
}
|
||||
if (Active.Map && Active.Map.id === id) {
|
||||
isLoaded()
|
||||
dataIsReadySetupMap()
|
||||
}
|
||||
else {
|
||||
Loading.show()
|
||||
|
@ -127,7 +123,7 @@ const Map = {
|
|||
DataModel.Stars = data.stars
|
||||
DataModel.attachCollectionEvents()
|
||||
self.requests = data.requests
|
||||
isLoaded()
|
||||
dataIsReadySetupMap()
|
||||
},
|
||||
error: function(res) {
|
||||
// forbidden
|
||||
|
|
|
@ -11,17 +11,16 @@ class InfoAndHelp extends Component {
|
|||
onHelpClick: PropTypes.func,
|
||||
onMapStar: PropTypes.func,
|
||||
onMapUnstar: PropTypes.func,
|
||||
onInfoClick: PropTypes.func,
|
||||
infoBoxhtml: PropTypes.string
|
||||
onInfoClick: PropTypes.func
|
||||
}
|
||||
|
||||
render () {
|
||||
const { mapIsStarred, map, currentUser, onInfoClick, infoBoxHtml, onMapStar, onMapUnstar, onHelpClick } = this.props
|
||||
const { mapIsStarred, map, currentUser, onInfoClick, onMapStar, onMapUnstar, onHelpClick } = this.props
|
||||
const starclassName = mapIsStarred ? 'starred' : ''
|
||||
const tooltip = mapIsStarred ? 'Unstar' : 'Star'
|
||||
const onStarClick = mapIsStarred ? onMapUnstar : onMapStar
|
||||
return <div className="infoAndHelp">
|
||||
{map && <MapInfoBox map={map} currentUser={currentUser} infoBoxHtml={infoBoxHtml} />}
|
||||
{map && <MapInfoBox map={map} currentUser={currentUser} />}
|
||||
{map && currentUser && <div className={`starMap infoElement mapElement ${starclassName}`} onClick={onStarClick}>
|
||||
<div className="tooltipsAbove">{tooltip}</div>
|
||||
</div>}
|
||||
|
|
|
@ -4,20 +4,129 @@ import PropTypes from 'prop-types'
|
|||
class MapInfoBox extends Component {
|
||||
static propTypes = {
|
||||
currentUser: PropTypes.object,
|
||||
map: PropTypes.object,
|
||||
infoBoxHtml: PropTypes.string
|
||||
map: PropTypes.object
|
||||
}
|
||||
|
||||
render () {
|
||||
const { currentUser, map, infoBoxHtml } = this.props
|
||||
createContributorList = () => {
|
||||
const { currentUser, map } = this.props
|
||||
var relevantPeople = [] // TODO: map.get('permission') === 'commons' ? DataModel.Mappers : DataModel.Collaborators
|
||||
var activeMapperIsCreator = currentUser && currentUser.id === map.get('user_id')
|
||||
return (
|
||||
<div>
|
||||
<ul>
|
||||
{relevantPeople.map((m) => {
|
||||
var isCreator = map.get('user_id') === m.get('id')
|
||||
return (
|
||||
<li>
|
||||
<a href={`/explore/mapper/${m.get('id')}`}>
|
||||
<img className="rtUserImage" width="25" height="25" src={m.get('image')} />
|
||||
{m.get('name')}
|
||||
{isCreator && ' (creator)'}
|
||||
</a>
|
||||
{activeMapperIsCreator && !isCreator && <span className="removeCollaborator" data-id={m.get('id')}></span>}
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
{activeMapperIsCreator && <div className="collabSearchField">
|
||||
<span className="addCollab"></span>
|
||||
<input className="collaboratorSearchField" placeholder="Add a collaborator" />
|
||||
</div>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
render = () => {
|
||||
const { currentUser, map } = this.props
|
||||
if (!map) return null
|
||||
const html = {__html: infoBoxHtml}
|
||||
const permission = map.get('permission')
|
||||
const topic_count = map.get('topic_count')
|
||||
const synapse_count = map.get('synapse_count')
|
||||
const isCreator = map.authorizePermissionChange(currentUser)
|
||||
const canEdit = map.authorizeToEdit(currentUser)
|
||||
const relevantPeople = [] // TODO: permission === 'commons' ? DataModel.Mappers : DataModel.Collaborators
|
||||
const shareable = permission !== 'private'
|
||||
|
||||
const contributor_count = relevantPeople.length
|
||||
let contributors_class = relevantPeople.length > 1 ? 'multiple' : ''
|
||||
contributors_class += relevantPeople.length === 2 ? ' mTwo' : ''
|
||||
const contributor_image = relevantPeople.length > 0 ? relevantPeople.models[0].get('image') : '/images/user.png'
|
||||
|
||||
const user_name = isCreator ? 'You' : map.get('user_name')
|
||||
const created_at = map.get('created_at_clean')
|
||||
const updated_at = map.get('updated_at_clean')
|
||||
|
||||
let classes = 'mapInfoBox mapElement mapElementHidden permission '
|
||||
classes += isCreator ? 'yourMap' : ''
|
||||
classes += canEdit ? ' canEdit' : ''
|
||||
return <div className={classes} dangerouslySetInnerHTML={html}></div>
|
||||
|
||||
return <div className={classes}>
|
||||
<div className="requestTitle">Click here to name this map</div>
|
||||
<div className="mapInfoName" id="mapInfoName">
|
||||
{canEdit ? <span className="best_in_place best_in_place_name"
|
||||
id={`best_in_place_map_${map.id}_name`}
|
||||
data-bip-url={`/maps/${map.id}`}
|
||||
data-bip-object="map"
|
||||
data-bip-attribute="name"
|
||||
data-bip-type="textarea"
|
||||
data-bip-activator="#mapInfoName"
|
||||
data-bip-value={map.get('name')}
|
||||
>{map.get('name')}</span> : map.get('name')}
|
||||
</div>
|
||||
|
||||
<div className="mapInfoStat">
|
||||
<div className="infoStatIcon mapContributors hoverForTip">
|
||||
<img id="mapContribs" className={contributors_class}
|
||||
width="25" height="25" src={contributor_image} />
|
||||
<span className="count">{contributor_count}</span>
|
||||
<div className="tip">{this.createContributorList()}</div>
|
||||
</div>
|
||||
<div className="infoStatIcon mapTopics">
|
||||
{topic_count}
|
||||
</div>
|
||||
<div className="infoStatIcon mapSynapses">
|
||||
{synapse_count}
|
||||
</div>
|
||||
<div className={`infoStatIcon mapPermission ${permission} hoverForTip`}>
|
||||
{isCreator && <div className='tooltips'>
|
||||
As the creator, you can change the permission of this map, and the permission of all the topics and synapses you have authority to change will change as well.
|
||||
</div>}
|
||||
</div>
|
||||
<div className="clearfloat"></div>
|
||||
</div>
|
||||
<div className="mapInfoDesc" id="mapInfoDesc">
|
||||
{canEdit ? <span className="best_in_place best_in_place_desc"
|
||||
id={`best_in_place_map_${map.id}_desc`}
|
||||
data-bip-url={`/maps/${map.id}`}
|
||||
data-bip-object="map"
|
||||
data-bip-attribute="desc"
|
||||
data-bip-nil="Click to add description..."
|
||||
data-bip-type="textarea"
|
||||
data-bip-activator="#mapInfoDesc"
|
||||
data-bip-value={map.get('desc')}
|
||||
>{map.get('desc')}</span> : map.get('desc')}
|
||||
</div>
|
||||
|
||||
<div className="mapInfoMeta">
|
||||
<p className="mapCreatedAt"><span>Created by:</span> {user_name} on {created_at}</p>
|
||||
<p className="mapEditedAt"><span>Last edited:</span> {updated_at}</p>
|
||||
<div className="mapInfoButtonsWrapper">
|
||||
<div className="mapInfoThumbnail">
|
||||
<div className="thumbnail"></div>
|
||||
<div className="tooltip">Update Thumbnail</div>
|
||||
<span>Thumb</span>
|
||||
</div>
|
||||
<div className="mapInfoDelete">
|
||||
<div className="deleteMap"></div>
|
||||
<span>Delete</span>
|
||||
</div>
|
||||
<div className="mapInfoShare">
|
||||
<div className="mapInfoShareIcon"></div>
|
||||
<span>Share</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@ export default class MapView extends Component {
|
|||
filterAllMappers: PropTypes.func,
|
||||
filterAllSynapses: PropTypes.func,
|
||||
toggleMapInfoBox: PropTypes.func,
|
||||
infoBoxHtml: PropTypes.string,
|
||||
currentUser: PropTypes.object,
|
||||
endActiveMap: PropTypes.func,
|
||||
launchNewMap: PropTypes.func,
|
||||
|
@ -78,7 +77,7 @@ export default class MapView extends Component {
|
|||
|
||||
render = () => {
|
||||
const { mobile, map, currentUser, onOpen, onClose,
|
||||
toggleMapInfoBox, infoBoxHtml, allForFiltering, visibleForFiltering,
|
||||
toggleMapInfoBox, allForFiltering, visibleForFiltering,
|
||||
toggleMetacode, toggleMapper, toggleSynapse, filterAllMetacodes,
|
||||
filterAllMappers, filterAllSynapses, filterData,
|
||||
openImportLightbox, forkMap, openHelpLightbox,
|
||||
|
@ -129,8 +128,7 @@ export default class MapView extends Component {
|
|||
onInfoClick={toggleMapInfoBox}
|
||||
onMapStar={onMapStar}
|
||||
onMapUnstar={onMapUnstar}
|
||||
onHelpClick={openHelpLightbox}
|
||||
infoBoxHtml={infoBoxHtml} />
|
||||
onHelpClick={openHelpLightbox} />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue