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
5bf8b46c
Unverified
Commit
5bf8b46c
authored
Apr 04, 2019
by
Robert Knight
Committed by
GitHub
Apr 04, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1029 from hypothesis/group-list-item-oos-react
Convert `<group-list-item-out-of-scope>` to React
parents
14b2bd17
c2f99fdc
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
157 additions
and
144 deletions
+157
-144
group-list-item-out-of-scope.js
src/sidebar/components/group-list-item-out-of-scope.js
+96
-21
group-list-item-out-of-scope-test.js
...ebar/components/test/group-list-item-out-of-scope-test.js
+58
-57
index.js
src/sidebar/index.js
+3
-2
group-list-item-out-of-scope.html
src/sidebar/templates/group-list-item-out-of-scope.html
+0
-64
No files found.
src/sidebar/components/group-list-item-out-of-scope.js
View file @
5bf8b46c
'use strict'
;
const
classnames
=
require
(
'classnames'
);
const
{
Fragment
,
createElement
}
=
require
(
'preact'
);
const
{
useState
}
=
require
(
'preact/hooks'
);
const
propTypes
=
require
(
'prop-types'
);
const
{
orgName
,
trackViewGroupActivity
,
}
=
require
(
'../util/group-list-item-common'
);
// @ngInject
function
GroupListItemOutOfScopeController
(
analytics
)
{
// Track whether the group details are expanded.
this
.
isDetailsExpanded
=
false
;
const
outOfScopeIcon
=
(
<
svg
className
=
"svg-icon group-list-item-out-of-scope__icon--unavailable"
xmlns
=
"http://www.w3.org/2000/svg"
width
=
"100%"
height
=
"100%"
viewBox
=
"0 0 24 24"
>
<
path
fill
=
"none"
d
=
"M0 0h24v24H0V0z"
/>
<
path
d
=
"M11 15h2v2h-2zm0-8h2v6h-2zm.99-5C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"
/>
<
/svg
>
);
/**
* Toggle the expanded setting on un-selectable groups.
*/
this
.
toggleGroupDetails
=
function
(
event
)
{
event
.
stopPropagation
();
this
.
isDetailsExpanded
=
!
this
.
isDetailsExpanded
;
};
function
GroupListItemOutOfScope
({
analytics
,
group
})
{
const
[
isExpanded
,
setExpanded
]
=
useState
(
false
);
this
.
orgName
=
function
()
{
return
orgName
(
this
.
group
);
const
toggleGroupDetails
=
event
=>
{
event
.
stopPropagation
();
setExpanded
(
!
isExpanded
);
};
this
.
trackViewGroupActivity
=
function
()
{
const
groupOrgName
=
orgName
(
group
);
const
trackViewActivity
=
event
=>
{
event
.
stopPropagation
();
trackViewGroupActivity
(
analytics
);
};
return
(
<
div
className
=
"group-list-item__item group-list-item-out-of-scope__item"
onClick
=
{
toggleGroupDetails
}
tabIndex
=
"0"
>
{
/* the group icon */
}
<
div
className
=
"group-list-item__icon-container"
>
{
group
.
logo
&&
(
<
img
className
=
"group-list-item__icon group-list-item__icon--organization"
alt
=
{
groupOrgName
}
src
=
{
group
.
logo
}
/
>
)}
<
/div
>
{
/* the group name */
}
<
div
className
=
{
classnames
({
'group-list-item-out-of-scope__details'
:
true
,
expanded
:
isExpanded
,
})}
>
{
outOfScopeIcon
}
<
a
className
=
"group-list-item__name-link"
href
=
""
title
=
"This URL cannot be annotated in this group."
>
{
group
.
name
}
<
/a
>
<
br
/>
{
/* explanation of why group is not available */
}
{
!
isExpanded
&&
(
<
p
className
=
"group-list-item-out-of-scope__details-toggle"
>
Why
is
this
group
unavailable
?
<
/p
>
)}
{
isExpanded
&&
(
<
Fragment
>
<
p
className
=
"group-list-item-out-of-scope__details-unavailable-message"
>
This
group
has
been
restricted
to
selected
URLs
by
its
administrators
.
<
/p
>
{
group
.
links
.
html
&&
(
<
p
className
=
"group-list-item-out-of-scope__details-actions"
>
<
a
className
=
"button button--text group-list-item-out-of-scope__details-group-page-link"
href
=
{
group
.
links
.
html
}
target
=
"_blank"
onClick
=
{
trackViewActivity
}
rel
=
"noopener noreferrer"
>
Go
to
group
page
<
/a
>
<
/p
>
)}
<
/Fragment
>
)}
<
/div
>
<
/div
>
);
}
module
.
exports
=
{
controller
:
GroupListItemOutOfScopeController
,
controllerAs
:
'vm'
,
bindings
:
{
group
:
'<'
,
},
template
:
require
(
'../templates/group-list-item-out-of-scope.html'
),
GroupListItemOutOfScope
.
propTypes
=
{
group
:
propTypes
.
object
,
analytics
:
propTypes
.
object
,
};
GroupListItemOutOfScope
.
injectedProps
=
[
'analytics'
];
module
.
exports
=
GroupListItemOutOfScope
;
src/sidebar/components/test/group-list-item-out-of-scope-test.js
View file @
5bf8b46c
'use strict'
;
const
angular
=
require
(
'angular'
);
const
{
mount
}
=
require
(
'enzyme'
);
const
preact
=
require
(
'preact'
);
const
{
createElement
}
=
require
(
'preact'
);
const
proxyquire
=
require
(
'proxyquire'
);
const
util
=
require
(
'../../directive/test/util'
);
const
{
events
}
=
require
(
'../../services/analytics'
);
describe
(
'
g
roupListItemOutOfScope'
,
()
=>
{
describe
(
'
G
roupListItemOutOfScope'
,
()
=>
{
let
fakeAnalytics
;
let
fakeGroupListItemCommon
;
let
GroupListItemOutOfScope
;
const
fakeGroup
=
{
id
:
'groupid'
,
links
:
{
html
:
'https://hypothes.is/groups/groupid'
,
},
logo
:
'dummy://hypothes.is/logo.svg'
,
organization
:
{
name
:
'org'
},
};
// Click on the item to expand or collapse it.
const
toggle
=
wrapper
=>
wrapper
.
find
(
'div'
)
.
first
()
.
simulate
(
'click'
);
before
(()
=>
{
fakeGroupListItemCommon
=
{
...
...
@@ -16,18 +34,14 @@ describe('groupListItemOutOfScope', () => {
trackViewGroupActivity
:
sinon
.
stub
(),
};
// Return groupListItemOutOfScope with groupListItemCommon stubbed out.
const
groupListItemOutOfScope
=
proxyquire
(
'../group-list-item-out-of-scope'
,
{
'../util/group-list-item-common'
:
fakeGroupListItemCommon
,
'@noCallThru'
:
true
,
}
);
GroupListItemOutOfScope
=
proxyquire
(
'../group-list-item-out-of-scope'
,
{
// Use same instance of Preact module in tests and mocked module.
// See https://robertknight.me.uk/posts/browserify-dependency-mocking/
preact
,
angular
.
module
(
'app'
,
[])
.
component
(
'groupListItemOutOfScope'
,
groupListItemOutOfScope
);
'../util/group-list-item-common'
:
fakeGroupListItemCommon
,
'@noCallThru'
:
true
,
}
);
});
beforeEach
(()
=>
{
...
...
@@ -35,21 +49,23 @@ describe('groupListItemOutOfScope', () => {
track
:
sinon
.
stub
(),
events
,
};
angular
.
mock
.
module
(
'app'
,
{
analytics
:
fakeAnalytics
});
});
const
createGroupListItemOutOfScope
=
fakeGroup
=>
{
return
util
.
createDirective
(
document
,
'groupListItemOutOfScope'
,
{
group
:
fakeGroup
,
}
);
return
mount
(
<
GroupListItemOutOfScope
analytics
=
{
fakeAnalytics
}
group
=
{
fakeGroup
}
/
>
);
};
it
(
'calls groupListItemCommon.trackViewGroupActivity when trackViewGroupActivity is called'
,
()
=>
{
const
fakeGroup
=
{
id
:
'groupid'
};
it
(
'calls trackViewGroupActivity when "Go to group page" link is clicked'
,
()
=>
{
const
wrapper
=
createGroupListItemOutOfScope
(
fakeGroup
);
toggle
(
wrapper
);
const
element
=
createGroupListItemOutOfScope
(
fakeGroup
);
element
.
ctrl
.
trackViewGroupActivity
();
const
link
=
wrapper
.
find
(
'a'
)
.
filterWhere
(
link
=>
link
.
text
()
===
'Go to group page'
);
link
.
simulate
(
'click'
);
assert
.
calledWith
(
fakeGroupListItemCommon
.
trackViewGroupActivity
,
...
...
@@ -57,50 +73,35 @@ describe('groupListItemOutOfScope', () => {
);
});
it
(
'returns groupListItemCommon.orgName when orgName is called'
,
()
=>
{
const
fakeGroup
=
{
id
:
'groupid'
,
organization
:
{
name
:
'org'
}
};
it
(
'does not show "Go to group page" link if the group has no HTML link'
,
()
=>
{
const
group
=
{
...
fakeGroup
,
links
:
{}
};
const
wrapper
=
createGroupListItemOutOfScope
(
group
);
const
link
=
wrapper
.
find
(
'a'
)
.
filterWhere
(
link
=>
link
.
text
()
===
'Go to group page'
);
assert
.
isFalse
(
link
.
exists
());
});
it
(
'sets alt text of logo'
,
()
=>
{
fakeGroupListItemCommon
.
orgName
.
withArgs
(
fakeGroup
)
.
returns
(
fakeGroup
.
organization
.
name
);
const
element
=
createGroupListItemOutOfScope
(
fakeGroup
);
const
orgName
=
element
.
ctrl
.
orgName
()
;
const
wrapper
=
createGroupListItemOutOfScope
(
fakeGroup
);
const
orgName
=
wrapper
.
find
(
'img'
).
props
().
alt
;
assert
.
calledWith
(
fakeGroupListItemCommon
.
orgName
,
fakeGroup
);
assert
.
equal
(
orgName
,
fakeGroup
.
organization
.
name
);
});
describe
(
'toggleGroupDetails'
,
()
=>
{
it
(
'sets the default expanded value to false'
,
()
=>
{
const
fakeGroup
=
{
id
:
'groupid'
};
it
(
'toggles expanded state when clicked'
,
()
=>
{
const
wrapper
=
createGroupListItemOutOfScope
(
fakeGroup
);
const
element
=
createGroupListItemOutOfScope
(
fakeGroup
);
assert
.
isFalse
(
wrapper
.
exists
(
'.expanded'
)
);
assert
.
isFalse
(
element
.
ctrl
.
isDetailsExpanded
);
});
it
(
'toggles the expanded value'
,
()
=>
{
const
fakeGroup
=
{
id
:
'groupid'
};
const
element
=
createGroupListItemOutOfScope
(
fakeGroup
);
const
fakeEvent
=
{
stopPropagation
:
sinon
.
stub
()
};
element
.
ctrl
.
toggleGroupDetails
(
fakeEvent
);
assert
.
isTrue
(
element
.
ctrl
.
isDetailsExpanded
);
element
.
ctrl
.
toggleGroupDetails
(
fakeEvent
);
assert
.
isFalse
(
element
.
ctrl
.
isDetailsExpanded
);
});
it
(
'stops the event from propagating when toggling'
,
()
=>
{
const
fakeGroup
=
{
id
:
'groupid'
};
const
element
=
createGroupListItemOutOfScope
(
fakeGroup
);
const
fakeEvent
=
{
stopPropagation
:
sinon
.
spy
()
};
toggle
(
wrapper
);
assert
.
isTrue
(
wrapper
.
exists
(
'.expanded'
));
element
.
ctrl
.
toggleGroupDetails
(
fakeEvent
);
sinon
.
assert
.
called
(
fakeEvent
.
stopPropagation
);
});
toggle
(
wrapper
);
assert
.
isFalse
(
wrapper
.
exists
(
'.expanded'
));
});
});
src/sidebar/index.js
View file @
5bf8b46c
...
...
@@ -30,7 +30,6 @@ document.body.setAttribute('ng-csp', '');
disableOpenerForExternalLinks
(
document
.
body
);
const
angular
=
require
(
'angular'
);
const
wrapReactComponent
=
require
(
'./util/wrap-react-component'
);
// autofill-event relies on the existence of window.angular so
// it must be require'd after angular is first require'd
...
...
@@ -39,6 +38,8 @@ require('autofill-event');
// Enable debugging checks for Preact.
require
(
'preact/debug'
);
const
wrapReactComponent
=
require
(
'./util/wrap-react-component'
);
// Setup Angular integration for Raven
if
(
appConfig
.
raven
)
{
raven
.
angularModule
(
angular
);
...
...
@@ -161,7 +162,7 @@ function startAngularApp(config) {
)
.
component
(
'groupListItemOutOfScope'
,
require
(
'./components/group-list-item-out-of-scope'
)
wrapReactComponent
(
require
(
'./components/group-list-item-out-of-scope'
)
)
)
.
component
(
'groupListSection'
,
require
(
'./components/group-list-section'
))
.
component
(
'helpLink'
,
require
(
'./components/help-link'
))
...
...
src/sidebar/templates/group-list-item-out-of-scope.html
deleted
100644 → 0
View file @
14b2bd17
<div
class=
"group-list-item-out-of-scope__item"
ng-class=
"{'group-list-item__item': true, 'is-selected': false}"
ng-click=
"vm.toggleGroupDetails($event)"
tabindex=
"0"
>
<!-- the group icon !-->
<div
class=
"group-list-item__icon-container"
>
<img
class=
"group-list-item__icon group-list-item__icon--organization"
alt=
"{{ vm.orgName() }}"
ng-src=
"{{ vm.group.logo }}"
ng-if=
"vm.group.logo"
/>
</div>
<!-- the group name and share link !-->
<div
ng-class=
"{'group-list-item-out-of-scope__details': true, expanded: vm.isDetailsExpanded}"
>
<svg
class=
"svg-icon group-list-item-out-of-scope__icon--unavailable"
xmlns=
"http://www.w3.org/2000/svg"
width=
"100%"
height=
"100%"
viewBox=
"0 0 24 24"
>
<path
fill=
"none"
d=
"M0 0h24v24H0V0z"
/>
<path
d=
"M11 15h2v2h-2zm0-8h2v6h-2zm.99-5C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"
/>
</svg>
<a
class=
"group-list-item__name-link"
href=
""
title=
"Group not annotatable on this domain."
>
{{vm.group.name}}
</a
><br
/>
<p
class=
"group-list-item-out-of-scope__details-toggle"
ng-if=
"!vm.isDetailsExpanded"
>
Why is this group unavailable?
</p>
<p
class=
"group-list-item-out-of-scope__details-unavailable-message"
ng-if=
"vm.isDetailsExpanded"
>
This group has been restricted to selected URLs by its administrators.
</p>
<p
class=
"group-list-item-out-of-scope__details-actions"
ng-if=
"vm.isDetailsExpanded"
>
<a
class=
"button button--text group-list-item-out-of-scope__details-group-page-link"
href=
"{{vm.group.links.html}}"
target=
"_blank"
ng-click=
"vm.trackViewGroupActivity()"
>
Go to group page
</a
>
</p>
</div>
</div>
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