Commit 7abcfaef authored by Lyza Danger Gardner's avatar Lyza Danger Gardner

Replace `ShareDialog` with `ShareAnnotationsPanel`

- Remove old angular component and supporting modules/files
- Update `hypothesis-app` component
- Update `TopBar` component
parent 116c51bb
'use strict';
const scrollIntoView = require('scroll-into-view');
const events = require('../events');
const { parseAccountID } = require('../util/account-id');
const scopeTimeout = require('../util/scope-timeout');
const serviceConfig = require('../service-config');
const bridgeEvents = require('../../shared/bridge-events');
......@@ -60,7 +57,6 @@ function HypothesisAppController(
this.auth = { status: 'unknown' };
// App dialogs
this.shareDialog = { visible: false };
this.helpPanel = { visible: false };
// Check to see if we're in the sidebar, or on a standalone page such as
......@@ -79,19 +75,6 @@ function HypothesisAppController(
self.auth = authStateFromProfile(profile);
});
/** Scroll to the view to the element matching the given selector */
function scrollToView(selector) {
// Add a timeout so that if the element has just been shown (eg. via ngIf)
// it is added to the DOM before we try to locate and scroll to it.
scopeTimeout(
$scope,
function() {
scrollIntoView($document[0].querySelector(selector));
},
0
);
}
/**
* Start the login flow. This will present the user with the login dialog.
*
......@@ -127,12 +110,6 @@ function HypothesisAppController(
$window.open(serviceUrl('signup'));
};
// Display the dialog for sharing the current page
this.share = function() {
this.shareDialog.visible = true;
scrollToView('share-dialog');
};
this.showHelpPanel = function() {
const service = serviceConfig(settings) || {};
if (service.onHelpRequestProvided) {
......
'use strict';
// @ngInject
function ShareDialogController($scope, $element, analytics, store) {
const self = this;
function updateSharePageLink(frames) {
if (!frames.length) {
self.sharePageLink = '';
return;
}
self.sharePageLink =
'https://hyp.is/go?url=' + encodeURIComponent(frames[0].uri);
}
const shareLinkInput = $element[0].querySelector('.js-share-link');
shareLinkInput.focus();
shareLinkInput.select();
$scope.$watch(function() {
return store.frames();
}, updateSharePageLink);
$scope.onShareClick = function(target) {
if (target) {
analytics.track(analytics.events.DOCUMENT_SHARED, target);
}
};
}
module.exports = {
controller: ShareDialogController,
controllerAs: 'vm',
bindings: {
onClose: '&',
},
template: require('../templates/share-dialog.html'),
};
......@@ -252,11 +252,6 @@ describe('sidebar.components.hypothesis-app', function() {
});
});
it('does not show the share dialog at start', function() {
const ctrl = createController();
assert.isFalse(ctrl.shareDialog.visible);
});
describe('#signUp', function() {
it('tracks sign up requests in analytics', function() {
const ctrl = createController();
......@@ -409,14 +404,6 @@ describe('sidebar.components.hypothesis-app', function() {
});
});
describe('#share()', function() {
it('shows the share dialog', function() {
const ctrl = createController();
ctrl.share();
assert.equal(ctrl.shareDialog.visible, true);
});
});
describe('#logout()', function() {
// Tests shared by both of the contexts below.
function doSharedTests() {
......
'use strict';
const angular = require('angular');
const util = require('../../directive/test/util');
describe('shareDialog', function() {
let fakeAnalytics;
let fakeStore;
beforeEach(function() {
fakeAnalytics = {
track: sinon.stub(),
events: {},
};
fakeStore = { frames: sinon.stub().returns([]) };
angular
.module('h', [])
.component('shareDialog', require('../share-dialog'))
.value('analytics', fakeAnalytics)
.value('store', fakeStore)
.value('urlEncodeFilter', function(val) {
return val;
});
angular.mock.module('h');
});
it('generates new share link', function() {
const element = util.createDirective(document, 'shareDialog', {});
const uri = 'http://example.com';
fakeStore.frames.returns([{ uri }]);
element.scope.$digest();
assert.equal(
element.ctrl.sharePageLink,
'https://hyp.is/go?url=' + encodeURIComponent(uri)
);
});
it('tracks the target being shared', function() {
const element = util.createDirective(document, 'shareDialog');
const clickShareIcon = function(iconName) {
element.find('.' + iconName).click();
};
clickShareIcon('h-icon-twitter');
assert.equal(fakeAnalytics.track.args[0][1], 'twitter');
clickShareIcon('h-icon-facebook');
assert.equal(fakeAnalytics.track.args[1][1], 'facebook');
clickShareIcon('h-icon-mail');
assert.equal(fakeAnalytics.track.args[2][1], 'email');
});
});
......@@ -3,6 +3,8 @@
const { createElement } = require('preact');
const { shallow } = require('enzyme');
const uiConstants = require('../../ui-constants');
const GroupList = require('../group-list');
const SearchInput = require('../search-input');
const StreamSearchInput = require('../stream-search-input');
......@@ -21,8 +23,14 @@ describe('TopBar', () => {
fakeStore = {
filterQuery: sinon.stub().returns(null),
getState: sinon.stub().returns({
sidebarPanels: {
activePanelName: null,
},
}),
pendingUpdateCount: sinon.stub().returns(0),
setFilterQuery: sinon.stub(),
toggleSidebarPanel: sinon.stub(),
};
fakeStreamer = {
......@@ -143,9 +151,9 @@ describe('TopBar', () => {
});
context('when using a first-party service', () => {
it('shows the share page button', () => {
it('shows the share annotations button', () => {
const wrapper = createTopBar();
assert.isTrue(wrapper.exists('[title="Share this page"]'));
assert.isTrue(wrapper.exists('[title="Share annotations on this page"]'));
});
});
......@@ -154,17 +162,31 @@ describe('TopBar', () => {
fakeIsThirdPartyService.returns(true);
});
it("doesn't show the share page button", () => {
it("doesn't show the share annotations button", () => {
const wrapper = createTopBar();
assert.isFalse(
wrapper.exists('[title="Share annotations on this page"]')
);
});
});
it('toggles the share annotations panel when "Share" is clicked', () => {
const wrapper = createTopBar();
assert.isFalse(wrapper.exists('[title="Share this page"]'));
wrapper.find('[title="Share annotations on this page"]').simulate('click');
assert.called(fakeStore.toggleSidebarPanel);
});
it('adds an active-state class to the "Share" icon when the panel is open', () => {
fakeStore.getState.returns({
sidebarPanels: {
activePanelName: uiConstants.PANEL_SHARE_ANNOTATIONS,
},
});
it('displays the share page when "Share this page" is clicked', () => {
const onSharePage = sinon.stub();
const wrapper = createTopBar({ onSharePage });
wrapper.find('[title="Share this page"]').simulate('click');
assert.called(onSharePage);
const wrapper = createTopBar();
const shareEl = wrapper.find('[title="Share annotations on this page"]');
assert.include(shareEl.prop('className'), 'top-bar__btn--active');
});
it('displays search input in the sidebar', () => {
......
......@@ -8,6 +8,7 @@ const useStore = require('../store/use-store');
const { applyTheme } = require('../util/theme');
const isThirdPartyService = require('../util/is-third-party-service');
const { withServices } = require('../util/service-context');
const uiConstants = require('../ui-constants');
const GroupList = require('./group-list');
const SearchInput = require('./search-input');
......@@ -25,7 +26,6 @@ function TopBar({
isSidebar,
onLogin,
onLogout,
onSharePage,
onShowHelpPanel,
onSignUp,
settings,
......@@ -40,8 +40,17 @@ function TopBar({
const pendingUpdateCount = useStore(store => store.pendingUpdateCount());
const togglePanelFn = useStore(store => store.toggleSidebarPanel);
const currentActivePanel = useStore(
store => store.getState().sidebarPanels.activePanelName
);
const applyPendingUpdates = () => streamer.applyPendingUpdates();
const toggleSharePanel = () => {
togglePanelFn(uiConstants.PANEL_SHARE_ANNOTATIONS);
};
const loginControl = (
<Fragment>
{auth.status === 'unknown' && (
......@@ -104,12 +113,15 @@ function TopBar({
<SortMenu />
{showSharePageButton && (
<button
className="top-bar__btn"
onClick={onSharePage}
title="Share this page"
aria-label="Share this page"
className={classnames('top-bar__btn', {
'top-bar__btn--active':
currentActivePanel === uiConstants.PANEL_SHARE_ANNOTATIONS,
})}
onClick={toggleSharePanel}
title="Share annotations on this page"
aria-label="Share annotations on this page"
>
<i className="h-icon-annotation-share" />
<SvgIcon name="share" />
</button>
)}
<button
......@@ -158,9 +170,6 @@ TopBar.propTypes = {
/** Callback invoked when user clicks "Logout" action in account menu. */
onLogout: propTypes.func,
/** Callback invoked when user clicks "Share" toolbar action. */
onSharePage: propTypes.func,
/** Callback invoked when user clicks "Sign up" button. */
onSignUp: propTypes.func,
......
......@@ -188,7 +188,6 @@ function startAngularApp(config) {
wrapReactComponent(require('./components/share-annotations-panel'))
)
.component('sidebarTutorial', require('./components/sidebar-tutorial'))
.component('shareDialog', require('./components/share-dialog'))
.component('streamContent', require('./components/stream-content'))
.component('svgIcon', wrapReactComponent(require('./components/svg-icon')))
.component('tagEditor', require('./components/tag-editor'))
......
......@@ -4,21 +4,17 @@
on-login="vm.login()"
on-sign-up="vm.signUp()"
on-logout="vm.logout()"
on-share-page="vm.share()"
on-show-help-panel="vm.showHelpPanel()"
is-sidebar="::vm.isSidebar">
</top-bar>
<div class="content">
<sidebar-tutorial ng-if="vm.isSidebar"></sidebar-tutorial>
<share-dialog
ng-if="vm.shareDialog.visible"
on-close="vm.shareDialog.visible = false">
</share-dialog>
<help-panel ng-if="vm.helpPanel.visible"
on-close="vm.helpPanel.visible = false"
auth="vm.auth">
</help-panel>
<share-annotations-panel></share-annotations-panel>
<main ng-view=""></main>
</div>
</div>
<div class="sheet">
<i class="close h-icon-close"
role="button"
title="Close"
ng-click="vm.onClose()"></i>
<div class="form-vertical">
<ul class="nav nav-tabs">
<li class="active"><a href="">Share</a></li>
</ul>
<div class="tab-content">
<p>Share the link below to show anyone these annotations and invite them to contribute their own.</p>
<p><input class="js-share-link form-input"
type="text"
ng-value="vm.sharePageLink"
readonly /></p>
<p class="share-link-icons">
<a href="https://twitter.com/intent/tweet?url={{vm.sharePageLink | urlEncode}}&hashtags=annotated"
target="_blank"
title="Tweet link"
class="share-link-icon h-icon-twitter"
ng-click="onShareClick('twitter')"></a>
<a href="https://www.facebook.com/sharer/sharer.php?u={{vm.sharePageLink | urlEncode}}"
target="_blank"
title="Share on Facebook"
class="share-link-icon h-icon-facebook"
ng-click="onShareClick('facebook')"></a>
<a href="mailto:?subject=Let's%20Annotate&amp;body={{vm.sharePageLink}}"
target="_blank"
title="Share via email"
class="share-link-icon h-icon-mail"
ng-click="onShareClick('email')"></a>
</p>
</div>
</div>
</div>
// form for sharing links
.share-link-container {
font-size: $body1-font-size;
line-height: $body1-line-height;
margin-top: 1px;
white-space: normal;
}
.share-link {
color: $gray-light;
}
.share-link:hover {
width: 100%;
color: $gray-dark;
}
.share-link-icons {
display: flex;
flex-direction: row;
justify-content: center;
}
.share-link-icon {
color: $color-dove-gray;
display: inline-block;
font-size: 24px;
text-decoration: none;
margin-left: 5px;
margin-right: 5px;
&:hover {
color: $brand-color;
}
}
......@@ -77,6 +77,9 @@
&:hover {
color: $gray-dark;
}
&--active {
color: $gray-dark;
}
}
// Button which indicates that other users have made or edited annotations
......
......@@ -41,7 +41,6 @@ $base-line-height: 20px;
@import './components/primary-action-btn';
@import './components/search-status-bar';
@import './components/selection-tabs';
@import './components/share-link';
@import './components/share-annotations-panel';
@import './components/search-input';
@import './components/sidebar-panel';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment