Commit 2998e577 authored by chdorner's avatar chdorner

Search for PDF fingerprint and non-file URL for annotations

This will allow us to switch back to using the URL for the
`target.source` when creating annotations, which will then allow us to
link back to the exact document where the annotation was created.
parent 7b4fc59d
...@@ -46,11 +46,20 @@ module.exports = class CrossFrame ...@@ -46,11 +46,20 @@ module.exports = class CrossFrame
if err if err
channel.destroy() channel.destroy()
else else
searchUris = [info.uri]
documentFingerprint = null documentFingerprint = null
if info.metadata and info.metadata.documentFingerprint if info.metadata and info.metadata.documentFingerprint
documentFingerprint = info.metadata.documentFingerprint documentFingerprint = info.metadata.documentFingerprint
searchUris = info.metadata.link.map((link) -> link.href)
$rootScope.$apply => $rootScope.$apply =>
@frames.push({channel: channel, uri: info.uri, documentFingerprint: documentFingerprint}) @frames.push({
channel: channel,
uri: info.uri,
searchUris: searchUris,
documentFingerprint: documentFingerprint
})
this.connect = -> this.connect = ->
discovery = createDiscovery() discovery = createDiscovery()
......
...@@ -72,5 +72,23 @@ describe 'CrossFrame', -> ...@@ -72,5 +72,23 @@ describe 'CrossFrame', ->
fakeBridge.onConnect.yields(channel) fakeBridge.onConnect.yields(channel)
crossframe.connect() crossframe.connect()
assert.deepEqual(crossframe.frames, [ assert.deepEqual(crossframe.frames, [
{channel: channel, uri: uri, documentFingerprint: null} {channel: channel, uri: uri, searchUris: [uri], documentFingerprint: null}
])
it 'updates the frames array with multiple search uris when the document is a PDF', ->
uri = 'http://example.com/test.pdf'
fingerprint = 'urn:x-pdf:fingerprint'
channel = {
call: sandbox.stub().yields(null, {
uri: uri,
metadata: {
link: [{href: uri}, {href: fingerprint}],
documentFingerprint: fingerprint,
},
})
}
fakeBridge.onConnect.yields(channel)
crossframe.connect()
assert.deepEqual(crossframe.frames, [
{channel: channel, uri: uri, searchUris: [uri, fingerprint], documentFingerprint: fingerprint}
]) ])
...@@ -19,8 +19,12 @@ function FakeSearchClient(resource, opts) { ...@@ -19,8 +19,12 @@ function FakeSearchClient(resource, opts) {
this.get = sinon.spy(function (query) { this.get = sinon.spy(function (query) {
assert.ok(query.uri); assert.ok(query.uri);
this.emit('results', [{id: query.uri + '123', group: '__world__'}]); for (var i = 0; i < query.uri.length; i++) {
this.emit('results', [{id: query.uri + '456', group: 'private-group'}]); var uri = query.uri[i];
this.emit('results', [{id: uri + '123', group: '__world__'}]);
this.emit('results', [{id: uri + '456', group: 'private-group'}]);
}
this.emit('end'); this.emit('end');
}); });
} }
...@@ -143,10 +147,12 @@ describe('WidgetController', function () { ...@@ -143,10 +147,12 @@ describe('WidgetController', function () {
// When new clients connect, all existing annotations should be unloaded // When new clients connect, all existing annotations should be unloaded
// before reloading annotations for each currently-connected client // before reloading annotations for each currently-connected client
annotationUI.addAnnotations([{id: '123'}]); annotationUI.addAnnotations([{id: '123'}]);
fakeCrossFrame.frames.push({uri: 'http://example.com/page-a'}); var uri1 = 'http://example.com/page-a';
fakeCrossFrame.frames.push({uri: uri1, searchUris: [uri1]});
$scope.$digest(); $scope.$digest();
fakeAnnotationMapper.unloadAnnotations = sandbox.spy(); fakeAnnotationMapper.unloadAnnotations = sandbox.spy();
fakeCrossFrame.frames.push({uri: 'http://example.com/page-b'}); var uri2 = 'http://example.com/page-b';
fakeCrossFrame.frames.push({uri: uri2, searchUris: [uri2]});
$scope.$digest(); $scope.$digest();
assert.calledWith(fakeAnnotationMapper.unloadAnnotations, assert.calledWith(fakeAnnotationMapper.unloadAnnotations,
annotationUI.getState().annotations); annotationUI.getState().annotations);
...@@ -154,17 +160,29 @@ describe('WidgetController', function () { ...@@ -154,17 +160,29 @@ describe('WidgetController', function () {
it('loads all annotations for a frame', function () { it('loads all annotations for a frame', function () {
var uri = 'http://example.com'; var uri = 'http://example.com';
fakeCrossFrame.frames.push({uri: uri}); fakeCrossFrame.frames.push({uri: uri, searchUris: [uri]});
$scope.$digest();
var loadSpy = fakeAnnotationMapper.loadAnnotations;
assert.calledWith(loadSpy, [sinon.match({id: uri + '123'})]);
assert.calledWith(loadSpy, [sinon.match({id: uri + '456'})]);
});
it('loads all annotations for a frame with multiple urls', function () {
var uri = 'http://example.com/test.pdf';
var fingerprint = 'urn:x-pdf:fingerprint';
fakeCrossFrame.frames.push({uri: uri, searchUris: [uri, fingerprint]});
$scope.$digest(); $scope.$digest();
var loadSpy = fakeAnnotationMapper.loadAnnotations; var loadSpy = fakeAnnotationMapper.loadAnnotations;
assert.calledWith(loadSpy, [sinon.match({id: uri + '123'})]); assert.calledWith(loadSpy, [sinon.match({id: uri + '123'})]);
assert.calledWith(loadSpy, [sinon.match({id: fingerprint + '123'})]);
assert.calledWith(loadSpy, [sinon.match({id: uri + '456'})]); assert.calledWith(loadSpy, [sinon.match({id: uri + '456'})]);
assert.calledWith(loadSpy, [sinon.match({id: fingerprint + '456'})]);
}); });
it('loads all annotations for all frames', function () { it('loads all annotations for all frames', function () {
var uris = ['http://example.com', 'http://foobar.com']; var uris = ['http://example.com', 'http://foobar.com'];
fakeCrossFrame.frames = uris.map(function (uri) { fakeCrossFrame.frames = uris.map(function (uri) {
return {uri: uri}; return {uri: uri, searchUris: [uri]};
}); });
$scope.$digest(); $scope.$digest();
var loadSpy = fakeAnnotationMapper.loadAnnotations; var loadSpy = fakeAnnotationMapper.loadAnnotations;
...@@ -179,7 +197,7 @@ describe('WidgetController', function () { ...@@ -179,7 +197,7 @@ describe('WidgetController', function () {
var id = uri + '123'; var id = uri + '123';
beforeEach(function () { beforeEach(function () {
fakeCrossFrame.frames = [{uri: uri}]; fakeCrossFrame.frames = [{uri: uri, searchUris: [uri]}];
annotationUI.selectAnnotations([id]); annotationUI.selectAnnotations([id]);
$scope.$digest(); $scope.$digest();
}); });
...@@ -197,7 +215,7 @@ describe('WidgetController', function () { ...@@ -197,7 +215,7 @@ describe('WidgetController', function () {
}); });
it('fetches annotations for all groups', function () { it('fetches annotations for all groups', function () {
assert.calledWith(searchClients[0].get, {uri: uri, group: null}); assert.calledWith(searchClients[0].get, {uri: [uri], group: null});
}); });
it('loads annotations in one batch', function () { it('loads annotations in one batch', function () {
...@@ -209,7 +227,7 @@ describe('WidgetController', function () { ...@@ -209,7 +227,7 @@ describe('WidgetController', function () {
var uri = 'http://example.com'; var uri = 'http://example.com';
beforeEach(function () { beforeEach(function () {
fakeCrossFrame.frames = [{uri: uri}]; fakeCrossFrame.frames = [{uri: uri, searchUris: [uri]}];
fakeGroups.focused = function () { return { id: 'a-group' }; }; fakeGroups.focused = function () { return { id: 'a-group' }; };
$scope.$digest(); $scope.$digest();
}); });
...@@ -219,7 +237,7 @@ describe('WidgetController', function () { ...@@ -219,7 +237,7 @@ describe('WidgetController', function () {
}); });
it('fetches annotations for the current group', function () { it('fetches annotations for the current group', function () {
assert.calledWith(searchClients[0].get, {uri: uri, group: 'a-group'}); assert.calledWith(searchClients[0].get, {uri: [uri], group: 'a-group'});
}); });
it('loads annotations in batches', function () { it('loads annotations in batches', function () {
...@@ -232,7 +250,7 @@ describe('WidgetController', function () { ...@@ -232,7 +250,7 @@ describe('WidgetController', function () {
var id = uri + 'does-not-exist'; var id = uri + 'does-not-exist';
beforeEach(function () { beforeEach(function () {
fakeCrossFrame.frames = [{uri: uri}]; fakeCrossFrame.frames = [{uri: uri, searchUris: [uri]}];
annotationUI.selectAnnotations([id]); annotationUI.selectAnnotations([id]);
fakeGroups.focused = function () { return { id: 'private-group' }; }; fakeGroups.focused = function () { return { id: 'private-group' }; };
$scope.$digest(); $scope.$digest();
...@@ -250,7 +268,7 @@ describe('WidgetController', function () { ...@@ -250,7 +268,7 @@ describe('WidgetController', function () {
it('focuses and scrolls to the annotation if already selected', function () { it('focuses and scrolls to the annotation if already selected', function () {
var uri = 'http://example.com'; var uri = 'http://example.com';
annotationUI.selectAnnotations(['123']); annotationUI.selectAnnotations(['123']);
fakeCrossFrame.frames.push({uri: uri}); fakeCrossFrame.frames.push({uri: uri, searchUris: [uri]});
var annot = { var annot = {
$$tag: 'atag', $$tag: 'atag',
id: '123', id: '123',
...@@ -272,7 +290,7 @@ describe('WidgetController', function () { ...@@ -272,7 +290,7 @@ describe('WidgetController', function () {
fakeDrafts.unsaved.returns([{id: uri + '123'}, {id: uri + '456'}]); fakeDrafts.unsaved.returns([{id: uri + '123'}, {id: uri + '456'}]);
fakeCrossFrame.frames.push({uri: uri}); fakeCrossFrame.frames.push({uri: uri, searchUris: [uri]});
var loadSpy = fakeAnnotationMapper.loadAnnotations; var loadSpy = fakeAnnotationMapper.loadAnnotations;
$scope.$broadcast(events.GROUP_FOCUSED); $scope.$broadcast(events.GROUP_FOCUSED);
......
...@@ -143,7 +143,7 @@ module.exports = function WidgetController( ...@@ -143,7 +143,7 @@ module.exports = function WidgetController(
annotationUI.addAnnotations(drafts.unsaved()); annotationUI.addAnnotations(drafts.unsaved());
} }
function _loadAnnotationsFor(uri, group) { function _loadAnnotationsFor(uris, group) {
var searchClient = new SearchClient(store.SearchResource, { var searchClient = new SearchClient(store.SearchResource, {
// If no group is specified, we are fetching annotations from // If no group is specified, we are fetching annotations from
// all groups in order to find out which group contains the selected // all groups in order to find out which group contains the selected
...@@ -177,7 +177,7 @@ module.exports = function WidgetController( ...@@ -177,7 +177,7 @@ module.exports = function WidgetController(
// Remove client from list of active search clients // Remove client from list of active search clients
searchClients.splice(searchClients.indexOf(searchClient), 1); searchClients.splice(searchClients.indexOf(searchClient), 1);
}); });
searchClient.get({uri: uri, group: group}); searchClient.get({uri: uris, group: group});
} }
function isLoading() { function isLoading() {
...@@ -197,12 +197,14 @@ module.exports = function WidgetController( ...@@ -197,12 +197,14 @@ module.exports = function WidgetController(
client.cancel(); client.cancel();
}); });
var urls = frames.reduce(function (urls, frame) { var searchUris = frames.reduce(function (uris, frame) {
if (urls.indexOf(frame.uri) !== -1) { for (var i = 0; i < frame.searchUris.length; i++) {
return urls; var uri = frame.searchUris[i];
} else { if (uris.indexOf(uri) === -1) {
return urls.concat(frame.uri); uris.push(uri);
}
} }
return uris;
}, []); }, []);
// If there is no selection, load annotations only for the focused group. // If there is no selection, load annotations only for the focused group.
...@@ -219,12 +221,10 @@ module.exports = function WidgetController( ...@@ -219,12 +221,10 @@ module.exports = function WidgetController(
var group = annotationUI.hasSelectedAnnotations() ? var group = annotationUI.hasSelectedAnnotations() ?
null : groups.focused().id; null : groups.focused().id;
for (var i=0; i < urls.length; i++) { if (searchUris.length > 0) {
_loadAnnotationsFor(urls[i], group); _loadAnnotationsFor(searchUris, group);
}
if (urls.length > 0) { streamFilter.resetFilter().addClause('/uri', 'one_of', searchUris);
streamFilter.resetFilter().addClause('/uri', 'one_of', urls);
streamer.setConfig('filter', {filter: streamFilter.getFilter()}); streamer.setConfig('filter', {filter: streamFilter.getFilter()});
} }
} }
......
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