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
b67fdbd7
Commit
b67fdbd7
authored
Jun 18, 2019
by
Lyza Danger Gardner
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Break out `annotation-user` component from `annotation-header`
parent
acde844a
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
229 additions
and
24 deletions
+229
-24
annotation-user.js
src/sidebar/components/annotation-user.js
+62
-0
annotation-user-test.js
src/sidebar/components/test/annotation-user-test.js
+144
-0
index.js
src/sidebar/index.js
+4
-0
annotation-header.html
src/sidebar/templates/annotation-header.html
+2
-14
annotation-user.scss
src/styles/sidebar/components/annotation-user.scss
+14
-0
annotation.scss
src/styles/sidebar/components/annotation.scss
+2
-10
sidebar.scss
src/styles/sidebar/sidebar.scss
+1
-0
No files found.
src/sidebar/components/annotation-user.js
0 → 100644
View file @
b67fdbd7
'use strict'
;
const
propTypes
=
require
(
'prop-types'
);
const
{
createElement
}
=
require
(
'preact'
);
const
{
isThirdPartyUser
,
username
}
=
require
(
'../util/account-id'
);
const
{
withServices
}
=
require
(
'../util/service-context'
);
/**
* Display information about an annotation's user. Link to the user's
* activity if it is a first-party user or `settings.usernameUrl` is present.
*/
function
AnnotationUser
({
annotation
,
features
,
serviceUrl
,
settings
})
{
const
user
=
annotation
.
user
;
const
isFirstPartyUser
=
!
isThirdPartyUser
(
user
,
settings
.
authDomain
);
const
username_
=
username
(
user
);
// How should the user's name be displayed?
const
displayName
=
(()
=>
{
if
(
isFirstPartyUser
&&
!
features
.
flagEnabled
(
'client_display_names'
))
{
return
username_
;
}
if
(
annotation
.
user_info
&&
annotation
.
user_info
.
display_name
)
{
return
annotation
.
user_info
.
display_name
;
}
return
username_
;
})();
const
shouldLinkToActivity
=
isFirstPartyUser
||
settings
.
usernameUrl
;
if
(
shouldLinkToActivity
)
{
return
(
<
a
className
=
"annotation-user"
href
=
{
isFirstPartyUser
?
serviceUrl
(
'user'
,
{
user
})
:
`
${
settings
.
usernameUrl
}${
username_
}
`
}
target
=
"_blank"
rel
=
"noopener noreferrer"
>
{
displayName
}
<
/a
>
);
}
return
<
div
className
=
"annotation-user"
>
{
displayName
}
<
/div>
;
}
AnnotationUser
.
propTypes
=
{
/** The annotation whose user is relevant */
annotation
:
propTypes
.
object
.
isRequired
,
/** services */
features
:
propTypes
.
object
.
isRequired
,
serviceUrl
:
propTypes
.
func
.
isRequired
,
settings
:
propTypes
.
object
.
isRequired
,
};
AnnotationUser
.
injectedProps
=
[
'features'
,
'serviceUrl'
,
'settings'
];
module
.
exports
=
withServices
(
AnnotationUser
);
src/sidebar/components/test/annotation-user-test.js
0 → 100644
View file @
b67fdbd7
'use strict'
;
const
{
createElement
}
=
require
(
'preact'
);
const
{
shallow
}
=
require
(
'enzyme'
);
const
AnnotationUser
=
require
(
'../annotation-user'
);
describe
(
'AnnotationUser'
,
()
=>
{
let
fakeAnnotation
;
let
fakeFeatures
;
let
fakeIsThirdPartyUser
;
let
fakeServiceUrl
;
let
fakeSettings
;
let
fakeUsername
;
const
createAnnotationUser
=
()
=>
{
return
shallow
(
<
AnnotationUser
annotation
=
{
fakeAnnotation
}
features
=
{
fakeFeatures
}
serviceUrl
=
{
fakeServiceUrl
}
settings
=
{
fakeSettings
}
/
>
).
dive
();
// Dive needed because of `withServices` usage in component
};
beforeEach
(()
=>
{
fakeAnnotation
=
{
user
:
'someone@hypothes.is'
,
};
fakeFeatures
=
{
flagEnabled
:
sinon
.
stub
()
};
fakeIsThirdPartyUser
=
sinon
.
stub
().
returns
(
false
);
fakeServiceUrl
=
sinon
.
stub
();
fakeSettings
=
{};
fakeUsername
=
sinon
.
stub
();
AnnotationUser
.
$imports
.
$mock
({
'../util/account-id'
:
{
isThirdPartyUser
:
fakeIsThirdPartyUser
,
username
:
fakeUsername
,
},
});
});
afterEach
(()
=>
{
AnnotationUser
.
$imports
.
$restore
();
});
describe
(
'link to user activity'
,
()
=>
{
context
(
'first-party user'
,
()
=>
{
it
(
'should provide a link to the user profile'
,
()
=>
{
fakeIsThirdPartyUser
.
returns
(
false
);
fakeServiceUrl
.
returns
(
'link-to-user'
);
const
wrapper
=
createAnnotationUser
();
const
linkEl
=
wrapper
.
find
(
'a'
);
assert
.
isOk
(
linkEl
.
exists
());
assert
.
calledWith
(
fakeServiceUrl
,
'user'
,
{
user
:
fakeAnnotation
.
user
,
});
assert
.
equal
(
linkEl
.
prop
(
'href'
),
'link-to-user'
);
});
});
context
(
'third-party user'
,
()
=>
{
beforeEach
(()
=>
{
fakeIsThirdPartyUser
.
returns
(
true
);
});
it
(
'should link to user if `settings.usernameUrl` is set'
,
()
=>
{
fakeSettings
.
usernameUrl
=
'http://example.com?user='
;
fakeUsername
.
returns
(
'elephant'
);
const
wrapper
=
createAnnotationUser
();
const
linkEl
=
wrapper
.
find
(
'a'
);
assert
.
isOk
(
linkEl
.
exists
());
assert
.
equal
(
linkEl
.
prop
(
'href'
),
'http://example.com?user=elephant'
);
});
it
(
'should not link to user if `settings.usernameUrl` is not set'
,
()
=>
{
const
wrapper
=
createAnnotationUser
();
const
linkEl
=
wrapper
.
find
(
'a'
);
assert
.
isNotOk
(
linkEl
.
exists
());
});
});
});
describe
(
'rendered user name'
,
()
=>
{
context
(
'feature flag on'
,
()
=>
{
beforeEach
(()
=>
{
fakeFeatures
.
flagEnabled
.
withArgs
(
'client_display_names'
).
returns
(
true
);
});
it
(
'should render a display name when feature flag on and info available'
,
()
=>
{
fakeAnnotation
.
user_info
=
{
display_name
:
'Maple Oaks'
,
};
const
wrapper
=
createAnnotationUser
();
const
linkEl
=
wrapper
.
find
(
'a'
);
assert
.
equal
(
linkEl
.
text
(),
'Maple Oaks'
);
});
it
(
'should render a username when feature flag on but info not present'
,
()
=>
{
fakeUsername
.
returns
(
'myusername'
);
const
wrapper
=
createAnnotationUser
();
const
linkEl
=
wrapper
.
find
(
'a'
);
assert
.
equal
(
linkEl
.
text
(),
'myusername'
);
});
});
context
(
'feature flag off'
,
()
=>
{
it
(
'should render a username for first-party users when feature flag off'
,
()
=>
{
fakeFeatures
.
flagEnabled
.
returns
(
false
);
fakeUsername
.
returns
(
'myusername'
);
fakeAnnotation
.
user_info
=
{
display_name
:
'Maple Oaks'
,
};
const
wrapper
=
createAnnotationUser
();
const
linkEl
=
wrapper
.
find
(
'a'
);
assert
.
equal
(
linkEl
.
text
(),
'myusername'
);
});
it
(
'should render a display name for third-party users'
,
()
=>
{
fakeAnnotation
.
user_info
=
{
display_name
:
'Maple Oaks'
,
};
fakeIsThirdPartyUser
.
returns
(
true
);
fakeFeatures
.
flagEnabled
.
returns
(
false
);
const
wrapper
=
createAnnotationUser
();
assert
.
equal
(
wrapper
.
text
(),
'Maple Oaks'
);
});
});
});
});
src/sidebar/index.js
View file @
b67fdbd7
...
@@ -155,6 +155,10 @@ function startAngularApp(config) {
...
@@ -155,6 +155,10 @@ function startAngularApp(config) {
require
(
'./components/annotation-share-dialog'
)
require
(
'./components/annotation-share-dialog'
)
)
)
.
component
(
'annotationThread'
,
require
(
'./components/annotation-thread'
))
.
component
(
'annotationThread'
,
require
(
'./components/annotation-thread'
))
.
component
(
'annotationUser'
,
wrapReactComponent
(
require
(
'./components/annotation-user'
))
)
.
component
(
.
component
(
'annotationViewerContent'
,
'annotationViewerContent'
,
require
(
'./components/annotation-viewer-content'
)
require
(
'./components/annotation-viewer-content'
)
...
...
src/sidebar/templates/annotation-header.html
View file @
b67fdbd7
<header
class=
"annotation-header"
>
<header
class=
"annotation-header"
>
<!-- User -->
<!-- User -->
<span
ng-if=
"vm.user()"
>
<span
ng-if=
"vm.user()"
>
<a
class=
"annotation-header__user"
<annotation-user
annotation=
"vm.annotation"
></annotation-user>
target=
"_blank"
ng-if=
"!vm.isThirdPartyUser()"
ng-href=
"{{vm.serviceUrl('user',{user:vm.user()})}}"
>
{{vm.displayName()}}
</a>
<a
class=
"annotation-header__user"
target=
"_blank"
ng-if=
"vm.isThirdPartyUser() && vm.thirdPartyUsernameLink()"
href=
"{{ vm.thirdPartyUsernameLink() }}"
>
{{vm.displayName()}}
</a>
<span
class=
"annotation-header__user"
ng-if=
"vm.isThirdPartyUser() && !vm.thirdPartyUsernameLink()"
>
{{vm.displayName()}}
</span>
<span
class=
"annotation-collapsed-replies"
>
<span
class=
"annotation-collapsed-replies"
>
<a
class=
"annotation-link"
href=
""
<a
class=
"annotation-link"
href=
""
ng-click=
"vm.onReplyCountClick()"
ng-click=
"vm.onReplyCountClick()"
ng-pluralize
count=
"vm.replyCount"
ng-pluralize
count=
"vm.replyCount"
when=
"{'0': '', 'one': '1 reply', 'other': '{} replies'}"
></a>
when=
"{'0': '', 'one': '1 reply', 'other': '{} replies'}"
></a>
</span>
</span>
<br>
<br
/
>
<span
class=
"annotation-header__share-info"
>
<span
class=
"annotation-header__share-info"
>
<a
class=
"annotation-header__group"
<a
class=
"annotation-header__group"
target=
"_blank"
ng-if=
"vm.group() && vm.group().links.html"
href=
"{{vm.group().links.html}}"
>
target=
"_blank"
ng-if=
"vm.group() && vm.group().links.html"
href=
"{{vm.group().links.html}}"
>
...
...
src/styles/sidebar/components/annotation-user.scss
0 → 100644
View file @
b67fdbd7
.annotation-user
,
.annotation-user
a
{
@include
font-normal
;
color
:
$grey-7
;
font-weight
:
bold
;
.is-dimmed
&
{
color
:
$grey-5
;
}
.is-highlighted
&
{
color
:
$grey-7
;
}
}
src/styles/sidebar/components/annotation.scss
View file @
b67fdbd7
...
@@ -29,19 +29,17 @@
...
@@ -29,19 +29,17 @@
}
}
.annotation.is-dimmed
{
.annotation.is-dimmed
{
// Lighten the
username and
bodies of dimmed annotations to make other
// Lighten the bodies of dimmed annotations to make other
// annotations which are not dimmed stand out
// annotations which are not dimmed stand out
.annotation-header__user
,
.annotation-body
{
.annotation-body
{
color
:
$grey-5
;
color
:
$grey-5
;
}
}
}
}
.annotation.is-highlighted
{
.annotation.is-highlighted
{
// Slightly darken the
username and
bodies of highlighted annotations to
// Slightly darken the bodies of highlighted annotations to
// make them stand out next to others, which will have the `is-dimmed` state
// make them stand out next to others, which will have the `is-dimmed` state
// set
// set
.annotation-header__user
,
.annotation-body
{
.annotation-body
{
color
:
$grey-7
;
color
:
$grey-7
;
}
}
...
@@ -155,12 +153,6 @@
...
@@ -155,12 +153,6 @@
height
:
208px
;
height
:
208px
;
}
}
.annotation-header__user
{
@include
font-normal
;
color
:
$grey-7
;
font-weight
:
bold
;
}
.annotation-replies
{
.annotation-replies
{
float
:
left
;
float
:
left
;
margin-top
:
2px
;
margin-top
:
2px
;
...
...
src/styles/sidebar/sidebar.scss
View file @
b67fdbd7
...
@@ -22,6 +22,7 @@ $base-line-height: 20px;
...
@@ -22,6 +22,7 @@ $base-line-height: 20px;
@import
'./components/annotation-share-dialog'
;
@import
'./components/annotation-share-dialog'
;
@import
'./components/annotation-publish-control'
;
@import
'./components/annotation-publish-control'
;
@import
'./components/annotation-thread'
;
@import
'./components/annotation-thread'
;
@import
'./components/annotation-user'
;
@import
'./components/excerpt'
;
@import
'./components/excerpt'
;
@import
'./components/group-list'
;
@import
'./components/group-list'
;
@import
'./components/group-list-item'
;
@import
'./components/group-list-item'
;
...
...
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