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
66cf493a
Commit
66cf493a
authored
Feb 10, 2021
by
Lyza Danger Gardner
Committed by
Lyza Gardner
Feb 12, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Merge `AnnotationMissing` into `Annotation`
parent
963f5961
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
105 additions
and
235 deletions
+105
-235
Annotation.js
src/sidebar/components/Annotation.js
+36
-27
AnnotationMissing.js
src/sidebar/components/AnnotationMissing.js
+0
-63
Thread.js
src/sidebar/components/Thread.js
+18
-34
Annotation-test.js
src/sidebar/components/test/Annotation-test.js
+48
-0
AnnotationMissing-test.js
src/sidebar/components/test/AnnotationMissing-test.js
+0
-100
Thread-test.js
src/sidebar/components/test/Thread-test.js
+3
-11
No files found.
src/sidebar/components/Annotation.js
View file @
66cf493a
...
...
@@ -19,7 +19,9 @@ import AnnotationReplyToggle from './AnnotationReplyToggle';
/**
* @typedef AnnotationProps
* @prop {Annotation} annotation
* @prop {Annotation} [annotation] - The annotation to render. If undefined,
* this Annotation will render as a "missing annotation" and will stand in
* as an Annotation for threads that lack an annotation.
* @prop {boolean} hasAppliedFilter - Is any filter applied currently?
* @prop {boolean} isReply
* @prop {VoidFunction} onToggleReplies - Callback to expand/collapse reply threads
...
...
@@ -44,21 +46,17 @@ function Annotation({
threadIsCollapsed
,
annotationsService
,
})
{
const
store
=
useStoreProxy
();
const
isFocused
=
store
.
isAnnotationFocused
(
annotation
.
$tag
);
// An annotation will have a draft if it is being edited
const
draft
=
store
.
getDraft
(
annotation
);
const
userid
=
store
.
profile
().
userid
;
const
isSaving
=
store
.
isSavingAnnotation
(
annotation
);
const
isCollapsedReply
=
isReply
&&
threadIsCollapsed
;
const
hasQuote
=
!!
quote
(
annotation
);
const
store
=
useStoreProxy
(
);
const
isEditing
=
!!
draft
&&
!
isSaving
;
const
hasQuote
=
annotation
&&
!!
quote
(
annotation
);
const
isFocused
=
annotation
&&
store
.
isAnnotationFocused
(
annotation
.
$tag
);
const
isSaving
=
annotation
&&
store
.
isSavingAnnotation
(
annotation
);
const
isEditing
=
annotation
&&
!!
store
.
getDraft
(
annotation
)
&&
!
isSaving
;
const
showActions
=
!
isSaving
&&
!
isEditing
;
const
userid
=
store
.
profile
().
userid
;
const
showActions
=
annotation
&&
!
isSaving
&&
!
isEditing
;
const
showReplyToggle
=
!
isReply
&&
!
hasAppliedFilter
&&
replyCount
>
0
;
const
onReply
=
()
=>
annotationsService
.
reply
(
annotation
,
userid
);
...
...
@@ -66,29 +64,40 @@ function Annotation({
return
(
<
article
className
=
{
classnames
(
'Annotation'
,
{
'Annotation--missing'
:
!
annotation
,
'Annotation--reply'
:
isReply
,
'is-collapsed'
:
threadIsCollapsed
,
'is-focused'
:
isFocused
,
})}
>
<
AnnotationHeader
annotation
=
{
annotation
}
isEditing
=
{
isEditing
}
replyCount
=
{
replyCount
}
showDocumentInfo
=
{
showDocumentInfo
}
threadIsCollapsed
=
{
threadIsCollapsed
}
/
>
{
hasQuote
&&
(
<
AnnotationQuote
annotation
=
{
annotation
}
isFocused
=
{
isFocused
}
/
>
{
annotation
&&
(
<>
<
AnnotationHeader
annotation
=
{
annotation
}
isEditing
=
{
isEditing
}
replyCount
=
{
replyCount
}
showDocumentInfo
=
{
showDocumentInfo
}
threadIsCollapsed
=
{
threadIsCollapsed
}
/
>
{
hasQuote
&&
(
<
AnnotationQuote
annotation
=
{
annotation
}
isFocused
=
{
isFocused
}
/
>
)}
{
!
isCollapsedReply
&&
!
isEditing
&&
(
<
AnnotationBody
annotation
=
{
annotation
}
/
>
)}
{
isEditing
&&
<
AnnotationEditor
annotation
=
{
annotation
}
/>
}
<
/
>
)}
{
!
isCollapsedReply
&&
!
isEditing
&&
(
<
AnnotationBody
annotation
=
{
annotation
}
/
>
{
!
annotation
&&
!
isCollapsedReply
&&
(
<
div
>
<
em
>
Message
not
available
.
<
/em
>
<
/div
>
)}
{
isEditing
&&
<
AnnotationEditor
annotation
=
{
annotation
}
/>
}
{
!
isCollapsedReply
&&
(
<
footer
className
=
"Annotation__footer"
>
<
div
className
=
"Annotation__controls u-layout-row"
>
...
...
@@ -116,7 +125,7 @@ function Annotation({
}
Annotation
.
propTypes
=
{
annotation
:
propTypes
.
object
.
isRequired
,
annotation
:
propTypes
.
object
,
hasAppliedFilter
:
propTypes
.
bool
.
isRequired
,
isReply
:
propTypes
.
bool
,
onToggleReplies
:
propTypes
.
func
,
...
...
src/sidebar/components/AnnotationMissing.js
deleted
100644 → 0
View file @
963f5961
import
classnames
from
'classnames'
;
import
propTypes
from
'prop-types'
;
import
AnnotationReplyToggle
from
'./AnnotationReplyToggle'
;
/**
* @typedef {import('./Annotation').AnnotationProps} AnnotationProps
* @typedef {Omit<AnnotationProps, 'annotation'|'showDocumentInfo'|'annotationsService'>} AnnotationMissingProps
*/
/**
* Renders in place of an annotation if a thread's annotation is missing.
*
* @param {AnnotationMissingProps} props
*/
function
AnnotationMissing
({
hasAppliedFilter
,
isReply
,
onToggleReplies
,
replyCount
,
threadIsCollapsed
,
})
{
const
showReplyToggle
=
!
isReply
&&
!
hasAppliedFilter
&&
replyCount
>
0
;
const
isCollapsedReply
=
isReply
&&
threadIsCollapsed
;
return
(
<
article
className
=
{
classnames
(
'Annotation'
,
'Annotation--missing'
,
{
'is-collapsed'
:
threadIsCollapsed
,
})}
>
{
!
isCollapsedReply
&&
(
<
div
>
<
em
>
Message
not
available
.
<
/em
>
<
/div
>
)}
{
!
isCollapsedReply
&&
(
<
footer
className
=
"Annotation__footer"
>
<
div
className
=
"Annotation__controls u-layout-row"
>
{
showReplyToggle
&&
(
<
AnnotationReplyToggle
onToggleReplies
=
{
onToggleReplies
}
replyCount
=
{
replyCount
}
threadIsCollapsed
=
{
threadIsCollapsed
}
/
>
)}
<
/div
>
<
/footer
>
)}
<
/article
>
);
}
AnnotationMissing
.
propTypes
=
{
hasAppliedFilter
:
propTypes
.
bool
,
isReply
:
propTypes
.
bool
.
isRequired
,
onToggleReplies
:
propTypes
.
func
,
replyCount
:
propTypes
.
number
.
isRequired
,
threadIsCollapsed
:
propTypes
.
bool
,
};
export
default
AnnotationMissing
;
src/sidebar/components/Thread.js
View file @
66cf493a
...
...
@@ -7,7 +7,6 @@ import { withServices } from '../service-context';
import
{
countHidden
,
countVisible
}
from
'../helpers/thread'
;
import
Annotation
from
'./Annotation'
;
import
AnnotationMissing
from
'./AnnotationMissing'
;
import
Button
from
'./Button'
;
import
ModerationBanner
from
'./ModerationBanner'
;
...
...
@@ -28,10 +27,6 @@ import ModerationBanner from './ModerationBanner';
* @param {ThreadProps} props
*/
function
Thread
({
showDocumentInfo
=
false
,
thread
,
threadsService
})
{
// Only render this thread's annotation if it exists and the thread is `visible`
const
showAnnotation
=
thread
.
annotation
&&
thread
.
visible
;
const
showMissingAnnotation
=
thread
.
visible
&&
!
thread
.
annotation
;
// Render this thread's replies only if the thread is expanded
const
showChildren
=
!
thread
.
collapsed
;
...
...
@@ -60,11 +55,13 @@ function Thread({ showDocumentInfo = false, thread, threadsService }) {
// Memoize annotation content to avoid re-rendering an annotation when content
// in other annotations/threads change.
const
annotationContent
=
useMemo
(
()
=>
{
if
(
showAnnotation
)
{
return
(
const
annotationContent
=
useMemo
(
()
=>
thread
.
visible
&&
(
<>
<
ModerationBanner
annotation
=
{
thread
.
annotation
}
/
>
{
thread
.
annotation
&&
(
<
ModerationBanner
annotation
=
{
thread
.
annotation
}
/
>
)}
<
Annotation
annotation
=
{
thread
.
annotation
}
hasAppliedFilter
=
{
hasAppliedFilter
}
...
...
@@ -75,31 +72,18 @@ function Thread({ showDocumentInfo = false, thread, threadsService }) {
threadIsCollapsed
=
{
thread
.
collapsed
}
/
>
<
/
>
);
}
else
if
(
showMissingAnnotation
)
{
return
(
<
AnnotationMissing
hasAppliedFilter
=
{
hasAppliedFilter
}
isReply
=
{
!!
thread
.
parent
}
onToggleReplies
=
{
onToggleReplies
}
replyCount
=
{
thread
.
replyCount
}
threadIsCollapsed
=
{
thread
.
collapsed
}
/
>
);
}
else
{
return
null
;
}
},
[
hasAppliedFilter
,
onToggleReplies
,
showAnnotation
,
showMissingAnnotation
,
showDocumentInfo
,
thread
.
annotation
,
thread
.
parent
,
thread
.
replyCount
,
thread
.
collapsed
,
]);
),
[
hasAppliedFilter
,
onToggleReplies
,
showDocumentInfo
,
thread
.
annotation
,
thread
.
parent
,
thread
.
replyCount
,
thread
.
collapsed
,
thread
.
visible
,
]
);
return
(
<
section
...
...
src/sidebar/components/test/Annotation-test.js
View file @
66cf493a
...
...
@@ -249,6 +249,54 @@ describe('Annotation', () => {
assert
.
isTrue
(
wrapper
.
find
(
'footer'
).
exists
());
});
});
context
(
'missing annotation'
,
()
=>
{
it
(
'should render a message about annotation unavailability'
,
()
=>
{
const
wrapper
=
createComponent
({
annotation
:
undefined
});
assert
.
equal
(
wrapper
.
text
(),
'Message not available.'
);
});
it
(
'should not render a message if collapsed reply'
,
()
=>
{
const
wrapper
=
createComponent
({
annotation
:
undefined
,
isReply
:
true
,
threadIsCollapsed
:
true
,
});
assert
.
equal
(
wrapper
.
text
(),
''
);
});
it
(
'should render reply toggle controls if there are replies'
,
()
=>
{
const
wrapper
=
createComponent
({
annotation
:
undefined
,
replyCount
:
5
,
threadIsCollapsed
:
true
,
});
const
toggle
=
wrapper
.
find
(
'AnnotationReplyToggle'
);
assert
.
isTrue
(
toggle
.
exists
());
assert
.
equal
(
toggle
.
props
().
onToggleReplies
,
fakeOnToggleReplies
);
assert
.
equal
(
toggle
.
props
().
replyCount
,
5
);
assert
.
equal
(
toggle
.
props
().
threadIsCollapsed
,
true
);
});
it
(
'should not render reply toggle controls if collapsed reply'
,
()
=>
{
const
wrapper
=
createComponent
({
annotation
:
undefined
,
isReply
:
true
,
replyCount
:
5
,
threadIsCollapsed
:
true
,
});
const
toggle
=
wrapper
.
find
(
'AnnotationReplyToggle'
);
assert
.
isFalse
(
toggle
.
exists
());
});
it
(
'should not render other annotation sub-components'
);
});
});
it
(
...
...
src/sidebar/components/test/AnnotationMissing-test.js
deleted
100644 → 0
View file @
963f5961
import
{
mount
}
from
'enzyme'
;
import
AnnotationMissing
,
{
$imports
}
from
'../AnnotationMissing'
;
import
{
checkAccessibility
}
from
'../../../test-util/accessibility'
;
import
mockImportedComponents
from
'../../../test-util/mock-imported-components'
;
describe
(
'AnnotationMissing'
,
()
=>
{
let
fakeOnToggleReplies
;
function
createComponent
(
props
=
{})
{
return
mount
(
<
AnnotationMissing
hasAppliedFilter
=
{
false
}
isReply
=
{
false
}
onToggleReplies
=
{
fakeOnToggleReplies
}
replyCount
=
{
5
}
threadIsCollapsed
=
{
true
}
{...
props
}
/
>
);
}
beforeEach
(()
=>
{
fakeOnToggleReplies
=
sinon
.
stub
();
$imports
.
$mock
(
mockImportedComponents
());
});
afterEach
(()
=>
{
$imports
.
$restore
();
});
context
(
'collapsed reply'
,
()
=>
{
it
(
'does not show message-unavailable text'
,
()
=>
{
const
wrapper
=
createComponent
({
isReply
:
true
,
threadIsCollapsed
:
true
,
});
assert
.
equal
(
wrapper
.
text
(),
''
);
});
it
(
'does not render a reply toggle'
,
()
=>
{
const
wrapper
=
createComponent
({
isReply
:
true
,
threadIsCollapsed
:
true
,
});
assert
.
isFalse
(
wrapper
.
find
(
'AnnotationReplyToggle'
).
exists
());
});
});
context
(
'collapsed thread, not a reply'
,
()
=>
{
it
(
'shows message-unavailable text'
,
()
=>
{
const
wrapper
=
createComponent
({
isReply
:
false
,
threadIsCollapsed
:
true
,
});
assert
.
match
(
wrapper
.
text
(),
/Message not available/
);
});
it
(
'renders a reply toggle control'
,
()
=>
{
const
wrapper
=
createComponent
({
isReply
:
false
,
threadIsCollapsed
:
true
,
});
const
toggle
=
wrapper
.
find
(
'AnnotationReplyToggle'
);
assert
.
equal
(
toggle
.
props
().
onToggleReplies
,
fakeOnToggleReplies
);
});
});
context
(
'expanded thread, not a reply'
,
()
=>
{
it
(
'shows message-unavailable text'
,
()
=>
{
const
wrapper
=
createComponent
({
isReply
:
false
,
threadIsCollapsed
:
false
,
});
assert
.
match
(
wrapper
.
text
(),
/Message not available/
);
});
it
(
'renders a reply toggle control'
,
()
=>
{
const
wrapper
=
createComponent
({
isReply
:
false
,
threadIsCollapsed
:
false
,
});
const
toggle
=
wrapper
.
find
(
'AnnotationReplyToggle'
);
assert
.
equal
(
toggle
.
props
().
onToggleReplies
,
fakeOnToggleReplies
);
});
});
it
(
'should pass a11y checks'
,
checkAccessibility
({
content
:
()
=>
createComponent
(),
})
);
});
src/sidebar/components/test/Thread-test.js
View file @
66cf493a
...
...
@@ -197,19 +197,12 @@ describe('Thread', () => {
noAnnotationThread
.
annotation
=
undefined
;
});
it
(
'
does not render an annotation or a moderation banner
'
,
()
=>
{
it
(
'
renders an annotation component
'
,
()
=>
{
const
wrapper
=
createComponent
({
thread
:
noAnnotationThread
});
assert
.
isFalse
(
wrapper
.
find
(
'Annotation'
).
exists
());
assert
.
isFalse
(
wrapper
.
find
(
'ModerationBanner'
).
exists
());
});
it
(
'renders a missing annotation component'
,
()
=>
{
const
wrapper
=
createComponent
({
thread
:
noAnnotationThread
});
const
annotationMissing
=
wrapper
.
find
(
'AnnotationMissing'
);
const
annotation
=
wrapper
.
find
(
'Annotation'
);
assert
.
isTrue
(
annotation
Missing
.
exists
());
assert
.
isTrue
(
annotation
.
exists
());
});
});
...
...
@@ -226,7 +219,6 @@ describe('Thread', () => {
const
wrapper
=
createComponent
({
thread
:
noAnnotationThread
});
assert
.
isFalse
(
wrapper
.
find
(
'Annotation'
).
exists
());
assert
.
isFalse
(
wrapper
.
find
(
'AnnotationMissing'
).
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