View
@@ -8,11 +8,12 @@ describe 'WidgetController', ->
$scope = null
fakeAnnotationMapper = null
fakeAnnotationUI = null
fakeAuth = null
fakeCrossFrame = null
fakeDrafts = null
fakeStore = null
fakeStreamer = null
fakeStreamFilter = null
fakeThreading = null
sandbox = null
viewer = null
@@ -30,9 +31,10 @@ describe 'WidgetController', ->
tool: 'comment'
clearSelectedAnnotations: sandbox.spy()
}
fakeAuth = {user: null}
fakeCrossFrame = {providers: []}
fakeDrafts = {remove: sandbox.spy()}
fakeStore = {
SearchResource:
get: (query, callback) ->
@@ -57,13 +59,20 @@ describe 'WidgetController', ->
getFilter: sandbox.stub().returns({})
}
fakeThreading = {
idTable: {}
register: (annotation) ->
@idTable[annotation.id] = message: annotation
}
$provide.value 'annotationMapper', fakeAnnotationMapper
$provide.value 'annotationUI', fakeAnnotationUI
$provide.value 'auth', fakeAuth
$provide.value 'crossframe', fakeCrossFrame
$provide.value 'drafts', fakeDrafts
$provide.value 'store', fakeStore
$provide.value 'streamer', fakeStreamer
$provide.value 'streamFilter', fakeStreamFilter
$provide.value 'threading', fakeThreading
return
beforeEach inject ($controller, $rootScope) ->
@@ -85,3 +94,52 @@ describe 'WidgetController', ->
assert.calledWith(loadSpy, [40..59])
assert.calledWith(loadSpy, [60..79])
assert.calledWith(loadSpy, [80..99])
describe 'streamer.onmessage', ->
it 'calls annotationMapper.loadAnnotations() upon "create" action', ->
anns = ["my", "annotations"]
fakeStreamer.onmessage
type: "annotation-notification"
options: action: "create"
payload: anns
assert.calledWith fakeAnnotationMapper.loadAnnotations, anns
it 'calls annotationMapper.loadAnnotations() upon "update" action', ->
anns = ["my", "annotations"]
fakeStreamer.onmessage
type: "annotation-notification"
options: action: "update"
payload: anns
assert.calledWith fakeAnnotationMapper.loadAnnotations, anns
it 'calls annotationMapper.loadAnnotations() upon "past" action', ->
anns = ["my", "annotations"]
fakeStreamer.onmessage
type: "annotation-notification"
options: action: "past"
payload: anns
assert.calledWith fakeAnnotationMapper.loadAnnotations, anns
it 'looks up annotations at threading upon "delete" action', ->
$scope.$emit = sinon.spy()
# Prepare the annotation that we have locally
localAnnotation =
id: "fake ID"
data: "local data"
# Introduce our annotation into threading
fakeThreading.register localAnnotation
# Prepare the annotation that will come "from the wire"
remoteAnnotation =
id: localAnnotation.id # same id as locally
data: "remote data" # different data
# Simulate a delete action
fakeStreamer.onmessage
type: "annotation-notification"
options: action: "delete"
payload: [ remoteAnnotation ]
assert.calledWith $scope.$emit, "annotationDeleted", localAnnotation
View
@@ -5,7 +5,7 @@ mail = require('./vendor/jwz')
module.exports = class Threading
# Mix in message thread properties into the prototype. The body of the
# class will overwrite any methods applied here. If you need inheritance
# assign the message thread to a local varible.
# assign the message thread to a local variable.
# The mail object is exported by the jwz.js library.
$.extend(this.prototype, mail.messageThread())
View
@@ -3,13 +3,16 @@ angular = require('angular')
module.exports = class WidgetController
this.$inject = [
'$scope', 'annotationUI', 'crossframe', 'annotationMapper',
'auth', 'streamer', 'streamFilter', 'store'
'$rootScope', '$scope', 'annotationMapper', 'annotationUI', 'crossframe',
'drafts', 'streamer', 'streamFilter', 'store', 'threading'
]
constructor: (
$scope, annotationUI, crossframe, annotationMapper,
auth, streamer, streamFilter, store
$rootScope, $scope, annotationMapper, annotationUI, crossframe,
drafts, streamer, streamFilter, store, threading
) ->
$scope.threading = threading
$scope.threadRoot = $scope.threading?.root
# Tells the view that these annotations are embedded into the owner doc
$scope.isEmbedded = true
$scope.isStream = true
@@ -73,3 +76,29 @@ module.exports = class WidgetController
!!($scope.focusedAnnotations ? {})[annotation?.$$tag]
$scope.notOrphan = (container) -> !container?.message?.$orphan
listener = $rootScope.$on 'cleanupAnnotations', ->
# Clean up any annotations
for id, container of $scope.threading.idTable when container.message
$scope.$emit('annotationDeleted', container.message)
drafts.remove container.message
$scope.$on '$destroy', ->
listener()
# Listen to updates
streamer.onmessage = (data) ->
return if !data or data.type != 'annotation-notification'
action = data.options.action
payload = data.payload
return unless payload.length
switch action
when 'create', 'update', 'past'
annotationMapper.loadAnnotations payload
when 'delete'
for annotation in payload
if a = threading.idTable[annotation.id]?.message
$scope.$emit('annotationDeleted', a)
$scope.$digest()