solid-app-set
Version:
Solid-compatible App set
1,075 lines (1,040 loc) • 44.6 kB
JavaScript
/*
Microblog pane
Charles McKenzie <charles2@mit.edu>
*/
/* global alert */
var UI = require('solid-ui')
module.exports = {
icon: UI.icons.originalIconBase + 'microblog/microblog.png',
name: 'microblogPane',
label: function (subject) {
if (UI.store.whether(subject, UI.ns.rdf('type'), UI.ns.foaf('Person'))) {
return 'Microblog'
} else {
return null
}
},
render: function (s, doc) {
//* **********************************************
// NAMESPACES SECTION
//* **********************************************
var SIOC = UI.rdf.Namespace('http://rdfs.org/sioc/ns#')
var SIOCt = UI.rdf.Namespace('http://rdfs.org/sioc/types#')
var FOAF = UI.rdf.Namespace('http://xmlns.com/foaf/0.1/')
var terms = UI.rdf.Namespace('http://purl.org/dc/terms/')
var RDF = UI.ns.rdf
var kb = UI.store
var charCount = 140
var sf = UI.store.fetcher
//* **********************************************
// BACK END
//* **********************************************
var sparqlUpdater = kb.updater
// ----------------------------------------------
// FOLLOW LIST
// store the URIs of followed users for
// dereferencing the @replies
// ----------------------------------------------
var FollowList = function (user) {
this.userlist = {}
this.uris = {}
var myFollows = kb.each(kb.sym(user), SIOC('follows'))
for (var mf in myFollows) {
this.add(kb.any(myFollows[mf], SIOC('id')), myFollows[mf].uri)
}
}
FollowList.prototype.add = function (user, uri) {
// add a user to the follows store
if (this.userlist[user]) {
if (!(uri in this.uris)) {
this.userlist[user].push(uri)
this.uris[uri] = ''
}
} else {
this.userlist[user] = [uri]
}
}
FollowList.prototype.selectUser = function (user) {
// check if a user is in the follows list.
if (this.userlist[user]) {
return [(this.userlist[user].length === 1), this.userlist[user]]
} else {
// user does not follow any users with this nick
return [false, []]
}
}
// ----------------------------------------------
// FAVORITES
// controls the list of favorites.
// constructor expects a user as uri.
// ----------------------------------------------
var Favorites = function (user) {
this.favorites = {}
this.favoritesURI = ''
if (!user) { // TODO is this even useful?
return
}
this.user = user.split('#')[0]
let created = kb.each(kb.sym(user), SIOC('creator_of'))
for (let c in created) {
if (kb.whether(created[c], RDF('type'), SIOCt('FavouriteThings'))) {
this.favoritesURI = created[c]
var favs = kb.each(created[c], SIOC('container_of'))
for (var f in favs) {
this.favorites[favs[f]] = ''
}
break
}
}
}
Favorites.prototype.favorited = function (post) {
/* Favorited- returns true if the post is a favorite
false otherwise */
return (kb.sym(post) in this.favorites)
}
Favorites.prototype.add = function (post, callback) {
var batch = new UI.rdf.Statement(this.favoritesURI, SIOC('container_of'), kb.sym(post), kb.sym(this.user))
sparqlUpdater.insert_statement(batch,
function (a, success, c) {
if (success) {
kb.add(batch.subject, batch.predicate, batch.object, batch.why)
}
callback(a, success, c)
})
}
Favorites.prototype.remove = function (post, callback) {
var batch = new UI.rdf.Statement(this.favoritesURI, SIOC('container_of'), kb.sym(post), kb.sym(this.user))
sparqlUpdater.delete_statement(batch,
function (a, success, c) {
if (success) {
kb.add(batch.subject, batch.predicate, batch.object, batch.why)
}
callback(a, success, c)
})
}
// ----------------------------------------------
// MICROBLOG
// store the uri's of followed users for
// dereferencing the @replies.
// ----------------------------------------------
var Microblog = function (kb) {
this.kb = kb
// attempt to fetch user account from local preferences if just
// in case the user's foaf was not writable. add it to the store
// this will probably need to change.
var theUser = UI.authn.currentUser()
if (theUser) {
var theAccount = tabulator.preferences.get('acct')
if (theAccount) {
theAccount = kb.sym(theAccount)
}
if (theUser && theAccount) {
kb.add(theUser, FOAF('holdsAccount'), theAccount, theUser.uri.split('#')[0])
}
}
}
Microblog.prototype.getUser = function (uri) {
let User = {}
User.name = (kb.any(uri, SIOC('name'))) ? kb.any(uri, SIOC('name')) : ''
User.avatar = (kb.any(uri, SIOC('avatar'))) ? kb.any(uri, SIOC('avatar')) : ''
User.id = kb.any(uri, SIOC('id'))
User.sym = uri
return User
}
Microblog.prototype.getPost = function (uri) {
var Post = {}
// date ----------
var postLink = new Date(kb.anyValue(uri, terms('created')))
var h = postLink.getHours()
var a = (h > 12) ? ' PM' : ' AM'
h = (h > 12) ? (h - 12) : h
var m = postLink.getMinutes()
m = (m < 10) ? '0' + m : m
var mo = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
var da = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
var ds = da[postLink.getDay()] + ' ' + postLink.getDate() + ' ' + mo[postLink.getMonth()] + ' ' + postLink.getFullYear()
postLink = h + ':' + m + a + ' on ' + ds
Post.date = postLink
// ---------
Post.mentions = ''
Post.message = String(kb.any(uri, SIOC('content')))
Post.creator = kb.any(uri, SIOC('has_creator'))
Post.uri = ''
return Post
}
Microblog.prototype.gen_random_uri = function (base) {
// generate random uri
var uriNonce = base + '#n' + Math.floor(Math.random() * 10e+9)
return kb.sym(uriNonce)
}
Microblog.prototype.statusUpdate = function (statusMsg, callback, replyTo, meta) {
var myUserURI = this.getMyURI()
let myUser = kb.sym(myUserURI.split('#')[0])
var newPost = this.gen_random_uri(myUser.uri)
var microlist = kb.each(kb.sym(myUserURI), SIOC('creator_of'))
var micro
for (var microlistelement in microlist) {
if (kb.whether(microlist[microlistelement], RDF('type'), SIOCt('Microblog')) &&
!kb.whether(microlist[microlistelement], SIOC('topic'), kb.sym(this.getMyURI()))) {
micro = microlist[microlistelement]
break
}
}
// generate new post
var batch = [
new UI.rdf.Statement(newPost, RDF('type'), SIOCt('MicroblogPost'), myUser),
new UI.rdf.Statement(newPost, SIOC('has_creator'), kb.sym(myUserURI), myUser),
new UI.rdf.Statement(newPost, SIOC('content'), statusMsg, myUser),
new UI.rdf.Statement(newPost, terms('created'), new Date(), myUser),
new UI.rdf.Statement(micro, SIOC('container_of'), newPost, myUser)
]
// message replies
if (replyTo) {
batch.push(new UI.rdf.Statement(newPost, SIOC('reply_of'), kb.sym(replyTo), myUser))
}
// @replies, #hashtags, !groupReplies
for (var r in meta.recipients) {
batch.push(new UI.rdf.Statement(newPost, SIOC('topic'), kb.sym(meta.recipients[r]), myUser))
batch.push(new UI.rdf.Statement(kb.any(), SIOC('container_of'), newPost, myUser))
var mblogs = kb.each(kb.sym(meta.recipients[r]), SIOC('creator_of'))
for (var mbl in mblogs) {
if (kb.whether(mblogs[mbl], SIOC('topic'), kb.sym(meta.recipients[r]))) {
var replyBatch = new UI.rdf.Statement(
mblogs[mbl],
SIOC('container_of'),
newPost,
kb.sym(meta.recipients[r].split('#')[0]))
sparqlUpdater.insert_statement(replyBatch)
}
}
}
sparqlUpdater.insert_statement(batch,
function (a, b, c) {
callback(a, b, c, batch)
})
}
Microblog.prototype.getMyURI = function () {
var me = UI.authn.currentUser()
console.log(me)
var myMicroblog = kb.any(kb.sym(me), FOAF('holdsAccount'))
console.log('\n\n' + myMicroblog)
return (myMicroblog) ? myMicroblog.uri : false
}
Microblog.prototype.generateNewMB = function (id, name, avatar, loc) {
var host = loc + '/' + id
var rememberMicroblog = function () {
tabulator.preferences.set('acct', host + '#' + id)
}
var cbgenUserMB = function (a, success, c, d) {
if (success) {
alert('Microblog generated at ' + host + '#' + id +
'please add <b>' + host + '</b> to your foaf.')
// mbCancelNewMB() @@TBD
// assume the foaf is not writable and store the microblog to the
// preferences for later retrieval.
// this will probably need to change.
rememberMicroblog()
for (var triple in d) {
kb.add(d[triple].subject, d[triple].predicate, d[triple].object, d[triple].why)
}
}
}
var genUserMB = [
// user
new UI.rdf.Statement(kb.sym(host + '#' + id), RDF('type'), SIOC('User'), kb.sym(host)),
new UI.rdf.Statement(kb.sym(host + '#' + id), SIOC('creator_of'), kb.sym(host + '#mb'), kb.sym(host)),
new UI.rdf.Statement(kb.sym(host + '#' + id), SIOC('creator_of'), kb.sym(host + '#mbn'), kb.sym(host)),
new UI.rdf.Statement(kb.sym(host + '#' + id), SIOC('creator_of'), kb.sym(host + '#fav'), kb.sym(host)),
new UI.rdf.Statement(kb.sym(host + '#' + id), SIOC('name'), name, kb.sym(host)),
new UI.rdf.Statement(kb.sym(host + '#' + id), SIOC('id'), id, kb.sym(host)),
new UI.rdf.Statement(kb.sym(host + '#' + id), RDF('label'), id, kb.sym(host)),
new UI.rdf.Statement(s, FOAF('holdsAccount'), kb.sym(host + '#' + id), kb.sym(host)),
// microblog
new UI.rdf.Statement(kb.sym(host + '#mb'), RDF('type'), SIOCt('Microblog'), kb.sym(host)),
new UI.rdf.Statement(kb.sym(host + '#mb'), SIOC('has_creator'), kb.sym(host + '#' + id), kb.sym(host)),
// notification microblog
new UI.rdf.Statement(kb.sym(host + '#mbn'), RDF('type'), SIOCt('Microblog'), kb.sym(host)),
new UI.rdf.Statement(kb.sym(host + '#mbn'), SIOC('topic'), kb.sym(host + '#' + id), kb.sym(host)),
new UI.rdf.Statement(kb.sym(host + '#mbn'), SIOC('has_creator'), kb.sym(host + '#' + id), kb.sym(host)),
// favorites container
new UI.rdf.Statement(kb.sym(host + '#fav'), RDF('type'), SIOCt('FavouriteThings'), kb.sym(host)),
new UI.rdf.Statement(kb.sym(host + '#fav'), SIOC('has_creator'), kb.sym(host + '#' + id), kb.sym(host))
]
if (avatar) {
// avatar optional
genUserMB.push(new UI.rdf.Statement(kb.sym(host + '#' + id), SIOC('avatar'), kb.sym(avatar), kb.sym(host)))
}
sparqlUpdater.insert_statement(genUserMB, cbgenUserMB)
}
var mb = new Microblog(kb)
var myFavorites = new Favorites(mb.getMyURI())
var myFollowList = new FollowList(mb.getMyURI())
//* **********************************************
// FRONT END FUNCTIONALITY
//* **********************************************
// ----------------------------------------------
// PANE
// User Interface for the Microblog Pane
// ----------------------------------------------
var Pane = function (s, doc, microblogPane) {
var TabManager = function (doc) {
this.tablist = {}
this.doc = doc
this.tabView = doc.createElement('ul')
this.tabView.className = 'tabslist'
}
TabManager.prototype.create = function (id, caption, view, isDefault) {
var tab = this.doc.createElement('li')
tab.innerHTML = caption
if (isDefault) { tab.className = 'active' }
tab.id = id
let change = this.change
let tablist = this.tablist
tab.addEventListener('click', function (evt) { change(evt.target.id, tablist, doc) }, false)
this.tablist[id] = {'view': view.id, 'tab': tab}
this.tabView.appendChild(tab)
}
TabManager.prototype.getTabView = function () {
return this.tabView
}
TabManager.prototype.change = function (id, tablist, doc) {
for (var tab in tablist) {
if (tab === id) {
tablist[id]['tab'].className = 'active'
doc.getElementById(tablist[id]['view']).className += ' active'
} else {
var view = doc.getElementById(tablist[tab].view)
view.className = view.className.replace(/\w*active\w*/, '')
tablist[tab].tab.className = tablist[id].tab.className.replace(/\w*active\w*/, '')
}
}
}
this.microblogPane = microblogPane
var accounts = kb.each(s, FOAF('holdsAccount'))
for (var a in accounts) {
if (kb.whether(accounts[a], RDF('type'), SIOC('User')) &&
kb.whether(kb.any(accounts[a], SIOC('creator_of')), RDF('type'), SIOCt('Microblog'))) {
var account = accounts[a]
break
}
}
this.Ifollow = kb.whether(kb.sym(mb.getMyURI()), SIOC('follows'), account)
var resourceType = kb.any(s, RDF('type'))
if (resourceType.uri === SIOCt('Microblog').uri || resourceType.uri === SIOCt('MicroblogPost').uri) {
this.thisIsMe = (kb.any(s, SIOC('has_creator')).uri === mb.getMyURI())
} else if (resourceType.uri === SIOC('User').uri) {
this.thisIsMe = (s.uri === mb.getMyURI())
} else if (resourceType.uri === FOAF('Person').uri) {
let me = UI.authn.currentUser()
let meUri = me && me.uri
this.thisIsMe = (s.uri === meUri)
} else {
this.thisIsMe = false
}
this.Tab = new TabManager(doc)
}
Pane.prototype.notify = function (messageString) {
var xmsg = doc.createElement('li')
xmsg.className = 'notify'
xmsg.innerHTML = messageString
doc.getElementById('notify-container').appendChild(xmsg)
setTimeout(function () {
doc.getElementById('notify-container').removeChild(xmsg)
// delete xmsg;
},
4000)
}
Pane.prototype.header = function (s, doc) {
var that = this
function lsFollowUser () {
var myUser = kb.sym(mb.getMyURI())
// var Ifollow = that.Ifollow
var username = that.creator.name
var mbconfirmFollow = function (uri, success, msg) {
if (success === true) {
if (!that.Ifollow) {
// prevent duplicate entries from being added to kb (because that was happening)
if (!kb.whether(followMe.subject, followMe.predicate, followMe.object, followMe.why)) {
kb.add(followMe.subject, followMe.predicate, followMe.object, followMe.why)
}
} else {
kb.removeMany(followMe.subject, followMe.predicate, followMe.object, followMe.why)
}
console.log(that.Ifollow)
that.Ifollow = !that.Ifollow
xfollowButton.disabled = false
console.log(that.Ifollow)
var followButtonLabel = (that.Ifollow) ? 'Unfollow ' : 'Follow '
var doFollow = (that.Ifollow) ? 'now follow ' : 'no longer follow '
xfollowButton.value = followButtonLabel + username
that.notify('You ' + doFollow + username + '.')
}
}
var followMe = new UI.rdf.Statement(myUser, SIOC('follows'), that.creator.sym, myUser)
xfollowButton.disabled = true
xfollowButton.value = 'Updating...'
if (!that.Ifollow) {
sparqlUpdater.insert_statement(followMe, mbconfirmFollow)
} else {
sparqlUpdater.delete_statement(followMe, mbconfirmFollow)
}
}
var notify = function (messageString) {
var xmsg = doc.createElement('li')
xmsg.className = 'notify'
xmsg.innerHTML = messageString
doc.getElementById('notify-container').appendChild(xmsg)
setTimeout(function () {
doc.getElementById('notify-container').removeChild(xmsg)
// delete xmsg;
},
4000)
}
var mbCancelNewMB = function (evt) {
xupdateContainer.removeChild(xupdateContainer.childNodes[xupdateContainer.childNodes.length - 1])
xcreateNewMB.disabled = false
}
var lsCreateNewMB = function (evt) {
// disable the create new microblog button.
// then prefills the information.
xcreateNewMB.disabled = true
var xcmb = doc.createElement('div')
var xcmbName = doc.createElement('input')
if (kb.whether(s, FOAF('name'))) {
// handle use of FOAF:NAME
xcmbName.value = kb.any(s, FOAF('name'))
} else {
// handle use of family and given name
xcmbName.value = (kb.any(s, FOAF('givenname')))
? kb.any(s, FOAF('givenname')) + ' ' : ''
xcmbName.value += (kb.any(s, FOAF('family_name')))
? kb.any(s, FOAF('givenname')) : ''
xcmbName.value = kb.any(s, FOAF('givenname')) + ' ' +
kb.any(s, FOAF('family_name'))
}
var xcmbId = doc.createElement('input')
xcmbId.value = (kb.any(s, FOAF('nick'))) ? kb.any(s, FOAF('nick')) : ''
var xcmbAvatar = doc.createElement('input')
if (kb.whether(s, FOAF('img'))) {
// handle use of img
xcmbAvatar.value = kb.any(s, FOAF('img')).uri
} else {
// otherwise try depiction
xcmbAvatar.value = (kb.any(s, FOAF('depiction')))
? kb.any(s, FOAF('depiction')).uri : ''
}
var workspace
// = kb.any(s,WORKSPACE) //TODO - ADD URI FOR WORKSPACE DEFINITION
var xcmbWritable = doc.createElement('input')
xcmbWritable.value = workspace || 'http://dig.csail.mit.edu/2007/wiki/sandbox' // @@@
xcmb.innerHTML = `
<form class ="createNewMB" id="createNewMB">
<p id="xcmbname"><span class="">Name: </span></p>
<p id="xcmbid">Id: </p>
<p id="xcmbavatar">Avatar: </p>
<p id="xcmbwritable">Host my microblog at: </p>
<input type="button" id="mbCancel" value="Cancel" />
<input type="submit" id="mbCreate" value="Create!" />
</form>
`
xupdateContainer.appendChild(xcmb)
doc.getElementById('xcmbname').appendChild(xcmbName)
doc.getElementById('xcmbid').appendChild(xcmbId)
doc.getElementById('xcmbavatar').appendChild(xcmbAvatar)
doc.getElementById('xcmbwritable').appendChild(xcmbWritable)
doc.getElementById('mbCancel').addEventListener('click', mbCancelNewMB, false)
doc.getElementById('createNewMB').addEventListener('submit', function () {
mb.generateNewMB(xcmbId.value, xcmbName.value, xcmbAvatar.value, xcmbWritable.value)
}, false)
xcmbName.focus()
}
var mbSubmitPost = function () {
var meta = {
recipients: []
}
// user has selected a microblog to post to
if (mb.getMyURI()) {
// let myUser = kb.sym(mb.getMyURI())
// submission callback
var cbconfirmSubmit = function (uri, success, responseText, d) {
if (success === true) {
for (var triple in d) {
kb.add(d[triple].subject, d[triple].predicate, d[triple].object, d[triple].why)
}
xupdateSubmit.disabled = false
xupdateStatus.value = ''
mbLetterCount()
notify('Microblog Updated.')
if (that.thisIsMe) {
doc.getElementById('postNotificationList').insertBefore(that.generatePost(d[0].subject), doc.getElementById('postNotificationList').childNodes[0])
}
} else {
notify('There was a problem submitting your post.')
}
}
var words = xupdateStatus.value.split(' ')
var mbUpdateWithReplies = function () {
xupdateSubmit.disabled = true
xupdateSubmit.value = 'Updating...'
mb.statusUpdate(xupdateStatus.value, cbconfirmSubmit, xinReplyToContainer.value, meta)
}
for (var word in words) {
if (words[word].match(/@\w+/)) {
var atUser = words[word].replace(/\W/g, '')
var recipient = myFollowList.selectUser(atUser)
if (recipient[0] === true) {
meta.recipients.push(recipient[1][0])
} else if (recipient[1].length > 1) {
// if multiple users allow the user to choose
var xrecipients = doc.createElement('select')
var xrecipientsSubmit = doc.createElement('input')
xrecipientsSubmit.type = 'button'
xrecipientsSubmit.value = 'Continue'
xrecipientsSubmit.addEventListener('click',
function () {
meta.recipients.push(recipient[1][xrecipients.value])
mbUpdateWithReplies()
xrecipients.parentNode.removeChild(xrecipientsSubmit)
xrecipients.parentNode.removeChild(xrecipients)
},
false)
var recipChoice = function (recip, c) {
var name = kb.any(kb.sym(recip), SIOC('name'))
var choice = doc.createElement('option')
choice.value = c
choice.innerHTML = name
return choice
}
for (var r in recipient[1]) {
xrecipients.appendChild(recipChoice(recipient[1][r], r))
}
xupdateContainer.appendChild(xrecipients)
xupdateContainer.appendChild(xrecipientsSubmit)
return
} else {
// no users known or self reference.
if (String(kb.any(kb.sym(mb.getMyURI()), SIOC('id'))).toLowerCase() === atUser.toLowerCase()) {
meta.recipients.push(mb.getMyURI())
} else {
notify('You do not follow ' + atUser + '. Try following ' + atUser + ' before mentioning them.')
return
}
}
}
/* else if(words[word].match(/\#\w+/)){
//hashtag
} else if(words[word].match(/\!\w+/)){
//usergroup
} */
}
mbUpdateWithReplies()
} else {
notify('Please set your microblog first.')
}
}
var mbLetterCount = function () {
xupdateStatusCounter.innerHTML = charCount - xupdateStatus.value.length
xupdateStatusCounter.style.color = (charCount - xupdateStatus.value.length < 0) ? '#c33' : ''
if (xupdateStatus.value.length === 0) {
xinReplyToContainer.value = ''
xupdateSubmit.value = 'Send'
}
}
// reply viewer
var xviewReply = doc.createElement('ul')
xviewReply.className = 'replyView'
xviewReply.addEventListener('click', function () {
xviewReply.className = 'replyView'
}, false)
this.xviewReply = xviewReply
var headerContainer = doc.createElement('div')
headerContainer.className = 'header-container'
// ---create status update box---
var xnotify = doc.createElement('ul')
xnotify.id = 'notify-container'
xnotify.className = 'notify-container'
this.xnotify = xnotify
var xupdateContainer = doc.createElement('form')
xupdateContainer.className = 'update-container'
xupdateContainer.innerHTML = '<h3>What are you up to?</h3>'
if (mb.getMyURI()) {
var xinReplyToContainer = doc.createElement('input')
xinReplyToContainer.id = 'xinReplyToContainer'
xinReplyToContainer.type = 'hidden'
var xupdateStatus = doc.createElement('textarea')
xupdateStatus.id = 'xupdateStatus'
var xupdateStatusCounter = doc.createElement('span')
xupdateStatusCounter.appendChild(doc.createTextNode(charCount))
xupdateStatus.cols = 30
xupdateStatus.addEventListener('keyup', mbLetterCount, false)
xupdateStatus.addEventListener('focus', mbLetterCount, false)
var xupdateSubmit = doc.createElement('input')
xupdateSubmit.id = 'xupdateSubmit'
xupdateSubmit.type = 'submit'
xupdateSubmit.value = 'Send'
xupdateContainer.appendChild(xinReplyToContainer)
xupdateContainer.appendChild(xupdateStatusCounter)
xupdateContainer.appendChild(xupdateStatus)
xupdateContainer.appendChild(xupdateSubmit)
xupdateContainer.addEventListener('submit', mbSubmitPost, false)
} else {
var xnewUser = doc.createTextNode(
'Hi, it looks like you don\'t have a microblog, ' +
' would you like to create one? ')
var xcreateNewMB = doc.createElement('input')
xcreateNewMB.type = 'button'
xcreateNewMB.value = 'Create a new Microblog'
xcreateNewMB.addEventListener('click', lsCreateNewMB, false)
xupdateContainer.appendChild(xnewUser)
xupdateContainer.appendChild(xcreateNewMB)
}
headerContainer.appendChild(xupdateContainer)
var subheaderContainer = doc.createElement('div')
subheaderContainer.className = 'subheader-container'
// user header
// this.creator
var creators = kb.each(s, FOAF('holdsAccount'))
for (var c in creators) {
if (kb.whether(creators[c], RDF('type'), SIOC('User')) &&
kb.whether(kb.any(creators[c], SIOC('creator_of')), RDF('type'), SIOCt('Microblog'))) {
var creator = creators[c]
// var mb = kb.sym(creator.uri.split("#")[0]);
// UI.store.fetcher.refresh(mb);
break
// TODO add support for more than one microblog in same foaf
}
}
if (creator) {
this.creator = mb.getUser(creator)
// ---display avatar, if available ---
if (this.creator.avatar !== '') {
var avatar = doc.createElement('img')
avatar.src = this.creator.avatar.uri
subheaderContainer.appendChild(avatar)
}
// ---generate name ---
var userName = doc.createElement('h1')
userName.className = 'fn'
userName.appendChild(doc.createTextNode(this.creator.name + ' (' + this.creator.id + ')'))
subheaderContainer.appendChild(userName)
// ---display follow button---
if (!this.thisIsMe && mb.getMyURI()) {
var xfollowButton = doc.createElement('input')
xfollowButton.setAttribute('type', 'button')
let followButtonLabel = (this.Ifollow) ? 'Unfollow ' : 'Follow '
xfollowButton.value = followButtonLabel + this.creator.name
xfollowButton.addEventListener('click', lsFollowUser, false)
subheaderContainer.appendChild(xfollowButton)
}
// user header end
// header tabs
var xtabsList = this.Tab.getTabView()
headerContainer.appendChild(subheaderContainer)
headerContainer.appendChild(xtabsList)
}
return headerContainer
}
Pane.prototype.generatePost = function (post, me) {
/*
generatePost - Creates and formats microblog posts
post - symbol of the uri the post in question
*/
var that = this
var viewPost = function (uris) {
let xviewReply = that.xviewReply
for (let i = 0; i < xviewReply.childNodes.length; i++) {
xviewReply.removeChild(xviewReply.childNodes[0])
}
var xcloseContainer = doc.createElement('li')
xcloseContainer.className = 'closeContainer'
var xcloseButton = doc.createElement('span')
xcloseButton.innerHTML = '×'
xcloseButton.className = 'closeButton'
xcloseContainer.appendChild(xcloseButton)
xviewReply.appendChild(xcloseContainer)
for (var uri in uris) {
xviewReply.appendChild(that.generatePost(kb.sym(uris[uri]), this.thisIsMe, 'view'))
}
xviewReply.className = 'replyView-active'
that.microblogPane.appendChild(xviewReply)
}
// container for post
var xpost = doc.createElement('li')
xpost.className = 'post'
xpost.setAttribute('id', String(post.uri).split('#')[1])
var Post = mb.getPost(post)
// username text
// var uname = kb.any(kb.any(post, SIOC('has_creator')), SIOC('id'))
var uholdsaccount = kb.any(undefined, FOAF('holdsAccount'), kb.any(post, SIOC('has_creator')))
var xuname = doc.createElement('a')
xuname.href = uholdsaccount.uri
xuname.className = 'userLink'
var xunameText = doc.createTextNode(mb.getUser(Post.creator).id)
xuname.appendChild(xunameText)
// user image
var xuavatar = doc.createElement('img')
xuavatar.src = mb.getUser(Post.creator).avatar.uri
xuavatar.className = 'postAvatar'
// post content
var xpostContent = doc.createElement('blockquote')
var postText = Post.message
// post date
var xpostLink = doc.createElement('a')
xpostLink.className = 'postLink'
xpostLink.addEventListener('click',
function () {
viewPost([post.uri])
},
false)
xpostLink.id = 'post_' + String(post.uri).split('#')[1]
xpostLink.setAttribute('content', post.uri)
xpostLink.setAttribute('property', 'permalink')
let postLink = doc.createTextNode((Post.date) ? Post.date : 'post date unknown')
xpostLink.appendChild(postLink)
// LINK META DATA (MENTIONS, HASHTAGS, GROUPS)
var mentions = kb.each(post, SIOC('topic'))
let tags = {}
for (var mention in mentions) {
sf.lookUpThing(mentions[mention])
let id = kb.any(mentions[mention], SIOC('id'))
tags['@' + id] = mentions[mention]
}
var postTags = postText.match(/(@|#|!)\w+/g)
var postFunction = function () {
let p = postTags.pop()
return (tags[p]) ? kb.any(undefined, FOAF('holdsAccount'), tags[p]).uri : p
}
for (var t in tags) {
var person = t.replace(/@/, '')
var replacePerson = RegExp('(@|!|#)(' + person + ')')
postText = postText.replace(replacePerson, '$1<a href="' + postFunction() + '">$2</a>')
}
xpostContent.innerHTML = postText
// in reply to logic
// This has the potential to support a post that replies to many messages.
var inReplyTo = kb.each(post, SIOC('reply_of'))
var xreplyTo = doc.createElement('span')
for (var reply in inReplyTo) {
var theReply
theReply = String(inReplyTo[reply]).replace(/<|>/g, '')
var genReplyTo = function () {
var reply = doc.createElement('a')
reply.innerHTML = ', <b>in reply to</b>'
reply.addEventListener('click',
function () {
viewPost([post.uri, theReply])
return false
},
false)
return reply
}
xreplyTo.appendChild(genReplyTo())
}
// END LINK META DATA
// add the reply to and delete buttons to the interface
var mbReplyTo = function () {
var id = mb.getUser(Post.creator).id
var xupdateStatus = doc.getElementById('xupdateStatus')
var xinReplyToContainer = doc.getElementById('xinReplyToContainer')
var xupdateSubmit = doc.getElementById('xupdateSubmit')
xupdateStatus.value = '@' + id + ' '
xupdateStatus.focus()
xinReplyToContainer.value = post.uri
xupdateSubmit.value = 'Reply'
}
var mbDeletePost = function (evt) {
var lsconfirmNo = function () {
doc.getElementById('notify-container').removeChild(xconfirmDeletionDialog)
evt.target.disabled = false
}
var lsconfirmYes = function () {
reallyDelete()
doc.getElementById('notify-container').removeChild(xconfirmDeletionDialog)
}
evt.target.disabled = true
var xconfirmDeletionDialog = doc.createElement('li')
xconfirmDeletionDialog.className = 'notify conf'
xconfirmDeletionDialog.innerHTML += '<p>Are you sure you want to delete this post?</p>'
xconfirmDeletionDialog.addEventListener('keyup',
function (evt) {
if (evt.keyCode === 27) {
lsconfirmNo()
}
},
false)
var confirmyes = doc.createElement('input')
confirmyes.type = 'button'
confirmyes.className = 'confirm'
confirmyes.value = 'Delete'
confirmyes.addEventListener('click', lsconfirmYes, false)
var confirmno = doc.createElement('input')
confirmno.type = 'button'
confirmno.className = 'confirm'
confirmno.value = 'Cancel'
confirmno.addEventListener('click', lsconfirmNo, false)
xconfirmDeletionDialog.appendChild(confirmno)
xconfirmDeletionDialog.appendChild(confirmyes)
doc.getElementById('notify-container').appendChild(xconfirmDeletionDialog)
confirmno.focus()
var reallyDelete = function () {
// callback after deletion
var mbconfirmDeletePost = function (a, success) {
if (success) {
that.notify('Post deleted.')
// update the ui to reflect model changes.
var deleteThisNode = evt.target.parentNode
deleteThisNode.parentNode.removeChild(deleteThisNode)
kb.removeMany(deleteMe)
} else {
that.notify('Oops, there was a problem, please try again')
evt.target.disabled = true
}
}
// delete references to post
var deleteContainerOf = function (a, success) {
if (success) {
var deleteContainer = kb.statementsMatching(
undefined, SIOC('container_of'), kb.sym(doc.getElementById(
'post_' + evt.target.parentNode.id).getAttribute('content')))
sparqlUpdater.batch_delete_statement(deleteContainer, mbconfirmDeletePost)
} else {
that.notify('Oops, there was a problem, please try again')
evt.target.disabled = false
}
}
// delete attributes of post
evt.target.disabled = true
let deleteMe = kb.statementsMatching(kb.sym(doc.getElementById(
'post_' + evt.target.parentNode.id).getAttribute('content')))
sparqlUpdater.batch_delete_statement(deleteMe, deleteContainerOf)
}
}
if (mb.getMyURI()) {
// If the microblog in question does not belong to the user,
// display the delete post and reply to post buttons.
var themaker = kb.any(post, SIOC('has_creator'))
if (mb.getMyURI() !== themaker.uri) {
var xreplyButton = doc.createElement('input')
xreplyButton.type = 'button'
xreplyButton.value = 'reply'
xreplyButton.className = 'reply'
xreplyButton.addEventListener('click', mbReplyTo, false)
} else {
var xdeleteButton = doc.createElement('input')
xdeleteButton.type = 'button'
xdeleteButton.value = 'Delete'
xdeleteButton.className = 'reply'
xdeleteButton.addEventListener('click', mbDeletePost, false)
}
}
var mbFavorite = function (evt) {
var nid = evt.target.parentNode.id
var favpost = doc.getElementById('post_' + nid).getAttribute('content')
xfavorite.className += ' ing'
var cbFavorite = function (a, success, c, d) {
if (success) {
xfavorite.className = (xfavorite.className.split(' ')[1] === 'ed')
? 'favorit' : 'favorit ed'
}
}
if (!myFavorites.favorited(favpost)) {
myFavorites.add(favpost, cbFavorite)
} else {
myFavorites.remove(favpost, cbFavorite)
}
}
var xfavorite = doc.createElement('a')
xfavorite.innerHTML = '★'
xfavorite.addEventListener('click', mbFavorite, false)
if (myFavorites.favorited(post.uri)) {
xfavorite.className = 'favorit ed'
} else {
xfavorite.className = 'favorit'
}
// build
xpost.appendChild(xuavatar)
xpost.appendChild(xpostContent)
if (mb.getMyURI()) {
xpost.appendChild(xfavorite)
if (mb.getMyURI() !== themaker.uri) {
xpost.appendChild(xreplyButton)
} else {
xpost.appendChild(xdeleteButton)
}
}
xpost.appendChild(xuname)
xpost.appendChild(xpostLink)
if (inReplyTo !== '') {
xpost.appendChild(xreplyTo)
}
return xpost
}
Pane.prototype.generatePostList = function (gmbPosts) {
/*
generatePostList - Generate the posts and
display their results on the interface.
*/
var postList = doc.createElement('ul')
var postlist = {}
var datelist = []
for (var post in gmbPosts) {
var postDate = kb.any(gmbPosts[post], terms('created'))
if (postDate) {
datelist.push(postDate)
postlist[postDate] = this.generatePost(gmbPosts[post], this.thisIsMe)
}
}
datelist.sort().reverse()
for (var d in datelist) {
postList.appendChild(postlist[datelist[d]])
}
return postList
}
Pane.prototype.followsView = function () {
var getFollowed = function (user) {
var userid = kb.any(user, SIOC('id'))
var follow = doc.createElement('li')
follow.className = 'follow'
userid = userid || user.uri
var fol = kb.any(undefined, FOAF('holdsAccount'), user)
fol = (fol) ? fol.uri : user.uri
follow.innerHTML = '<a href="' + fol + '">' +
userid + '</a>'
return follow
}
var xfollows = doc.createElement('div')
xfollows.id = 'xfollows'
xfollows.className = 'followlist-container view-container'
if (this.creator && kb.whether(this.creator.sym, SIOC('follows'))) {
var creatorFollows = kb.each(this.creator.sym, SIOC('follows'))
var xfollowsList = doc.createElement('ul')
for (var thisPerson in creatorFollows) {
xfollowsList.appendChild(getFollowed(creatorFollows[thisPerson]))
}
xfollows.appendChild(xfollowsList)
}
this.Tab.create('tab-follows', 'Follows', xfollows, false)
return xfollows
}
Pane.prototype.streamView = function (s, doc) {
var postContainer = doc.createElement('div')
postContainer.id = 'postContainer'
postContainer.className = 'post-container view-container active'
var mbPosts = []
if (kb.whether(s, FOAF('name')) && kb.whether(s, FOAF('holdsAccount'))) {
sf.lookUpThing(kb.any(s, FOAF('holdsAccount')))
var follows = kb.each(kb.any(s, FOAF('holdsAccount')), SIOC('follows'))
for (var f in follows) {
sf.lookUpThing(follows[f])
// look up people user follows
var smicroblogs = kb.each(follows[f], SIOC('creator_of'))
// get the follows microblogs
for (var smb in smicroblogs) {
sf.lookUpThing(smicroblogs[smb])
if (kb.whether(smicroblogs[smb], SIOC('topic'), follows[f])) {
continue
} else {
mbPosts = mbPosts.concat(kb.each(smicroblogs[smb], SIOC('container_of')))
}
}
}
}
if (mbPosts.length > 0) {
var postList = this.generatePostList(mbPosts)
// generate stream
postList.id = 'postList'
postList.className = 'postList'
postContainer.appendChild(postList)
}
this.Tab.create('tab-stream', 'By Follows', postContainer, true)
return postContainer
}
Pane.prototype.notificationsView = function (s, doc) {
var postNotificationContainer = doc.createElement('div')
postNotificationContainer.id = 'postNotificationContainer'
postNotificationContainer.className = 'notification-container view-container'
var postMentionContainer = doc.createElement('div')
postMentionContainer.id = 'postMentionContainer'
postMentionContainer.className = 'mention-container view-container'
var mbnPosts = []
var mbmPosts = []
// get mbs that I am the creator of.
var theUser = kb.any(s, FOAF('holdsAccount'))
var user = kb.any(theUser, SIOC('id'))
var microblogs = kb.each(theUser, SIOC('creator_of'))
for (var mbm in microblogs) {
sf.lookUpThing(microblogs[mbm])
if (kb.whether(microblogs[mbm], SIOC('topic'), theUser)) {
mbmPosts = mbmPosts.concat(kb.each(microblogs[mbm], SIOC('container_of')))
} else {
if (kb.whether(microblogs[mbm], RDF('type'), SIOCt('Microblog'))) {
mbnPosts = mbnPosts.concat(kb.each(microblogs[mbm], SIOC('container_of')))
}
}
}
var postNotificationList = this.generatePostList(mbnPosts)
postNotificationList.id = 'postNotificationList'
postNotificationList.className = 'postList'
postNotificationContainer.appendChild(postNotificationList)
var postMentionList = this.generatePostList(mbmPosts)
postMentionList.id = 'postMentionList'
postMentionList.className = 'postList'
postMentionContainer.appendChild(postMentionList)
this.postMentionContainer = postMentionContainer
this.postNotificationContainer = postNotificationContainer
this.Tab.create('tab-by-user', 'By ' + user, postNotificationContainer, false)
this.Tab.create('tab-at-user', '@' + user, postMentionContainer, false)
}
Pane.prototype.build = function () {
var microblogPane = this.microblogPane
this.headerContainer = this.header(s, doc)
this.postContainer = this.streamView(s, doc)
this.notificationsView(s, doc)
this.xfollows = this.followsView()
microblogPane.className = 'ppane'
microblogPane.appendChild(this.xviewReply)
microblogPane.appendChild(this.xnotify)
microblogPane.appendChild(this.headerContainer)
if (this.xfollows !== undefined) { microblogPane.appendChild(this.xfollows) }
microblogPane.appendChild(this.postContainer)
microblogPane.appendChild(this.postNotificationContainer)
microblogPane.appendChild(this.postMentionContainer)
}
var microblogpane = doc.createElement('div')
// var getusersfollows = function(uri){
// var follows = new Object();
// var followsa = {follows:0, matches:0};
// var accounts = kb.each(s, FOAF("holdsAccount"));
// //get all of the accounts that a person holds
// for (var acct in accounts){
// var account = accounts[acct].uri;
// var act = kb.each(kb.sym(account),SIOC("follows"));
// for (var a in act){
// var thisuri = act[a].uri.split("#")[0];
// if (!follows[thisuri]){followsa.follows+=1;}
// follows[thisuri] =true;
// }
// }
//
// var buildPaneUI = function(uri){
// followsa.matches = (follows[uri]) ? followsa.matches+1: followsa.matches;
// console.log(follows.toSource());
// if(followsa.follows == followsa.matches ){
var ppane = new Pane(s, doc, microblogpane)
ppane.build()
// return false;
// }
// else{
// return true;
// }
// }
// sf.addCallback('done',buildPaneUI);
// sf.addCallback('fail',buildPaneUI);
// //fetch each of the followers
// for (var f in follows){
// sf.refresh(kb.sym(f));
// }
// }(s);
return microblogpane
}
}