Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Share avatar #4236

Merged
merged 8 commits into from
Nov 12, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .buildpacks
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
https://github.com/heroku/heroku-buildpack-nodejs.git
https://github.com/stomita/heroku-buildpack-phantomjs.git
8 changes: 7 additions & 1 deletion config.json.example
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,11 @@
"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":{
"bucket":"bucket",
"accessKeyId":"accessKeyId",
"secretAccessKey":"secretAccessKey"
}

}
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -25,24 +26,26 @@
"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",
"paypal-ipn": "~1.0.1",
"paypal-recurring": "git://github.com/jaybryant/paypal-recurring#656b496f43440893c984700191666a5c5c535dca",
"pretty-data": "git://github.com/vkiryukhin/pretty-data#master",
"request": "~2.44.0",
"s3-upload-stream": "^1.0.6",
"stripe": "*",
"swagger-node-express": "git://github.com/lefnire/swagger-node-express#habitrpg",
"universal-analytics": "~0.3.2",
Expand Down
12 changes: 11 additions & 1 deletion public/css/avatar.styl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 11 additions & 1 deletion public/js/controllers/footerCtrl.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,17 @@
// Scripts only for desktop
if (!window.env.IS_MOBILE) {
// Add This
$.getScript("//s7.addthis.com/js/250/addthis_widget.js#pubid=lefnire");
//$.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 <head>
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() {
Expand Down
15 changes: 15 additions & 0 deletions public/js/static.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(){
Expand Down
2 changes: 2 additions & 0 deletions public/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
]
}
Expand Down
53 changes: 53 additions & 0 deletions src/controllers/dataexport.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ 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 = nconf.get("S3:bucket");
var request = require('request');

/*
------------------------------------------------------------------------
Expand Down Expand Up @@ -83,3 +90,49 @@ 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';
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);
// see http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#createMultipartUpload-property
var upload = s3Stream.upload({
Bucket: bucket,
Key: filename,
ACL: "public-read",
StorageClass: "REDUCED_REDUNDANCY",
ContentType: "image/png",
Expires: +moment().add({minutes: 3})
});
upload.on('error', function (err) {
next(err);
});
upload.on('uploaded', function (details) {
res.redirect(details.Location);
});
file[0].pipe(upload);
});
})
};
5 changes: 4 additions & 1 deletion src/routes/dataexport.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
28 changes: 28 additions & 0 deletions views/avatar-static.jade
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
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').
window.habitrpg
.controller('StaticAvatarCtrl', ['$scope', function($scope){
$scope.profile = window.env.user;
}])

//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})
3 changes: 3 additions & 0 deletions views/index.jade
Original file line number Diff line number Diff line change
Expand Up @@ -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)};

Expand Down
2 changes: 2 additions & 0 deletions views/shared/header/avatar.jade
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ mixin avatar(opts)

.character-sprites

.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
span(ng-if='profile.items.currentMount', class='Mount_Body_{{profile.items.currentMount}}')
Expand Down
78 changes: 41 additions & 37 deletions views/static/front.jade
Original file line number Diff line number Diff line change
Expand Up @@ -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')
|&nbsp;
h2=env.t('landingp3header')
//I'm not sold on "Consquences as the title here. Anyone got a better idea?
p.lead
=env.t('landingp3')
|&nbsp;
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')
|&nbsp;
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')
|&nbsp;
=env.t('landingend4')
=env.t('landingp3')
|&nbsp;
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')
|&nbsp;
=env.t('landingend4')