From e6a99f33a9fe423689e36280cae3a0b18a696623 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Fri, 7 Nov 2014 17:04:41 -0700 Subject: [PATCH 1/8] feat(sharing): add ability to share avatar. adds static page with avatar screen, and generates image from it --- config.json.example | 7 +++++- package.json | 6 +++-- src/routes/pages.js | 44 +++++++++++++++++++++++++++++++++++ views/avatar-static.jade | 50 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 views/avatar-static.jade diff --git a/config.json.example b/config.json.example index 821bb91fc37..dcfb3fb8d3c 100644 --- a/config.json.example +++ b/config.json.example @@ -25,5 +25,10 @@ "PAYPAL_SIGNATURE": "PAYPAL_SIGNATURE", "EMAIL_SERVER_URL": "http://example.com", "EMAIL_SERVER_AUTH_USER": "user", - "EMAIL_SERVER_AUTH_PASSWORD": "password" + "EMAIL_SERVER_AUTH_PASSWORD": "password", + "S3":{ + "accessKeyId":"accessKeyId", + "secretAccessKey":"secretAccessKey" + } + } diff --git a/package.json b/package.json index 002cd497b30..a3e0fde4369 100644 --- a/package.json +++ b/package.json @@ -25,17 +25,18 @@ "grunt-nodemon": "~0.3.0", "habitrpg-shared": "git://github.com/HabitRPG/habitrpg-shared#develop", "icalendar": "git://github.com/lefnire/node-icalendar#master", + "jade": "~1.7.0", "js2xmlparser": "~0.1.2", "lodash": "~2.4.1", - "jade": "~1.7.0", "method-override": "~2.2.0", - "mongoose": "~3.8.17", "moment": "~2.8.3", + "mongoose": "~3.8.17", "mongoose-id-autoinc": "~2013.7.14-4", "nconf": "~0.6.9", "newrelic": "~1.11.2", "nib": "~1.0.1", "nodemailer": "~0.5.2", + "pageres": "^1.0.1", "passport": "~0.2.1", "passport-facebook": "Fonger/passport-facebook#a8f98adcddad99caa9a918bc7b76462c92c5c9fd", "paypal-express-checkout": "git://github.com/HabitRPG/node-paypal-express-checkout#habitrpg", @@ -43,6 +44,7 @@ "paypal-recurring": "git://github.com/jaybryant/paypal-recurring#656b496f43440893c984700191666a5c5c535dca", "pretty-data": "git://github.com/vkiryukhin/pretty-data#master", "request": "~2.44.0", + "s3": "^4.3.1", "stripe": "*", "swagger-node-express": "git://github.com/lefnire/swagger-node-express#habitrpg", "universal-analytics": "~0.3.2", diff --git a/src/routes/pages.js b/src/routes/pages.js index 113375c16e4..23fb894c18c 100644 --- a/src/routes/pages.js +++ b/src/routes/pages.js @@ -28,6 +28,50 @@ _.each(pages, function(name){ }); }) +var mongoose = require('mongoose'); +router.get('/static/avatar-:uuid.html', i18n.getUserLanguage, middleware.locals, function(req, res) { + mongoose.model('User').findById(req.params.uuid).select('stats profile items achievements preferences backer contributor').exec(function(err, user){ + res.render('avatar-static', { + title: user.profile.name, + env: _.defaults({user:user},res.locals.habitrpg) + }); + }) +}); +var Pageres = require('pageres'); //https://github.com/sindresorhus/pageres +var s3 = require('s3'); //https://github.com/andrewrk/node-s3-client +var bucket = 'habitrpg-dev'; +var client = s3.createClient({ + s3Options: { + accessKeyId: nconf.get("S3").accessKeyId, + secretAccessKey: nconf.get("S3").secretAccessKey + } +}); +router.get('/static/avatar-:uuid.png', i18n.getUserLanguage, middleware.locals, function(req, res, next) { + var filename = 'avatar-'+req.params.uuid+'.png'; + new Pageres({delay: 1}) + .src(nconf.get('BASE_URL')+'/static/avatar-'+req.params.uuid+'.html', ['140x147'], {crop: true, filename: filename.replace('.png','')}) + .dest(__dirname)//TODO Delete this aftewards, or stream directly to s3 instead + .run(function (err, file) { + if (err) return next(err); + var params = { + localFile: __dirname + "/" + filename, + s3Params: { Bucket: bucket, Key: filename } + }; + var uploader = client.uploadFile(params); + uploader.on('error', function(err) { + console.error("unable to upload:", err.stack); + }); + //uploader.on('progress', function() { + // console.log("progress", uploader.progressMd5Amount, + // uploader.progressAmount, uploader.progressTotal); + //}); + uploader.on('end', function() { + res.json(200,{file: s3.getPublicUrlHttp(bucket,filename)}); + console.log("done uploading"); + }); + }); +}); + // --------- Redirects -------- router.get('/static/extensions', function(req, res) { diff --git a/views/avatar-static.jade b/views/avatar-static.jade new file mode 100644 index 00000000000..717af92fd1b --- /dev/null +++ b/views/avatar-static.jade @@ -0,0 +1,50 @@ +doctype html +html(ng-app="habitrpg") + head + title=title + link(rel='shortcut icon', href='#{env.getBuildUrl("favicon.ico")}?v=3') + + meta(charset='utf-8') + meta(name='viewport', content='width=device-width, initial-scale=1.0') + meta(name='apple-mobile-web-app-capable', content='yes') + + script(type='text/javascript'). + window.env = !{JSON.stringify(env)}; + + != env.getManifestFiles("app") + + script(type='text/javascript'). + hello.init({ + facebook : window.env.FACEBOOK_KEY + }); + + window.habitrpg + .controller('StaticAvatarCtrl', ['$scope', '$http', function($scope, $http){ + $scope.profile = window.env.user; + + $scope.postToWall = function(network, customMessage) { + hello(network).login({scope: 'publish'}).then(function (auth) { + $http.get('/static/avatar-'+$scope.profile._id+'.png').success(function(r){ + //TODO experiment with just the page as a link + hello(auth.network).api('/me/feed', 'post', { + picture: r.file, // also see link, picture, icon //https://developers.facebook.com/docs/graph-api/reference/v2.2/status#publishing + message: customMessage || "Check out my HabitRPG progress!" + }).then(function (r) { + debugger; + }); + }) + }); + } + }]) + + + + //webfonts + link(href='//fonts.googleapis.com/css?family=Lato:300,400,700,400italic,700italic', rel='stylesheet', type='text/css') + + body(ng-cloak) + include ./shared/header/avatar + div(ng-controller='StaticAvatarCtrl') + +herobox({main:true}) + button.btn.btn-primary(ng-click='postToWall("facebook", customMessage)') Post to Facebook + textarea(placeholder="Check out my HabitRPG progress!",ng-model="customMessage") From 18b350ebcce3ec7374f44af44ca2bca44e1e85d1 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 11 Nov 2014 16:05:14 -0700 Subject: [PATCH 2/8] feat(sharing): directly stream avatar screenshot to aws --- package.json | 3 ++- src/routes/pages.js | 38 +++++++++++++++----------------------- 2 files changed, 17 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index a3e0fde4369..48503271e07 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "main": "./src/server.js", "dependencies": { "async": "~0.9.0", + "aws-sdk": "^2.0.25", "bower": "~1.3.12", "coffee-script": "1.6.x", "connect-ratelimit": "0.0.7", @@ -44,7 +45,7 @@ "paypal-recurring": "git://github.com/jaybryant/paypal-recurring#656b496f43440893c984700191666a5c5c535dca", "pretty-data": "git://github.com/vkiryukhin/pretty-data#master", "request": "~2.44.0", - "s3": "^4.3.1", + "s3-upload-stream": "^1.0.6", "stripe": "*", "swagger-node-express": "git://github.com/lefnire/swagger-node-express#habitrpg", "universal-analytics": "~0.3.2", diff --git a/src/routes/pages.js b/src/routes/pages.js index 23fb894c18c..259b414237d 100644 --- a/src/routes/pages.js +++ b/src/routes/pages.js @@ -38,36 +38,28 @@ router.get('/static/avatar-:uuid.html', i18n.getUserLanguage, middleware.locals, }) }); var Pageres = require('pageres'); //https://github.com/sindresorhus/pageres -var s3 = require('s3'); //https://github.com/andrewrk/node-s3-client +var AWS = require('aws-sdk'); +AWS.config.update({accessKeyId: nconf.get("S3").accessKeyId, secretAccessKey: nconf.get("S3").secretAccessKey}); +var s3Stream = require('s3-upload-stream')(new AWS.S3()); //https://github.com/nathanpeck/s3-upload-stream var bucket = 'habitrpg-dev'; -var client = s3.createClient({ - s3Options: { - accessKeyId: nconf.get("S3").accessKeyId, - secretAccessKey: nconf.get("S3").secretAccessKey - } -}); + router.get('/static/avatar-:uuid.png', i18n.getUserLanguage, middleware.locals, function(req, res, next) { var filename = 'avatar-'+req.params.uuid+'.png'; - new Pageres({delay: 1}) + new Pageres()//{delay:1} .src(nconf.get('BASE_URL')+'/static/avatar-'+req.params.uuid+'.html', ['140x147'], {crop: true, filename: filename.replace('.png','')}) - .dest(__dirname)//TODO Delete this aftewards, or stream directly to s3 instead .run(function (err, file) { if (err) return next(err); - var params = { - localFile: __dirname + "/" + filename, - s3Params: { Bucket: bucket, Key: filename } - }; - var uploader = client.uploadFile(params); - uploader.on('error', function(err) { - console.error("unable to upload:", err.stack); + var upload = s3Stream.upload({ + Bucket: bucket, + Key: filename, + ACL: "public-read", + StorageClass: "REDUCED_REDUNDANCY", + ContentType: "binary/octet-stream" }); - //uploader.on('progress', function() { - // console.log("progress", uploader.progressMd5Amount, - // uploader.progressAmount, uploader.progressTotal); - //}); - uploader.on('end', function() { - res.json(200,{file: s3.getPublicUrlHttp(bucket,filename)}); - console.log("done uploading"); + file[0].pipe(upload); + + upload.on('uploaded', function (details) { + res.redirect(details.Location); }); }); }); From 69da58503a24c177b8c0f13360466384e27ba6e2 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 11 Nov 2014 15:03:19 -0700 Subject: [PATCH 3/8] feat(sharing): move avatar-sharing to herobox, use addthis instead of custom solution. refactor from pages/* to export/* --- public/css/avatar.styl | 12 +++++++- public/js/controllers/footerCtrl.js | 5 ++-- src/controllers/dataexport.js | 45 +++++++++++++++++++++++++++++ src/routes/dataexport.js | 5 +++- src/routes/pages.js | 36 ----------------------- views/avatar-static.jade | 24 +-------------- views/index.jade | 3 ++ views/shared/header/avatar.jade | 2 ++ 8 files changed, 69 insertions(+), 63 deletions(-) diff --git a/public/css/avatar.styl b/public/css/avatar.styl index 10432e1c770..20f03c3a0fd 100644 --- a/public/css/avatar.styl +++ b/public/css/avatar.styl @@ -73,7 +73,17 @@ future re: pets and whatnot, this is just temporary. &.isUser background: $color-herobox // Set a different background color for the current user &:hover, &:focus - background: lighten($color-herobox, 16.18%) + background: lighten($color-herobox, 16.18%) + + .addthis_pill_style + width: 50px !important + .addthis_native_toolbox + position: absolute + top:2px + right:2px + opacity:0 + &:hover .addthis_native_toolbox + opacity:1 //Need to find a way to indicate who is leader without using background-color as it won't work when a background image is applied //.herobox.isLeader.noBackgroundImage diff --git a/public/js/controllers/footerCtrl.js b/public/js/controllers/footerCtrl.js index f1e4f7f0b52..2a043f52f82 100644 --- a/public/js/controllers/footerCtrl.js +++ b/public/js/controllers/footerCtrl.js @@ -38,8 +38,9 @@ // Scripts only for desktop if (!window.env.IS_MOBILE) { - // Add This - $.getScript("//s7.addthis.com/js/250/addthis_widget.js#pubid=lefnire"); + // Add This - FIXME why isn't this working when here? instead it's now in + //$.getScript("//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5016f6cc44ad68a4"); + window.addthis_options = 'facebook,twitter,googleplus,tumblr'; // Google Charts $.getScript("//www.google.com/jsapi", function() { diff --git a/src/controllers/dataexport.js b/src/controllers/dataexport.js index 48a08b1d386..0ee176bbe29 100644 --- a/src/controllers/dataexport.js +++ b/src/controllers/dataexport.js @@ -8,6 +8,12 @@ var js2xmlparser = require("js2xmlparser"); var pd = require('pretty-data').pd; var User = require('../models/user').model; +// Avatar screenshot/static-page includes +var Pageres = require('pageres'); //https://github.com/sindresorhus/pageres +var AWS = require('aws-sdk'); +AWS.config.update({accessKeyId: nconf.get("S3").accessKeyId, secretAccessKey: nconf.get("S3").secretAccessKey}); +var s3Stream = require('s3-upload-stream')(new AWS.S3()); //https://github.com/nathanpeck/s3-upload-stream +var bucket = 'habitrpg-dev'; /* ------------------------------------------------------------------------ @@ -83,3 +89,42 @@ expressres.jsonstring = function(obj, headers, status) { body = pd.json(JSON.stringify(obj)); return this.send(body, headers, status); }; + +/* + ------------------------------------------------------------------------ + Static page and image screenshot of avatar + ------------------------------------------------------------------------ + */ + + +dataexport.avatarPage = function(req, res) { + User.findById(req.params.uuid).select('stats profile items achievements preferences backer contributor').exec(function(err, user){ + res.render('avatar-static', { + title: user.profile.name, + env: _.defaults({user:user},res.locals.habitrpg) + }); + }) +}; + +dataexport.avatarImage = function(req, res, next) { + var filename = 'avatar-'+req.params.uuid+'.png'; + new Pageres()//{delay:1} + .src(nconf.get('BASE_URL')+'/export/avatar-'+req.params.uuid+'.html', ['140x147'], {crop: true, filename: filename.replace('.png','')}) + .run(function (err, file) { + if (err) return next(err); + var upload = s3Stream.upload({ + Bucket: bucket, + Key: filename, + ACL: "public-read", + StorageClass: "REDUCED_REDUNDANCY", + ContentType: "binary/octet-stream" + }); + upload.on('error', function (err) { + next(err); + }); + upload.on('uploaded', function (details) { + res.redirect(details.Location); + }); + file[0].pipe(upload); + }); +}; diff --git a/src/routes/dataexport.js b/src/routes/dataexport.js index ad2e2797d0d..ba279571246 100644 --- a/src/routes/dataexport.js +++ b/src/routes/dataexport.js @@ -3,11 +3,14 @@ var router = new express.Router(); var dataexport = require('../controllers/dataexport'); var auth = require('../controllers/auth'); var nconf = require('nconf'); -var i18n = require('../i18n') +var i18n = require('../i18n'); +var middleware = require('../middleware.js'); /* Data export */ router.get('/history.csv',auth.authWithSession,i18n.getUserLanguage,dataexport.history); //[todo] encode data output options in the data controller and use these to build routes router.get('/userdata.xml',auth.authWithSession,i18n.getUserLanguage,dataexport.leanuser,dataexport.userdata.xml); router.get('/userdata.json',auth.authWithSession,i18n.getUserLanguage,dataexport.leanuser,dataexport.userdata.json); +router.get('/avatar-:uuid.html', i18n.getUserLanguage, middleware.locals, dataexport.avatarPage); +router.get('/avatar-:uuid.png', i18n.getUserLanguage, middleware.locals, dataexport.avatarImage); module.exports = router; diff --git a/src/routes/pages.js b/src/routes/pages.js index 259b414237d..113375c16e4 100644 --- a/src/routes/pages.js +++ b/src/routes/pages.js @@ -28,42 +28,6 @@ _.each(pages, function(name){ }); }) -var mongoose = require('mongoose'); -router.get('/static/avatar-:uuid.html', i18n.getUserLanguage, middleware.locals, function(req, res) { - mongoose.model('User').findById(req.params.uuid).select('stats profile items achievements preferences backer contributor').exec(function(err, user){ - res.render('avatar-static', { - title: user.profile.name, - env: _.defaults({user:user},res.locals.habitrpg) - }); - }) -}); -var Pageres = require('pageres'); //https://github.com/sindresorhus/pageres -var AWS = require('aws-sdk'); -AWS.config.update({accessKeyId: nconf.get("S3").accessKeyId, secretAccessKey: nconf.get("S3").secretAccessKey}); -var s3Stream = require('s3-upload-stream')(new AWS.S3()); //https://github.com/nathanpeck/s3-upload-stream -var bucket = 'habitrpg-dev'; - -router.get('/static/avatar-:uuid.png', i18n.getUserLanguage, middleware.locals, function(req, res, next) { - var filename = 'avatar-'+req.params.uuid+'.png'; - new Pageres()//{delay:1} - .src(nconf.get('BASE_URL')+'/static/avatar-'+req.params.uuid+'.html', ['140x147'], {crop: true, filename: filename.replace('.png','')}) - .run(function (err, file) { - if (err) return next(err); - var upload = s3Stream.upload({ - Bucket: bucket, - Key: filename, - ACL: "public-read", - StorageClass: "REDUCED_REDUNDANCY", - ContentType: "binary/octet-stream" - }); - file[0].pipe(upload); - - upload.on('uploaded', function (details) { - res.redirect(details.Location); - }); - }); -}); - // --------- Redirects -------- router.get('/static/extensions', function(req, res) { diff --git a/views/avatar-static.jade b/views/avatar-static.jade index 717af92fd1b..9223081dba0 100644 --- a/views/avatar-static.jade +++ b/views/avatar-static.jade @@ -14,31 +14,11 @@ html(ng-app="habitrpg") != env.getManifestFiles("app") script(type='text/javascript'). - hello.init({ - facebook : window.env.FACEBOOK_KEY - }); - window.habitrpg - .controller('StaticAvatarCtrl', ['$scope', '$http', function($scope, $http){ + .controller('StaticAvatarCtrl', ['$scope', function($scope){ $scope.profile = window.env.user; - - $scope.postToWall = function(network, customMessage) { - hello(network).login({scope: 'publish'}).then(function (auth) { - $http.get('/static/avatar-'+$scope.profile._id+'.png').success(function(r){ - //TODO experiment with just the page as a link - hello(auth.network).api('/me/feed', 'post', { - picture: r.file, // also see link, picture, icon //https://developers.facebook.com/docs/graph-api/reference/v2.2/status#publishing - message: customMessage || "Check out my HabitRPG progress!" - }).then(function (r) { - debugger; - }); - }) - }); - } }]) - - //webfonts link(href='//fonts.googleapis.com/css?family=Lato:300,400,700,400italic,700italic', rel='stylesheet', type='text/css') @@ -46,5 +26,3 @@ html(ng-app="habitrpg") include ./shared/header/avatar div(ng-controller='StaticAvatarCtrl') +herobox({main:true}) - button.btn.btn-primary(ng-click='postToWall("facebook", customMessage)') Post to Facebook - textarea(placeholder="Check out my HabitRPG progress!",ng-model="customMessage") diff --git a/views/index.jade b/views/index.jade index 802e3873ebd..bd9f42f9f5b 100644 --- a/views/index.jade +++ b/views/index.jade @@ -10,6 +10,9 @@ html(ng-app="habitrpg", ng-controller="RootCtrl", ng-class='{"applying-action":a meta(name='viewport', content='width=device-width, initial-scale=1.0') meta(name='apple-mobile-web-app-capable', content='yes') + //FIXME for some reason this won't load when in footerCtrl.js#deferredScripts() + script(type="text/javascript", src="//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5016f6cc44ad68a4", async="async") + script(type='text/javascript'). window.env = !{JSON.stringify(env)}; diff --git a/views/shared/header/avatar.jade b/views/shared/header/avatar.jade index 415abe6ede8..4bec44df16f 100644 --- a/views/shared/header/avatar.jade +++ b/views/shared/header/avatar.jade @@ -7,6 +7,8 @@ mixin avatar(opts) .character-sprites + .addthis_native_toolbox(ng-if='profile._id==user._id', data-url="#{env.BASE_URL}/export/avatar-{{profile._id}}.html", data-title="Check out my HabitRPG progress!") + // Mount Body if !opts.minimal span(ng-if='profile.items.currentMount', class='Mount_Body_{{profile.items.currentMount}}') From 3e21e1f4483ecbe516c8ba8db835dae49ad71da9 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 11 Nov 2014 17:04:53 -0700 Subject: [PATCH 4/8] feat(sharing): implement caching of avatar img. img as image/png instead of octet/stream --- src/controllers/dataexport.js | 13 ++++++++++--- views/shared/header/avatar.jade | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/controllers/dataexport.js b/src/controllers/dataexport.js index 0ee176bbe29..2b2a5b8d0f1 100644 --- a/src/controllers/dataexport.js +++ b/src/controllers/dataexport.js @@ -14,6 +14,7 @@ var AWS = require('aws-sdk'); AWS.config.update({accessKeyId: nconf.get("S3").accessKeyId, secretAccessKey: nconf.get("S3").secretAccessKey}); var s3Stream = require('s3-upload-stream')(new AWS.S3()); //https://github.com/nathanpeck/s3-upload-stream var bucket = 'habitrpg-dev'; +var request = require('request'); /* ------------------------------------------------------------------------ @@ -108,8 +109,12 @@ dataexport.avatarPage = function(req, res) { dataexport.avatarImage = function(req, res, next) { var filename = 'avatar-'+req.params.uuid+'.png'; - new Pageres()//{delay:1} - .src(nconf.get('BASE_URL')+'/export/avatar-'+req.params.uuid+'.html', ['140x147'], {crop: true, filename: filename.replace('.png','')}) + request.head('https://'+bucket+'.s3.amazonaws.com/'+filename, function(err,response,body) { + // cache images for 10 minutes on aws, else upload a new one + if (response.statusCode==200 && moment().diff(response.headers['last-modified'], 'minutes') < 10) + return res.redirect(301, 'https://' + bucket + '.s3.amazonaws.com/' + filename); + new Pageres()//{delay:1} + .src(nconf.get('BASE_URL') + '/export/avatar-' + req.params.uuid + '.html', ['140x147'], {crop: true, filename: filename.replace('.png', '')}) .run(function (err, file) { if (err) return next(err); var upload = s3Stream.upload({ @@ -117,7 +122,8 @@ dataexport.avatarImage = function(req, res, next) { Key: filename, ACL: "public-read", StorageClass: "REDUCED_REDUNDANCY", - ContentType: "binary/octet-stream" + ContentType: "image/png", + Expires: +moment().add({minutes: 3}) }); upload.on('error', function (err) { next(err); @@ -127,4 +133,5 @@ dataexport.avatarImage = function(req, res, next) { }); file[0].pipe(upload); }); + }) }; diff --git a/views/shared/header/avatar.jade b/views/shared/header/avatar.jade index 4bec44df16f..3c03ac1131c 100644 --- a/views/shared/header/avatar.jade +++ b/views/shared/header/avatar.jade @@ -7,7 +7,7 @@ mixin avatar(opts) .character-sprites - .addthis_native_toolbox(ng-if='profile._id==user._id', data-url="#{env.BASE_URL}/export/avatar-{{profile._id}}.html", data-title="Check out my HabitRPG progress!") + .addthis_native_toolbox(ng-if='profile._id==user._id', data-url="#{env.BASE_URL}/export/avatar-{{profile._id}}.png", data-title="Check out my HabitRPG progress!") // Mount Body if !opts.minimal From 3a415a45a96b5260ca4bc25b56da117dd0432a98 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 11 Nov 2014 17:52:03 -0700 Subject: [PATCH 5/8] feat(sharing): add download link --- public/js/controllers/footerCtrl.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/public/js/controllers/footerCtrl.js b/public/js/controllers/footerCtrl.js index 2a043f52f82..afd7ca02291 100644 --- a/public/js/controllers/footerCtrl.js +++ b/public/js/controllers/footerCtrl.js @@ -40,7 +40,16 @@ if (!window.env.IS_MOBILE) { // Add This - FIXME why isn't this working when here? instead it's now in //$.getScript("//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5016f6cc44ad68a4"); - window.addthis_options = 'facebook,twitter,googleplus,tumblr'; + var addthisServices = 'facebook,twitter,googleplus,tumblr,'+window.env.BASE_URL.replace('https://','').replace('http://',''); + window.addthis_config = { + services_custom:{ + name: "Download", + url: window.env.BASE_URL+"/export/avatar-"+User.user._id+".png", + icon: window.env.BASE_URL+"/favicon.ico" + }, + services_expanded:addthisServices, + services_compact:addthisServices + }; // Google Charts $.getScript("//www.google.com/jsapi", function() { From 15f318ccc2b455856273d6ff33a1b0f42adc23ac Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 11 Nov 2014 19:11:04 -0700 Subject: [PATCH 6/8] feat(sharing): screw it, social links + img + text aint working, just redirect to homepage + show member modal --- public/js/static.js | 15 +++++++ public/manifest.json | 2 + views/shared/header/avatar.jade | 2 +- views/static/front.jade | 78 +++++++++++++++++---------------- 4 files changed, 59 insertions(+), 38 deletions(-) diff --git a/public/js/static.js b/public/js/static.js index 66e2b8ee72d..860dbf5587c 100644 --- a/public/js/static.js +++ b/public/js/static.js @@ -6,6 +6,21 @@ window.habitrpgStatic = angular.module('habitrpgStatic', ['notificationServices' .constant("STORAGE_SETTINGS_ID", 'habit-mobile-settings') .constant("MOBILE_APP", false) +.controller("RootCtrl", ['$scope', '$location', '$modal', '$http', function($scope, $location, $modal, $http){ + // must be #?memberId=xx, see https://github.com/angular/angular.js/issues/7239 + var memberId = $location.search()['memberId']; + if (memberId) { + $http.get('/api/v2/members/'+memberId).success(function(data, status, headers, config){ + $scope.profile = data; + $scope.Content = window.habitrpgShared.content; + $modal.open({ + templateUrl: 'modals/member.html', + scope: $scope + }); + }) + } + }]) + .controller("PlansCtrl", ['$rootScope', function($rootScope) { $rootScope.clickContact = function(){ diff --git a/public/manifest.json b/public/manifest.json index aaa890463cc..b2a06332a85 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -99,6 +99,8 @@ "bower_components/bootstrap/dist/css/bootstrap.css", "bower_components/css-social-buttons/css/zocial.css", "bower_components/jquery-colorbox/example1/colorbox.css", + "app.css", + "bower_components/habitrpg-shared/dist/habitrpg-shared.css", "static.css" ] } diff --git a/views/shared/header/avatar.jade b/views/shared/header/avatar.jade index 3c03ac1131c..41d70ba1ea1 100644 --- a/views/shared/header/avatar.jade +++ b/views/shared/header/avatar.jade @@ -7,7 +7,7 @@ mixin avatar(opts) .character-sprites - .addthis_native_toolbox(ng-if='profile._id==user._id', data-url="#{env.BASE_URL}/export/avatar-{{profile._id}}.png", data-title="Check out my HabitRPG progress!") + .addthis_native_toolbox(ng-if='profile._id==user._id', data-url="#{env.BASE_URL}/static/front/#?memberId={{profile._id}}", data-title="Check out my HabitRPG progress!") // Mount Body if !opts.minimal diff --git a/views/static/front.jade b/views/static/front.jade index 2e03b1fef6a..9927ef35518 100644 --- a/views/static/front.jade +++ b/views/static/front.jade @@ -8,41 +8,45 @@ block title title=env.t('titleFront') block content - .marketing - //we need to use something that's not jumbotron for this, but still keep it centered - //could someone write something else to make it pretty? - img(src='/bower_components/habitrpg-shared/img/logo/habitrpg_pixel.png', alt='HabitRPG logo') - //this image needs to be replaced by something more enticing, that shows off the features of hRPG - //while acting similarly to a logo - h1#tagline=env.t('tagline') - p.lead - button.btn.btn-primary.btn-lg#frontpage-play-button(ng-click='playButtonClick()')=env.t('playButton') - hr - img(src='/marketing/devices.png') - //we'd want the tagline centered, for sure, and a bit more pop, but without using jumbotron - //it could also be part of the image, as long as the alt text included it - //in fact, I think I really want it on the image, rather than as text, but language issues - br - p.lead=env.t('landingp1') - h2=env.t('landingp2header') - //images in these parts could be useful, too - //if there's a language workaround, image headers? people like pictures! - p.lead - =env.t('landingp2') - |  - h2=env.t('landingp3header') - //I'm not sold on "Consquences as the title here. Anyone got a better idea? - p.lead - =env.t('landingp3') - |  - h2=env.t('landingp4header') - p.lead=env.t('landingp4') - //- TODO - h2=env.t('landingend') + div(ng-controller='RootCtrl') + include ../shared/header/avatar + include ../shared/modals/members + + .marketing + //we need to use something that's not jumbotron for this, but still keep it centered + //could someone write something else to make it pretty? + img(src='/bower_components/habitrpg-shared/img/logo/habitrpg_pixel.png', alt='HabitRPG logo') + //this image needs to be replaced by something more enticing, that shows off the features of hRPG + //while acting similarly to a logo + h1#tagline=env.t('tagline') + p.lead + button.btn.btn-primary.btn-lg#frontpage-play-button(ng-click='playButtonClick()')=env.t('playButton') + hr + img(src='/marketing/devices.png') + //we'd want the tagline centered, for sure, and a bit more pop, but without using jumbotron + //it could also be part of the image, as long as the alt text included it + //in fact, I think I really want it on the image, rather than as text, but language issues + br + p.lead=env.t('landingp1') + h2=env.t('landingp2header') + //images in these parts could be useful, too + //if there's a language workaround, image headers? people like pictures! + p.lead + =env.t('landingp2') + |  + h2=env.t('landingp3header') + //I'm not sold on "Consquences as the title here. Anyone got a better idea? p.lead - =env.t('landingend2') - a(href="FEATURESPAGEHERE")=env.t('landingfeatureslink') - =env.t('landingend3') - a(href="ENTERPRISEPAGEHERE")=env.t('landingadminlink') - |  - =env.t('landingend4') + =env.t('landingp3') + |  + h2=env.t('landingp4header') + p.lead=env.t('landingp4') + //- TODO + h2=env.t('landingend') + p.lead + =env.t('landingend2') + a(href="FEATURESPAGEHERE")=env.t('landingfeatureslink') + =env.t('landingend3') + a(href="ENTERPRISEPAGEHERE")=env.t('landingadminlink') + |  + =env.t('landingend4') From 8f633e81db5aa7acd35f28d3cfb6a2eb798e31b8 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Wed, 12 Nov 2014 09:02:12 -0700 Subject: [PATCH 7/8] fix(sharing): add phantomjs buildpack to heroku (for pageres), proper use of nested nconf keys --- .buildpacks | 2 ++ public/js/controllers/footerCtrl.js | 4 ++-- src/controllers/dataexport.js | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 .buildpacks diff --git a/.buildpacks b/.buildpacks new file mode 100644 index 00000000000..b57b4bd3b08 --- /dev/null +++ b/.buildpacks @@ -0,0 +1,2 @@ +https://github.com/heroku/heroku-buildpack-nodejs.git +https://github.com/stomita/heroku-buildpack-phantomjs.git diff --git a/public/js/controllers/footerCtrl.js b/public/js/controllers/footerCtrl.js index afd7ca02291..9017602aec5 100644 --- a/public/js/controllers/footerCtrl.js +++ b/public/js/controllers/footerCtrl.js @@ -38,8 +38,8 @@ // Scripts only for desktop if (!window.env.IS_MOBILE) { - // Add This - FIXME why isn't this working when here? instead it's now in - //$.getScript("//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5016f6cc44ad68a4"); + // Add This + //$.getScript("//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5016f6cc44ad68a4"); //FIXME why isn't this working when here? instead it's now in var addthisServices = 'facebook,twitter,googleplus,tumblr,'+window.env.BASE_URL.replace('https://','').replace('http://',''); window.addthis_config = { services_custom:{ diff --git a/src/controllers/dataexport.js b/src/controllers/dataexport.js index 2b2a5b8d0f1..36f3e87feec 100644 --- a/src/controllers/dataexport.js +++ b/src/controllers/dataexport.js @@ -11,7 +11,7 @@ var User = require('../models/user').model; // Avatar screenshot/static-page includes var Pageres = require('pageres'); //https://github.com/sindresorhus/pageres var AWS = require('aws-sdk'); -AWS.config.update({accessKeyId: nconf.get("S3").accessKeyId, secretAccessKey: nconf.get("S3").secretAccessKey}); +AWS.config.update({accessKeyId: nconf.get("S3:accessKeyId"), secretAccessKey: nconf.get("S3:secretAccessKey")}); var s3Stream = require('s3-upload-stream')(new AWS.S3()); //https://github.com/nathanpeck/s3-upload-stream var bucket = 'habitrpg-dev'; var request = require('request'); From de509c83bec722bc514473fa19b7a68d8140558b Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Wed, 12 Nov 2014 14:40:33 -0700 Subject: [PATCH 8/8] fix(sharing): add bucket to nconf --- config.json.example | 1 + src/controllers/dataexport.js | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/config.json.example b/config.json.example index dcfb3fb8d3c..aefb56d1b90 100644 --- a/config.json.example +++ b/config.json.example @@ -27,6 +27,7 @@ "EMAIL_SERVER_AUTH_USER": "user", "EMAIL_SERVER_AUTH_PASSWORD": "password", "S3":{ + "bucket":"bucket", "accessKeyId":"accessKeyId", "secretAccessKey":"secretAccessKey" } diff --git a/src/controllers/dataexport.js b/src/controllers/dataexport.js index 36f3e87feec..8a48ee16385 100644 --- a/src/controllers/dataexport.js +++ b/src/controllers/dataexport.js @@ -13,7 +13,7 @@ var Pageres = require('pageres'); //https://github.com/sindresorhus/pageres var AWS = require('aws-sdk'); AWS.config.update({accessKeyId: nconf.get("S3:accessKeyId"), secretAccessKey: nconf.get("S3:secretAccessKey")}); var s3Stream = require('s3-upload-stream')(new AWS.S3()); //https://github.com/nathanpeck/s3-upload-stream -var bucket = 'habitrpg-dev'; +var bucket = nconf.get("S3:bucket"); var request = require('request'); /* @@ -117,6 +117,7 @@ dataexport.avatarImage = function(req, res, next) { .src(nconf.get('BASE_URL') + '/export/avatar-' + req.params.uuid + '.html', ['140x147'], {crop: true, filename: filename.replace('.png', '')}) .run(function (err, file) { if (err) return next(err); + // see http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#createMultipartUpload-property var upload = s3Stream.upload({ Bucket: bucket, Key: filename,