Commit da7b94c9 authored by Robert Knight's avatar Robert Knight

Add `extra.{source, original_id}` fields to imported annotations

Record the fact that imported annotations were created via the client's import
mechanism, and the original ID of the annotation. This is currently stored in
the `extra` field. h supports setting arbitrary fields at the top level of
annotations, so we could have put the data there instead. However using the
`extra` field for custom fields is a convention already used by some API
clients, and is distinct from a standard/validated field if we add one later on.

Fixes https://github.com/hypothesis/client/issues/5738
parent 23dffed3
...@@ -7,13 +7,31 @@ import type { ToastMessengerService } from './toast-messenger'; ...@@ -7,13 +7,31 @@ import type { ToastMessengerService } from './toast-messenger';
/** Number of annotations to import concurrently. */ /** Number of annotations to import concurrently. */
export const MAX_CONCURRENT_IMPORTS = 5; export const MAX_CONCURRENT_IMPORTS = 5;
/**
* Non-standard metadata fields added to imported annotations.
*
* These are added for analytics / reporting purposes. If we decide to make
* other uses of it, we should migrate these to a proper annotation metadata
* field.
*/
type ImportExtra = {
extra: {
/** Indicator for where the annotation came from. */
source: 'import';
/** Original ID of the annotation that was imported. */
original_id?: string;
};
};
/** /**
* The subset of annotation fields which are preserved during an import. * The subset of annotation fields which are preserved during an import.
*/ */
type ImportData = Pick< type ImportData = Pick<
APIAnnotationData, APIAnnotationData,
'document' | 'tags' | 'text' | 'target' | 'uri' 'document' | 'tags' | 'text' | 'target' | 'uri'
>; > &
ImportExtra;
/** /**
* Return a copy of `ann` that contains only fields which can be preserved by * Return a copy of `ann` that contains only fields which can be preserved by
...@@ -26,6 +44,10 @@ function getImportData(ann: APIAnnotationData): ImportData { ...@@ -26,6 +44,10 @@ function getImportData(ann: APIAnnotationData): ImportData {
text: ann.text, text: ann.text,
uri: ann.uri, uri: ann.uri,
document: ann.document, document: ann.document,
extra: {
source: 'import',
original_id: ann.id,
},
}; };
} }
......
...@@ -43,6 +43,7 @@ describe('ImportAnnotationsService', () => { ...@@ -43,6 +43,7 @@ describe('ImportAnnotationsService', () => {
function generateAnnotation(fields = {}) { function generateAnnotation(fields = {}) {
++counter; ++counter;
return { return {
id: `id-${counter}`,
uri: 'https://example.com', uri: 'https://example.com',
target: [ target: [
{ {
...@@ -56,6 +57,21 @@ describe('ImportAnnotationsService', () => { ...@@ -56,6 +57,21 @@ describe('ImportAnnotationsService', () => {
}; };
} }
/** Return the expected imported annotation for a given annotation. */
function importedAnnotation(ann) {
return {
document: ann.document,
tags: ann.tags,
target: ann.target,
text: ann.text,
uri: ann.uri,
extra: {
source: 'import',
original_id: ann.id,
},
};
}
describe('#import', () => { describe('#import', () => {
it('increments count of pending imports', async () => { it('increments count of pending imports', async () => {
const svc = createService(); const svc = createService();
...@@ -80,7 +96,7 @@ describe('ImportAnnotationsService', () => { ...@@ -80,7 +96,7 @@ describe('ImportAnnotationsService', () => {
assert.calledWith(fakeAnnotationsService.save, { assert.calledWith(fakeAnnotationsService.save, {
$tag: 'dummy', $tag: 'dummy',
...ann, ...importedAnnotation(ann),
}); });
}); });
...@@ -98,7 +114,7 @@ describe('ImportAnnotationsService', () => { ...@@ -98,7 +114,7 @@ describe('ImportAnnotationsService', () => {
for (const ann of anns) { for (const ann of anns) {
assert.calledWith(fakeAnnotationsService.save, { assert.calledWith(fakeAnnotationsService.save, {
$tag: 'dummy', $tag: 'dummy',
...ann, ...importedAnnotation(ann),
}); });
} }
}); });
......
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