Unverified Commit cf10d9f3 authored by Sean Hammond's avatar Sean Hammond Committed by GitHub

Merge pull request #695 from hypothesis/rename-annotationui-to-store

Rename "annotationUI" => "store"
parents 8b15381f f5a519be
......@@ -24,12 +24,12 @@ function fetchThread(api, id) {
// @ngInject
function AnnotationViewerContentController (
$location, $routeParams, annotationUI, api, rootThread, streamer,
$location, $routeParams, store, api, rootThread, streamer,
streamFilter, annotationMapper
) {
var self = this;
annotationUI.setAppIsSidebar(false);
store.setAppIsSidebar(false);
var id = $routeParams.id;
......@@ -37,12 +37,12 @@ function AnnotationViewerContentController (
$location.path('/stream').search('q', query);
};
annotationUI.subscribe(function () {
self.rootThread = rootThread.thread(annotationUI.getState());
store.subscribe(function () {
self.rootThread = rootThread.thread(store.getState());
});
this.setCollapsed = function (id, collapsed) {
annotationUI.setCollapsed(id, collapsed);
store.setCollapsed(id, collapsed);
};
this.ready = fetchThread(api, id).then(function (annots) {
......@@ -64,11 +64,11 @@ function AnnotationViewerContentController (
streamer.connect();
annots.forEach(function (annot) {
annotationUI.setCollapsed(annot.id, false);
store.setCollapsed(annot.id, false);
});
if (topLevelAnnot.id !== id) {
annotationUI.highlightAnnotations([id]);
store.highlightAnnotations([id]);
}
});
}
......
......@@ -25,7 +25,7 @@ function updateModel(annotation, changes, permissions) {
// @ngInject
function AnnotationController(
$document, $rootScope, $scope, $timeout, $window, analytics, annotationUI,
$document, $rootScope, $scope, $timeout, $window, analytics, store,
annotationMapper, api, drafts, flash, groups, permissions, serviceUrl,
session, settings, streamer) {
......@@ -199,7 +199,7 @@ function AnnotationController(
};
annotationMapper.flagAnnotation(self.annotation).then(function(){
analytics.track(analytics.events.ANNOTATION_FLAGGED);
annotationUI.updateFlagStatus(self.annotation.id, true);
store.updateFlagStatus(self.annotation.id, true);
}, onRejected);
};
......
......@@ -9,7 +9,7 @@
module.exports = {
controllerAs: 'vm',
// @ngInject
controller: function ($scope, $window, annotationUI, serviceUrl) {
controller: function ($scope, $window, store, serviceUrl) {
this.userAgent = $window.navigator.userAgent;
this.version = '__VERSION__'; // replaced by versionify
this.dateTime = new Date();
......@@ -17,7 +17,7 @@ module.exports = {
$scope.$watch(
function () {
return annotationUI.frames();
return store.frames();
},
function (frames) {
if (frames.length === 0) {
......
......@@ -35,7 +35,7 @@ function authStateFromProfile(profile) {
// @ngInject
function HypothesisAppController(
$document, $location, $rootScope, $route, $scope,
$window, analytics, annotationUI, auth, bridge, drafts, features,
$window, analytics, store, auth, bridge, drafts, features,
flash, frameSync, groups, serviceUrl, session, settings, streamer
) {
var self = this;
......@@ -58,14 +58,14 @@ function HypothesisAppController(
}
this.sortKey = function () {
return annotationUI.getState().sortKey;
return store.getState().sortKey;
};
this.sortKeysAvailable = function () {
return annotationUI.getState().sortKeysAvailable;
return store.getState().sortKeysAvailable;
};
this.setSortKey = annotationUI.setSortKey;
this.setSortKey = store.setSortKey;
// Reload the view when the user switches accounts
$scope.$on(events.USER_CHANGED, function (event, data) {
......@@ -168,10 +168,10 @@ function HypothesisAppController(
this.search = {
query: function () {
return annotationUI.getState().filterQuery;
return store.getState().filterQuery;
},
update: function (query) {
annotationUI.setFilterQuery(query);
store.setFilterQuery(query);
},
};
......
......@@ -3,7 +3,7 @@
var annotationMetadata = require('../annotation-metadata');
// @ngInject
function ModerationBannerController(annotationUI, flash, api) {
function ModerationBannerController(store, flash, api) {
var self = this;
this.flagCount = function () {
......@@ -28,7 +28,7 @@ function ModerationBannerController(annotationUI, flash, api) {
*/
this.hideAnnotation = function () {
api.annotation.hide({id: self.annotation.id}).then(function () {
annotationUI.hideAnnotation(self.annotation.id);
store.hideAnnotation(self.annotation.id);
}).catch(function () {
flash.error('Failed to hide annotation');
});
......@@ -39,7 +39,7 @@ function ModerationBannerController(annotationUI, flash, api) {
*/
this.unhideAnnotation = function () {
api.annotation.unhide({id: self.annotation.id}).then(function () {
annotationUI.unhideAnnotation(self.annotation.id);
store.unhideAnnotation(self.annotation.id);
}).catch(function () {
flash.error('Failed to unhide annotation');
});
......
......@@ -5,9 +5,9 @@ var events = require('../events');
module.exports = {
controllerAs: 'vm',
//@ngInject
controller: function ($rootScope, annotationUI) {
controller: function ($rootScope, store) {
this.onNewNoteBtnClick = function(){
var topLevelFrame = annotationUI.frames().find(f=>!f.id);
var topLevelFrame = store.frames().find(f=>!f.id);
var annot = {
target: [],
uri: topLevelFrame.uri,
......
......@@ -6,7 +6,7 @@ var uiConstants = require('../ui-constants');
module.exports = {
controllerAs: 'vm',
//@ngInject
controller: function ($element, annotationUI, features, session, settings) {
controller: function ($element, store, features, session, settings) {
this.TAB_ANNOTATIONS = uiConstants.TAB_ANNOTATIONS;
this.TAB_NOTES = uiConstants.TAB_NOTES;
this.TAB_ORPHANS = uiConstants.TAB_ORPHANS;
......@@ -16,8 +16,8 @@ module.exports = {
this.enableExperimentalNewNoteButton = settings.enableExperimentalNewNoteButton;
this.selectTab = function (type) {
annotationUI.clearSelectedAnnotations();
annotationUI.selectTab(type);
store.clearSelectedAnnotations();
store.selectTab(type);
};
this.showAnnotationsUnavailableMessage = function () {
......
......@@ -3,7 +3,7 @@
var VIA_PREFIX = 'https://via.hypothes.is/';
// @ngInject
function ShareDialogController($scope, $element, analytics, annotationUI) {
function ShareDialogController($scope, $element, analytics, store) {
var self = this;
function updateViaLink(frames) {
......@@ -24,7 +24,7 @@ function ShareDialogController($scope, $element, analytics, annotationUI) {
viaInput.focus();
viaInput.select();
$scope.$watch(function () { return annotationUI.frames(); },
$scope.$watch(function () { return store.frames(); },
updateViaLink);
$scope.onShareClick = function(target){
......
......@@ -34,17 +34,17 @@ function groupIDFromSelection(selection, results) {
// @ngInject
function SidebarContentController(
$scope, analytics, annotationUI, annotationMapper, api, drafts, features, frameSync,
$scope, analytics, store, annotationMapper, api, drafts, features, frameSync,
groups, rootThread, settings, streamer, streamFilter
) {
var self = this;
function thread() {
return rootThread.thread(annotationUI.getState());
return rootThread.thread(store.getState());
}
var unsubscribeAnnotationUI = annotationUI.subscribe(function () {
var state = annotationUI.getState();
var unsubscribeAnnotationUI = store.subscribe(function () {
var state = store.getState();
self.rootThread = thread();
self.selectedTab = state.selectedTab;
......@@ -79,13 +79,13 @@ function SidebarContentController(
/**
* Returns the Annotation object for the first annotation in the
* selected annotation set. Note that 'first' refers to the order
* of annotations passed to annotationUI when selecting annotations,
* of annotations passed to store when selecting annotations,
* not the order in which they appear in the document.
*/
function firstSelectedAnnotation() {
if (annotationUI.getState().selectedAnnotationMap) {
var id = Object.keys(annotationUI.getState().selectedAnnotationMap)[0];
return annotationUI.getState().annotations.find(function (annot) {
if (store.getState().selectedAnnotationMap) {
var id = Object.keys(store.getState().selectedAnnotationMap)[0];
return store.getState().annotations.find(function (annot) {
return annot.id === id;
});
} else {
......@@ -96,7 +96,7 @@ function SidebarContentController(
var searchClients = [];
function _resetAnnotations() {
annotationMapper.unloadAnnotations(annotationUI.savedAnnotations());
annotationMapper.unloadAnnotations(store.savedAnnotations());
}
function _loadAnnotationsFor(uris, group) {
......@@ -109,11 +109,11 @@ function SidebarContentController(
});
searchClients.push(searchClient);
searchClient.on('results', function (results) {
if (annotationUI.hasSelectedAnnotations()) {
if (store.hasSelectedAnnotations()) {
// Focus the group containing the selected annotation and filter
// annotations to those from this group
var groupID = groupIDFromSelection(
annotationUI.getState().selectedAnnotationMap, results);
store.getState().selectedAnnotationMap, results);
if (!groupID) {
// If the selected annotation is not available, fall back to
// loading annotations for the currently focused group
......@@ -139,9 +139,9 @@ function SidebarContentController(
searchClients.splice(searchClients.indexOf(searchClient), 1);
});
annotationUI.frames().forEach(function (frame) {
store.frames().forEach(function (frame) {
if (0 <= uris.indexOf(frame.uri)) {
annotationUI.updateFrameAnnotationFetchStatus(frame.uri, true);
store.updateFrameAnnotationFetchStatus(frame.uri, true);
}
});
});
......@@ -149,7 +149,7 @@ function SidebarContentController(
}
function isLoading() {
if (!annotationUI.frames().some(function (frame) { return frame.uri; })) {
if (!store.frames().some(function (frame) { return frame.uri; })) {
// The document's URL isn't known so the document must still be loading.
return true;
}
......@@ -183,10 +183,10 @@ function SidebarContentController(
// the batch size, this saves an extra roundtrip to the server
// to fetch the selected annotation in order to determine which group
// it is in before fetching the remaining annotations.
var group = annotationUI.hasSelectedAnnotations() ?
var group = store.hasSelectedAnnotations() ?
null : groups.focused().id;
var searchUris = annotationUI.searchUris();
var searchUris = store.searchUris();
if (searchUris.length > 0) {
_loadAnnotationsFor(searchUris, group);
......@@ -227,15 +227,15 @@ function SidebarContentController(
focusAnnotation(selectedAnnot);
scrollToAnnotation(selectedAnnot);
annotationUI.selectTab(tabs.tabForAnnotation(selectedAnnot));
store.selectTab(tabs.tabForAnnotation(selectedAnnot));
});
// Re-fetch annotations when focused group, logged-in user or connected frames
// change.
$scope.$watch(() => ([
groups.focused().id,
annotationUI.profile().userid,
...annotationUI.searchUris(),
store.profile().userid,
...store.searchUris(),
]), ([currentGroupId], [prevGroupId]) => {
if (currentGroupId !== prevGroupId) {
......@@ -246,20 +246,20 @@ function SidebarContentController(
if (isLoading()) {
return;
}
annotationUI.clearSelectedAnnotations();
store.clearSelectedAnnotations();
}
loadAnnotations();
}, true);
this.setCollapsed = function (id, collapsed) {
annotationUI.setCollapsed(id, collapsed);
store.setCollapsed(id, collapsed);
};
this.forceVisible = function (thread) {
annotationUI.setForceVisible(thread.id, true);
store.setForceVisible(thread.id, true);
if (thread.parent) {
annotationUI.setCollapsed(thread.parent.id, false);
store.setCollapsed(thread.parent.id, false);
}
};
......@@ -267,7 +267,7 @@ function SidebarContentController(
this.scrollTo = scrollToAnnotation;
this.selectedAnnotationCount = function () {
var selection = annotationUI.getState().selectedAnnotationMap;
var selection = store.getState().selectedAnnotationMap;
if (!selection) {
return 0;
}
......@@ -275,10 +275,10 @@ function SidebarContentController(
};
this.selectedAnnotationUnavailable = function () {
var selectedID = firstKey(annotationUI.getState().selectedAnnotationMap);
var selectedID = firstKey(store.getState().selectedAnnotationMap);
return !isLoading() &&
!!selectedID &&
!annotationUI.annotationExists(selectedID);
!store.annotationExists(selectedID);
};
this.shouldShowLoggedOutMessage = function () {
......@@ -302,10 +302,10 @@ function SidebarContentController(
// The user is logged out and has landed on a direct linked
// annotation. If there is an annotation selection and that
// selection is available to the user, show the CTA.
var selectedID = firstKey(annotationUI.getState().selectedAnnotationMap);
var selectedID = firstKey(store.getState().selectedAnnotationMap);
return !isLoading() &&
!!selectedID &&
annotationUI.annotationExists(selectedID);
store.annotationExists(selectedID);
};
this.isLoading = isLoading;
......@@ -325,13 +325,13 @@ function SidebarContentController(
};
this.clearSelection = function () {
var selectedTab = annotationUI.getState().selectedTab;
if (!annotationUI.getState().selectedTab || annotationUI.getState().selectedTab === uiConstants.TAB_ORPHANS) {
var selectedTab = store.getState().selectedTab;
if (!store.getState().selectedTab || store.getState().selectedTab === uiConstants.TAB_ORPHANS) {
selectedTab = uiConstants.TAB_ANNOTATIONS;
}
annotationUI.clearSelectedAnnotations();
annotationUI.selectTab(selectedTab);
store.clearSelectedAnnotations();
store.selectTab(selectedTab);
};
}
......
......@@ -2,12 +2,12 @@
// @ngInject
function StreamContentController(
$scope, $location, $route, $routeParams, annotationMapper, annotationUI,
$scope, $location, $route, $routeParams, annotationMapper, store,
api, queryParser, rootThread, searchFilter, streamFilter, streamer
) {
var self = this;
annotationUI.setAppIsSidebar(false);
store.setAppIsSidebar(false);
/** `offset` parameter for the next search API call. */
var offset = 0;
......@@ -39,7 +39,7 @@ function StreamContentController(
var lastQuery = $routeParams.q;
$scope.$on('$routeUpdate', function () {
if ($routeParams.q !== lastQuery) {
annotationUI.clearAnnotations();
store.clearAnnotations();
$route.reload();
}
});
......@@ -57,9 +57,9 @@ function StreamContentController(
// Perform the initial search
fetch(20);
this.setCollapsed = annotationUI.setCollapsed;
this.setCollapsed = store.setCollapsed;
this.forceVisible = function (id) {
annotationUI.setForceVisible(id, true);
store.setForceVisible(id, true);
};
Object.assign(this.search, {
......@@ -71,12 +71,12 @@ function StreamContentController(
},
});
annotationUI.subscribe(function () {
self.rootThread = rootThread.thread(annotationUI.getState());
store.subscribe(function () {
self.rootThread = rootThread.thread(store.getState());
});
// Sort the stream so that the newest annotations are at the top
annotationUI.setSortKey('Newest');
store.setSortKey('Newest');
this.loadMore = fetch;
}
......
......@@ -101,7 +101,7 @@ describe('annotation', function() {
};
var fakeAnalytics;
var fakeAnnotationMapper;
var fakeAnnotationUI;
var fakeStore;
var fakeDrafts;
var fakeFlash;
var fakeGroups;
......@@ -177,7 +177,7 @@ describe('annotation', function() {
flagAnnotation: sandbox.stub(),
};
fakeAnnotationUI = {
fakeStore = {
updateFlagStatus: sandbox.stub().returns(true),
};
......@@ -244,7 +244,7 @@ describe('annotation', function() {
$provide.value('analytics', fakeAnalytics);
$provide.value('annotationMapper', fakeAnnotationMapper);
$provide.value('annotationUI', fakeAnnotationUI);
$provide.value('store', fakeStore);
$provide.value('api', fakeApi);
$provide.value('drafts', fakeDrafts);
$provide.value('flash', fakeFlash);
......
......@@ -45,7 +45,7 @@ describe('annotationViewerContent', function () {
var locals = {
$location: {},
$routeParams: { id: 'test_annotation_id' },
annotationUI: {
store: {
setAppIsSidebar: sinon.stub(),
setCollapsed: sinon.stub(),
highlightAnnotations: sinon.stub(),
......@@ -105,7 +105,7 @@ describe('annotationViewerContent', function () {
]);
var controller = createController({api: fakeApi});
return controller.ctrl.ready.then(function () {
assert.notCalled(controller.annotationUI.highlightAnnotations);
assert.notCalled(controller.store.highlightAnnotations);
});
});
});
......@@ -130,8 +130,8 @@ describe('annotationViewerContent', function () {
]);
var controller = createController({api: fakeApi});
return controller.ctrl.ready.then(function () {
assert.calledWith(controller.annotationUI.setCollapsed, 'parent_id', false);
assert.calledWith(controller.annotationUI.setCollapsed, 'test_annotation_id', false);
assert.calledWith(controller.store.setCollapsed, 'parent_id', false);
assert.calledWith(controller.store.setCollapsed, 'test_annotation_id', false);
});
});
......@@ -142,7 +142,7 @@ describe('annotationViewerContent', function () {
]);
var controller = createController({api: fakeApi});
return controller.ctrl.ready.then(function () {
assert.calledWith(controller.annotationUI.highlightAnnotations,
assert.calledWith(controller.store.highlightAnnotations,
sinon.match(['test_annotation_id']));
});
});
......
......@@ -3,12 +3,12 @@
var angular = require('angular');
describe('helpPanel', function () {
var fakeAnnotationUI;
var fakeStore;
var $componentController;
var $rootScope;
beforeEach(function () {
fakeAnnotationUI = {
fakeStore = {
frames: sinon.stub().returns([]),
};
......@@ -16,7 +16,7 @@ describe('helpPanel', function () {
.component('helpPanel', require('../help-panel'));
angular.mock.module('h', {
annotationUI: fakeAnnotationUI,
store: fakeStore,
serviceUrl: sinon.stub(),
});
......@@ -27,7 +27,7 @@ describe('helpPanel', function () {
});
it('displays the URL and fingerprint of the first connected frame', function () {
fakeAnnotationUI.frames.returns([{
fakeStore.frames.returns([{
uri: 'https://publisher.org/article.pdf',
metadata: {
documentFingerprint: '12345',
......
......@@ -12,7 +12,7 @@ describe('sidebar.components.hypothesis-app', function () {
var $scope = null;
var $rootScope = null;
var fakeAnnotationMetadata = null;
var fakeAnnotationUI = null;
var fakeStore = null;
var fakeAnalytics = null;
var fakeAuth = null;
var fakeBridge = null;
......@@ -64,7 +64,7 @@ describe('sidebar.components.hypothesis-app', function () {
beforeEach(angular.mock.module('h'));
beforeEach(angular.mock.module(function ($provide) {
fakeAnnotationUI = {
fakeStore = {
tool: 'comment',
clearSelectedAnnotations: sandbox.spy(),
};
......@@ -130,7 +130,7 @@ describe('sidebar.components.hypothesis-app', function () {
call: sandbox.stub(),
};
$provide.value('annotationUI', fakeAnnotationUI);
$provide.value('store', fakeStore);
$provide.value('auth', fakeAuth);
$provide.value('analytics', fakeAnalytics);
$provide.value('drafts', fakeDrafts);
......
......@@ -10,7 +10,7 @@ var moderatedAnnotation = fixtures.moderatedAnnotation;
describe('moderationBanner', function () {
var bannerEl;
var fakeAnnotationUI;
var fakeStore;
var fakeFlash;
var fakeApi;
......@@ -20,7 +20,7 @@ describe('moderationBanner', function () {
});
beforeEach(function () {
fakeAnnotationUI = {
fakeStore = {
hideAnnotation: sinon.stub(),
unhideAnnotation: sinon.stub(),
};
......@@ -37,7 +37,7 @@ describe('moderationBanner', function () {
};
angular.mock.module('app', {
annotationUI: fakeAnnotationUI,
store: fakeStore,
api: fakeApi,
flash: fakeFlash,
});
......
......@@ -8,7 +8,7 @@ var util = require('../../directive/test/util');
describe('newNoteBtn', function () {
var $rootScope;
var sandbox = sinon.sandbox.create();
var fakeAnnotationUI = {
var fakeStore = {
frames: sinon.stub().returns([{ id: null, uri: 'www.example.org'}, { id: '1', uri: 'www.example.org'}]),
};
......@@ -25,7 +25,7 @@ describe('newNoteBtn', function () {
var fakeSettings = { theme: 'clean' };
angular.mock.module('app', {
annotationUI: fakeAnnotationUI,
store: fakeStore,
features: fakeFeatures,
settings: fakeSettings,
});
......@@ -45,7 +45,7 @@ describe('newNoteBtn', function () {
uri: 'www.example.org',
};
var elem = util.createDirective(document, 'newNoteBtn', {
annotationUI: fakeAnnotationUI,
store: fakeStore,
});
sandbox.spy($rootScope, '$broadcast');
elem.ctrl.onNewNoteBtnClick();
......
......@@ -22,13 +22,13 @@ describe('selectionTabs', function () {
});
beforeEach(function () {
var fakeAnnotationUI = {};
var fakeStore = {};
var fakeFeatures = {
flagEnabled: sinon.stub().returns(true),
};
angular.mock.module('app', {
annotationUI: fakeAnnotationUI,
store: fakeStore,
features: fakeFeatures,
session: fakeSession,
settings: fakeSettings,
......@@ -84,7 +84,7 @@ describe('selectionTabs', function () {
it('should show the clean theme when settings contains the clean theme option', function () {
angular.mock.module('app', {
annotationUI: {},
store: {},
features: {
flagEnabled: sinon.stub().returns(true),
},
......
......@@ -6,33 +6,33 @@ var util = require('../../directive/test/util');
describe('shareDialog', function () {
var fakeAnalytics;
var fakeAnnotationUI;
var fakeStore;
beforeEach(function () {
fakeAnalytics = {
track: sinon.stub(),
events: {},
};
fakeAnnotationUI = { frames: sinon.stub().returns([]) };
fakeStore = { frames: sinon.stub().returns([]) };
angular.module('h', [])
.component('shareDialog', require('../share-dialog'))
.value('analytics', fakeAnalytics)
.value('annotationUI', fakeAnnotationUI)
.value('store', fakeStore)
.value('urlEncodeFilter', function (val) { return val; });
angular.mock.module('h');
});
it('generates new via link', function () {
var element = util.createDirective(document, 'shareDialog', {});
fakeAnnotationUI.frames.returns([{ uri: 'http://example.com' }]);
fakeStore.frames.returns([{ uri: 'http://example.com' }]);
element.scope.$digest();
assert.equal(element.ctrl.viaPageLink, 'https://via.hypothes.is/http://example.com');
});
it('does not generate new via link if already on via', function () {
var element = util.createDirective(document, 'shareDialog', {});
fakeAnnotationUI.frames.returns([{
fakeStore.frames.returns([{
uri: 'https://via.hypothes.is/http://example.com',
}]);
element.scope.$digest();
......
......@@ -15,7 +15,7 @@ describe('StreamContentController', function () {
var fakeRoute;
var fakeRouteParams;
var fakeAnnotationMapper;
var fakeAnnotationUI;
var fakeStore;
var fakeQueryParser;
var fakeRootThread;
var fakeSearchFilter;
......@@ -35,7 +35,7 @@ describe('StreamContentController', function () {
loadAnnotations: sinon.spy(),
};
fakeAnnotationUI = {
fakeStore = {
clearAnnotations: sinon.spy(),
setAppIsSidebar: sinon.spy(),
setCollapsed: sinon.spy(),
......@@ -84,7 +84,7 @@ describe('StreamContentController', function () {
$route: fakeRoute,
$routeParams: fakeRouteParams,
annotationMapper: fakeAnnotationMapper,
annotationUI: fakeAnnotationUI,
store: fakeStore,
api: fakeApi,
queryParser: fakeQueryParser,
rootThread: fakeRootThread,
......@@ -136,7 +136,7 @@ describe('StreamContentController', function () {
createController();
fakeRouteParams.q = 'new query';
$rootScope.$broadcast('$routeUpdate');
assert.called(fakeAnnotationUI.clearAnnotations);
assert.called(fakeStore.clearAnnotations);
assert.calledOnce(fakeRoute.reload);
});
......@@ -144,7 +144,7 @@ describe('StreamContentController', function () {
fakeRouteParams.q = 'test query';
createController();
$rootScope.$broadcast('$routeUpdate');
assert.notCalled(fakeAnnotationUI.clearAnnotations);
assert.notCalled(fakeStore.clearAnnotations);
assert.notCalled(fakeRoute.reload);
});
});
......
......@@ -21,7 +21,7 @@
*
*/
// @ngInject
function start(annotationUI, settings, $window) {
function start(store, settings, $window) {
$window.addEventListener('message', function receiveMessage(event) {
let allowedOrigins = settings.rpcAllowedOrigins || [];
......@@ -40,7 +40,7 @@ function start(annotationUI, settings, $window) {
function jsonRpcResponse(request) {
// The set of methods that clients can call.
let methods = {
'searchUris': annotationUI.searchUris,
'searchUris': store.searchUris,
};
let method = methods[request.method];
......
......@@ -209,7 +209,7 @@ module.exports = angular.module('h', [
.service('viewFilter', require('./services/view-filter'))
// Redux store
.service('annotationUI', require('./store'))
.service('store', require('./store'))
// Utilities
.value('Discovery', require('../shared/discovery'))
......
......@@ -4,21 +4,21 @@ var angular = require('angular');
var events = require('../events');
function getExistingAnnotation(annotationUI, id) {
return annotationUI.getState().annotations.find(function (annot) {
function getExistingAnnotation(store, id) {
return store.getState().annotations.find(function (annot) {
return annot.id === id;
});
}
// Wraps the annotation store to trigger events for the CRUD actions
// @ngInject
function annotationMapper($rootScope, annotationUI, api) {
function annotationMapper($rootScope, store, api) {
function loadAnnotations(annotations, replies) {
annotations = annotations.concat(replies || []);
var loaded = [];
annotations.forEach(function (annotation) {
var existing = getExistingAnnotation(annotationUI, annotation.id);
var existing = getExistingAnnotation(store, annotation.id);
if (existing) {
$rootScope.$broadcast(events.ANNOTATION_UPDATED, annotation);
return;
......@@ -31,7 +31,7 @@ function annotationMapper($rootScope, annotationUI, api) {
function unloadAnnotations(annotations) {
var unloaded = annotations.map(function (annotation) {
var existing = getExistingAnnotation(annotationUI, annotation.id);
var existing = getExistingAnnotation(store, annotation.id);
if (existing && annotation !== existing) {
annotation = angular.copy(annotation, existing);
}
......
......@@ -41,7 +41,7 @@ function formatAnnot(ann) {
* sidebar.
*/
// @ngInject
function FrameSync($rootScope, $window, Discovery, annotationUI, bridge) {
function FrameSync($rootScope, $window, Discovery, store, bridge) {
// Set of tags of annotations that are currently loaded into the frame
var inFrame = new Set();
......@@ -56,8 +56,8 @@ function FrameSync($rootScope, $window, Discovery, annotationUI, bridge) {
var prevFrames = [];
var prevPublicAnns = 0;
annotationUI.subscribe(function () {
var state = annotationUI.getState();
store.subscribe(function () {
var state = store.getState();
if (state.annotations === prevAnnotations &&
state.frames === prevFrames) {
return;
......@@ -102,7 +102,7 @@ function FrameSync($rootScope, $window, Discovery, annotationUI, bridge) {
inFrame.delete(annot.$tag);
});
var frames = annotationUI.frames();
var frames = store.frames();
if (frames.length > 0) {
if (frames.every(function (frame) { return frame.isAnnotationFetchComplete; })) {
if (publicAnns === 0 || publicAnns !== prevPublicAnns) {
......@@ -135,7 +135,7 @@ function FrameSync($rootScope, $window, Discovery, annotationUI, bridge) {
// triggered by each `UPDATE_ANCHOR_STATUS` action that is dispatched.
var anchoringStatusUpdates = {};
var scheduleAnchoringStatusUpdate = debounce(() => {
annotationUI.updateAnchorStatus(anchoringStatusUpdates);
store.updateAnchorStatus(anchoringStatusUpdates);
$rootScope.$broadcast(events.ANNOTATIONS_SYNCED, Object.keys(anchoringStatusUpdates));
anchoringStatusUpdates = {};
}, 10);
......@@ -150,16 +150,16 @@ function FrameSync($rootScope, $window, Discovery, annotationUI, bridge) {
});
bridge.on('showAnnotations', function (tags) {
annotationUI.selectAnnotations(annotationUI.findIDsForTags(tags));
annotationUI.selectTab(uiConstants.TAB_ANNOTATIONS);
store.selectAnnotations(store.findIDsForTags(tags));
store.selectTab(uiConstants.TAB_ANNOTATIONS);
});
bridge.on('focusAnnotations', function (tags) {
annotationUI.focusAnnotations(tags || []);
store.focusAnnotations(tags || []);
});
bridge.on('toggleAnnotationSelection', function (tags) {
annotationUI.toggleSelectedAnnotations(annotationUI.findIDsForTags(tags));
store.toggleSelectedAnnotations(store.findIDsForTags(tags));
});
bridge.on('sidebarOpened', function () {
......@@ -192,7 +192,7 @@ function FrameSync($rootScope, $window, Discovery, annotationUI, bridge) {
}
$rootScope.$broadcast(events.FRAME_CONNECTED);
annotationUI.connectFrame({
store.connectFrame({
id: info.frameIdentifier,
metadata: info.metadata,
uri: info.uri,
......@@ -201,12 +201,12 @@ function FrameSync($rootScope, $window, Discovery, annotationUI, bridge) {
}
function destroyFrame(frameIdentifier) {
var frames = annotationUI.frames();
var frames = store.frames();
var frameToDestroy = frames.find(function (frame) {
return frame.id === frameIdentifier;
});
if (frameToDestroy) {
annotationUI.destroyFrame(frameToDestroy);
store.destroyFrame(frameToDestroy);
}
}
......
......@@ -18,7 +18,7 @@ var { awaitStateChange } = require('../util/state-util');
var serviceConfig = require('../service-config');
// @ngInject
function groups($rootScope, annotationUI, api, isSidebar, localStorage, serviceUrl, session,
function groups($rootScope, store, api, isSidebar, localStorage, serviceUrl, session,
settings) {
// The currently focused group. This is the group that's shown as selected in
// the groups dropdown, the annotations displayed are filtered to only ones
......@@ -33,7 +33,7 @@ function groups($rootScope, annotationUI, api, isSidebar, localStorage, serviceU
function getDocumentUriForGroupSearch() {
function mainUri() {
var uris = annotationUI.searchUris();
var uris = store.searchUris();
if (uris.length === 0) {
return null;
}
......@@ -43,7 +43,7 @@ function groups($rootScope, annotationUI, api, isSidebar, localStorage, serviceU
// HTTP URLs (so eg. we cannot use a "file:" URL or PDF fingerprint).
return uris.find(uri => uri.startsWith('http'));
}
return awaitStateChange(annotationUI, mainUri);
return awaitStateChange(store, mainUri);
}
/**
......
......@@ -33,14 +33,14 @@ var sortFns = {
* This performs two functions:
*
* 1. It listens for annotations being loaded, created and unloaded and
* dispatches annotationUI.{addAnnotations|removeAnnotations} actions.
* dispatches store.{addAnnotations|removeAnnotations} actions.
* 2. Listens for changes in the UI state and rebuilds the root conversation
* thread.
*
* The root thread is then displayed by viewer.html
*/
// @ngInject
function RootThread($rootScope, annotationUI, drafts, searchFilter, viewFilter) {
function RootThread($rootScope, store, drafts, searchFilter, viewFilter) {
/**
* Build the root conversation thread from the given UI state.
......@@ -84,7 +84,7 @@ function RootThread($rootScope, annotationUI, drafts, searchFilter, viewFilter)
}
function deleteNewAndEmptyAnnotations() {
annotationUI.getState().annotations.filter(function (ann) {
store.getState().annotations.filter(function (ann) {
return metadata.isNew(ann) && !drafts.getIfNotEmpty(ann);
}).forEach(function (ann) {
drafts.remove(ann);
......@@ -96,13 +96,13 @@ function RootThread($rootScope, annotationUI, drafts, searchFilter, viewFilter)
// and show them in the UI.
//
// Note: These events could all be converted into actions that are handled by
// the Redux store in annotationUI.
// the Redux store in store.
var loadEvents = [events.ANNOTATION_CREATED,
events.ANNOTATION_UPDATED,
events.ANNOTATIONS_LOADED];
loadEvents.forEach(function (event) {
$rootScope.$on(event, function (event, annotation) {
annotationUI.addAnnotations([].concat(annotation));
store.addAnnotations([].concat(annotation));
});
});
......@@ -111,37 +111,37 @@ function RootThread($rootScope, annotationUI, drafts, searchFilter, viewFilter)
// that are empty.
deleteNewAndEmptyAnnotations();
annotationUI.addAnnotations([ann]);
store.addAnnotations([ann]);
// If the annotation is of type note or annotation, make sure
// the appropriate tab is selected. If it is of type reply, user
// stays in the selected tab.
if (metadata.isPageNote(ann)) {
annotationUI.selectTab(uiConstants.TAB_NOTES);
store.selectTab(uiConstants.TAB_NOTES);
} else if (metadata.isAnnotation(ann)) {
annotationUI.selectTab(uiConstants.TAB_ANNOTATIONS);
store.selectTab(uiConstants.TAB_ANNOTATIONS);
}
(ann.references || []).forEach(function (parent) {
annotationUI.setCollapsed(parent, false);
store.setCollapsed(parent, false);
});
});
// Remove any annotations that are deleted or unloaded
$rootScope.$on(events.ANNOTATION_DELETED, function (event, annotation) {
annotationUI.removeAnnotations([annotation]);
store.removeAnnotations([annotation]);
if (annotation.id) {
annotationUI.removeSelectedAnnotation(annotation.id);
store.removeSelectedAnnotation(annotation.id);
}
});
$rootScope.$on(events.ANNOTATIONS_UNLOADED, function (event, annotations) {
annotationUI.removeAnnotations(annotations);
store.removeAnnotations(annotations);
});
// Once the focused group state is moved to the app state store, then the
// logic in this event handler can be moved to the annotations reducer.
$rootScope.$on(events.GROUP_FOCUSED, function (event, focusedGroupId) {
var updatedAnnots = annotationUI.getState().annotations.filter(function (ann) {
var updatedAnnots = store.getState().annotations.filter(function (ann) {
return metadata.isNew(ann) && !metadata.isReply(ann);
}).map(function (ann) {
return Object.assign(ann, {
......@@ -149,7 +149,7 @@ function RootThread($rootScope, annotationUI, drafts, searchFilter, viewFilter)
});
});
if (updatedAnnots.length > 0) {
annotationUI.addAnnotations(updatedAnnots);
store.addAnnotations(updatedAnnots);
}
});
......
......@@ -33,16 +33,16 @@ var urlUtil = require('../util/url-util');
*
* @ngInject
*/
function serviceUrl(annotationUI, apiRoutes) {
function serviceUrl(store, apiRoutes) {
apiRoutes.links()
.then(annotationUI.updateLinks)
.then(store.updateLinks)
.catch(function(error) {
console.warn('The links API request was rejected: ' + error.message);
});
return function(linkName, params) {
var links = annotationUI.getState().links;
var links = store.getState().links;
if (links === null) {
return '';
......
......@@ -20,7 +20,7 @@ var CACHE_TTL = 5 * 60 * 1000; // 5 minutes
*
* @ngInject
*/
function session($q, $rootScope, analytics, annotationUI, api, auth,
function session($q, $rootScope, analytics, store, api, auth,
flash, raven, settings, serviceConfig) {
// Cache the result of load()
var lastLoad;
......@@ -93,11 +93,11 @@ function session($q, $rootScope, analytics, annotationUI, api, auth,
* @return {Profile} The updated profile data
*/
function update(model) {
var prevSession = annotationUI.getState().session;
var prevSession = store.getState().session;
var userChanged = model.userid !== prevSession.userid;
// Update the session model used by the application
annotationUI.updateSession(model);
store.updateSession(model);
lastLoad = Promise.resolve(model);
lastLoadTime = Date.now();
......@@ -167,9 +167,9 @@ function session($q, $rootScope, analytics, annotationUI, api, auth,
// For the moment, we continue to expose the session state as a property on
// this service. In future, other services which access the session state
// will do so directly from annotationUI or via selector functions
// will do so directly from store or via selector functions
get state() {
return annotationUI.getState().session;
return store.getState().session;
},
update,
......
......@@ -20,7 +20,7 @@ var Socket = require('../websocket');
* @param settings - Application settings
*/
// @ngInject
function Streamer($rootScope, annotationMapper, annotationUI, auth,
function Streamer($rootScope, annotationMapper, store, auth,
groups, session, settings) {
// The randomly generated session UUID
var clientId = uuid.v4();
......@@ -37,7 +37,7 @@ function Streamer($rootScope, annotationMapper, annotationUI, auth,
// app.
//
// This state should be managed as part of the global app state in
// annotationUI, but that is currently difficult because applying updates
// store, but that is currently difficult because applying updates
// requires filtering annotations against the focused group (information not
// currently stored in the app state) and triggering events in order to update
// the annotations displayed in the page.
......@@ -62,7 +62,7 @@ function Streamer($rootScope, annotationMapper, annotationUI, auth,
// focused group, since we only display annotations from the focused
// group and reload all annotations and discard pending updates
// when switching groups.
if (ann.group === groups.focused().id || !annotationUI.isSidebar()) {
if (ann.group === groups.focused().id || !store.isSidebar()) {
pendingUpdates[ann.id] = ann;
}
});
......@@ -78,14 +78,14 @@ function Streamer($rootScope, annotationMapper, annotationUI, auth,
// even if the annotation is from the current group, it might be for a
// new annotation (saved in pendingUpdates and removed above), that has
// not yet been loaded.
if (annotationUI.annotationExists(ann.id)) {
if (store.annotationExists(ann.id)) {
pendingDeletions[ann.id] = true;
}
});
break;
}
if (!annotationUI.isSidebar()) {
if (!store.isSidebar()) {
applyPendingUpdates();
}
}
......@@ -125,7 +125,7 @@ function Streamer($rootScope, annotationMapper, annotationUI, auth,
} else if (message.type === 'session-change') {
handleSessionChangeNotification(message);
} else if (message.type === 'whoyouare') {
var userid = annotationUI.getState().session.userid;
var userid = store.getState().session.userid;
if (message.userid !== userid) {
console.warn('WebSocket user ID "%s" does not match logged-in ID "%s"', message.userid, userid);
}
......
......@@ -8,7 +8,7 @@ var events = require('../../events');
describe('annotationMapper', function() {
var sandbox = sinon.sandbox.create();
var $rootScope;
var annotationUI;
var store;
var fakeApi;
var annotationMapper;
......@@ -21,15 +21,15 @@ describe('annotationMapper', function() {
};
angular.module('app', [])
.service('annotationMapper', require('../annotation-mapper'))
.service('annotationUI', require('../../store'))
.service('store', require('../../store'))
.value('api', fakeApi)
.value('settings', {});
angular.mock.module('app');
angular.mock.inject(function (_$rootScope_, _annotationUI_, _annotationMapper_) {
angular.mock.inject(function (_$rootScope_, _store_, _annotationMapper_) {
$rootScope = _$rootScope_;
annotationMapper = _annotationMapper_;
annotationUI = _annotationUI_;
store = _store_;
});
});
......@@ -60,7 +60,7 @@ describe('annotationMapper', function() {
it('triggers the annotationUpdated event for each loaded annotation', function () {
sandbox.stub($rootScope, '$broadcast');
var annotations = immutable([{id: 1}, {id: 2}, {id: 3}]);
annotationUI.addAnnotations(angular.copy(annotations));
store.addAnnotations(angular.copy(annotations));
annotationMapper.loadAnnotations(annotations);
assert.called($rootScope.$broadcast);
......@@ -72,7 +72,7 @@ describe('annotationMapper', function() {
sandbox.stub($rootScope, '$broadcast');
var annotations = [{id: 1}];
var replies = [{id: 2}, {id: 3}, {id: 4}];
annotationUI.addAnnotations([{id:3}]);
store.addAnnotations([{id:3}]);
annotationMapper.loadAnnotations(annotations, replies);
assert($rootScope.$broadcast.calledWith(events.ANNOTATION_UPDATED,
......@@ -82,7 +82,7 @@ describe('annotationMapper', function() {
it('replaces the properties on the cached annotation with those from the loaded one', function () {
sandbox.stub($rootScope, '$broadcast');
var annotations = [{id: 1, url: 'http://example.com'}];
annotationUI.addAnnotations([{id:1, $tag: 'tag1'}]);
store.addAnnotations([{id:1, $tag: 'tag1'}]);
annotationMapper.loadAnnotations(annotations);
assert.called($rootScope.$broadcast);
......@@ -95,7 +95,7 @@ describe('annotationMapper', function() {
it('excludes cached annotations from the annotationLoaded event', function () {
sandbox.stub($rootScope, '$broadcast');
var annotations = [{id: 1, url: 'http://example.com'}];
annotationUI.addAnnotations([{id: 1, $tag: 'tag1'}]);
store.addAnnotations([{id: 1, $tag: 'tag1'}]);
annotationMapper.loadAnnotations(annotations);
assert.called($rootScope.$broadcast);
......@@ -115,7 +115,7 @@ describe('annotationMapper', function() {
it('replaces the properties on the cached annotation with those from the deleted one', function () {
sandbox.stub($rootScope, '$broadcast');
var annotations = [{id: 1, url: 'http://example.com'}];
annotationUI.addAnnotations([{id: 1, $tag: 'tag1'}]);
store.addAnnotations([{id: 1, $tag: 'tag1'}]);
annotationMapper.unloadAnnotations(annotations);
assert.calledWith($rootScope.$broadcast, events.ANNOTATIONS_UNLOADED, [{
......
......@@ -6,7 +6,7 @@ var EventEmitter = require('tiny-emitter');
var annotationFixtures = require('../../test/annotation-fixtures');
var events = require('../../events');
var FrameSync = require('../frame-sync').default;
var fakeStore = require('../../test/fake-redux-store');
var createFakeStore = require('../../test/fake-redux-store');
var formatAnnot = require('../frame-sync').formatAnnot;
var uiConstants = require('../../ui-constants');
......@@ -51,7 +51,7 @@ var fixtures = {
};
describe('sidebar.frame-sync', function () {
var fakeAnnotationUI;
var fakeStore;
var fakeBridge;
var frameSync;
var $rootScope;
......@@ -62,7 +62,7 @@ describe('sidebar.frame-sync', function () {
});
beforeEach(function () {
fakeAnnotationUI = fakeStore({annotations: []}, {
fakeStore = createFakeStore({annotations: []}, {
connectFrame: sinon.stub(),
destroyFrame: sinon.stub(),
findIDsForTags: sinon.stub(),
......@@ -92,7 +92,7 @@ describe('sidebar.frame-sync', function () {
angular.mock.module('app', {
Discovery: FakeDiscovery,
annotationUI: fakeAnnotationUI,
store: fakeStore,
bridge: fakeBridge,
});
......@@ -108,7 +108,7 @@ describe('sidebar.frame-sync', function () {
context('when annotations are loaded into the sidebar', function () {
it('sends a "loadAnnotations" message to the frame', function () {
fakeAnnotationUI.setState({annotations: [fixtures.ann]});
fakeStore.setState({annotations: [fixtures.ann]});
assert.calledWithMatch(fakeBridge.call, 'loadAnnotations', sinon.match([
formatAnnot(fixtures.ann),
]));
......@@ -116,10 +116,10 @@ describe('sidebar.frame-sync', function () {
it('sends a "loadAnnotations" message only for new annotations', function () {
var ann2 = Object.assign({}, fixtures.ann, {$tag: 't2', id: 'a2'});
fakeAnnotationUI.setState({annotations: [fixtures.ann]});
fakeStore.setState({annotations: [fixtures.ann]});
fakeBridge.call.reset();
fakeAnnotationUI.setState({annotations: [fixtures.ann, ann2]});
fakeStore.setState({annotations: [fixtures.ann, ann2]});
assert.calledWithMatch(fakeBridge.call, 'loadAnnotations', sinon.match([
formatAnnot(ann2),
......@@ -127,37 +127,37 @@ describe('sidebar.frame-sync', function () {
});
it('does not send a "loadAnnotations" message for replies', function () {
fakeAnnotationUI.setState({annotations: [annotationFixtures.newReply()]});
fakeStore.setState({annotations: [annotationFixtures.newReply()]});
assert.isFalse(fakeBridge.call.calledWith('loadAnnotations'));
});
});
context('when annotation count has changed', function () {
it('sends a "publicAnnotationCountChanged" message to the frame when there are public annotations', function () {
fakeAnnotationUI.setState({
fakeStore.setState({
annotations: [annotationFixtures.publicAnnotation()],
});
assert.calledWithMatch(fakeBridge.call, 'publicAnnotationCountChanged', sinon.match(1));
});
it('sends a "publicAnnotationCountChanged" message to the frame when there are only private annotations', function () {
fakeAnnotationUI.setState({
fakeStore.setState({
annotations: [annotationFixtures.defaultAnnotation()],
});
assert.calledWithMatch(fakeBridge.call, 'publicAnnotationCountChanged', sinon.match(0));
});
it('does not send a "publicAnnotationCountChanged" message to the frame if annotation fetch is not complete', function () {
fakeAnnotationUI.frames.returns([{uri: 'http://example.com'}]);
fakeAnnotationUI.setState({
fakeStore.frames.returns([{uri: 'http://example.com'}]);
fakeStore.setState({
annotations: [annotationFixtures.publicAnnotation()],
});
assert.isFalse(fakeBridge.call.calledWith('publicAnnotationCountChanged'));
});
it('does not send a "publicAnnotationCountChanged" message if there are no connected frames', function () {
fakeAnnotationUI.frames.returns([]);
fakeAnnotationUI.setState({
fakeStore.frames.returns([]);
fakeStore.setState({
annotations: [annotationFixtures.publicAnnotation()],
});
assert.isFalse(fakeBridge.call.calledWith('publicAnnotationCountChanged'));
......@@ -166,8 +166,8 @@ describe('sidebar.frame-sync', function () {
context('when annotations are removed from the sidebar', function () {
it('sends a "deleteAnnotation" message to the frame', function () {
fakeAnnotationUI.setState({annotations: [fixtures.ann]});
fakeAnnotationUI.setState({annotations: []});
fakeStore.setState({annotations: [fixtures.ann]});
fakeStore.setState({annotations: []});
assert.calledWithMatch(fakeBridge.call, 'deleteAnnotation',
sinon.match(formatAnnot(fixtures.ann)));
});
......@@ -210,7 +210,7 @@ describe('sidebar.frame-sync', function () {
expireDebounceTimeout();
assert.calledWith(fakeAnnotationUI.updateAnchorStatus, { t1: 'anchored' });
assert.calledWith(fakeStore.updateAnchorStatus, { t1: 'anchored' });
});
it('coalesces multiple "sync" messages', () => {
......@@ -219,7 +219,7 @@ describe('sidebar.frame-sync', function () {
expireDebounceTimeout();
assert.calledWith(fakeAnnotationUI.updateAnchorStatus, {
assert.calledWith(fakeStore.updateAnchorStatus, {
t1: 'anchored',
t2: 'orphan',
});
......@@ -249,7 +249,7 @@ describe('sidebar.frame-sync', function () {
fakeBridge.emit('connect', fakeChannel);
assert.calledWith(fakeAnnotationUI.connectFrame, {
assert.calledWith(fakeStore.connectFrame, {
id: frameInfo.frameIdentifier,
metadata: frameInfo.metadata,
uri: frameInfo.uri,
......@@ -263,32 +263,32 @@ describe('sidebar.frame-sync', function () {
it('removes the frame from the frames list', function () {
fakeBridge.emit('destroyFrame', frameId);
assert.calledWith(fakeAnnotationUI.destroyFrame, fixtures.framesListEntry);
assert.calledWith(fakeStore.destroyFrame, fixtures.framesListEntry);
});
});
describe('on "showAnnotations" message', function () {
it('selects annotations which have an ID', function () {
fakeAnnotationUI.findIDsForTags.returns(['id1','id2','id3']);
fakeStore.findIDsForTags.returns(['id1','id2','id3']);
fakeBridge.emit('showAnnotations', ['tag1', 'tag2', 'tag3']);
assert.calledWith(fakeAnnotationUI.selectAnnotations, ['id1', 'id2', 'id3']);
assert.calledWith(fakeAnnotationUI.selectTab, uiConstants.TAB_ANNOTATIONS);
assert.calledWith(fakeStore.selectAnnotations, ['id1', 'id2', 'id3']);
assert.calledWith(fakeStore.selectTab, uiConstants.TAB_ANNOTATIONS);
});
});
describe('on "focusAnnotations" message', function () {
it('focuses the annotations', function () {
fakeBridge.emit('focusAnnotations', ['tag1', 'tag2', 'tag3']);
assert.calledWith(fakeAnnotationUI.focusAnnotations, ['tag1', 'tag2', 'tag3']);
assert.calledWith(fakeStore.focusAnnotations, ['tag1', 'tag2', 'tag3']);
});
});
describe('on "toggleAnnotationSelection" message', function () {
it('toggles the selected state of the annotations', function () {
fakeAnnotationUI.findIDsForTags.returns(['id1','id2','id3']);
fakeStore.findIDsForTags.returns(['id1','id2','id3']);
fakeBridge.emit('toggleAnnotationSelection', ['tag1', 'tag2', 'tag3']);
assert.calledWith(fakeAnnotationUI.toggleSelectedAnnotations, ['id1', 'id2', 'id3']);
assert.calledWith(fakeStore.toggleSelectedAnnotations, ['id1', 'id2', 'id3']);
});
});
......
......@@ -13,7 +13,7 @@ var sessionWithThreeGroups = function() {
};
describe('groups', function() {
var fakeAnnotationUI;
var fakeStore;
var fakeIsSidebar;
var fakeSession;
var fakeSettings;
......@@ -26,7 +26,7 @@ describe('groups', function() {
beforeEach(function() {
sandbox = sinon.sandbox.create();
fakeAnnotationUI = fakeReduxStore({
fakeStore = fakeReduxStore({
searchUris: ['http://example.org'],
},{
searchUris() {
......@@ -77,7 +77,7 @@ describe('groups', function() {
});
function service() {
return groups(fakeRootScope, fakeAnnotationUI, fakeApi, fakeIsSidebar, fakeLocalStorage, fakeServiceUrl,
return groups(fakeRootScope, fakeStore, fakeApi, fakeIsSidebar, fakeLocalStorage, fakeServiceUrl,
fakeSession, fakeSettings);
}
......@@ -134,9 +134,9 @@ describe('groups', function() {
it('waits for the document URL to be determined', () => {
var svc = service();
fakeAnnotationUI.setState({ searchUris: [] });
fakeStore.setState({ searchUris: [] });
var loaded = svc.load();
fakeAnnotationUI.setState({ searchUris: ['https://asite.com'] });
fakeStore.setState({ searchUris: ['https://asite.com'] });
return loaded.then(() => {
assert.calledWith(fakeApi.groups.list, { document_uri: 'https://asite.com' });
......@@ -150,7 +150,7 @@ describe('groups', function() {
});
it('does not wait for the document URL', () => {
fakeAnnotationUI.setState({ searchUris: [] });
fakeStore.setState({ searchUris: [] });
var svc = service();
return svc.load().then(() => {
assert.calledWith(fakeApi.groups.list, {});
......
......@@ -2,8 +2,8 @@
var proxyquire = require('proxyquire');
/** Return a fake annotationUI object. */
function fakeAnnotationUI() {
/** Return a fake store object. */
function fakeStore() {
var links = null;
return {
updateLinks: function(newLinks) {
......@@ -24,16 +24,16 @@ function createServiceUrl(linksPromise) {
'../util/url-util': { replaceURLParams: replaceURLParams },
});
var annotationUI = fakeAnnotationUI();
var store = fakeStore();
var apiRoutes = {
links: sinon.stub().returns(linksPromise),
};
return {
annotationUI: annotationUI,
store: store,
apiRoutes,
serviceUrl: serviceUrlFactory(annotationUI, apiRoutes),
serviceUrl: serviceUrlFactory(store, apiRoutes),
replaceURLParams: replaceURLParams,
};
}
......@@ -76,7 +76,7 @@ describe('sidebar.service-url', function () {
});
context('after the API response has been received', function() {
var annotationUI;
var store;
var linksPromise;
var replaceURLParams;
var serviceUrl;
......@@ -90,14 +90,14 @@ describe('sidebar.service-url', function () {
var parts = createServiceUrl(linksPromise);
annotationUI = parts.annotationUI;
store = parts.store;
serviceUrl = parts.serviceUrl;
replaceURLParams = parts.replaceURLParams;
});
it('updates annotationUI with the real links', function() {
it('updates store with the real links', function() {
return linksPromise.then(function(links) {
assert.deepEqual(annotationUI.getState(), {links: links});
assert.deepEqual(store.getState(), {links: links});
});
});
......
......@@ -32,7 +32,7 @@ describe('sidebar.session', function () {
track: sinon.stub(),
events: require('../analytics')().events,
};
var fakeAnnotationUI = {
var fakeStore = {
getState: function () {
return {session: state};
},
......@@ -60,7 +60,7 @@ describe('sidebar.session', function () {
mock.module('h', {
analytics: fakeAnalytics,
annotationUI: fakeAnnotationUI,
store: fakeStore,
api: fakeApi,
auth: fakeAuth,
flash: fakeFlash,
......
......@@ -67,7 +67,7 @@ inherits(FakeSocket, EventEmitter);
describe('Streamer', function () {
var fakeAnnotationMapper;
var fakeAnnotationUI;
var fakeStore;
var fakeAuth;
var fakeGroups;
var fakeRootScope;
......@@ -80,7 +80,7 @@ describe('Streamer', function () {
activeStreamer = new Streamer(
fakeRootScope,
fakeAnnotationMapper,
fakeAnnotationUI,
fakeStore,
fakeAuth,
fakeGroups,
fakeSession,
......@@ -112,7 +112,7 @@ describe('Streamer', function () {
unloadAnnotations: sinon.stub(),
};
fakeAnnotationUI = {
fakeStore = {
annotationExists: sinon.stub().returns(false),
isSidebar: sinon.stub().returns(true),
getState: sinon.stub().returns({
......@@ -254,7 +254,7 @@ describe('Streamer', function () {
context('when the app is the stream', function () {
beforeEach(function () {
fakeAnnotationUI.isSidebar.returns(false);
fakeStore.isSidebar.returns(false);
});
it('does not defer updates', function () {
......@@ -288,7 +288,7 @@ describe('Streamer', function () {
it('saves pending deletions if the annotation is loaded', function () {
var id = fixtures.deleteNotification.payload[0].id;
fakeAnnotationUI.annotationExists.returns(true);
fakeStore.annotationExists.returns(true);
fakeWebSocket.notify(fixtures.deleteNotification);
......@@ -298,7 +298,7 @@ describe('Streamer', function () {
it('discards pending deletions if the annotation is not loaded', function () {
var id = fixtures.deleteNotification.payload[0].id;
fakeAnnotationUI.annotationExists.returns(false);
fakeStore.annotationExists.returns(false);
fakeWebSocket.notify(fixtures.deleteNotification);
......@@ -312,7 +312,7 @@ describe('Streamer', function () {
});
it('discards pending updates if an unloaded annotation is deleted', function () {
fakeAnnotationUI.annotationExists.returns(false);
fakeStore.annotationExists.returns(false);
fakeWebSocket.notify(fixtures.createNotification);
fakeWebSocket.notify(fixtures.deleteNotification);
......@@ -346,7 +346,7 @@ describe('Streamer', function () {
});
it('applies pending deletions', function () {
fakeAnnotationUI.annotationExists.returns(true);
fakeStore.annotationExists.returns(true);
fakeWebSocket.notify(fixtures.deleteNotification);
activeStreamer.applyPendingUpdates();
......@@ -382,7 +382,7 @@ describe('Streamer', function () {
}, changeEvents);
unroll('discards pending deletions when #event occurs', function (testCase) {
fakeAnnotationUI.annotationExists.returns(true);
fakeStore.annotationExists.returns(true);
fakeWebSocket.notify(fixtures.deleteNotification);
fakeRootScope.$broadcast(testCase.event, {id: 'an-id'});
......@@ -432,7 +432,7 @@ describe('Streamer', function () {
});
unroll('does nothing if the userid matches the logged-in userid', function (testCase) {
fakeAnnotationUI.getState.returns({
fakeStore.getState.returns({
session: {
userid: testCase.userid,
},
......@@ -454,7 +454,7 @@ describe('Streamer', function () {
}]);
unroll('logs a warning if the userid does not match the logged-in userid', function (testCase) {
fakeAnnotationUI.getState.returns({
fakeStore.getState.returns({
session: {
userid: testCase.userid,
},
......
......@@ -89,12 +89,12 @@ function store($rootScope, settings) {
enhancer);
// Expose helper functions that create actions as methods of the
// `annotationUI` service to make using them easier from app code. eg.
// `store` service to make using them easier from app code. eg.
//
// Instead of:
// annotationUI.dispatch(annotations.actions.addAnnotations(annotations))
// store.dispatch(annotations.actions.addAnnotations(annotations))
// You can use:
// annotationUI.addAnnotations(annotations)
// store.addAnnotations(annotations)
//
var actionCreators = redux.bindActionCreators(Object.assign({},
annotationsModule.actions,
......@@ -105,13 +105,13 @@ function store($rootScope, settings) {
viewerModule.actions
), store.dispatch);
// Expose selectors as methods of the `annotationUI` to make using them easier
// Expose selectors as methods of the `store` to make using them easier
// from app code.
//
// eg. Instead of:
// selection.isAnnotationSelected(annotationUI.getState(), id)
// selection.isAnnotationSelected(store.getState(), id)
// You can use:
// annotationUI.isAnnotationSelected(id)
// store.isAnnotationSelected(id)
var selectors = util.bindSelectors(Object.assign({},
annotationsModule.selectors,
framesModule.selectors,
......
This diff is collapsed.
......@@ -5,13 +5,13 @@ var crossOriginRPC = require('../cross-origin-rpc');
describe('crossOriginRPC', function() {
describe('server', function() {
let addedListener; // The postMessage() listener that the server adds.
let fakeAnnotationUI;
let fakeStore;
let fakeWindow;
let settings;
let source;
beforeEach(function() {
fakeAnnotationUI = {
fakeStore = {
searchUris: sinon.stub().returns('THE_SEARCH_URIS'),
};
......@@ -40,14 +40,14 @@ describe('crossOriginRPC', function() {
}
it('adds a postMessage() event listener function', function() {
crossOriginRPC.server.start(fakeAnnotationUI, {}, fakeWindow);
crossOriginRPC.server.start(fakeStore, {}, fakeWindow);
assert.isTrue(fakeWindow.addEventListener.calledOnce);
assert.isTrue(fakeWindow.addEventListener.calledWith('message'));
});
it('sends a response with the result from the called method', function() {
crossOriginRPC.server.start(fakeAnnotationUI, settings, fakeWindow);
crossOriginRPC.server.start(fakeStore, settings, fakeWindow);
postMessage({
data: { method: 'searchUris', id: 42 },
......@@ -72,7 +72,7 @@ describe('crossOriginRPC', function() {
{ rpcAllowedOrigins: ['https://allowed1.com', 'https://allowed2.com'] },
].forEach(function(settings) {
it("doesn't respond if the origin isn't allowed", function() {
crossOriginRPC.server.start(fakeAnnotationUI, settings, fakeWindow);
crossOriginRPC.server.start(fakeStore, settings, fakeWindow);
postMessage({
origin: 'https://notallowed.com',
......@@ -85,7 +85,7 @@ describe('crossOriginRPC', function() {
});
it("responds with an error if there's no method", function() {
crossOriginRPC.server.start(fakeAnnotationUI, settings, fakeWindow);
crossOriginRPC.server.start(fakeStore, settings, fakeWindow);
let jsonRpcRequest = { id: 42 }; // No "method" member.
postMessage({
......@@ -113,7 +113,7 @@ describe('crossOriginRPC', function() {
null,
].forEach(function(method) {
it('responds with an error if the method is unknown', function() {
crossOriginRPC.server.start(fakeAnnotationUI, settings, fakeWindow);
crossOriginRPC.server.start(fakeStore, settings, fakeWindow);
postMessage({
origin: 'https://allowed1.com',
......
......@@ -30,7 +30,7 @@ var fixtures = immutable({
});
describe('annotation threading', function () {
var annotationUI;
var store;
var rootThread;
beforeEach(function () {
......@@ -44,7 +44,7 @@ describe('annotation threading', function () {
};
angular.module('app', [])
.service('annotationUI', require('../../store'))
.service('store', require('../../store'))
.service('drafts', require('../../services/drafts'))
.service('rootThread', require('../../services/root-thread'))
.service('searchFilter', require('../../services/search-filter'))
......@@ -55,34 +55,34 @@ describe('annotation threading', function () {
angular.mock.module('app');
angular.mock.inject(function (_annotationUI_, _rootThread_) {
annotationUI = _annotationUI_;
angular.mock.inject(function (_store_, _rootThread_) {
store = _store_;
rootThread = _rootThread_;
});
});
it('should display newly loaded annotations', function () {
annotationUI.addAnnotations(fixtures.annotations);
assert.equal(rootThread.thread(annotationUI.getState()).children.length, 2);
store.addAnnotations(fixtures.annotations);
assert.equal(rootThread.thread(store.getState()).children.length, 2);
});
it('should not display unloaded annotations', function () {
annotationUI.addAnnotations(fixtures.annotations);
annotationUI.removeAnnotations(fixtures.annotations);
assert.equal(rootThread.thread(annotationUI.getState()).children.length, 0);
store.addAnnotations(fixtures.annotations);
store.removeAnnotations(fixtures.annotations);
assert.equal(rootThread.thread(store.getState()).children.length, 0);
});
it('should filter annotations when a search is set', function () {
annotationUI.addAnnotations(fixtures.annotations);
annotationUI.setFilterQuery('second');
assert.equal(rootThread.thread(annotationUI.getState()).children.length, 1);
assert.equal(rootThread.thread(annotationUI.getState()).children[0].id, '2');
store.addAnnotations(fixtures.annotations);
store.setFilterQuery('second');
assert.equal(rootThread.thread(store.getState()).children.length, 1);
assert.equal(rootThread.thread(store.getState()).children[0].id, '2');
});
unroll('should sort annotations by #mode', function (testCase) {
annotationUI.addAnnotations(fixtures.annotations);
annotationUI.setSortKey(testCase.sortKey);
var actualOrder = rootThread.thread(annotationUI.getState()).children.map(function (thread) {
store.addAnnotations(fixtures.annotations);
store.setSortKey(testCase.sortKey);
var actualOrder = rootThread.thread(store.getState()).children.map(function (thread) {
return thread.annotation.id;
});
assert.deepEqual(actualOrder, testCase.expectedOrder);
......
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