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
f319e86f
Commit
f319e86f
authored
Jan 22, 2020
by
Lyza Danger Gardner
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add some footer components to `AnnotationOmega`
Stub out some not-yet-implemented callbacks
parent
1914170d
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
257 additions
and
17 deletions
+257
-17
annotation-omega.js
src/sidebar/components/annotation-omega.js
+49
-1
annotation-omega-test.js
src/sidebar/components/test/annotation-omega-test.js
+208
-16
No files found.
src/sidebar/components/annotation-omega.js
View file @
f319e86f
...
@@ -2,10 +2,14 @@ import { createElement } from 'preact';
...
@@ -2,10 +2,14 @@ import { createElement } from 'preact';
import
propTypes
from
'prop-types'
;
import
propTypes
from
'prop-types'
;
import
useStore
from
'../store/use-store'
;
import
useStore
from
'../store/use-store'
;
import
{
quote
}
from
'../util/annotation-metadata'
;
import
{
isNew
,
isReply
,
quote
}
from
'../util/annotation-metadata'
;
import
{
isShared
}
from
'../util/permissions'
;
import
AnnotationActionBar
from
'./annotation-action-bar'
;
import
AnnotationBody
from
'./annotation-body'
;
import
AnnotationBody
from
'./annotation-body'
;
import
AnnotationHeader
from
'./annotation-header'
;
import
AnnotationHeader
from
'./annotation-header'
;
import
AnnotationLicense
from
'./annotation-license'
;
import
AnnotationPublishControl
from
'./annotation-publish-control'
;
import
AnnotationQuote
from
'./annotation-quote'
;
import
AnnotationQuote
from
'./annotation-quote'
;
import
TagEditor
from
'./tag-editor'
;
import
TagEditor
from
'./tag-editor'
;
import
TagList
from
'./tag-list'
;
import
TagList
from
'./tag-list'
;
...
@@ -20,16 +24,24 @@ function AnnotationOmega({
...
@@ -20,16 +24,24 @@ function AnnotationOmega({
showDocumentInfo
,
showDocumentInfo
,
})
{
})
{
const
createDraft
=
useStore
(
store
=>
store
.
createDraft
);
const
createDraft
=
useStore
(
store
=>
store
.
createDraft
);
const
setDefault
=
useStore
(
store
=>
store
.
setDefault
);
// An annotation will have a draft if it is being edited
// An annotation will have a draft if it is being edited
const
draft
=
useStore
(
store
=>
store
.
getDraft
(
annotation
));
const
draft
=
useStore
(
store
=>
store
.
getDraft
(
annotation
));
const
group
=
useStore
(
store
=>
store
.
getGroup
(
annotation
.
group
));
const
isPrivate
=
draft
?
draft
.
isPrivate
:
!
isShared
(
annotation
.
permissions
);
const
tags
=
draft
?
draft
.
tags
:
annotation
.
tags
;
const
tags
=
draft
?
draft
.
tags
:
annotation
.
tags
;
const
text
=
draft
?
draft
.
text
:
annotation
.
text
;
const
text
=
draft
?
draft
.
text
:
annotation
.
text
;
const
hasQuote
=
!!
quote
(
annotation
);
const
hasQuote
=
!!
quote
(
annotation
);
const
isEmpty
=
!
text
&&
!
tags
.
length
;
const
isSaving
=
false
;
const
isSaving
=
false
;
const
isEditing
=
!!
draft
&&
!
isSaving
;
const
isEditing
=
!!
draft
&&
!
isSaving
;
const
shouldShowActions
=
!
isEditing
&&
!
isNew
(
annotation
);
const
shouldShowLicense
=
isEditing
&&
!
isPrivate
&&
group
.
type
!==
'private'
;
const
onEditTags
=
({
tags
})
=>
{
const
onEditTags
=
({
tags
})
=>
{
createDraft
(
annotation
,
{
...
draft
,
tags
});
createDraft
(
annotation
,
{
...
draft
,
tags
});
};
};
...
@@ -38,6 +50,20 @@ function AnnotationOmega({
...
@@ -38,6 +50,20 @@ function AnnotationOmega({
createDraft
(
annotation
,
{
...
draft
,
text
});
createDraft
(
annotation
,
{
...
draft
,
text
});
};
};
const
onSetPrivacy
=
({
level
})
=>
{
createDraft
(
annotation
,
{
...
draft
,
isPrivate
:
level
===
'private'
});
// Persist this as privacy default for future annotations unless this is a reply
if
(
!
isReply
(
annotation
))
{
setDefault
(
'annotationPrivacy'
,
level
);
}
};
// TODO
const
fakeOnEdit
=
()
=>
alert
(
'Enter edit mode: TBD'
);
const
fakeOnReply
=
()
=>
alert
(
'Reply: TBD'
);
const
fakeOnRevert
=
()
=>
alert
(
'Revert changes: TBD'
);
const
fakeOnSave
=
()
=>
alert
(
'Save changes: TBD'
);
return
(
return
(
<
div
className
=
"annotation-omega"
>
<
div
className
=
"annotation-omega"
>
<
AnnotationHeader
<
AnnotationHeader
...
@@ -56,6 +82,28 @@ function AnnotationOmega({
...
@@ -56,6 +82,28 @@ function AnnotationOmega({
/
>
/
>
{
isEditing
&&
<
TagEditor
onEditTags
=
{
onEditTags
}
tagList
=
{
tags
}
/>
}
{
isEditing
&&
<
TagEditor
onEditTags
=
{
onEditTags
}
tagList
=
{
tags
}
/>
}
{
!
isEditing
&&
<
TagList
annotation
=
{
annotation
}
tags
=
{
tags
}
/>
}
{
!
isEditing
&&
<
TagList
annotation
=
{
annotation
}
tags
=
{
tags
}
/>
}
<
footer
className
=
"annotation-footer"
>
{
isEditing
&&
(
<
AnnotationPublishControl
group
=
{
group
}
isDisabled
=
{
isEmpty
}
isShared
=
{
!
isPrivate
}
onCancel
=
{
fakeOnRevert
}
onSave
=
{
fakeOnSave
}
onSetPrivacy
=
{
onSetPrivacy
}
/
>
)}
{
shouldShowLicense
&&
<
AnnotationLicense
/>
}
{
shouldShowActions
&&
(
<
div
className
=
"annotation-actions"
>
<
AnnotationActionBar
annotation
=
{
annotation
}
onEdit
=
{
fakeOnEdit
}
onReply
=
{
fakeOnReply
}
/
>
<
/div
>
)}
<
/footer
>
<
/div
>
<
/div
>
);
);
}
}
...
...
src/sidebar/components/test/annotation-omega-test.js
View file @
f319e86f
...
@@ -15,9 +15,19 @@ describe('AnnotationOmega', () => {
...
@@ -15,9 +15,19 @@ describe('AnnotationOmega', () => {
let
fakeOnReplyCountClick
;
let
fakeOnReplyCountClick
;
// Dependency Mocks
// Dependency Mocks
let
fakeQuote
;
let
fakeMetadata
;
let
fakePermissions
;
let
fakeStore
;
let
fakeStore
;
const
setEditingMode
=
(
isEditing
=
true
)
=>
{
// The presence of a draft will make `isEditing` `true`
if
(
isEditing
)
{
fakeStore
.
getDraft
.
returns
(
fixtures
.
defaultDraft
());
}
else
{
fakeStore
.
getDraft
.
returns
(
null
);
}
};
const
createComponent
=
props
=>
{
const
createComponent
=
props
=>
{
return
mount
(
return
mount
(
<
Annotation
<
Annotation
...
@@ -33,17 +43,29 @@ describe('AnnotationOmega', () => {
...
@@ -33,17 +43,29 @@ describe('AnnotationOmega', () => {
beforeEach
(()
=>
{
beforeEach
(()
=>
{
fakeOnReplyCountClick
=
sinon
.
stub
();
fakeOnReplyCountClick
=
sinon
.
stub
();
fakeQuote
=
sinon
.
stub
();
fakeMetadata
=
{
isNew
:
sinon
.
stub
(),
isReply
:
sinon
.
stub
().
returns
(
false
),
quote
:
sinon
.
stub
(),
};
fakePermissions
=
{
isShared
:
sinon
.
stub
().
returns
(
true
),
};
fakeStore
=
{
fakeStore
=
{
createDraft
:
sinon
.
stub
(),
createDraft
:
sinon
.
stub
(),
getDraft
:
sinon
.
stub
().
returns
(
null
),
getDraft
:
sinon
.
stub
().
returns
(
null
),
getGroup
:
sinon
.
stub
().
returns
({
type
:
'private'
,
}),
setDefault
:
sinon
.
stub
(),
};
};
$imports
.
$mock
(
mockImportedComponents
());
$imports
.
$mock
(
mockImportedComponents
());
$imports
.
$mock
({
$imports
.
$mock
({
'../util/annotation-metadata'
:
{
'../util/annotation-metadata'
:
fakeMetadata
,
quote
:
fakeQuote
,
'../util/permissions'
:
fakePermissions
,
},
'../store/use-store'
:
callback
=>
callback
(
fakeStore
),
'../store/use-store'
:
callback
=>
callback
(
fakeStore
),
});
});
});
});
...
@@ -54,7 +76,7 @@ describe('AnnotationOmega', () => {
...
@@ -54,7 +76,7 @@ describe('AnnotationOmega', () => {
describe
(
'annotation quote'
,
()
=>
{
describe
(
'annotation quote'
,
()
=>
{
it
(
'renders quote if annotation has a quote'
,
()
=>
{
it
(
'renders quote if annotation has a quote'
,
()
=>
{
fake
Q
uote
.
returns
(
'quote'
);
fake
Metadata
.
q
uote
.
returns
(
'quote'
);
const
wrapper
=
createComponent
();
const
wrapper
=
createComponent
();
const
quote
=
wrapper
.
find
(
'AnnotationQuote'
);
const
quote
=
wrapper
.
find
(
'AnnotationQuote'
);
...
@@ -62,7 +84,7 @@ describe('AnnotationOmega', () => {
...
@@ -62,7 +84,7 @@ describe('AnnotationOmega', () => {
});
});
it
(
'does not render quote if annotation does not have a quote'
,
()
=>
{
it
(
'does not render quote if annotation does not have a quote'
,
()
=>
{
fake
Q
uote
.
returns
(
null
);
fake
Metadata
.
q
uote
.
returns
(
null
);
const
wrapper
=
createComponent
();
const
wrapper
=
createComponent
();
...
@@ -72,7 +94,7 @@ describe('AnnotationOmega', () => {
...
@@ -72,7 +94,7 @@ describe('AnnotationOmega', () => {
});
});
describe
(
'annotation body and excerpt'
,
()
=>
{
describe
(
'annotation body and excerpt'
,
()
=>
{
it
(
'updates annotation
state
when text edited'
,
()
=>
{
it
(
'updates annotation
draft
when text edited'
,
()
=>
{
const
wrapper
=
createComponent
();
const
wrapper
=
createComponent
();
const
body
=
wrapper
.
find
(
'AnnotationBody'
);
const
body
=
wrapper
.
find
(
'AnnotationBody'
);
...
@@ -80,23 +102,24 @@ describe('AnnotationOmega', () => {
...
@@ -80,23 +102,24 @@ describe('AnnotationOmega', () => {
body
.
props
().
onEditText
({
text
:
'updated text'
});
body
.
props
().
onEditText
({
text
:
'updated text'
});
});
});
const
call
=
fakeStore
.
createDraft
.
getCall
(
0
);
assert
.
calledOnce
(
fakeStore
.
createDraft
);
assert
.
calledOnce
(
fakeStore
.
createDraft
);
assert
.
equal
(
call
.
args
[
1
].
text
,
'updated text'
);
});
});
});
});
describe
(
'tags'
,
()
=>
{
describe
(
'tags'
,
()
=>
{
it
(
'renders tag editor if `isEditing'
,
()
=>
{
it
(
'renders tag editor if `isEditing'
,
()
=>
{
// The presence of a draft will make `isEditing` `true`
setEditingMode
(
true
);
fakeStore
.
getDraft
.
returns
(
fixtures
.
defaultDraft
());
const
wrapper
=
createComponent
();
const
wrapper
=
createComponent
();
assert
.
is
Ok
(
wrapper
.
find
(
'TagEditor'
).
exists
());
assert
.
is
True
(
wrapper
.
find
(
'TagEditor'
).
exists
());
assert
.
notOk
(
wrapper
.
find
(
'TagList'
).
exists
());
assert
.
isFalse
(
wrapper
.
find
(
'TagList'
).
exists
());
});
});
it
(
'updates annotation
state
if tags changed'
,
()
=>
{
it
(
'updates annotation
draft
if tags changed'
,
()
=>
{
fakeStore
.
getDraft
.
returns
(
fixtures
.
defaultDraft
()
);
setEditingMode
(
true
);
const
wrapper
=
createComponent
();
const
wrapper
=
createComponent
();
wrapper
wrapper
...
@@ -104,14 +127,183 @@ describe('AnnotationOmega', () => {
...
@@ -104,14 +127,183 @@ describe('AnnotationOmega', () => {
.
props
()
.
props
()
.
onEditTags
({
tags
:
[
'uno'
,
'dos'
]
});
.
onEditTags
({
tags
:
[
'uno'
,
'dos'
]
});
const
call
=
fakeStore
.
createDraft
.
getCall
(
0
);
assert
.
calledOnce
(
fakeStore
.
createDraft
);
assert
.
calledOnce
(
fakeStore
.
createDraft
);
assert
.
sameMembers
(
call
.
args
[
1
].
tags
,
[
'uno'
,
'dos'
]);
});
});
it
(
'renders tag list if not `isEditing'
,
()
=>
{
it
(
'renders tag list if not `isEditing'
,
()
=>
{
const
wrapper
=
createComponent
();
const
wrapper
=
createComponent
();
assert
.
isOk
(
wrapper
.
find
(
'TagList'
).
exists
());
assert
.
isTrue
(
wrapper
.
find
(
'TagList'
).
exists
());
assert
.
notOk
(
wrapper
.
find
(
'TagEditor'
).
exists
());
assert
.
isFalse
(
wrapper
.
find
(
'TagEditor'
).
exists
());
});
});
describe
(
'publish control'
,
()
=>
{
it
(
'should show the publish control if in edit mode'
,
()
=>
{
setEditingMode
(
true
);
const
wrapper
=
createComponent
();
assert
.
isTrue
(
wrapper
.
find
(
'AnnotationPublishControl'
).
exists
());
});
it
(
'should not show the publish control if not in edit mode'
,
()
=>
{
setEditingMode
(
false
);
const
wrapper
=
createComponent
();
assert
.
isFalse
(
wrapper
.
find
(
'AnnotationPublishControl'
).
exists
());
});
it
(
'should set the publish control to disabled if annotation is empty'
,
()
=>
{
const
draft
=
fixtures
.
defaultDraft
();
draft
.
tags
=
[];
draft
.
text
=
''
;
fakeStore
.
getDraft
.
returns
(
draft
);
const
wrapper
=
createComponent
();
assert
.
isTrue
(
wrapper
.
find
(
'AnnotationPublishControl'
).
props
().
isDisabled
);
});
it
(
'should set `isShared` to `false` if annotation is private'
,
()
=>
{
const
draft
=
fixtures
.
defaultDraft
();
draft
.
isPrivate
=
true
;
fakeStore
.
getDraft
.
returns
(
draft
);
const
wrapper
=
createComponent
();
assert
.
isFalse
(
wrapper
.
find
(
'AnnotationPublishControl'
).
props
().
isShared
);
});
it
(
'should set `isShared` to `true` if annotation is shared'
,
()
=>
{
const
draft
=
fixtures
.
defaultDraft
();
draft
.
isPrivate
=
false
;
fakeStore
.
getDraft
.
returns
(
draft
);
const
wrapper
=
createComponent
();
assert
.
isTrue
(
wrapper
.
find
(
'AnnotationPublishControl'
).
props
().
isShared
);
});
it
(
'should update annotation privacy when changed by publish control'
,
()
=>
{
setEditingMode
(
true
);
const
wrapper
=
createComponent
();
act
(()
=>
{
wrapper
.
find
(
'AnnotationPublishControl'
)
.
props
()
.
onSetPrivacy
({
level
:
'private'
});
});
const
call
=
fakeStore
.
createDraft
.
getCall
(
0
);
assert
.
calledOnce
(
fakeStore
.
createDraft
);
assert
.
isTrue
(
call
.
args
[
1
].
isPrivate
);
});
it
(
'should update annotation privacy default on change'
,
()
=>
{
setEditingMode
(
true
);
const
wrapper
=
createComponent
();
act
(()
=>
{
wrapper
.
find
(
'AnnotationPublishControl'
)
.
props
()
.
onSetPrivacy
({
level
:
'private'
});
});
assert
.
calledOnce
(
fakeStore
.
setDefault
);
assert
.
calledWith
(
fakeStore
.
setDefault
,
'annotationPrivacy'
,
'private'
);
});
it
(
'should not update annotation privacy default on change if annotation is reply'
,
()
=>
{
fakeMetadata
.
isReply
.
returns
(
true
);
setEditingMode
(
true
);
const
wrapper
=
createComponent
();
act
(()
=>
{
wrapper
.
find
(
'AnnotationPublishControl'
)
.
props
()
.
onSetPrivacy
({
level
:
'private'
});
});
assert
.
equal
(
fakeStore
.
setDefault
.
callCount
,
0
);
});
});
describe
(
'license information'
,
()
=>
{
it
(
'should show license information when editing shared annotations in public groups'
,
()
=>
{
fakeStore
.
getGroup
.
returns
({
type
:
'open'
});
setEditingMode
(
true
);
const
wrapper
=
createComponent
();
assert
.
isTrue
(
wrapper
.
find
(
'AnnotationLicense'
).
exists
());
});
it
(
'should not show license information when not editing'
,
()
=>
{
fakeStore
.
getGroup
.
returns
({
type
:
'open'
});
setEditingMode
(
false
);
const
wrapper
=
createComponent
();
assert
.
isFalse
(
wrapper
.
find
(
'AnnotationLicense'
).
exists
());
});
it
(
'should not show license information for annotations in private groups'
,
()
=>
{
fakeStore
.
getGroup
.
returns
({
type
:
'private'
});
setEditingMode
(
true
);
const
wrapper
=
createComponent
();
assert
.
isFalse
(
wrapper
.
find
(
'AnnotationLicense'
).
exists
());
});
it
(
'should not show license information for private annotations'
,
()
=>
{
const
draft
=
fixtures
.
defaultDraft
();
draft
.
isPrivate
=
true
;
fakeStore
.
getGroup
.
returns
({
type
:
'open'
});
fakeStore
.
getDraft
.
returns
(
draft
);
const
wrapper
=
createComponent
();
assert
.
isFalse
(
wrapper
.
find
(
'AnnotationLicense'
).
exists
());
});
});
describe
(
'annotation actions'
,
()
=>
{
it
(
'should show annotation actions'
,
()
=>
{
const
wrapper
=
createComponent
();
assert
.
isTrue
(
wrapper
.
find
(
'AnnotationActionBar'
).
exists
());
});
it
(
'should not show annotation actions when editing'
,
()
=>
{
setEditingMode
(
true
);
const
wrapper
=
createComponent
();
assert
.
isFalse
(
wrapper
.
find
(
'AnnotationActionBar'
).
exists
());
});
it
(
'should not show annotation actions for new annotation'
,
()
=>
{
fakeMetadata
.
isNew
.
returns
(
true
);
const
wrapper
=
createComponent
();
assert
.
isFalse
(
wrapper
.
find
(
'AnnotationActionBar'
).
exists
());
});
});
});
});
});
});
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