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
35e92333
Commit
35e92333
authored
Apr 20, 2020
by
Lyza Danger Gardner
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor focus-annotations functionality
parent
0374e506
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
107 additions
and
42 deletions
+107
-42
annotation-quote.js
src/sidebar/components/annotation-quote.js
+7
-6
annotation.js
src/sidebar/components/annotation.js
+7
-1
annotation-quote-test.js
src/sidebar/components/test/annotation-quote-test.js
+6
-1
annotation-test.js
src/sidebar/components/test/annotation-test.js
+17
-0
frame-sync.js
src/sidebar/services/frame-sync.js
+3
-2
frame-sync-test.js
src/sidebar/services/test/frame-sync-test.js
+18
-0
selection.js
src/sidebar/store/modules/selection.js
+12
-4
selection-test.js
src/sidebar/store/modules/test/selection-test.js
+18
-13
annotation-quote.scss
src/styles/sidebar/components/annotation-quote.scss
+19
-15
No files found.
src/sidebar/components/annotation-quote.js
View file @
35e92333
...
@@ -11,7 +11,7 @@ import Excerpt from './excerpt';
...
@@ -11,7 +11,7 @@ import Excerpt from './excerpt';
/**
/**
* Display the selected text from the document associated with an annotation.
* Display the selected text from the document associated with an annotation.
*/
*/
function
AnnotationQuote
({
annotation
,
settings
=
{}
})
{
function
AnnotationQuote
({
annotation
,
isFocused
,
settings
=
{}
})
{
// The language for the quote may be different than the client's UI (set by
// The language for the quote may be different than the client's UI (set by
// `<html lang="...">`).
// `<html lang="...">`).
//
//
...
@@ -24,10 +24,10 @@ function AnnotationQuote({ annotation, settings = {} }) {
...
@@ -24,10 +24,10 @@ function AnnotationQuote({ annotation, settings = {} }) {
return
(
return
(
<
section
<
section
className
=
{
classnames
(
className
=
{
classnames
(
'annotation-quote'
,
{
'
annotation-quote'
,
'
is-orphan'
:
isOrphan
(
annotation
)
,
isOrphan
(
annotation
)
&&
'is-orphan'
'is-focused'
:
isFocused
,
)}
}
)}
>
>
<
Excerpt
<
Excerpt
collapsedHeight
=
{
35
}
collapsedHeight
=
{
35
}
...
@@ -49,7 +49,8 @@ function AnnotationQuote({ annotation, settings = {} }) {
...
@@ -49,7 +49,8 @@ function AnnotationQuote({ annotation, settings = {} }) {
AnnotationQuote
.
propTypes
=
{
AnnotationQuote
.
propTypes
=
{
annotation
:
propTypes
.
object
.
isRequired
,
annotation
:
propTypes
.
object
.
isRequired
,
/** Is this annotation currently focused? */
isFocused
:
propTypes
.
bool
,
// Used for theming.
// Used for theming.
settings
:
propTypes
.
object
,
settings
:
propTypes
.
object
,
};
};
...
...
src/sidebar/components/annotation.js
View file @
35e92333
...
@@ -27,6 +27,9 @@ function Annotation({
...
@@ -27,6 +27,9 @@ function Annotation({
toastMessenger
,
toastMessenger
,
})
{
})
{
const
createDraft
=
useStore
(
store
=>
store
.
createDraft
);
const
createDraft
=
useStore
(
store
=>
store
.
createDraft
);
const
isFocused
=
useStore
(
store
=>
store
.
isAnnotationFocused
(
annotation
.
$tag
)
);
const
setCollapsed
=
useStore
(
store
=>
store
.
setCollapsed
);
const
setCollapsed
=
useStore
(
store
=>
store
.
setCollapsed
);
// An annotation will have a draft if it is being edited
// An annotation will have a draft if it is being edited
...
@@ -90,6 +93,7 @@ function Annotation({
...
@@ -90,6 +93,7 @@ function Annotation({
className
=
{
classnames
(
'annotation'
,
{
className
=
{
classnames
(
'annotation'
,
{
'annotation--reply'
:
isReply
(
annotation
),
'annotation--reply'
:
isReply
(
annotation
),
'is-collapsed'
:
threadIsCollapsed
,
'is-collapsed'
:
threadIsCollapsed
,
'is-focused'
:
isFocused
,
})}
})}
onKeyDown
=
{
onKeyDown
}
onKeyDown
=
{
onKeyDown
}
>
>
...
@@ -101,7 +105,9 @@ function Annotation({
...
@@ -101,7 +105,9 @@ function Annotation({
threadIsCollapsed
=
{
threadIsCollapsed
}
threadIsCollapsed
=
{
threadIsCollapsed
}
/
>
/
>
{
hasQuote
&&
<
AnnotationQuote
annotation
=
{
annotation
}
/>
}
{
hasQuote
&&
(
<
AnnotationQuote
annotation
=
{
annotation
}
isFocused
=
{
isFocused
}
/
>
)}
{
!
isCollapsedReply
&&
(
{
!
isCollapsedReply
&&
(
<
AnnotationBody
<
AnnotationBody
...
...
src/sidebar/components/test/annotation-quote-test.js
View file @
35e92333
...
@@ -14,7 +14,12 @@ describe('AnnotationQuote', () => {
...
@@ -14,7 +14,12 @@ describe('AnnotationQuote', () => {
function
createQuote
(
props
)
{
function
createQuote
(
props
)
{
return
mount
(
return
mount
(
<
AnnotationQuote
annotation
=
{
fakeAnnotation
}
settings
=
{{}}
{...
props
}
/
>
<
AnnotationQuote
annotation
=
{
fakeAnnotation
}
isFocused
=
{
false
}
settings
=
{{}}
{...
props
}
/
>
);
);
}
}
...
...
src/sidebar/components/test/annotation-test.js
View file @
35e92333
...
@@ -69,6 +69,7 @@ describe('Annotation', () => {
...
@@ -69,6 +69,7 @@ describe('Annotation', () => {
getGroup
:
sinon
.
stub
().
returns
({
getGroup
:
sinon
.
stub
().
returns
({
type
:
'private'
,
type
:
'private'
,
}),
}),
isAnnotationFocused
:
sinon
.
stub
().
returns
(
false
),
isSavingAnnotation
:
sinon
.
stub
().
returns
(
false
),
isSavingAnnotation
:
sinon
.
stub
().
returns
(
false
),
profile
:
sinon
.
stub
().
returns
({
userid
:
'acct:foo@bar.com'
}),
profile
:
sinon
.
stub
().
returns
({
userid
:
'acct:foo@bar.com'
}),
setCollapsed
:
sinon
.
stub
(),
setCollapsed
:
sinon
.
stub
(),
...
@@ -97,6 +98,14 @@ describe('Annotation', () => {
...
@@ -97,6 +98,14 @@ describe('Annotation', () => {
assert
.
isFalse
(
annot
.
hasClass
(
'is-collapsed'
));
assert
.
isFalse
(
annot
.
hasClass
(
'is-collapsed'
));
});
});
it
(
'applies a focused class if annotation is focused'
,
()
=>
{
fakeStore
.
isAnnotationFocused
.
returns
(
true
);
const
wrapper
=
createComponent
({
threadIsCollapsed
:
false
});
const
annot
=
wrapper
.
find
(
'.annotation'
);
assert
.
isTrue
(
annot
.
hasClass
(
'is-focused'
));
});
it
(
'should assign a collapsed class if the annotation thread is collapsed'
,
()
=>
{
it
(
'should assign a collapsed class if the annotation thread is collapsed'
,
()
=>
{
const
wrapper
=
createComponent
({
threadIsCollapsed
:
true
});
const
wrapper
=
createComponent
({
threadIsCollapsed
:
true
});
const
annot
=
wrapper
.
find
(
'.annotation'
);
const
annot
=
wrapper
.
find
(
'.annotation'
);
...
@@ -114,6 +123,14 @@ describe('Annotation', () => {
...
@@ -114,6 +123,14 @@ describe('Annotation', () => {
assert
.
isTrue
(
quote
.
exists
());
assert
.
isTrue
(
quote
.
exists
());
});
});
it
(
'sets the quote to "focused" if annotation is currently focused'
,
()
=>
{
fakeStore
.
isAnnotationFocused
.
returns
(
true
);
fakeMetadata
.
quote
.
returns
(
'quote'
);
const
wrapper
=
createComponent
();
assert
.
isTrue
(
wrapper
.
find
(
'AnnotationQuote'
).
props
().
isFocused
);
});
it
(
'does not render quote if annotation does not have a quote'
,
()
=>
{
it
(
'does not render quote if annotation does not have a quote'
,
()
=>
{
fakeMetadata
.
quote
.
returns
(
null
);
fakeMetadata
.
quote
.
returns
(
null
);
...
...
src/sidebar/services/frame-sync.js
View file @
35e92333
...
@@ -235,14 +235,15 @@ export default function FrameSync($rootScope, $window, store, bridge) {
...
@@ -235,14 +235,15 @@ export default function FrameSync($rootScope, $window, store, bridge) {
};
};
/**
/**
* Focus annotations with the given tags.
* Focus annotations with the given
$
tags.
*
*
* This is used to indicate the highlight in the document that corresponds to
* This is used to indicate the highlight in the document that corresponds to
* a given annotation in the sidebar.
* a given annotation in the sidebar.
*
*
* @param {string[]} tags
* @param {string[]} tags
- annotation $tags
*/
*/
this
.
focusAnnotations
=
function
(
tags
)
{
this
.
focusAnnotations
=
function
(
tags
)
{
store
.
focusAnnotations
(
tags
);
bridge
.
call
(
'focusAnnotations'
,
tags
);
bridge
.
call
(
'focusAnnotations'
,
tags
);
};
};
...
...
src/sidebar/services/test/frame-sync-test.js
View file @
35e92333
...
@@ -401,4 +401,22 @@ describe('sidebar/services/frame-sync', function () {
...
@@ -401,4 +401,22 @@ describe('sidebar/services/frame-sync', function () {
assert
.
calledWith
(
fakeBridge
.
call
,
'setVisibleHighlights'
);
assert
.
calledWith
(
fakeBridge
.
call
,
'setVisibleHighlights'
);
});
});
});
});
describe
(
'when annotations are focused in the sidebar'
,
()
=>
{
it
(
'should update the focused annotations in the store'
,
()
=>
{
frameSync
.
focusAnnotations
([
'a1'
,
'a2'
]);
assert
.
calledWith
(
fakeStore
.
focusAnnotations
,
sinon
.
match
.
array
.
deepEquals
([
'a1'
,
'a2'
])
);
});
it
(
'notify the host page'
,
()
=>
{
frameSync
.
focusAnnotations
([
1
,
2
]);
assert
.
calledWith
(
fakeBridge
.
call
,
'focusAnnotations'
,
sinon
.
match
.
array
.
deepEquals
([
1
,
2
])
);
});
});
});
});
src/sidebar/store/modules/selection.js
View file @
35e92333
...
@@ -92,8 +92,8 @@ const setTab = (selectedTab, newTab) => {
...
@@ -92,8 +92,8 @@ const setTab = (selectedTab, newTab) => {
function
init
(
settings
)
{
function
init
(
settings
)
{
return
{
return
{
//
Contains a map of annotation tag:true pairs.
//
An array of annotation `$tag`s representing annotations that are focused
focusedAnnotation
Map
:
null
,
focusedAnnotation
s
:
[]
,
// Contains a map of annotation id:true pairs.
// Contains a map of annotation id:true pairs.
selectedAnnotationMap
:
initialSelection
(
settings
),
selectedAnnotationMap
:
initialSelection
(
settings
),
...
@@ -153,7 +153,7 @@ const update = {
...
@@ -153,7 +153,7 @@ const update = {
},
},
FOCUS_ANNOTATIONS
:
function
(
state
,
action
)
{
FOCUS_ANNOTATIONS
:
function
(
state
,
action
)
{
return
{
focusedAnnotation
Map
:
action
.
focused
};
return
{
focusedAnnotation
s
:
[...
action
.
focusedTags
]
};
},
},
SET_FOCUS_MODE_FOCUSED
:
function
(
state
,
action
)
{
SET_FOCUS_MODE_FOCUSED
:
function
(
state
,
action
)
{
...
@@ -318,7 +318,7 @@ function setForceVisible(id, visible) {
...
@@ -318,7 +318,7 @@ function setForceVisible(id, visible) {
function
focusAnnotations
(
tags
)
{
function
focusAnnotations
(
tags
)
{
return
{
return
{
type
:
actions
.
FOCUS_ANNOTATIONS
,
type
:
actions
.
FOCUS_ANNOTATIONS
,
focused
:
freeze
(
toSet
(
tags
))
,
focused
Tags
:
tags
,
};
};
}
}
...
@@ -395,6 +395,13 @@ function setSortKey(key) {
...
@@ -395,6 +395,13 @@ function setSortKey(key) {
};
};
}
}
/** Is the annotation referenced by `$tag` currently focused? */
function
isAnnotationFocused
(
state
,
$tag
)
{
return
state
.
selection
.
focusedAnnotations
.
some
(
focusedAnn
=>
$tag
&&
focusedAnn
===
$tag
);
}
/**
/**
* Returns true if the annotation with the given `id` is selected.
* Returns true if the annotation with the given `id` is selected.
*/
*/
...
@@ -542,6 +549,7 @@ export default {
...
@@ -542,6 +549,7 @@ export default {
focusModeHasUser
,
focusModeHasUser
,
focusModeUserId
,
focusModeUserId
,
focusModeUserPrettyName
,
focusModeUserPrettyName
,
isAnnotationFocused
,
isAnnotationSelected
,
isAnnotationSelected
,
getFirstSelectedAnnotationId
,
getFirstSelectedAnnotationId
,
getSelectedAnnotationMap
,
getSelectedAnnotationMap
,
...
...
src/sidebar/store/modules/test/selection-test.js
View file @
35e92333
...
@@ -43,28 +43,22 @@ describe('sidebar/store/modules/selection', () => {
...
@@ -43,28 +43,22 @@ describe('sidebar/store/modules/selection', () => {
});
});
describe
(
'focusAnnotations()'
,
function
()
{
describe
(
'focusAnnotations()'
,
function
()
{
it
(
'adds the p
assed annotations to the focusedAnnotationMap
'
,
function
()
{
it
(
'adds the p
rovided annotation IDs to the focused annotations
'
,
function
()
{
store
.
focusAnnotations
([
1
,
2
,
3
]);
store
.
focusAnnotations
([
1
,
2
,
3
]);
assert
.
deepEqual
(
getSelectionState
().
focusedAnnotationMap
,
{
assert
.
deepEqual
(
getSelectionState
().
focusedAnnotations
,
[
1
,
2
,
3
]);
1
:
true
,
2
:
true
,
3
:
true
,
});
});
});
it
(
'replaces any
annotations originally in the map
'
,
function
()
{
it
(
'replaces any
other focused annotation IDs
'
,
function
()
{
store
.
focusAnnotations
([
1
]);
store
.
focusAnnotations
([
1
]);
store
.
focusAnnotations
([
2
,
3
]);
store
.
focusAnnotations
([
2
,
3
]);
assert
.
deepEqual
(
getSelectionState
().
focusedAnnotationMap
,
{
assert
.
deepEqual
(
getSelectionState
().
focusedAnnotations
,
[
2
,
3
]);
2
:
true
,
3
:
true
,
});
});
});
it
(
'
nulls the map if no annotations are focus
ed'
,
function
()
{
it
(
'
sets focused annotations to an empty array if no IDs provid
ed'
,
function
()
{
store
.
focusAnnotations
([
1
]);
store
.
focusAnnotations
([
1
]);
store
.
focusAnnotations
([]);
store
.
focusAnnotations
([]);
assert
.
isNull
(
getSelectionState
().
focusedAnnotationMap
);
assert
.
isArray
(
getSelectionState
().
focusedAnnotations
);
assert
.
isEmpty
(
getSelectionState
().
focusedAnnotations
);
});
});
});
});
...
@@ -368,6 +362,17 @@ describe('sidebar/store/modules/selection', () => {
...
@@ -368,6 +362,17 @@ describe('sidebar/store/modules/selection', () => {
});
});
});
});
describe
(
'isAnnotationFocused'
,
()
=>
{
it
(
'returns true if the provided annotation ID is in the set of focused annotations'
,
()
=>
{
store
.
focusAnnotations
([
1
,
2
]);
assert
.
isTrue
(
store
.
isAnnotationFocused
(
2
));
});
it
(
'returns false if the provided annotation ID is not in the set of focused annotations'
,
()
=>
{
assert
.
isFalse
(
store
.
isAnnotationFocused
(
2
));
});
});
describe
(
'selectTab()'
,
function
()
{
describe
(
'selectTab()'
,
function
()
{
it
(
'sets the selected tab'
,
function
()
{
it
(
'sets the selected tab'
,
function
()
{
store
.
selectTab
(
uiConstants
.
TAB_ANNOTATIONS
);
store
.
selectTab
(
uiConstants
.
TAB_ANNOTATIONS
);
...
...
src/styles/sidebar/components/annotation-quote.scss
View file @
35e92333
...
@@ -2,23 +2,27 @@
...
@@ -2,23 +2,27 @@
.annotation-quote
{
.annotation-quote
{
margin
:
1em
0
;
margin
:
1em
0
;
}
.annotation-quote.is-orphan
{
&
.is-orphan
{
text-decoration
:
line-through
;
text-decoration
:
line-through
;
}
}
&
__quote
{
@include
var
.
font-normal
;
.annotation-quote__quote
{
border-left
:
3px
solid
var
.
$grey-3
;
@include
var
.
font-normal
;
color
:
var
.
$grey-5
;
font-family
:
sans-serif
;
font-size
:
12px
;
font-style
:
italic
;
letter-spacing
:
0
.1px
;
padding
:
0
1em
;
border-left
:
3px
solid
var
.
$grey-3
;
// Prevent long URLs etc. in quote causing overflow
color
:
var
.
$grey-5
;
overflow-wrap
:
break-word
;
font-family
:
sans-serif
;
}
font-size
:
12px
;
font-style
:
italic
;
letter-spacing
:
0
.1px
;
padding
:
0
1em
;
// Prevent long URLs etc. in quote causing overflow
&
.is-focused
&
__quote
{
overflow-wrap
:
break-word
;
border-left
:
var
.
$highlight
3px
solid
;
}
}
}
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