Commit 9423f971 authored by Randall Leeds's avatar Randall Leeds

Inject AnnotationUI ctrl and digest in cross frame

Keep the AppController away from the root scope and just emit the
lifecycle events for the services. Instantiate AnnotationUIController
with proper injection. Handle digests in the cross-frame service.
parent c2dc963f
# Keeps the annotation scope properties up to date by watching for changes # Watch the UI state and update scope properties.
# in the annotationUI object and reacting to user input. This is not a
# controller in the Angular sense, but rather just keeps UI and state in sync.
class AnnotationUIController class AnnotationUIController
constructor: (annotationUI, $rootScope, appScope) -> this.$inject = ['$rootScope', '$scope', 'annotationUI']
constructor: ( $rootScope, $scope, annotationUI ) ->
$rootScope.$watch (-> annotationUI.selectedAnnotationMap), (map={}) -> $rootScope.$watch (-> annotationUI.selectedAnnotationMap), (map={}) ->
count = Object.keys(map).length count = Object.keys(map).length
appScope.selectedAnnotationsCount = count $scope.selectedAnnotationsCount = count
if count if count
appScope.selectedAnnotations = map $scope.selectedAnnotations = map
else else
appScope.selectedAnnotations = null $scope.selectedAnnotations = null
$rootScope.$watch (-> annotationUI.focusedAnnotationMap), (map={}) -> $rootScope.$watch (-> annotationUI.focusedAnnotationMap), (map={}) ->
appScope.focusedAnnotations = map $scope.focusedAnnotations = map
$rootScope.$on 'getDocumentInfo', ->
appScope.$digest()
appScope.$evalAsync(angular.noop)
$rootScope.$on 'beforeAnnotationCreated', ->
appScope.$evalAsync(angular.noop)
$rootScope.$on 'annotationsLoaded', ->
appScope.$evalAsync(angular.noop)
$rootScope.$on 'annotationDeleted', (event, annotation) -> $rootScope.$on 'annotationDeleted', (event, annotation) ->
annotationUI.removeSelectedAnnotation(annotation) annotationUI.removeSelectedAnnotation(annotation)
...@@ -31,18 +20,18 @@ class AnnotationUIController ...@@ -31,18 +20,18 @@ class AnnotationUIController
class AppController class AppController
this.$inject = [ this.$inject = [
'$document', '$location', '$route', '$scope', '$window', '$rootScope', '$controller', '$document', '$location', '$route', '$scope', '$window',
'auth', 'drafts', 'identity', 'auth', 'drafts', 'identity',
'permissions', 'streamer', 'streamfilter', 'annotationUI', 'permissions', 'streamer', 'streamfilter', 'annotationUI',
'annotationMapper', 'threading' 'annotationMapper', 'threading'
] ]
constructor: ( constructor: (
$document, $location, $route, $scope, $window, $rootScope, $controller, $document, $location, $route, $scope, $window,
auth, drafts, identity, auth, drafts, identity,
permissions, streamer, streamfilter, annotationUI, permissions, streamer, streamfilter, annotationUI,
annotationMapper, threading annotationMapper, threading
) -> ) ->
new AnnotationUIController(annotationUI, $rootScope, $scope) $controller(AnnotationUIController, {$scope})
$scope.auth = auth $scope.auth = auth
isFirstRun = $location.search().hasOwnProperty('firstrun') isFirstRun = $location.search().hasOwnProperty('firstrun')
...@@ -59,7 +48,7 @@ class AppController ...@@ -59,7 +48,7 @@ class AppController
annotationMapper.loadAnnotations data annotationMapper.loadAnnotations data
when 'delete' when 'delete'
for annotation in data for annotation in data
$rootScope.$emit('annotationDeleted', annotation) $scope.$emit('annotationDeleted', annotation)
streamer.onmessage = (data) -> streamer.onmessage = (data) ->
return if !data or data.type != 'annotation-notification' return if !data or data.type != 'annotation-notification'
...@@ -76,11 +65,11 @@ class AppController ...@@ -76,11 +65,11 @@ class AppController
for id, container of $scope.threading.idTable when container.message for id, container of $scope.threading.idTable when container.message
# Remove annotations not belonging to this user when highlighting. # Remove annotations not belonging to this user when highlighting.
if annotationUI.tool is 'highlight' and annotation.user != auth.user if annotationUI.tool is 'highlight' and annotation.user != auth.user
$rootScope.$emit('annotationDeleted', container.message) $scope.$emit('annotationDeleted', container.message)
drafts.remove annotation drafts.remove annotation
# Remove annotations the user is not authorized to view. # Remove annotations the user is not authorized to view.
else if not permissions.permits 'read', container.message, auth.user else if not permissions.permits 'read', container.message, auth.user
$rootScope.$emit('annotationDeleted', container.message) $scope.$emit('annotationDeleted', container.message)
drafts.remove container.message drafts.remove container.message
$scope.$watch 'sort.name', (name) -> $scope.$watch 'sort.name', (name) ->
...@@ -101,7 +90,7 @@ class AppController ...@@ -101,7 +90,7 @@ class AppController
# Update any edits in progress. # Update any edits in progress.
for draft in drafts.all() for draft in drafts.all()
$rootScope.$emit('beforeAnnotationCreated', draft) $scope.$emit('beforeAnnotationCreated', draft)
# Reopen the streamer. # Reopen the streamer.
streamer.close() streamer.close()
...@@ -251,4 +240,4 @@ angular.module('h') ...@@ -251,4 +240,4 @@ angular.module('h')
.controller('AppController', AppController) .controller('AppController', AppController)
.controller('ViewerController', ViewerController) .controller('ViewerController', ViewerController)
.controller('AnnotationViewerController', AnnotationViewerController) .controller('AnnotationViewerController', AnnotationViewerController)
.value('AnnotationUIController', AnnotationUIController) .controller('AnnotationUIController', AnnotationUIController)
...@@ -40,9 +40,11 @@ class CrossFrameService ...@@ -40,9 +40,11 @@ class CrossFrameService
parsed[k] = v parsed[k] = v
parsed parsed
emit: (args...) -> emit: (args...) ->
$rootScope.$emit.call($rootScope, args...) $rootScope.$apply ->
$rootScope.$emit.call($rootScope, args...)
on: (event, handler) -> on: (event, handler) ->
$rootScope.$on(event, (event, args...) -> handler.apply(this, args)) $rootScope.$apply ->
$rootScope.$on(event, (event, args...) -> handler.apply(this, args))
new AnnotationSync(bridge, options) new AnnotationSync(bridge, options)
...@@ -55,9 +57,9 @@ class CrossFrameService ...@@ -55,9 +57,9 @@ class CrossFrameService
channel.call channel.call
method: 'getDocumentInfo' method: 'getDocumentInfo'
success: (info) => success: (info) =>
provider.entities = (link.href for link in info.metadata.link) $rootScope.$apply =>
@providers.push(provider) provider.entities = (link.href for link in info.metadata.link)
$rootScope.$emit('getDocumentInfo') @providers.push(provider)
this.connect = -> this.connect = ->
discovery = createDiscovery() discovery = createDiscovery()
......
...@@ -86,55 +86,43 @@ describe 'h', -> ...@@ -86,55 +86,43 @@ describe 'h', ->
describe 'AnnotationUIController', -> describe 'AnnotationUIController', ->
$scope = null $scope = null
$rootScope = null $rootScope = null
fakeAnnotationUI = null annotationUI = null
beforeEach module('h') beforeEach module('h')
beforeEach inject (_$rootScope_, AnnotationUIController) -> beforeEach inject ($controller, _$rootScope_) ->
$rootScope = _$rootScope_ $rootScope = _$rootScope_
$scope = $rootScope.$new() $scope = $rootScope.$new()
$scope.search = {} $scope.search = {}
fakeAnnotationUI = annotationUI =
tool: 'comment' tool: 'comment'
selectedAnnotationMap: null selectedAnnotationMap: null
focusedAnnotationsMap: null focusedAnnotationsMap: null
removeSelectedAnnotation: sandbox.stub() removeSelectedAnnotation: sandbox.stub()
new AnnotationUIController(fakeAnnotationUI, $rootScope, $scope) $controller 'AnnotationUIController', {$scope, annotationUI}
it 'updates the view when the selection changes', -> it 'updates the view when the selection changes', ->
fakeAnnotationUI.selectedAnnotationMap = {1: true, 2: true} annotationUI.selectedAnnotationMap = {1: true, 2: true}
$rootScope.$digest() $rootScope.$digest()
assert.deepEqual($scope.selectedAnnotations, {1: true, 2: true}) assert.deepEqual($scope.selectedAnnotations, {1: true, 2: true})
it 'updates the selection counter when the selection changes', -> it 'updates the selection counter when the selection changes', ->
fakeAnnotationUI.selectedAnnotationMap = {1: true, 2: true} annotationUI.selectedAnnotationMap = {1: true, 2: true}
$rootScope.$digest() $rootScope.$digest()
assert.deepEqual($scope.selectedAnnotationsCount, 2) assert.deepEqual($scope.selectedAnnotationsCount, 2)
it 'clears the selection when no annotations are selected', -> it 'clears the selection when no annotations are selected', ->
fakeAnnotationUI.selectedAnnotationMap = {} annotationUI.selectedAnnotationMap = {}
$rootScope.$digest() $rootScope.$digest()
assert.deepEqual($scope.selectedAnnotations, null) assert.deepEqual($scope.selectedAnnotations, null)
assert.deepEqual($scope.selectedAnnotationsCount, 0) assert.deepEqual($scope.selectedAnnotationsCount, 0)
it 'updates the focused annotations when the focus map changes', -> it 'updates the focused annotations when the focus map changes', ->
fakeAnnotationUI.focusedAnnotationMap = {1: true, 2: true} annotationUI.focusedAnnotationMap = {1: true, 2: true}
$rootScope.$digest() $rootScope.$digest()
assert.deepEqual($scope.focusedAnnotations, {1: true, 2: true}) assert.deepEqual($scope.focusedAnnotations, {1: true, 2: true})
describe 'on annotationsLoaded', ->
it 'enqueues a re-render of the current scope', ->
target = sandbox.stub($scope, '$evalAsync')
$rootScope.$emit('annotationsLoaded', [{}, {}, {}])
assert.called(target)
describe 'on getDocumentInfo', ->
it 'enqueues a re-render of the current scope', ->
target = sandbox.stub($scope, '$evalAsync')
$rootScope.$emit('getDocumentInfo', [{}, {}, {}])
assert.called(target)
describe 'on annotationDeleted', -> describe 'on annotationDeleted', ->
it 'removes the deleted annotation from the selection', -> it 'removes the deleted annotation from the selection', ->
$rootScope.$emit('annotationDeleted', {id: 1}) $rootScope.$emit('annotationDeleted', {id: 1})
assert.calledWith(fakeAnnotationUI.removeSelectedAnnotation, {id: 1}) assert.calledWith(annotationUI.removeSelectedAnnotation, {id: 1})
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment