Commit 3277f2f4 authored by Jake Hartnell's avatar Jake Hartnell

Add ability to generate via links from the sidebar.

- Use document plugin to get canonical url for sharing.
- Introduce Topbar share icon
- Add social media icons to icomoon
- Generate via uri in the share-dialog directive
- Add sharing via Facebook, Twitter, Google plus, and email
- Make account dialog and share dialog consistent
- Add information about sharing to the help page.
- Add tests (Thanks @nickstenning!)
parent 41fa4384
...@@ -43,8 +43,18 @@ module.exports = class AppController ...@@ -43,8 +43,18 @@ module.exports = class AppController
applyUpdates(action, payload) applyUpdates(action, payload)
$scope.$digest() $scope.$digest()
# App dialogs
$scope.accountDialog = visible: false
$scope.shareDialog = visible: false
# Check to see if we are on the stream page so we can hide share button.
if $window.top is $window
$scope.showShareButton = false
else
$scope.showShareButton = true
oncancel = -> oncancel = ->
$scope.dialog.visible = false $scope.accountDialog.visible = false
cleanupAnnotations = -> cleanupAnnotations = ->
# Clean up any annotations that need to be unloaded. # Clean up any annotations that need to be unloaded.
...@@ -68,7 +78,7 @@ module.exports = class AppController ...@@ -68,7 +78,7 @@ module.exports = class AppController
if isFirstRun and not (newVal or oldVal) if isFirstRun and not (newVal or oldVal)
$scope.login() $scope.login()
else else
$scope.dialog.visible = false $scope.accountDialog.visible = false
# Update any edits in progress. # Update any edits in progress.
for draft in drafts.all() for draft in drafts.all()
...@@ -85,12 +95,12 @@ module.exports = class AppController ...@@ -85,12 +95,12 @@ module.exports = class AppController
$route.reload() $route.reload()
$scope.login = -> $scope.login = ->
$scope.dialog.visible = true $scope.accountDialog.visible = true
identity.request {oncancel} identity.request {oncancel}
$scope.logout = -> $scope.logout = ->
return unless drafts.discard() return unless drafts.discard()
$scope.dialog.visible = false $scope.accountDialog.visible = false
identity.logout() identity.logout()
$scope.loadMore = (number) -> $scope.loadMore = (number) ->
...@@ -100,8 +110,6 @@ module.exports = class AppController ...@@ -100,8 +110,6 @@ module.exports = class AppController
$scope.search.query = '' $scope.search.query = ''
annotationUI.clearSelectedAnnotations() annotationUI.clearSelectedAnnotations()
$scope.dialog = visible: false
$scope.search = $scope.search =
query: $location.search()['q'] query: $location.search()['q']
......
...@@ -111,6 +111,7 @@ module.exports = angular.module('h', [ ...@@ -111,6 +111,7 @@ module.exports = angular.module('h', [
.directive('spinner', require('./directive/spinner')) .directive('spinner', require('./directive/spinner'))
.directive('tabbable', require('./directive/tabbable')) .directive('tabbable', require('./directive/tabbable'))
.directive('tabReveal', require('./directive/tab-reveal')) .directive('tabReveal', require('./directive/tab-reveal'))
.directive('shareDialog', require('./directive/share-dialog'))
.filter('converter', require('./filter/converter')) .filter('converter', require('./filter/converter'))
.filter('moment', require('./filter/moment')) .filter('moment', require('./filter/moment'))
......
###*
# @ngdoc directive
# @name share-dialog
# @restrict A
# @description This dialog generates a via link to the page h is currently
# loaded on.
###
module.exports = ['crossframe', (crossframe) ->
link: (scope, elem, attrs, ctrl) ->
scope.viaPageLink = ''
# Watch scope.shareDialog.visible: when it changes to true, focus input
# and selection.
scope.$watch (-> scope.shareDialog?.visible), (visible) ->
if visible
scope.$evalAsync(-> elem.find('#via').focus().select())
scope.$watchCollection (-> crossframe.providers), ->
if crossframe.providers?.length
# XXX: Consider multiple providers in the future
p = crossframe.providers[0]
if p.entities?.length
e = p.entities[0]
scope.viaPageLink = 'https://via.hypothes.is/' + e
restrict: 'A'
templateUrl: 'share_dialog.html'
]
{module, inject} = require('angular-mock')
assert = chai.assert
describe 'share-dialog', ->
$scope = null
$compile = null
fakeCrossFrame = null
before ->
angular.module('h', [])
.directive('shareDialog', require('../share-dialog'))
beforeEach module('h')
beforeEach module('h.templates')
beforeEach module ($provide) ->
fakeCrossFrame = {providers: []}
$provide.value 'crossframe', fakeCrossFrame
return
beforeEach inject (_$compile_, _$rootScope_) ->
$compile = _$compile_
$scope = _$rootScope_.$new()
it 'generates new via link', ->
$element = $compile('<div share-dialog="">')($scope)
fakeCrossFrame.providers.push {entities: ['http://example.com']}
$scope.$digest()
assert.equal($scope.viaPageLink,
'https://via.hypothes.is/http://example.com')
...@@ -117,7 +117,11 @@ describe 'AppController', -> ...@@ -117,7 +117,11 @@ describe 'AppController', ->
it 'does not show login form for logged in users', -> it 'does not show login form for logged in users', ->
createController() createController()
assert.isFalse($scope.dialog.visible) assert.isFalse($scope.accountDialog.visible)
it 'does not show the share dialog at start', ->
createController()
assert.isFalse($scope.shareDialog.visible)
describe 'applyUpdate', -> describe 'applyUpdate', ->
......
...@@ -111,6 +111,27 @@ html { ...@@ -111,6 +111,27 @@ html {
} }
// Share this view /////////////////////
.share-dialog-toggle {
top: 1px;
left: 8px;
position: relative;
cursor: pointer;
color: $gray-light;
float: left;
margin-right: 15px;
&:hover {
color: $gray-dark;
}
}
.share-links {
a {
font-size: 1.5em;
padding: .3em;
}
}
//FORM RELATED//////////////////////////////// //FORM RELATED////////////////////////////////
.form-horizontal { .form-horizontal {
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
@include clearfix; @include clearfix;
position: relative; position: relative;
padding: 0 1.5385em; padding: 0 1.5385em;
color: $gray; color: $gray-darker;
} }
.simple-search-form * { .simple-search-form * {
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
} }
:not(:focus) ~ .simple-search-icon { :not(:focus) ~ .simple-search-icon {
color: $gray-lighter; color: $gray-light;
} }
input.simple-search-input { input.simple-search-input {
......
This diff is collapsed.
This diff is collapsed.
<div id="dialog" class="sheet content">
<i class="close h-icon-close"
role="button"
title="Close"
ng-click="shareDialog.visible = false"></i>
<div class="form-vertical tabbable">
<div class="form tab-pane" data-title="Share">
<p>Share the link below to show anyone these annotations and invite them to contribute their own.</p>
<p><input id="via"
class="form-input"
type="text"
ng-value="viaPageLink"
readonly /></p>
<p class="share-links">
<a href="//twitter.com/intent/tweet?url={{viaPageLink}}"
target="_blank"
title="Tweet link"
class="h-icon-twitter"></a>
<a href="//www.facebook.com/sharer/sharer.php?u={{viaPageLink}}"
target="_blank"
title="Share on Facebook"
class="h-icon-facebook"></a>
<a href="//plus.google.com/share?url={{viaPageLink}}"
target="_blank"
title="Post on Google Plus"
class="h-icon-google-plus"></a>
<a href="mailto:?subject=Let's%20Annotate&amp;body={{viaPageLink}}"
title="Share via email"
class="h-icon-mail"></a>
</p>
</div>
</div>
</div>
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