Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also .

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also .
Choose a Base Repository
hypothesis/h
40a/h
AFDudley/h
BigBlueHat/h
BinaryStars/h
CCH543/h
Cinemacloud/h
Ericgood/h
FTG-003/h
Forethinker/h
GratefulTony/h
HGldJ1966/h
JJediny/h
John-Williams/h
Laurian/h
LittleFancy/h
MattyQ/h
Mishkin2015/h
RichardLitt/h
Staffan1/h
SteelWagstaff/h
TowerBR/h
VanyTang/h
abigailricarte/h
ackermann/h
alecchap/h
alesarrett/h
alexsegura/h
almereyda/h
alon/h
andzi/h
angelicxsoul/h
ansmoh/h
apurvajalit/h
arjunvasan/h
asdevor/h
bZichett/h
badgettrg/Webmarks
balmas/h
balupton/h
bbarker/h
bennlich/h
benthor/h
blakewest/h
bogste/h
bradparks/h
brittanystoroz/h
buiquangchien/h
cdchapman/h
charblanc/h
chowsamihq/h
chr7stos/Webmarks
chrber/h
chrismPssina/h
christinaphamAD/h
cmbirk/h
codeaudit/h
coolcool21/h
cove/h
csillag/h
danjimilk/h
dannyhope/h
daredream/h
davidmcclure/h
dennisplucinik/h
dezynetechnologies/h
diegodlh/h
djcun95/h
donsequitur/h
edsu/h
eiro10/h
emckean/h
ercchy/h
eshellman/h
fangang123/h
fchasen/h
fcrimins/h
fhirsch/h
ficolo/h
fragkopoulos/h
gauravkeerthi/h
geass/h
gergely-ujvari/h
gitter-badger/h
gnott/h
gobengo/h
gorinovic/h
gus3000/h
hashin/h
helemaalbigt/h
hmstepanek/h
hwasiti/h
hylhero/h
hyperstudio/h
iHDeveloper/h
imeysam/h
jackspaceBerkeley/h
jarey/h
jasdeep/h
jason790/h
jasonzou/j
jazahn/h
jccr/h
jean/h
jeka57/h
jeremydean/h
jermnelson/h
jibe-b/h
jnishiyama/h
jojksd/h
jpadilla/h
jtremback/h
judell/h
juli-so/h
kabacs/h
karissa/h
kaushikvijay/h
kaydoh/h
kill4uk/h
klopiinas/h
klrkdekira/h
koulihong311/h
krassif/h
krstnkngs/h
leoqmp/h
linhua55/h
lucadealfaro/h
lyspooner/h
lyzadanger/h
m1yag1/h
magee/h
mambocab/h
manunymous/h
maraino/h
mari-ja/h
markbarratt/h
martinq/h
mbbaig/h
mcarv63/h
meawoppl/h
meflyup/h
metasj/h
mgasner/h
mgax/h
mollycr/h
mrchrisadams/h
mrienstra/h
mshavlovsky/h
muddasani/h
nagyist/hyphothesis-h
nagyistoce/hypothesis-h
nanxio/h
neozhangthe1/h
ningyifan/h
nkingsley/h
nlholdem/h
nlisgo/h
noscripter/h
nshkuro/h
odnodn/h
oliversauter/h
openbizgit/h
opengovfoundation/h
openstax/hypothesis-server
ouroboros8/h
pablomarti/h
pamo/h
philipn/h
philschatz/h
pinballwonder/h
plainspace/h
raowl/h
rickyhan/h
rmoorman/h
rmtsukuru/h
robertknight/h
rowhit/h
rsarxiv/h
saakaifoundry/h
samrose/h
scharf/h
shepazu/h
sherah/h
shofheinz/h
soapdog/h
ssin122/test-h
st-fresh/h
stuk88/h
sylvanmist/h
tetratorus/h
tilgovi/h
tomnar/h
trivenews/h
truthadjustr/h
utngz/h
voidfiles/h
wenchen/h
yargevad/h
yumatch/h
zshen777/h
Nothing to show
Choose a Head Repository
hypothesis/h
40a/h
AFDudley/h
BigBlueHat/h
BinaryStars/h
CCH543/h
Cinemacloud/h
Ericgood/h
FTG-003/h
Forethinker/h
GratefulTony/h
HGldJ1966/h
JJediny/h
John-Williams/h
Laurian/h
LittleFancy/h
MattyQ/h
Mishkin2015/h
RichardLitt/h
Staffan1/h
SteelWagstaff/h
TowerBR/h
VanyTang/h
abigailricarte/h
ackermann/h
alecchap/h
alesarrett/h
alexsegura/h
almereyda/h
alon/h
andzi/h
angelicxsoul/h
ansmoh/h
apurvajalit/h
arjunvasan/h
asdevor/h
bZichett/h
badgettrg/Webmarks
balmas/h
balupton/h
bbarker/h
bennlich/h
benthor/h
blakewest/h
bogste/h
bradparks/h
brittanystoroz/h
buiquangchien/h
cdchapman/h
charblanc/h
chowsamihq/h
chr7stos/Webmarks
chrber/h
chrismPssina/h
christinaphamAD/h
cmbirk/h
codeaudit/h
coolcool21/h
cove/h
csillag/h
danjimilk/h
dannyhope/h
daredream/h
davidmcclure/h
dennisplucinik/h
dezynetechnologies/h
diegodlh/h
djcun95/h
donsequitur/h
edsu/h
eiro10/h
emckean/h
ercchy/h
eshellman/h
fangang123/h
fchasen/h
fcrimins/h
fhirsch/h
ficolo/h
fragkopoulos/h
gauravkeerthi/h
geass/h
gergely-ujvari/h
gitter-badger/h
gnott/h
gobengo/h
gorinovic/h
gus3000/h
hashin/h
helemaalbigt/h
hmstepanek/h
hwasiti/h
hylhero/h
hyperstudio/h
iHDeveloper/h
imeysam/h
jackspaceBerkeley/h
jarey/h
jasdeep/h
jason790/h
jasonzou/j
jazahn/h
jccr/h
jean/h
jeka57/h
jeremydean/h
jermnelson/h
jibe-b/h
jnishiyama/h
jojksd/h
jpadilla/h
jtremback/h
judell/h
juli-so/h
kabacs/h
karissa/h
kaushikvijay/h
kaydoh/h
kill4uk/h
klopiinas/h
klrkdekira/h
koulihong311/h
krassif/h
krstnkngs/h
leoqmp/h
linhua55/h
lucadealfaro/h
lyspooner/h
lyzadanger/h
m1yag1/h
magee/h
mambocab/h
manunymous/h
maraino/h
mari-ja/h
markbarratt/h
martinq/h
mbbaig/h
mcarv63/h
meawoppl/h
meflyup/h
metasj/h
mgasner/h
mgax/h
mollycr/h
mrchrisadams/h
mrienstra/h
mshavlovsky/h
muddasani/h
nagyist/hyphothesis-h
nagyistoce/hypothesis-h
nanxio/h
neozhangthe1/h
ningyifan/h
nkingsley/h
nlholdem/h
nlisgo/h
noscripter/h
nshkuro/h
odnodn/h
oliversauter/h
openbizgit/h
opengovfoundation/h
openstax/hypothesis-server
ouroboros8/h
pablomarti/h
pamo/h
philipn/h
philschatz/h
pinballwonder/h
plainspace/h
raowl/h
rickyhan/h
rmoorman/h
rmtsukuru/h
robertknight/h
rowhit/h
rsarxiv/h
saakaifoundry/h
samrose/h
scharf/h
shepazu/h
sherah/h
shofheinz/h
soapdog/h
ssin122/test-h
st-fresh/h
stuk88/h
sylvanmist/h
tetratorus/h
tilgovi/h
tomnar/h
trivenews/h
truthadjustr/h
utngz/h
voidfiles/h
wenchen/h
yargevad/h
yumatch/h
zshen777/h
Nothing to show
  • 12 commits
  • 12 files changed
  • 0 commit comments
  • 4 contributors
