Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
coopwire-hypothesis
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
孙灵跃 Leon Sun
coopwire-hypothesis
Commits
06678e64
Commit
06678e64
authored
Aug 29, 2023
by
Robert Knight
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Preserve private/shared status of annotations on import
Fixes
https://github.com/hypothesis/client/issues/5757
parent
c2d543aa
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
86 additions
and
0 deletions
+86
-0
import-annotations.ts
src/sidebar/services/import-annotations.ts
+21
-0
import-annotations-test.js
src/sidebar/services/test/import-annotations-test.js
+65
-0
No files found.
src/sidebar/services/import-annotations.ts
View file @
06678e64
import
type
{
Annotation
,
APIAnnotationData
}
from
'../../types/api'
;
import
type
{
Annotation
,
APIAnnotationData
}
from
'../../types/api'
;
import
{
quote
}
from
'../helpers/annotation-metadata'
;
import
{
quote
}
from
'../helpers/annotation-metadata'
;
import
{
isShared
,
privatePermissions
,
sharedPermissions
,
}
from
'../helpers/permissions'
;
import
type
{
SidebarStore
}
from
'../store'
;
import
type
{
SidebarStore
}
from
'../store'
;
import
type
{
Frame
}
from
'../store/modules/frames'
;
import
type
{
Frame
}
from
'../store/modules/frames'
;
import
type
{
AnnotationsService
}
from
'./annotations'
;
import
type
{
AnnotationsService
}
from
'./annotations'
;
...
@@ -154,6 +159,15 @@ export class ImportAnnotationsService {
...
@@ -154,6 +159,15 @@ export class ImportAnnotationsService {
async
import
(
anns
:
APIAnnotationData
[]):
Promise
<
ImportResult
[]
>
{
async
import
(
anns
:
APIAnnotationData
[]):
Promise
<
ImportResult
[]
>
{
this
.
_store
.
beginImport
(
anns
.
length
);
this
.
_store
.
beginImport
(
anns
.
length
);
const
currentUser
=
this
.
_store
.
profile
().
userid
;
if
(
!
currentUser
)
{
throw
new
Error
(
'Cannot import when logged out'
);
}
const
currentGroup
=
this
.
_store
.
focusedGroupId
();
if
(
!
currentGroup
)
{
throw
new
Error
(
'Cannot import when no group is selected'
);
}
const
existingAnns
=
this
.
_store
.
allAnnotations
();
const
existingAnns
=
this
.
_store
.
allAnnotations
();
const
currentFrame
=
this
.
_store
.
mainFrame
();
const
currentFrame
=
this
.
_store
.
mainFrame
();
...
@@ -173,6 +187,13 @@ export class ImportAnnotationsService {
...
@@ -173,6 +187,13 @@ export class ImportAnnotationsService {
const
saveData
=
const
saveData
=
this
.
_annotationsService
.
annotationFromData
(
importData
);
this
.
_annotationsService
.
annotationFromData
(
importData
);
// Preserve shared / private status from existing annotation. We map
// the existing permissions to a shared/not-shared boolean and
// regenerate permissions, since the current user/group may differ.
saveData
.
permissions
=
isShared
(
ann
.
permissions
)
?
sharedPermissions
(
currentUser
,
currentGroup
)
:
privatePermissions
(
currentUser
);
// Persist the annotation.
// Persist the annotation.
const
saved
=
await
this
.
_annotationsService
.
save
(
saveData
);
const
saved
=
await
this
.
_annotationsService
.
save
(
saveData
);
...
...
src/sidebar/services/test/import-annotations-test.js
View file @
06678e64
import
{
privatePermissions
,
sharedPermissions
,
}
from
'../../helpers/permissions'
;
import
{
ImportAnnotationsService
}
from
'../import-annotations'
;
import
{
ImportAnnotationsService
}
from
'../import-annotations'
;
describe
(
'ImportAnnotationsService'
,
()
=>
{
describe
(
'ImportAnnotationsService'
,
()
=>
{
...
@@ -13,7 +17,11 @@ describe('ImportAnnotationsService', () => {
...
@@ -13,7 +17,11 @@ describe('ImportAnnotationsService', () => {
allAnnotations
:
sinon
.
stub
().
returns
([]),
allAnnotations
:
sinon
.
stub
().
returns
([]),
beginImport
:
sinon
.
stub
(),
beginImport
:
sinon
.
stub
(),
completeImport
:
sinon
.
stub
(),
completeImport
:
sinon
.
stub
(),
focusedGroupId
:
sinon
.
stub
().
returns
(
'group-a'
),
mainFrame
:
sinon
.
stub
().
returns
(
null
),
mainFrame
:
sinon
.
stub
().
returns
(
null
),
profile
:
sinon
.
stub
().
returns
({
userid
:
'acct:foo@example.org'
,
}),
};
};
fakeToastMessenger
=
{
fakeToastMessenger
=
{
...
@@ -54,6 +62,14 @@ describe('ImportAnnotationsService', () => {
...
@@ -54,6 +62,14 @@ describe('ImportAnnotationsService', () => {
text
:
`Annotation
${
counter
}
`
,
text
:
`Annotation
${
counter
}
`
,
tags
:
[
'foo'
],
tags
:
[
'foo'
],
document
:
{
title
:
'Example'
},
document
:
{
title
:
'Example'
},
permissions
:
sharedPermissions
(
fakeStore
.
profile
().
userid
,
// nb. We intentionally use a different group ID here than the current
// "focused" group in the store. The shared-ness will be preserved, but
// not the group ID.
'some-other-group'
,
),
...
fields
,
...
fields
,
};
};
}
}
...
@@ -70,6 +86,10 @@ describe('ImportAnnotationsService', () => {
...
@@ -70,6 +86,10 @@ describe('ImportAnnotationsService', () => {
source
:
'import'
,
source
:
'import'
,
original_id
:
ann
.
id
,
original_id
:
ann
.
id
,
},
},
permissions
:
sharedPermissions
(
fakeStore
.
profile
().
userid
,
fakeStore
.
focusedGroupId
(),
),
};
};
}
}
...
@@ -101,6 +121,21 @@ describe('ImportAnnotationsService', () => {
...
@@ -101,6 +121,21 @@ describe('ImportAnnotationsService', () => {
});
});
});
});
it
(
'preserves the private status of private annotations'
,
async
()
=>
{
const
originalUser
=
'acct:original@example.com'
;
const
svc
=
createService
();
const
ann
=
generateAnnotation
();
ann
.
permissions
=
privatePermissions
(
originalUser
);
await
svc
.
import
([
ann
]);
assert
.
calledWith
(
fakeAnnotationsService
.
save
,
{
$tag
:
'dummy'
,
...
importedAnnotation
(
ann
),
permissions
:
privatePermissions
(
fakeStore
.
profile
().
userid
),
});
});
it
(
'sets annotation URI and document metadata to match current document'
,
async
()
=>
{
it
(
'sets annotation URI and document metadata to match current document'
,
async
()
=>
{
const
newUri
=
'new_document_uri'
;
const
newUri
=
'new_document_uri'
;
const
newTitle
=
'new_document_title'
;
const
newTitle
=
'new_document_title'
;
...
@@ -190,5 +225,35 @@ describe('ImportAnnotationsService', () => {
...
@@ -190,5 +225,35 @@ describe('ImportAnnotationsService', () => {
assert
.
calledWith
(
fakeToastMessenger
.
error
,
'2 imports failed'
);
assert
.
calledWith
(
fakeToastMessenger
.
error
,
'2 imports failed'
);
});
});
it
(
'throws an error if called when user is logged out'
,
async
()
=>
{
const
svc
=
createService
();
fakeStore
.
profile
.
returns
({
userid
:
null
});
let
error
;
try
{
await
svc
.
import
([
generateAnnotation
()]);
}
catch
(
err
)
{
error
=
err
;
}
assert
.
instanceOf
(
error
,
Error
);
assert
.
equal
(
error
.
message
,
'Cannot import when logged out'
);
});
it
(
'throws an error if called when no group is selected'
,
async
()
=>
{
const
svc
=
createService
();
fakeStore
.
focusedGroupId
.
returns
(
null
);
let
error
;
try
{
await
svc
.
import
([
generateAnnotation
()]);
}
catch
(
err
)
{
error
=
err
;
}
assert
.
instanceOf
(
error
,
Error
);
assert
.
equal
(
error
.
message
,
'Cannot import when no group is selected'
);
});
});
});
});
});
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment