2016-09-26 13:37:42 +08:00
/* global Metamaps, $, Hogan, Bloodhound, Countable */
2016-04-14 14:01:21 +08:00
2016-10-07 17:26:20 +08:00
import outdent from 'outdent'
2016-09-23 08:05:26 +08:00
import Active from '../Active'
2016-09-22 23:51:13 +08:00
import GlobalUI from '../GlobalUI'
import Router from '../Router'
2016-09-23 14:12:27 +08:00
import Util from '../Util'
2016-09-22 18:31:56 +08:00
2016-04-14 14:01:21 +08:00
/ *
2016-09-22 23:51:13 +08:00
* Metamaps . Collaborators
* Metamaps . Erb
* Metamaps . Mappers
* Metamaps . Maps
* Metamaps . Synapses
* Metamaps . Topics
2016-04-14 14:01:21 +08:00
* /
2016-09-22 23:51:13 +08:00
const InfoBox = {
2016-04-14 14:01:21 +08:00
isOpen : false ,
changing : false ,
selectingPermission : false ,
2016-04-24 11:50:35 -04:00
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>" ,
2016-10-07 17:26:20 +08:00
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 } } < / s p a n > ` ,
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 } } < / s p a n > ` ,
2016-04-14 14:01:21 +08:00
init : function ( ) {
2016-09-22 23:51:13 +08:00
var self = InfoBox
2016-04-14 14:01:21 +08:00
$ ( '.mapInfoIcon' ) . click ( self . toggleBox )
$ ( '.mapInfoBox' ) . click ( function ( event ) {
event . stopPropagation ( )
} )
$ ( 'body' ) . click ( self . close )
2016-08-16 08:03:06 -04:00
self . attachEventListeners ( )
2016-04-24 11:50:35 -04:00
2016-04-14 14:01:21 +08:00
self . generateBoxHTML = Hogan . compile ( $ ( '#mapInfoBoxTemplate' ) . html ( ) )
2016-08-16 08:03:06 -04:00
var querystring = window . location . search . replace ( /^\?/ , '' )
if ( querystring == 'new' ) {
self . open ( )
2016-08-30 16:59:29 -04:00
$ ( '.mapInfoBox' ) . addClass ( 'mapRequestTitle' )
2016-10-02 22:49:45 -04:00
$ ( '#mapInfoName' ) . trigger ( 'click' )
$ ( '#mapInfoName textarea' ) . focus ( )
$ ( '#mapInfoName textarea' ) . select ( )
2016-08-16 08:03:06 -04:00
}
2016-04-14 14:01:21 +08:00
} ,
toggleBox : function ( event ) {
2016-09-22 23:51:13 +08:00
var self = InfoBox
2016-04-14 14:01:21 +08:00
if ( self . isOpen ) self . close ( )
else self . open ( )
event . stopPropagation ( )
} ,
open : function ( ) {
2016-09-22 23:51:13 +08:00
var self = InfoBox
2016-04-14 14:01:21 +08:00
$ ( '.mapInfoIcon div' ) . addClass ( 'hide' )
if ( ! self . isOpen && ! self . changing ) {
self . changing = true
$ ( '.mapInfoBox' ) . fadeIn ( 200 , function ( ) {
self . changing = false
self . isOpen = true
} )
}
} ,
close : function ( ) {
2016-09-22 23:51:13 +08:00
var self = InfoBox
2016-04-14 14:01:21 +08:00
$ ( '.mapInfoIcon div' ) . removeClass ( 'hide' )
if ( ! self . changing ) {
self . changing = true
$ ( '.mapInfoBox' ) . fadeOut ( 200 , function ( ) {
self . changing = false
self . isOpen = false
self . hidePermissionSelect ( )
$ ( '.mapContributors .tip' ) . hide ( )
} )
}
} ,
load : function ( ) {
2016-09-22 23:51:13 +08:00
var self = InfoBox
2016-04-14 14:01:21 +08:00
2016-09-22 18:31:56 +08:00
var map = Active . Map
2016-04-14 14:01:21 +08:00
2016-04-24 11:50:35 -04:00
var obj = map . pick ( 'permission' , 'topic_count' , 'synapse_count' )
2016-04-14 14:01:21 +08:00
2016-09-22 18:31:56 +08:00
var isCreator = map . authorizePermissionChange ( Active . Mapper )
var canEdit = map . authorizeToEdit ( Active . Mapper )
2016-04-24 11:50:35 -04:00
var relevantPeople = map . get ( 'permission' ) === 'commons' ? Metamaps . Mappers : Metamaps . Collaborators
2016-04-14 14:01:21 +08:00
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 : ''
2016-04-24 11:50:35 -04:00
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' ) : Metamaps . Erb [ 'user.png' ]
2016-04-14 14:01:21 +08:00
obj [ 'contributor_list' ] = self . createContributorList ( )
2016-04-24 11:50:35 -04:00
2016-04-14 14:01:21 +08:00
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' )
var classes = isCreator ? 'yourMap' : ''
classes += canEdit ? ' canEdit' : ''
classes += shareable ? ' shareable' : ''
$ ( '.mapInfoBox' ) . removeClass ( 'shareable yourMap canEdit' )
. addClass ( classes )
. html ( self . generateBoxHTML . render ( obj ) )
self . attachEventListeners ( )
} ,
attachEventListeners : function ( ) {
2016-09-22 23:51:13 +08:00
var self = InfoBox
2016-04-14 14:01:21 +08:00
$ ( '.mapInfoBox.canEdit .best_in_place' ) . best _in _place ( )
// because anyone who can edit the map can change the map title
var bipName = $ ( '.mapInfoBox .best_in_place_name' )
bipName . unbind ( 'best_in_place:activate' ) . bind ( 'best_in_place:activate' , function ( ) {
var $el = bipName . find ( 'textarea' )
var el = $el [ 0 ]
$el . attr ( 'maxlength' , '140' )
$ ( '.mapInfoName' ) . append ( '<div class="nameCounter forMap"></div>' )
var callback = function ( data ) {
$ ( '.nameCounter.forMap' ) . html ( data . all + '/140' )
}
Countable . live ( el , callback )
} )
bipName . unbind ( 'best_in_place:deactivate' ) . bind ( 'best_in_place:deactivate' , function ( ) {
$ ( '.nameCounter.forMap' ) . remove ( )
} )
$ ( '.mapInfoName .best_in_place_name' ) . unbind ( 'ajax:success' ) . bind ( 'ajax:success' , function ( ) {
var name = $ ( this ) . html ( )
2016-09-22 18:31:56 +08:00
Active . Map . set ( 'name' , name )
Active . Map . trigger ( 'saved' )
2016-08-17 10:00:37 -04:00
// mobile menu
$ ( '#header_content' ) . html ( name )
2016-08-30 16:59:29 -04:00
$ ( '.mapInfoBox' ) . removeClass ( 'mapRequestTitle' )
2016-10-02 22:49:45 -04:00
document . title = ` ${ name } | Metamaps `
window . history . replaceState ( '' , ` ${ name } | Metamaps ` , window . location . pathname )
2016-04-14 14:01:21 +08:00
} )
$ ( '.mapInfoDesc .best_in_place_desc' ) . unbind ( 'ajax:success' ) . bind ( 'ajax:success' , function ( ) {
var desc = $ ( this ) . html ( )
2016-09-22 18:31:56 +08:00
Active . Map . set ( 'desc' , desc )
Active . Map . trigger ( 'saved' )
2016-04-14 14:01:21 +08:00
} )
2016-10-08 16:42:34 +08:00
$ ( '.mapInfoDesc .best_in_place_desc, .mapInfoName .best_in_place_name' ) . unbind ( 'keypress' ) . keypress ( function ( e ) {
const ENTER = 13
if ( e . which === ENTER ) {
$ ( this ) . data ( 'bestInPlaceEditor' ) . update ( )
}
} )
2016-04-14 14:01:21 +08:00
$ ( '.yourMap .mapPermission' ) . unbind ( ) . click ( self . onPermissionClick )
// .yourMap in the unbind/bind is just a namespace for the events
// not a reference to the class .yourMap on the .mapInfoBox
$ ( '.mapInfoBox.yourMap' ) . unbind ( '.yourMap' ) . bind ( 'click.yourMap' , self . hidePermissionSelect )
$ ( '.yourMap .mapInfoDelete' ) . unbind ( ) . click ( self . deleteActiveMap )
$ ( '.mapContributors span, #mapContribs' ) . unbind ( ) . click ( function ( event ) {
$ ( '.mapContributors .tip' ) . toggle ( )
event . stopPropagation ( )
} )
$ ( '.mapContributors .tip' ) . unbind ( ) . click ( function ( event ) {
event . stopPropagation ( )
} )
2016-09-22 23:51:13 +08:00
$ ( '.mapContributors .tip li a' ) . click ( Router . intercept )
2016-04-14 14:01:21 +08:00
$ ( '.mapInfoBox' ) . unbind ( '.hideTip' ) . bind ( 'click.hideTip' , function ( ) {
$ ( '.mapContributors .tip' ) . hide ( )
} )
2016-04-24 11:50:35 -04:00
self . addTypeahead ( )
} ,
addTypeahead : function ( ) {
2016-09-22 23:51:13 +08:00
var self = InfoBox
2016-04-24 11:50:35 -04:00
2016-09-22 18:31:56 +08:00
if ( ! Active . Map ) return
2016-04-24 11:50:35 -04:00
// for autocomplete
var collaborators = {
name : 'collaborators' ,
limit : 9999 ,
display : function ( s ) { return s . label ; } ,
templates : {
notFound : function ( s ) {
return Hogan . compile ( $ ( '#collaboratorSearchTemplate' ) . html ( ) ) . render ( {
value : "No results" ,
label : "No results" ,
rtype : "noresult" ,
profile : Metamaps . Erb [ 'user.png' ] ,
} ) ;
} ,
suggestion : function ( s ) {
return Hogan . compile ( $ ( '#collaboratorSearchTemplate' ) . html ( ) ) . render ( s ) ;
} ,
} ,
source : new Bloodhound ( {
datumTokenizer : Bloodhound . tokenizers . obj . whitespace ( 'value' ) ,
queryTokenizer : Bloodhound . tokenizers . whitespace ,
remote : {
url : '/search/mappers?term=%QUERY' ,
wildcard : '%QUERY' ,
} ,
} )
}
// for adding map collaborators, who will have edit rights
2016-09-22 18:31:56 +08:00
if ( Active . Mapper && Active . Mapper . id === Active . Map . get ( 'user_id' ) ) {
2016-04-24 11:50:35 -04:00
$ ( '.collaboratorSearchField' ) . typeahead (
{
highlight : false ,
} ,
[ collaborators ]
)
$ ( '.collaboratorSearchField' ) . bind ( 'typeahead:select' , self . handleResultClick )
$ ( '.mapContributors .removeCollaborator' ) . click ( function ( ) {
self . removeCollaborator ( parseInt ( $ ( this ) . data ( 'id' ) ) )
} )
}
} ,
removeCollaborator : function ( collaboratorId ) {
2016-09-22 23:51:13 +08:00
var self = InfoBox
2016-04-24 11:50:35 -04:00
Metamaps . Collaborators . remove ( Metamaps . Collaborators . get ( collaboratorId ) )
var mapperIds = Metamaps . Collaborators . models . map ( function ( mapper ) { return mapper . id } )
2016-09-22 18:31:56 +08:00
$ . post ( '/maps/' + Active . Map . id + '/access' , { access : mapperIds } )
2016-04-24 11:50:35 -04:00
self . updateNumbers ( )
} ,
addCollaborator : function ( newCollaboratorId ) {
2016-09-22 23:51:13 +08:00
var self = InfoBox
2016-04-24 11:50:35 -04:00
if ( Metamaps . Collaborators . get ( newCollaboratorId ) ) {
2016-09-22 18:31:56 +08:00
GlobalUI . notifyUser ( 'That user already has access' )
2016-04-24 11:50:35 -04:00
return
}
function callback ( mapper ) {
Metamaps . Collaborators . add ( mapper )
var mapperIds = Metamaps . Collaborators . models . map ( function ( mapper ) { return mapper . id } )
2016-09-22 18:31:56 +08:00
$ . post ( '/maps/' + Active . Map . id + '/access' , { access : mapperIds } )
2016-09-26 13:37:42 +08:00
var name = Metamaps . Collaborators . get ( newCollaboratorId ) . get ( 'name' )
2016-09-22 18:31:56 +08:00
GlobalUI . notifyUser ( name + ' will be notified by email' )
2016-04-24 11:50:35 -04:00
self . updateNumbers ( )
}
$ . getJSON ( '/users/' + newCollaboratorId + '.json' , callback )
} ,
handleResultClick : function ( event , item ) {
2016-09-22 23:51:13 +08:00
var self = InfoBox
2016-04-24 11:50:35 -04:00
self . addCollaborator ( item . id )
$ ( '.collaboratorSearchField' ) . typeahead ( 'val' , '' )
2016-04-14 14:01:21 +08:00
} ,
updateNameDescPerm : function ( name , desc , perm ) {
2016-08-30 16:59:29 -04:00
$ ( '.mapInfoBox' ) . removeClass ( 'mapRequestTitle' )
2016-04-14 14:01:21 +08:00
$ ( '.mapInfoName .best_in_place_name' ) . html ( name )
$ ( '.mapInfoDesc .best_in_place_desc' ) . html ( desc )
$ ( '.mapInfoBox .mapPermission' ) . removeClass ( 'commons public private' ) . addClass ( perm )
} ,
createContributorList : function ( ) {
2016-09-22 23:51:13 +08:00
var self = InfoBox
2016-09-22 18:31:56 +08:00
var relevantPeople = Active . Map . get ( 'permission' ) === 'commons' ? Metamaps . Mappers : Metamaps . Collaborators
var activeMapperIsCreator = Active . Mapper && Active . Mapper . id === Active . Map . get ( 'user_id' )
2016-04-14 14:01:21 +08:00
var string = ''
string += '<ul>'
2016-04-24 11:50:35 -04:00
relevantPeople . each ( function ( m ) {
2016-09-22 18:31:56 +08:00
var isCreator = Active . Map . get ( 'user_id' ) === m . get ( 'id' )
2016-04-24 11:50:35 -04:00
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>'
2016-04-14 14:01:21 +08:00
} )
string += '</ul>'
2016-04-24 11:50:35 -04:00
if ( activeMapperIsCreator ) {
string += '<div class="collabSearchField"><span class="addCollab"></span><input class="collaboratorSearchField" placeholder="Add a collaborator!"></input></div>'
}
2016-04-14 14:01:21 +08:00
return string
} ,
updateNumbers : function ( ) {
2016-09-22 18:31:56 +08:00
if ( ! Active . Map ) return
2016-08-08 21:46:05 +08:00
2016-09-22 23:51:13 +08:00
var self = InfoBox
2016-09-22 18:31:56 +08:00
var mapper = Active . Mapper
var relevantPeople = Active . Map . get ( 'permission' ) === 'commons' ? Metamaps . Mappers : Metamaps . Collaborators
2016-04-14 14:01:21 +08:00
var contributors _class = ''
2016-04-24 11:50:35 -04:00
if ( relevantPeople . length === 2 ) contributors _class = 'multiple mTwo'
else if ( relevantPeople . length > 2 ) contributors _class = 'multiple'
2016-04-14 14:01:21 +08:00
2016-04-24 11:50:35 -04:00
var contributors _image = Metamaps . Erb [ 'user.png' ]
if ( relevantPeople . length > 0 ) {
2016-04-14 14:01:21 +08:00
// get the first contributor and use their image
2016-04-24 11:50:35 -04:00
contributors _image = relevantPeople . models [ 0 ] . get ( 'image' )
2016-04-14 14:01:21 +08:00
}
$ ( '.mapContributors img' ) . attr ( 'src' , contributors _image ) . removeClass ( 'multiple mTwo' ) . addClass ( contributors _class )
2016-04-24 11:50:35 -04:00
$ ( '.mapContributors span' ) . text ( relevantPeople . length )
2016-04-14 14:01:21 +08:00
$ ( '.mapContributors .tip' ) . html ( self . createContributorList ( ) )
2016-04-24 11:50:35 -04:00
self . addTypeahead ( )
$ ( '.mapContributors .tip' ) . unbind ( ) . click ( function ( event ) {
event . stopPropagation ( )
} )
2016-04-14 14:01:21 +08:00
$ ( '.mapTopics' ) . text ( Metamaps . Topics . length )
$ ( '.mapSynapses' ) . text ( Metamaps . Synapses . length )
2016-09-22 23:51:13 +08:00
$ ( '.mapEditedAt' ) . html ( '<span>Last edited: </span>' + Util . nowDateFormatted ( ) )
2016-04-14 14:01:21 +08:00
} ,
onPermissionClick : function ( event ) {
2016-09-22 23:51:13 +08:00
var self = InfoBox
2016-04-14 14:01:21 +08:00
if ( ! self . selectingPermission ) {
self . selectingPermission = true
$ ( this ) . addClass ( 'minimize' ) // this line flips the drop down arrow to a pull up arrow
if ( $ ( this ) . hasClass ( 'commons' ) ) {
$ ( this ) . append ( '<ul class="permissionSelect"><li class="public"></li><li class="private"></li></ul>' )
} else if ( $ ( this ) . hasClass ( 'public' ) ) {
$ ( this ) . append ( '<ul class="permissionSelect"><li class="commons"></li><li class="private"></li></ul>' )
} else if ( $ ( this ) . hasClass ( 'private' ) ) {
$ ( this ) . append ( '<ul class="permissionSelect"><li class="commons"></li><li class="public"></li></ul>' )
}
$ ( '.mapPermission .permissionSelect li' ) . click ( self . selectPermission )
event . stopPropagation ( )
}
} ,
hidePermissionSelect : function ( ) {
2016-09-22 23:51:13 +08:00
var self = InfoBox
2016-04-14 14:01:21 +08:00
self . selectingPermission = false
$ ( '.mapPermission' ) . removeClass ( 'minimize' ) // this line flips the pull up arrow to a drop down arrow
$ ( '.mapPermission .permissionSelect' ) . remove ( )
} ,
selectPermission : function ( event ) {
2016-09-22 23:51:13 +08:00
var self = InfoBox
2016-04-14 14:01:21 +08:00
self . selectingPermission = false
var permission = $ ( this ) . attr ( 'class' )
2016-09-22 18:31:56 +08:00
Active . Map . save ( {
2016-04-14 14:01:21 +08:00
permission : permission
} )
2016-09-22 18:31:56 +08:00
Active . Map . updateMapWrapper ( )
2016-10-04 23:38:32 +08:00
const shareable = permission === 'private' ? '' : 'shareable'
2016-04-14 14:01:21 +08:00
$ ( '.mapPermission' ) . removeClass ( 'commons public private minimize' ) . addClass ( permission )
$ ( '.mapPermission .permissionSelect' ) . remove ( )
$ ( '.mapInfoBox' ) . removeClass ( 'shareable' ) . addClass ( shareable )
event . stopPropagation ( )
} ,
deleteActiveMap : function ( ) {
var confirmString = 'Are you sure you want to delete this map? '
confirmString += 'This action is irreversible. It will not delete the topics and synapses on the map.'
2016-09-26 13:37:42 +08:00
var doIt = window . confirm ( confirmString )
2016-09-22 18:31:56 +08:00
var map = Active . Map
var mapper = Active . Mapper
2016-04-14 14:01:21 +08:00
var authorized = map . authorizePermissionChange ( mapper )
if ( doIt && authorized ) {
2016-09-22 23:51:13 +08:00
InfoBox . close ( )
2016-04-14 14:01:21 +08:00
Metamaps . Maps . Active . remove ( map )
Metamaps . Maps . Featured . remove ( map )
Metamaps . Maps . Mine . remove ( map )
2016-04-24 11:50:35 -04:00
Metamaps . Maps . Shared . remove ( map )
2016-04-14 14:01:21 +08:00
map . destroy ( )
2016-09-22 23:51:13 +08:00
Router . home ( )
2016-09-22 18:31:56 +08:00
GlobalUI . notifyUser ( 'Map eliminated!' )
2016-04-14 14:01:21 +08:00
}
else if ( ! authorized ) {
2016-10-04 23:38:32 +08:00
window . alert ( "Hey now. We can't just go around willy nilly deleting other people's maps now can we? Run off and find something constructive to do, eh?" )
2016-04-14 14:01:21 +08:00
}
}
2016-09-22 23:51:13 +08:00
}
2016-09-22 15:21:59 +08:00
2016-09-22 23:51:13 +08:00
export default InfoBox