Commits on Mar 31, 2015
Use domain as citation title if no document
An annotation's document.title is used as the citation when displaying
an annotation. If this is an older annotation that has no document, fall
back to using the domain as the citation title instead.

Fixes #1542
Commits on Apr 01, 2015
Bump the number of annotations loaded per request to 200
The overhead associated with a single search call is high enough that
loading only 20 annotations at once is too little. In a naive test this
reduces the time take to request about 300 annotations from 5 seconds to
about 800ms (which, IMO, is still far too slow.)
Merge pull request #2120 from hypothesis/bump-initial-load-count
Bump the number of annotations loaded per request to 200
Commits on Apr 02, 2015
Move config blocks below all but run blocks
The config blocks should be after the declarations of services, at
least, so that they can decorate services.
Remove global icon alignment / size shift
This is a bad way to address places where what we really want is the
icon as a badge on an element that has text next it. We have special
styles for buttons, but not for other scenarios. Icons should be
resized based on semantic styles for their use rather than globally.
Make button icons larger
Partly a reaction to fce1f2c, which made icons overall smaller.
Remove inline style from pattern library
Pattern library should reflect actual usage.
Merge pull request #2118 from hypothesis/1542-source-url-not-visible-…
…on-older-annotations

Use domain as citation title if no document
View
@@ -6,6 +6,7 @@ install:
- gem install sass
- gem install compass
- pip install coveralls
- pip install mandrill
- pip install prospector
- make
services:
View
@@ -90,6 +90,7 @@ def get_by_username_or_email(cls, request, username, email):
)
).first()
# TODO: remove all this status bitfield stuff
@property
def email_confirmed(self):
return bool((self.status or 0) & 0b001)
@@ -123,6 +124,17 @@ def subscriptions(self, value):
else:
self.status = (self.status or 0) & ~0b100
@property
def invited(self):
return bool((self.status or 0) & 0b1000)
@invited.setter
def invited(self, value):
if value:
self.status = (self.status or 0) | 0b1000
else:
self.status = (self.status or 0) & ~0b1000
def _username_to_uid(username):
# We normalise usernames by dots and case in order to discourage attempts
View
@@ -0,0 +1,185 @@
# -*- coding: utf-8 -*-
"""
:mod:`h.claim.invite` is a utility to invite users to claim accounts
and is exposed as the command-line utility hypothesis-invite.
"""
import argparse
import logging
import os
import sys
import time
import mandrill
from pyramid import paster
from pyramid.request import Request
import transaction
from h.accounts import models
from h.claim.util import generate_claim_url
log = logging.getLogger('h.claim.invite')
def get_env(config_uri):
"""Return a preconfigured paste environment object."""
env = paster.bootstrap(config_uri)
return env
parser = argparse.ArgumentParser(
'hypothesis-invite',
description='Send invitation emails to users.'
)
parser.add_argument('config_uri', help='paster configuration URI')
parser.add_argument(
'--base',
help='base URL',
default='http://localhost:5000',
metavar='URL'
)
parser.add_argument(
'-n',
'--dry-run',
help='dry run (log but do not send email)',
action='store_true',
)
parser.add_argument(
'-l',
'--limit',
type=int,
metavar='N',
help='maximum users to invite',
)
parser.add_argument(
'-k',
'--key',
metavar='KEY',
help='Mandrill API key (defaults to MANDRILL_APIKEY variable)',
default=os.environ.get('MANDRILL_APIKEY'),
)
def get_users(session, limit=None):
return (
session
.query(models.User)
.filter(
models.User.password == u'',
models.User.status.op('&')(0b1000) == 0 # noqa
)
.limit(limit)
.all()
)
def get_merge_vars(request, users):
for user in users:
userid = 'acct:{}@{}'.format(user.username, request.host_url)
claim = generate_claim_url(request, userid)
recipient = user.email
merge_vars = [
{
'name': 'USERNAME',
'content': user.username,
},
{
'name': 'CLAIM_URL',
'content': claim,
},
]
yield {
'rcpt': recipient,
'vars': merge_vars
}
def get_recipients(users):
for user in users:
yield {
'email': user.email,
'name': user.username,
}
def send_invitations(request, api_key, users):
log.info('Collecting merge vars and recipients.')
merge_vars = list(get_merge_vars(request, users))
recipients = list(get_recipients(users))
try:
results = mandrill.Mandrill(api_key).messages.send_template(
template_content=[],
template_name='activation-email-to-reserved-usernames',
message={
'merge_vars': merge_vars,
'to': recipients,
}
)
except mandrill.Error:
log.exception('Error sending invitations.')
sys.exit(1)
return group_users_by_result(users, results)
def mark_invited(session, users):
for user in users:
user.invited = True
session.add(user)
transaction.commit()
def group_users_by_result(users, results):
users_by_email = {user.email: user for user in users}
success = []
error = []
for row in results:
user = users_by_email[row['email']]
if row['status'] in ['queued', 'sent']:
success.append(user)
else:
error.append(user)
return success, error
def main():
args = parser.parse_args()
request = Request.blank('', base_url=args.base)
env = paster.bootstrap(args.config_uri, request=request)
request.root = env['root']
paster.setup_logging(args.config_uri)
if not args.dry_run:
if args.key is None:
print 'No Mandrill API key specified.'
parser.print_help()
sys.exit(1)
# Provide an opportunity to bail out.
log.warning('Changes will be made and mail will be sent.')
log.info('Waiting five seconds.')
time.sleep(5)
log.info('Collecting reserved users.')
session = models.get_session(request)
users = get_users(session, limit=args.limit)
if args.dry_run:
log.info('Skipping actions ignored by dry run.')
success, error = users, []
else:
log.info('Sending invitations to %d users.', len(users))
success, error = send_invitations(request, args.key, users)
log.info('Marking users as invited.')
mark_invited(session, success)
log.info('%d succeeded / %d failed', len(success), len(error))
sys.exit(0)
if __name__ == '__main__':
main()
@@ -86,11 +86,6 @@ module.exports = angular.module('h', [
'toastr'
])
.config(configureDocument)
.config(configureLocation)
.config(configureRoutes)
.config(configureTemplates)
.controller('AppController', require('./app-controller'))
.controller('AnnotationUIController', require('./annotation-ui-controller'))
.controller('AnnotationViewerController', require('./annotation-viewer-controller'))
@@ -151,6 +146,11 @@ module.exports = angular.module('h', [
.value('AnnotationUISync', require('./annotation-ui-sync'))
.value('Discovery', require('./discovery'))
.config(configureDocument)
.config(configureLocation)
.config(configureRoutes)
.config(configureTemplates)
.run(setupCrossFrame)
.run(setupStreamer)
.run(setupHost)
@@ -211,15 +211,15 @@ AnnotationController = [
@annotationURI = new URL("/a/#{@annotation.id}", this.baseURI).href
# Extract the document metadata.
uri = model.uri
domain = new URL(uri).hostname
if model.document
uri = model.uri
if uri.indexOf("urn") is 0
# This URI is not clickable, see if we have something better
for link in model.document.link when link.href.indexOf("urn")
uri = link.href
break
domain = new URL(uri).hostname
documentTitle = if Array.isArray(model.document.title)
model.document.title[0]
else
@@ -229,11 +229,14 @@ AnnotationController = [
uri: uri
domain: domain
title: documentTitle or domain
if @document.title.length > 30
@document.title = @document.title[0..29] + ''
else
@document = null
@document =
uri: uri
domain: domain
title: domain
if @document.title.length > 30
@document.title = @document.title[0..29] + ''
# Form the tags for ngTagsInput.
@annotation.tags = ({text} for text in (model.tags or []))
@@ -209,10 +209,20 @@ describe 'annotation', ->
controller.render()
assert.equal(controller.document.title, 'example.com')
it 'skips the document object if no document is present on the annotation', ->
it 'still sets the uri correctly if the annotation has no document', ->
delete annotation.document
controller.render()
assert.isNull(controller.document)
assert(controller.document.uri == $scope.annotation.uri)
it 'still sets the domain correctly if the annotation has no document', ->
delete annotation.document
controller.render()
assert(controller.document.domain == 'example.com')
it 'uses the domain for the title when the annotation has no document', ->
delete annotation.document
controller.render()
assert(controller.document.title == 'example.com')
describe 'when there are no targets', ->
beforeEach ->
@@ -59,7 +59,6 @@ describe 'WidgetController', ->
$provide.value 'annotationMapper', fakeAnnotationMapper
$provide.value 'annotationUI', fakeAnnotationUI
$provide.value 'auth', fakeAuth
$provide.value 'crossframe', fakeCrossFrame
$provide.value 'store', fakeStore
$provide.value 'streamer', fakeStreamer
@@ -75,6 +74,7 @@ describe 'WidgetController', ->
describe 'loadAnnotations', ->
it 'loads all annotation for a provider', ->
viewer.chunkSize = 20
fakeCrossFrame.providers.push {entities: ['http://example.com']}
$scope.$digest()
loadSpy = fakeAnnotationMapper.loadAnnotations
@@ -4,21 +4,22 @@ angular = require('angular')
module.exports = class WidgetController
this.$inject = [
'$scope', 'annotationUI', 'crossframe', 'annotationMapper',
'auth', 'streamer', 'streamFilter', 'store'
'streamer', 'streamFilter', 'store'
]
constructor: (
$scope, annotationUI, crossframe, annotationMapper,
auth, streamer, streamFilter, store
streamer, streamFilter, store
) ->
# Tells the view that these annotations are embedded into the owner doc
$scope.isEmbedded = true
$scope.isStream = true
@chunkSize = 200
loaded = []
_loadAnnotationsFrom = (query, offset) ->
_loadAnnotationsFrom = (query, offset) =>
queryCore =
limit: 20
limit: @chunkSize
offset: offset
sort: 'created'
order: 'asc'
@@ -33,11 +33,3 @@
display: none;
visibility: hidden;
}
// Icons
[class^="h-icon-"], [class*=" h-icon-"] {
vertical-align: middle;
&:before {
font-size: 130%;
}
}
@@ -257,7 +257,9 @@
// Positions the icon nicely within the button.
.btn-icon {
vertical-align: middle;
font-size: 1.4em;
margin-right: .25em;
vertical-align: top;
}
// Absolutely positions a message/icon to the left of a button.
@@ -383,7 +383,7 @@ <h1>Buttons</h1>
<div class="form-field">
<button class="btn js-disabled" type="submit" name="">
<span class="btn-icon spinner"><span><span></span></span></span>
<span style="position: relative; bottom: 3px; left: 1px;">Button Loading</span>
Button Loading
</button>
</div>
</div>
@@ -511,9 +511,6 @@ <h1>Simple Search</h1>
<form class="simple-search-form">
<input class="simple-search-input" type="text" name="searchText" placeholder="Search…" />
<i class="simple-search-icon h-icon-search"></i>
<button class="simple-search-clear" type="reset">
<i class="h-icon-clear"></i>
</button>
</form>
</div>
</div>
Oops, something went wrong.

No commit comments for this range