--- a/swtr/server.py +++ b/swtr/server.py @@ -6,7 +6,7 @@ import config import requests import json -import urllib2 +import StringIO import imghdr app = flask.Flask(__name__) @@ -53,9 +53,11 @@ @app.route('/annotate', methods=['GET']) def annotate(): print flask.request.args['where'] - img = urllib2.urlopen(flask.request.args['where']).read() - if imghdr.what('ignore', img) is None: - root = lxml.html.parse(flask.request.args['where']).getroot() + # img = urllib2.urlopen(flask.request.args['where']).read() + request = requests.get(flask.request.args['where']) + content = request.text + if imghdr.what('ignore', content) is None: + root = lxml.html.parse(StringIO.StringIO(content)).getroot() root.make_links_absolute(flask.request.args['where'], resolve_base_href=True) @@ -78,6 +80,76 @@ "css/annotator.min.css")) annotatorCSS.set("rel", "stylesheet") annotatorCSS.set("type", "text/css") + + swtmakerCSS = root.makeelement('link') + root.body.append(swtmakerCSS) + swtmakerCSS.set("href", flask.url_for('static', + filename= + "css/swtmaker.css")) + swtmakerCSS.set("rel", "stylesheet") + swtmakerCSS.set("type", "text/css") + + bootstrapCSS = root.makeelement('link') + root.body.append(bootstrapCSS) + bootstrapCSS.set("href", flask.url_for('static', + filename= + "css/bootstrap.min.css")) + bootstrapCSS.set("rel", "stylesheet") + bootstrapCSS.set("type", "text/css") + + underscoreJS = root.makeelement('script') + root.body.append(underscoreJS) + underscoreJS.set("src", flask.url_for('static', + filename="js/lib/" + + "underscore-1.5.2.min.js")) + underscoreJS.set("type", "text/javascript") + + backboneJS = root.makeelement('script') + root.body.append(backboneJS) + backboneJS.set("src", flask.url_for('static', + filename= + "js/lib/backbone-1.0.0.min.js")) + backboneJS.set("type", "text/javascript") + + if 'auth_tok' in session: + auth_tok = session['auth_tok'] + else: + auth_tok = {'access_token': '', 'refresh_token': ''} + + configScript = root.makeelement('script') + root.body.append(configScript) + configScript.text = """window.swtr = window.swtr || {}; + swtr.swtstoreURL = {} + swtr.endpoints = {} + 'get': '/api/sweets/q', + 'post': '/api/sweets', + 'auth': '/oauth/authorize', + 'login': '/auth/login', + 'logout': '/auth/logout' + {}; + + swtr.access_token = '{}'; + swtr.refresh_token = '{}'; + swtr.app_id = '{}';swtr.app_secret = '{}'; + swtr.oauth_redirect_uri = '{}';""".format( + '{}', 'function() {}return "{}"{}'.format('{', + config.swtstoreURL, '};'), + '{', '}', auth_tok['access_token'], auth_tok['refresh_token'], + config.app_id, config.app_secret, + config.redirect_uri) + configScript.set("type", "text/javascript") + + # swtmakerScript = root.makeelement('script') + # root.body.append(swtmakerScript) + # swtmakerScript.set("src", flask.url_for('static', + # filename="js/swtmaker.js")) + # swtmakerScript.set("type", "text/javascript") + + oAuthScript = root.makeelement('script') + root.body.append(oAuthScript) + oAuthScript.set("src", flask.url_for('static', + filename="js/oauth.js")) + oAuthScript.set("type", "text/javascript") appScript = root.makeelement('script') root.body.append(appScript) --- a/swtr/static/js/app.js +++ b/swtr/static/js/app.js @@ -1,8 +1,240 @@ -(function() { - $(document).ready(function() { - var annotator = new Annotator(document.body); - annotator.addPlugin("Tags"); - annotator.addPlugin("Filter"); +window.swtr = window.swtr || {}; +(function(swtr) { + + swtr.handleOAuth = function() { + if(swtr.access_token) { + $('#signinview').html('Signing you in..'); + $.ajax({ + url: swtr.swtstoreURL()+'/api/users/me?access_token='+ + swtr.access_token, + success: function(data) { + $('#signinview').html('Signed in as ' + data.username); + swtr.who = data.username; + $("#sign-in").hide(); + }, + error: function() { + // $('#signinview').html('Error signing in! Please try again'); + $("#sign-in").show(); + } + }); + } else { + $('#signinview').html('Please sign in.'); + } + }; + + var TxtAnnoSwt = Backbone.Model.extend({ + defaults: { + 'who': '', + 'what': 'txt-anno', + 'where': '', + 'how': {} + }, + initialize: function(options) { + this.set(options); + } }); -})(); + + var TxtAnnoSwts = Backbone.Collection.extend({ + model: TxtAnnoSwt, + url: function() { + return swtr.swtstoreURL() + '/sweets'; + }, + // get all sweets/annotations of type #img-anno for a particular URI + // (where) + // @options is a javascript object, + // @options.where : URI of the resource for which swts to be fetched + // @options.who: optional username to filter sweets + // @options.success: success callback to call + // @options.error: error callback to call + getAll: function(options) { + // error checking + if(!options.where) { + throw Error('"where" option must be passed to get sweets of a URI'); + return false; + } + /*if(!swtr.access_token) { + throw new Error('Access Token required to get query that API'); + }*/ + // setting up params + var where = options.where, + who = options.who || null; + url = swtr.swtstoreURL() + swtr.endpoints.get + '?where=' + + encodeURIComponent(where) + '&access_token=' + swtr.access_token; + if(who) { + url += '&who=' + who; + } + // get them! + this.sync('read', this, { + url: url, + success: function() { + if(typeof options.success === 'function') { + options.success.apply(this, arguments); + } + }, + error: function() { + if(typeof options.error === 'function') { + options.error.apply(this, arguments); + } + } + }); + }, + // post newly created sweets to a sweet store + // @options is a javascript object, + // @options.where : URI of the resource for which swts to be fetched + // @options.who: optional username to filter sweets + // @options.success: success callback to call + // @options.error: error callback to call, + post: function(options) { + var new_sweets = this.getNew(); + var dummy_collection = new Backbone.Collection(new_sweets); + + if(!swtr.access_token) { + throw new Error('Access Token is required to sweet'); + return; + } + + var url = swtr.swtstoreURL() + swtr.endpoints.post + + '?access_token=' + swtr.access_token; + + this.sync('create', dummy_collection, { + url: url, + success: function() { + if(typeof options.success === 'function') { + options.success.apply(this, arguments); + } + }, + error: function() { + if(typeof options.error === 'function') { + options.error.apply(this, arguments); + } + } + }); + }, + // return newly created models from the collection + getNew: function() { + var new_models = []; + this.each(function(model) { + if(model.isNew()) { + new_models.push(model); + } + }); + return new_models; + }, + // update part of the collection after a save on the server + update: function() { + } + }); + + var TxtAnnoView = Backbone.View.extend({ + initialize: function() { + this.annotator = new Annotator(document.body); + swtr.anno = this.annotator; + this.annotator.addPlugin("Tags"); + this.listenTo(this.collection, "add", this.loadAnno); + this.annotator.subscribe("annotationCreated", this.storeAnno); + }, + storeAnno: function(annotation) { + var pageURL = window.location.search.split("=")[1]; + if(!(swtr.who)) { + swtr.who = "Guest"; + } + swtr.TxtAnnoSwts.add(new TxtAnnoSwt({how: annotation, + where: pageURL, + who: swtr.who})); + if($("#show-sweets").attr('disabled')) { + $("#show-sweets").removeAttr('disabled'); + } + }, + loadAnno: function(annotation) { + if(!(annotation.isNew())) { + swtr.anno.createAnnotation(annotation.get('how')); + swtr.anno.setupAnnotation(annotation.get('how')); + } + } + }); + + var AppView = Backbone.View.extend({ + el: document.body, + events: { + "click #show-sweets": 'showSweets', + "click #sweet-cancel": 'cancelSweet', + "click #post-sweet": 'postSweet', + "click #sign-in": 'signIn' + }, + oauth: new Oauth({ + app_id: swtr.app_id, + app_secret: swtr.app_secret, + endpoint: swtr.swtstoreURL() + swtr.endpoints.auth, + redirect_uri: swtr.oauth_redirect_uri, + scopes: 'email,sweet' + }), + sweetTemplate: '
<%= how %>
'+ + '