diff --git a/config.json b/config.json index 30172d72..a8488332 100644 --- a/config.json +++ b/config.json @@ -18,6 +18,17 @@ "CARTODB_API_KEY": "883965c96f62fd219721f59f2e7c20f08db0123b", "CARTODB_CRAGS_TABLE": "crags_dev", + "STRIPE_SECRET_KEY": "sk_test_jDlsyyvD8y77XMC7wC1w6cNB", + "STRIPE_PUBLISHABLE_KEY": "pk_test_hUrz7pk2qdjqgIU1BDuHraVv", + + "SENDOWL_HOST": "www.sendowl.com", + "SENDOWL_KEY": "463c1877e8b8dbc", + "SENDOWL_SECRET": "424f38d72e99c6f54d89", + + "SHIPWIRE_HOST": "api.beta.shipwire.com", + "SHIPWIRE_USER": "apis@island.io", + "SHIPWIRE_PASS": "dc3996da781463ee133bbfb2d6355202", + "FACEBOOK_NAME": "The (new) Island (dev)", "FACEBOOK_CLIENT_ID": 153015724883386, "FACEBOOK_CLIENT_SECRET": "8cba32f72580806cca22306a879052bd", diff --git a/lib/client.js b/lib/client.js index f882caae..4f48e815 100644 --- a/lib/client.js +++ b/lib/client.js @@ -32,7 +32,7 @@ var CHANNELS = [ 'watch' ]; -// Handle Execution of fetch sample queues. +// Handle Execution of fetch queues. function ExecutionQueue(maxInFlight) { var inFlight = 0; var queue = []; @@ -182,4 +182,4 @@ Client.prototype.getUser = function(obj, cb) { } else if (obj.target.indexOf('27crags') !== -1) { lib27crags.searchUser(obj.userId, cb); } -} +}; diff --git a/lib/resources.js b/lib/resources.js index 34b250b0..741da820 100644 --- a/lib/resources.js +++ b/lib/resources.js @@ -13,5 +13,6 @@ exports.resources = { notification: require('./resources/notification'), comment: require('./resources/comment'), instagram: require('./resources/instagram'), - signup: require('./resources/signup') -} + signup: require('./resources/signup'), + store: require('./resources/store') +}; diff --git a/lib/resources/member.js b/lib/resources/member.js index ad61deba..1e41a56e 100644 --- a/lib/resources/member.js +++ b/lib/resources/member.js @@ -156,7 +156,8 @@ var BLACKLIST = [ 'photos', 'image', 'images', - 'share' + 'share', + 'store' ]; var DEFUALT_CONFIG = { @@ -1118,6 +1119,7 @@ exports.routes = function () { delete doc.googleRefresh; delete doc.instagramToken; delete doc.instagramRefresh; + delete doc.address; res.send(doc); }); }); diff --git a/lib/resources/store.js b/lib/resources/store.js new file mode 100644 index 00000000..d3655900 --- /dev/null +++ b/lib/resources/store.js @@ -0,0 +1,308 @@ +/* + * store.js: Handles orders from the store. + * + */ + +// Module Dependencies +var util = require('util'); +var iutil = require('island-util'); +var _ = require('underscore'); +_.mixin(require('underscore.string')); +var profiles = require('island-collections').profiles; +var app = require('../../app'); +var Step = require('step'); +var store = require('../../store.json'); + +var MAX_PRODUCT_QUANTITY_PER_ORDER = + exports.MAX_PRODUCT_QUANTITY_PER_ORDER = 20; + +exports.init = function () { + return this.routes(); +}; + +exports.routes = function () { + var db = app.get('db'); + var errorHandler = app.get('errorHandler'); + var events = app.get('events'); + var emailer = app.get('emailer'); + var stripe = app.get('stripe'); + var sendowl = app.get('sendowl'); + var shipwire = app.get('shipwire'); + + app.post('/api/store/checkout', function (req, res) { + var token = req.body.token; + var cart = req.body.cart; + var shipping = req.body.shipping; + var description = req.body.description; + + if (!token) { + return res.send(403, {error: {message: 'Token invalid'}}); + } + + if (!cart || _.isEmpty(cart)) { + return res.send(403, {error: {message: 'Cart invalid'}}); + } + + if (!shipping || !shipping.shipTo || !shipping.shipments) { + return res.send(403, {error: {message: 'Shipping invalid'}}); + } + + if (!description) { + return res.send(403, {error: {message: 'Description invalid'}}); + } + + var products = []; + var overMaxQuantityPerOrder = []; + var amount = shipping.shipments[0].cost.amount * 100; + _.each(cart, function (quantity, sku) { + if (!store[sku]) { + return; + } + var product = { + sku: sku, + quantity: quantity, + name: store[sku].name, + price: store[sku].price + }; + products.push(product); + amount += (quantity * product.price); + if (product.quantity > MAX_PRODUCT_QUANTITY_PER_ORDER) { + overMaxQuantityPerOrder.push({ + name: product.name, + requested: product.quantity, + allowed: MAX_PRODUCT_QUANTITY_PER_ORDER + }); + } + }); + + if (products.length === 0) { + return res.send(403, {error: {message: 'Cart invalid'}}); + } + + if (overMaxQuantityPerOrder.length > 0) { + return res.send(403, {error: { + message: 'OVER_MAX_PRODUCT_QUANTITY_PER_ORDER', + data: overMaxQuantityPerOrder + }}); + } + + Step( + function () { + shipwire.stock.get(this); + }, + function (err, data) { + if (err) { + return this(err); + } + + var stock = {}; + _.each(data.resource.items, function (i) { + stock[i.resource.sku] = i.resource; + }); + + // Check inventory. + var unknownProducts = []; + var insufficientStock = []; + _.each(products, function (product) { + var inventory = stock[product.sku]; + if (!inventory) { + unknownProducts.push({ + name: product.name + }); + } else if (inventory.good < product.quantity) { + insufficientStock.push({ + name: product.name, + requested: product.quantity, + good: inventory.good + }); + } + }); + + if (unknownProducts.length > 0) { + return this({error: {code: 403, message: 'UNKNOWN_PRODUCT', + data: unknownProducts}}); + } + + if (insufficientStock.length > 0) { + return this({error: {code: 403, message: 'INSUFFICIENT_STOCK', + data: insufficientStock}}); + } + + stripe.charges.create({ + amount: amount, + currency: 'usd', + source: token.id, + description: description, + metadata: { + email: token.email + }, + statement_descriptor: _.prune(description, 22, '').toUpperCase() + }, this); + }, + function (err, charge) { + if (err) { + return this(err); + } + + if (!charge.paid || charge.status !== 'succeeded') { + return this({error: {code: 403, message: 'Payment failed'}}); + } + + var items = _.map(products, function (product) { + return { + sku: product.sku, + quantity: product.quantity, + commercialInvoiceValue: product.price / 100, + commercialInvoiceValueCurrency: charge.currency.toUpperCase() + }; + }); + + var order = { + orderNo: charge.id, + items: items, + options: { + warehouseRegion: 'CHI', + warehouseId: 13, + currency: charge.currency.toUpperCase() + }, + shipFrom: { + company: 'We Are Island, Inc.' + }, + shipTo: { + email: token.email, + name: shipping.shipTo.name, + address1: shipping.shipTo.address, + city: shipping.shipTo.city, + state: shipping.shipTo.state, + postalCode: shipping.shipTo.zip, + country: shipping.shipTo.country, + isCommercial: 0, + isPoBox: 0 + }, + packingList: { + message1: { + body: '- David Graham, Daniel Woods, Nalle Hukkataival, ' + + 'Jamie Emerson, Sander Pick, Eyal Cohen', + header: 'Thank you for supporting Island. Try hard out there.' + } + } + }; + + shipwire.orders.create(order, this); + }, + function (err, data) { + if (errorHandler(err, req, res)) return; + + var order = data.resource && data.resource.items && + data.resource.items[0] ? data.resource.items[0].resource: + null; + + if (data.status !== 200 || !order.orderNo || !order.id) { + return res.send(403, {error: {message: 'Order failed'}}); + } + + res.send({ + message: 'Huzzah! Thank you for supporting Island. We\'ll send an ' + + 'email from sales@island.io to ' + token.email + ' when your ' + + 'order has been received at our warehouse.', + orderNo: order.orderNo, + orderId: order.id + }); + } + ); + }); + + app.post('/api/store/shipping', function (req, res) { + var address = req.body.address; + var cart = req.body.cart; + + if (!address || !address.name || !address.address || !address.city || + !address.zip || !address.country) { + return res.send(403, {error: {message: 'Address invalid'}}); + } + + if (!cart || _.isEmpty(cart)) { + return res.send(403, {error: {message: 'Cart invalid'}}); + } + + var items = []; + var quantitiesValid = true; + _.each(cart, function (quantity, sku) { + if (!store[sku]) { + return; + } + items.push({sku: sku, quantity: quantity}); + if (quantity > MAX_PRODUCT_QUANTITY_PER_ORDER) { + quantitiesValid = false; + } + }); + + if (items.length === 0) { + return res.send(403, {error: {message: 'Cart invalid'}}); + } + + if (!quantitiesValid) { + return res.send(403, {error: { + message: 'OVER_MAX_PRODUCT_QUANTITY_PER_ORDER'}}); + } + + var params = { + options: { + currency: 'USD', + groupBy: 'all', + canSplit: 0, + warehouseArea: 'US' + }, + order: { + shipTo: { + address1: address.address, + city: address.city, + state: address.state, + postalCode: address.zip, + country: address.country, + isCommercial: 0, + isPoBox: 0 + }, + items: items + } + }; + + shipwire.rate.get(params, function (err, data) { + if (errorHandler(err, req, res)) return; + if (data.errors && data.errors.length > 0) { + return res.send(data.status, { + error: {message: data.errors[0].message} + }); + } + + var warnings = data.warnings; + if (warnings && warnings.length > 0) { + return res.send(400, { + error: {message: warnings[0].message} + }); + } + + var rates = data.resource.rates; + if (!rates || rates.length === 0) { + return res.send(400, { + error: { + message: 'No shipping options found for the specified address' + } + }); + } + + var options = data.resource.rates[0].serviceOptions; + if (!options || options.length === 0) { + return res.send(400, { + error: { + message: 'No shipping options found for the specified address' + } + }); + } + + res.send({shipTo: address, options: options}); + }); + }); + + return exports; +}; diff --git a/lib/service.js b/lib/service.js index b0372c47..aedfdb67 100644 --- a/lib/service.js +++ b/lib/service.js @@ -25,6 +25,7 @@ var app = require('../app'); var lib8a = require('island-lib8a'); var lib27crags = require('island-lib27crags'); var GradeConverter = new require('../public/js/GradeConverter').GradeConverter; +var store = require('../store.json'); var gradeConverter = { 'b': new GradeConverter('boulders').from('font').to('default'), @@ -73,6 +74,8 @@ exports.routes = function () { var db = app.get('db'); var events = app.get('events'); var poet = app.get('poet'); + var sendowl = app.get('sendowl'); + var shipwire = app.get('shipwire'); var errorHandler = app.get('errorHandler'); /* @@ -390,7 +393,23 @@ exports.routes = function () { _.extend(sidebar, list); cb(err); }); - } + }, + + _products: function (cb) { + var list = {products: {items: []}}; + shipwire.products.get(function (err, data) { + list.products.items = _(data.resource.items || []) + .map(function (i) { + return i.resource.storageConfiguration === 'INDIVIDUAL_ITEM' && + i.resource.sku.indexOf('TEST') === -1 && + i.resource.status !== 'notinuse' ? + _.extend(i.resource, store[i.resource.sku]): false; + }).filter(function (i) { return !!i; }); + _.extend(sidebar, list); + cb(err); + }); + }, + }; Step( @@ -1689,6 +1708,47 @@ exports.routes = function () { ); }); + // Store profile + app.get('/service/store', function (req, res) { + var cursor = req.body.cursor || 0; + var limit = req.body.limit || 5; + + Step( + function () { + var query = {action: {type: 'post', query: {'product.sku': + {$ne: null}}}}; + Events.feed(query, ['post'], {limit: limit, cursor: cursor}, + this.parallel()); + + getSidebar(req.user, req.user, ['products'], this.parallel()); + + if (req.user && req.query.n !== '0') { + db.Notifications.list({subscriber_id: req.user._id}, + {sort: {created: -1}, limit: 5, + inflate: {event: profiles.event}}, this.parallel()); + } + }, + function (err, feed, sidebar, notes) { + if (errorHandler(err, req, res)) return; + + var profile = { + member: req.user, + transloadit: transloadit(req), + content: _.extend(sidebar, {page: null, events: feed.events}) + }; + if (notes) { + profile.notes = { + cursor: 1, + more: notes.length === 5, + items: notes + }; + } + + res.send(iutil.client(profile)); + } + ); + }); + // Films profile app.get('/service/films', function (req, res) { var cursor = req.body.cursor || 0; @@ -2076,6 +2136,33 @@ exports.routes = function () { ); }, 'folder')); + // Store + app.get('/store', _.bind(handler, undefined, function (req, res) { + Step( + function () { + db.Posts.list({'product.sku': {$ne: null}}, {sort: {created: -1}}, + this); + }, + function (err, posts) { + if (errorHandler(err, req, res)) return; + db.fill(posts, 'Medias', 'parent_id', {sort: {created: -1}}, + function (err) { + if (errorHandler(err, req, res)) return; + + var media = _.find(_.first(posts).medias, function (v) { + return v.quality === 'ipad'; + }); + renderStatic(req, res, { + url: 'store', + title: 'Store', + description: 'Custon made goods and films.', + medias: [{image: media.poster, video: media.video}] + }); + }); + } + ); + }, 'folder')); + // Films app.get('/films', _.bind(handler, undefined, function (req, res) { Step( diff --git a/main.js b/main.js index 6c77afac..cc4b5c24 100755 --- a/main.js +++ b/main.js @@ -54,7 +54,6 @@ if (cluster.isMaster) { process.exit(1); } - // Module Dependencies var http = require('http'); var https = require('https'); var connect = require('connect'); @@ -83,20 +82,20 @@ if (cluster.isMaster) { var Emailer = require('island-emailer').Emailer; var resources = require('./lib/resources.js').resources; var Client = require('./lib/client').Client; + var Stripe = require('stripe'); + var SendOwl = require('sendowl-node').SendOwl; + var Shipwire = require('shipwire-node').Shipwire; var Poet = require('poet'); var service = require('./lib/service'); - // Setup Environments var app = require('./app').init(); - // Package info. app.set('package', _package_); // App port is env var in production. app.set('PORT', process.env.PORT || app.get('package').port); app.set('SECURE_PORT', app.get('package').securePort); - // Add connection config to app. _.each(require('./config.json'), function (v, k) { app.set(k, process.env[k] || v); }); @@ -109,7 +108,8 @@ if (cluster.isMaster) { estr = data; data = null; } - var fn = req.xhr ? res.send: res.render; + var fn = req.headers['user-agent'].indexOf('node-superagent') !== -1 || + req.xhr ? res.send: res.render; if (err || (!data && estr)) { var profile = { member: req.user, @@ -118,7 +118,7 @@ if (cluster.isMaster) { transloadit: service.transloadit(req) }; if (err) { - console.log('Error in errorHandler: ', (err.stack || err)); + console.log('Error in errorHandler:', (err.stack || err)); profile.error = err.error || err; fn.call(res, profile.error.code || 500, iutil.client(profile)); } else { @@ -140,7 +140,6 @@ if (cluster.isMaster) { // Use console for logging in dev app.set('log', console.log); - // App params app.set('ROOT_URI', ''); app.set('HOME_URI', 'http://localhost:' + app.get('PORT')); } @@ -156,14 +155,12 @@ if (cluster.isMaster) { json: true })); - // App params app.set('ROOT_URI', [app.get('package').builds.cloudfront, app.get('package').version].join('/')); app.set('HOME_URI', [app.get('package').protocol.name, app.get('package').domain].join('://')); } - // Redis connect this.parallel()(null, redis.createClient(app.get('REDIS_PORT'), app.get('REDIS_HOST_SESSION'))); this.parallel()(null, redis.createClient(app.get('REDIS_PORT'), @@ -179,7 +176,6 @@ if (cluster.isMaster) { return; } - // App config. app.set('db', db); app.set('emailer', new Emailer({ db: db, @@ -201,7 +197,6 @@ if (cluster.isMaster) { })); app.set('errorHandler', errorHandler); - // Express config app.set('views', __dirname + '/views'); app.set('view engine', 'jade'); app.set('sessionStore', new RedisStore({client: rc, maxAge: 2592000000})); @@ -257,7 +252,6 @@ if (cluster.isMaster) { app.all('*', function (req, res, next) { - // Check protocol. if (process.env.NODE_ENV === 'production' && app.get('package').protocol.name === 'https') { if (req.secure || _.find(app.get('package').protocol.allow, @@ -297,7 +291,6 @@ if (cluster.isMaster) { argv.index && cluster.worker.id === 1}, this.parallel()); - // Init search cache. app.set('cache', new Search({ redisHost: app.get('REDIS_HOST_CACHE'), redisPort: app.get('REDIS_PORT') @@ -306,7 +299,6 @@ if (cluster.isMaster) { function (err, connection) { if (err) return this(err); - // Init collections. if (_.size(collections) === 0) { return this(); } @@ -317,7 +309,6 @@ if (cluster.isMaster) { function (err) { if (err) return this(err); - // Init the blog. var poet = Poet(app, { posts: './blog/', postsPerPage: 5, @@ -343,6 +334,20 @@ if (cluster.isMaster) { app.set('sharing', require('./lib/sharing')); + app.set('stripe', Stripe(app.get('STRIPE_SECRET_KEY'))); + + app.set('sendowl', new SendOwl({ + host: app.get('SENDOWL_HOST'), + key: app.get('SENDOWL_KEY'), + secret: app.get('SENDOWL_SECRET') + })); + + app.set('shipwire', new Shipwire({ + host: app.get('SHIPWIRE_HOST'), + username: app.get('SHIPWIRE_USER'), + password: app.get('SHIPWIRE_PASS') + })); + _.each(resources, function (r, name) { r.init(); }); @@ -370,7 +375,6 @@ if (cluster.isMaster) { _server = http.createServer(app); } - // Socket handling var sio = socketio.listen(server, {log: false, secure: process.env.NODE_ENV === 'production'}); sio.set('store', new socketio.RedisStore({ @@ -380,7 +384,6 @@ if (cluster.isMaster) { redisClient: rc })); - // Development only. if (process.env.NODE_ENV !== 'production') { sio.set('log level', 2); } else { @@ -397,7 +400,6 @@ if (cluster.isMaster) { ]); } - // Socket auth sio.set('authorization', psio.authorize({ cookieParser: express.cookieParser, key: app.get('sessionKey'), @@ -407,18 +409,15 @@ if (cluster.isMaster) { success: function(data, accept) { accept(null, true); } })); - // Websocket connect sio.sockets.on('connection', function (webSock) { // Back-end socket for talking to other Island services var backSock = zmq.socket('sub'); backSock.connect(app.get('SUB_SOCKET_PORT')); - // Create new client. webSock.client = new Client(webSock, backSock); }); - // Start server if (process.env.NODE_ENV !== 'production') { server.listen(app.get('PORT')); } else { diff --git a/package.json b/package.json index dae54279..c526c38c 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,8 @@ "underscore": "~1.4.4", "underscore.deep": "^0.3.0", "underscore.string": "~2.3.1", - "zmq": "^2.8.0" + "zmq": "^2.8.0", + "shipwire-node": "^1.0.2" }, "devDependencies": { "assert": "^1.3.0", diff --git a/public/css/fontello-codes.css b/public/css/fontello-codes.css index 5d7d397b..1f5e64fc 100644 --- a/public/css/fontello-codes.css +++ b/public/css/fontello-codes.css @@ -49,4 +49,9 @@ .icon-basket:before { content: '\e82f'; } /* '' */ .icon-down-dir:before { content: '\e830'; } /* '' */ .icon-up-dir:before { content: '\e831'; } /* '' */ -.icon-flash:before { content: '\e832'; } /* '' */ \ No newline at end of file +.icon-flash:before { content: '\e832'; } /* '' */ +.icon-gauge:before { content: '\e833'; } /* '' */ +.icon-hourglass:before { content: '\e834'; } /* '' */ +.icon-frown:before { content: '\e835'; } /* '' */ +.icon-smile:before { content: '\e836'; } /* '' */ +.icon-meh:before { content: '\e837'; } /* '' */ \ No newline at end of file diff --git a/public/css/fontello-embedded.css b/public/css/fontello-embedded.css index a904f647..98de5c85 100644 --- a/public/css/fontello-embedded.css +++ b/public/css/fontello-embedded.css @@ -1,15 +1,15 @@ @font-face { font-family: 'fontello'; - src: url('../font/fontello.eot?69506781'); - src: url('../font/fontello.eot?69506781#iefix') format('embedded-opentype'), - url('../font/fontello.svg?69506781#fontello') format('svg'); + src: url('../font/fontello.eot?31177353'); + src: url('../font/fontello.eot?31177353#iefix') format('embedded-opentype'), + url('../font/fontello.svg?31177353#fontello') format('svg'); font-weight: normal; font-style: normal; } @font-face { font-family: 'fontello'; - src: url('data:application/octet-stream;base64,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') format('woff'), - url('data:application/octet-stream;base64,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') format('truetype'); + src: url('data:application/octet-stream;base64,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') format('woff'), + url('data:application/octet-stream;base64,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YFlmsAFjYCMgsAErI7AEQ2CwASuwBSVhsAUlsAJiILAAUFiwQGBZZrABY7AEJmEgsAQlYGQjsAMlYGRQWCEbIyFZIyAgsAQmI0ZhOFktsDcssAAWICAgsAUmIC5HI0cjYSM8OC2wOCywABYgsAgjQiAgIEYjR7ABKyNhOC2wOSywABawAyWwAiVHI0cjYbAAVFguIDwjIRuwAiWwAiVHI0cjYSCwBSWwBCVHI0cjYbAGJbAFJUmwAiVhuQgACABjYyMgWGIbIVljuAQAYiCwAFBYsEBgWWawAWNgIy4jICA8ijgjIVktsDossAAWILAIQyAuRyNHI2EgYLAgYGawAmIgsABQWLBAYFlmsAFjIyAgPIo4LbA7LCMgLkawAiVGUlggPFkusSsBFCstsDwsIyAuRrACJUZQWCA8WS6xKwEUKy2wPSwjIC5GsAIlRlJYIDxZIyAuRrACJUZQWCA8WS6xKwEUKy2wPiywNSsjIC5GsAIlRlJYIDxZLrErARQrLbA/LLA2K4ogIDywBCNCijgjIC5GsAIlRlJYIDxZLrErARQrsARDLrArKy2wQCywABawBCWwBCYgLkcjRyNhsAlDKyMgPCAuIzixKwEUKy2wQSyxCAQlQrAAFrAEJbAEJSAuRyNHI2EgsAQjQrAJQysgsGBQWCCwQFFYswIgAyAbswImAxpZQkIjIEewBEOwAmIgsABQWLBAYFlmsAFjYCCwASsgiophILACQ2BkI7ADQ2FkUFiwAkNhG7ADQ2BZsAMlsAJiILAAUFiwQGBZZrABY2GwAiVGYTgjIDwjOBshICBGI0ewASsjYTghWbErARQrLbBCLLA1Ky6xKwEUKy2wQyywNishIyAgPLAEI0IjOLErARQrsARDLrArKy2wRCywABUgR7AAI0KyAAEBFRQTLrAxKi2wRSywABUgR7AAI0KyAAEBFRQTLrAxKi2wRiyxAAEUE7AyKi2wRyywNCotsEgssAAWRSMgLiBGiiNhOLErARQrLbBJLLAII0KwSCstsEossgAAQSstsEsssgABQSstsEwssgEAQSstsE0ssgEBQSstsE4ssgAAQistsE8ssgABQistsFAssgEAQistsFEssgEBQistsFIssgAAPistsFMssgABPistsFQssgEAPistsFUssgEBPistsFYssgAAQCstsFcssgABQCstsFgssgEAQCstsFkssgEBQCstsFossgAAQystsFsssgABQystsFwssgEAQystsF0ssgEBQystsF4ssgAAPystsF8ssgABPystsGAssgEAPystsGEssgEBPystsGIssDcrLrErARQrLbBjLLA3K7A7Ky2wZCywNyuwPCstsGUssAAWsDcrsD0rLbBmLLA4Ky6xKwEUKy2wZyywOCuwOystsGgssDgrsDwrLbBpLLA4K7A9Ky2waiywOSsusSsBFCstsGsssDkrsDsrLbBsLLA5K7A8Ky2wbSywOSuwPSstsG4ssDorLrErARQrLbBvLLA6K7A7Ky2wcCywOiuwPCstsHEssDorsD0rLbByLLMJBAIDRVghGyMhWUIrsAhlsAMkUHiwARUwLQBLuADIUlixAQGOWbABuQgACABjcLEABUKxAAAqsQAFQrEACCqxAAVCsQAIKrEABUK5AAAACSqxAAVCuQAAAAkqsQMARLEkAYhRWLBAiFixA2REsSYBiFFYugiAAAEEQIhjVFixAwBEWVlZWbEADCq4Af+FsASNsQIARAA=') format('truetype'); } /* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */ /* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */ @@ -17,7 +17,7 @@ @media screen and (-webkit-min-device-pixel-ratio:0) { @font-face { font-family: 'fontello'; - src: url('../font/fontello.svg?69506781#fontello') format('svg'); + src: url('../font/fontello.svg?31177353#fontello') format('svg'); } } */ @@ -102,4 +102,9 @@ .icon-basket:before { content: '\e82f'; } /* '' */ .icon-down-dir:before { content: '\e830'; } /* '' */ .icon-up-dir:before { content: '\e831'; } /* '' */ -.icon-flash:before { content: '\e832'; } /* '' */ \ No newline at end of file +.icon-flash:before { content: '\e832'; } /* '' */ +.icon-gauge:before { content: '\e833'; } /* '' */ +.icon-hourglass:before { content: '\e834'; } /* '' */ +.icon-frown:before { content: '\e835'; } /* '' */ +.icon-smile:before { content: '\e836'; } /* '' */ +.icon-meh:before { content: '\e837'; } /* '' */ \ No newline at end of file diff --git a/public/css/fontello-ie7-codes.css b/public/css/fontello-ie7-codes.css index fbaedd4d..b02de4d1 100644 --- a/public/css/fontello-ie7-codes.css +++ b/public/css/fontello-ie7-codes.css @@ -49,4 +49,9 @@ .icon-basket { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-down-dir { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-up-dir { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } -.icon-flash { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } \ No newline at end of file +.icon-flash { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.icon-gauge { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.icon-hourglass { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.icon-frown { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.icon-smile { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.icon-meh { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } \ No newline at end of file diff --git a/public/css/fontello-ie7.css b/public/css/fontello-ie7.css index be00bcbe..edfab982 100644 --- a/public/css/fontello-ie7.css +++ b/public/css/fontello-ie7.css @@ -60,4 +60,9 @@ .icon-basket { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-down-dir { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-up-dir { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } -.icon-flash { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } \ No newline at end of file +.icon-flash { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.icon-gauge { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.icon-hourglass { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.icon-frown { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.icon-smile { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.icon-meh { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } \ No newline at end of file diff --git a/public/css/fontello.css b/public/css/fontello.css index 4845cff9..bceda834 100644 --- a/public/css/fontello.css +++ b/public/css/fontello.css @@ -1,10 +1,10 @@ @font-face { font-family: 'fontello'; - src: url('../font/fontello.eot?95586498'); - src: url('../font/fontello.eot?95586498#iefix') format('embedded-opentype'), - url('../font/fontello.woff?95586498') format('woff'), - url('../font/fontello.ttf?95586498') format('truetype'), - url('../font/fontello.svg?95586498#fontello') format('svg'); + src: url('../font/fontello.eot?55555488'); + src: url('../font/fontello.eot?55555488#iefix') format('embedded-opentype'), + url('../font/fontello.woff?55555488') format('woff'), + url('../font/fontello.ttf?55555488') format('truetype'), + url('../font/fontello.svg?55555488#fontello') format('svg'); font-weight: normal; font-style: normal; } @@ -14,7 +14,7 @@ @media screen and (-webkit-min-device-pixel-ratio:0) { @font-face { font-family: 'fontello'; - src: url('../font/fontello.svg?95586498#fontello') format('svg'); + src: url('../font/fontello.svg?55555488#fontello') format('svg'); } } */ @@ -104,4 +104,9 @@ .icon-basket:before { content: '\e82f'; } /* '' */ .icon-down-dir:before { content: '\e830'; } /* '' */ .icon-up-dir:before { content: '\e831'; } /* '' */ -.icon-flash:before { content: '\e832'; } /* '' */ \ No newline at end of file +.icon-flash:before { content: '\e832'; } /* '' */ +.icon-gauge:before { content: '\e833'; } /* '' */ +.icon-hourglass:before { content: '\e834'; } /* '' */ +.icon-frown:before { content: '\e835'; } /* '' */ +.icon-smile:before { content: '\e836'; } /* '' */ +.icon-meh:before { content: '\e837'; } /* '' */ \ No newline at end of file diff --git a/public/css/style.css b/public/css/style.css index 0a2595de..e18866b5 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -355,6 +355,9 @@ h1.title-left { color: #404040; font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; } +h1.title-left.no-image { + margin-left: 0; +} h1.title-left a, h1.title-left a:hover { background: none; @@ -604,6 +607,7 @@ input[type=radio] { display: inline; } input[type=text]:not(.text), +input[type=number], input[type=search], input[type=email], input[type=password] { @@ -956,15 +960,15 @@ a.button.buy-button { border: 1px solid transparent; background: #b1dc36; font-size: 12px; - margin-top: 12px; + margin-top: 17px; margin-right: 0; line-height: 24px; min-height: 24px; } a.button.buy-button:hover:not(.disabled) { - color: #1a1a1a; + color: #2f5a00; background: #b1dc36; - border: 1px solid #1a1a1a; + border: 1px solid #396400; } a.button.new-session-button, button.button.new-session-button, @@ -2433,7 +2437,11 @@ p.sidebar-tip span { .sidebar-tick:last-child { border-bottom: 1px solid #f2f2f2; } -.sidebar-broadcast { +.sidebar-products { + margin-top: 10px !important; +} +.sidebar-broadcast, +.sidebar-product { background: #fcfcfc; border: 1px solid #f2f2f2; -webkit-border-radius: 3px; @@ -2442,14 +2450,26 @@ p.sidebar-tip span { padding: 7px 0; margin-bottom: 15px; } -.sidebar-broadcast:last-child { +.sidebar-product { + padding: 0; +} +.sidebar-broadcast:last-child, +.sidebar-product:last-child { margin-bottom: 0; } -.sidebar-broadcast h1 { +.sidebar-broadcast h1, +.sidebar-product h1 { font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; font-size: 16px; padding: 0 7px 5px; } +.sidebar-product h1 { + padding: 10px; + color: #404040; + text-align: center; + border-bottom: 1px solid #f2f2f2; + font-weight: bold; +} .sidebar-broadcast h1 a { background: none; } @@ -2459,7 +2479,12 @@ p.sidebar-tip span { .sidebar-broadcast h1 a i { vertical-align: 1px; } -.sidebar-broadcast p { +.sidebar-product h1 a.buy-button { + float: right; + margin: -4px 0 0 0; +} +.sidebar-broadcast p, +.sidebar-product p { padding: 0 10px; color: #666; font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; @@ -2492,6 +2517,76 @@ a.sidebar-more { a.sidebar-more:hover { color: #4bb8d7; } +.sidebar-product-details { + padding: 0; +} +.sidebar-product-images { + height: 83px; + padding: 10px; +} +.sidebar-product-images img { + float: left; + font-size: 0; + width: 83px; + margin: 0; + padding: 0; + border-right: 1px solid transparent; +} +.sidebar-product-images img:hover { + opacity: 0.8; +} +.sidebar-product-images img:last-child { + border-right: none; +} +.sidebar-product-picker { + font-size: 0; + height: 25px; + padding: 10px; +} +.sidebar-product-picker a.button.buy-button { + display: block; + float: left; + margin: 0; + min-width: 0; + width: 50%; + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; +} +.sidebar-product-picker a.button.buy-button.buy-button-disabled { + float: none; + width: 100%; + cursor: default; + background: #e76533; + color: #fff; +} +a.button.buy-button-left { + border-right: 2px solid #396400; + -webkit-border-radius: 2px 0 0 2px; + -moz-border-radius: 2px 0 0 2px; + border-radius: 2px 0 0 2px; +} +a.button.buy-button-left:hover, +a.button.buy-button-left:focus { + border-right: 2px solid #396400 !important; +} +a.button.buy-button-right { + -webkit-border-radius: 0 2px 2px 0; + -moz-border-radius: 0 2px 2px 0; + border-radius: 0 2px 2px 0; +} +a.button.buy-button-right:hover, +a.button.buy-button-right:focus { + border-left-color: transparent !important; +} +a.button.empty-cart-button { + display: none; + padding: 0 10px; + border-left-width: 1px; +} +a.button.empty-cart-button:hover { + border-left-width: 1px !important; +} /*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––beta*/ .beta { margin-bottom: 30px; @@ -2500,6 +2595,7 @@ a.sidebar-more:hover { font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; font-size: 16px; line-height: 24px; + margin-bottom: 15px; } /*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––instagrams*/ .instagrams > div { @@ -3222,6 +3318,9 @@ img.page-title-avatar { -moz-border-radius: 2px; border-radius: 2px; } +.modal.modal-wide { + width: 650px; +} .modal-title { display: block; background: #f2f2f2; @@ -3280,6 +3379,68 @@ p.modal-message { .modal-body ol li { list-style: inherit; } +.modal-body.shipping-form form { + margin: 10px 0; +} +.modal-body.shipping-form table, +.modal-body.shipping-form table input[type=text] { + width: 100%; + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; +} +.modal-body.shipping-form table td { + padding: 0; + border: 1px solid #cdcdcd; + position: relative; +} +.modal-body.table.shipping-form table tr.clickable { + cursor: pointer; +} +.modal-body.table.shipping-form table tr.clickable:hover { + background: #fcfcfc; +} +.modal-body.table.shipping-form table td { + border: 1px solid #e6e6e6; + border-left: none; + border-right: none; + padding: 10px; + font-size: 13px; + word-wrap: break-word; +} +.modal-body.shipping-form table td.sibling-focus-right { + border-right-color: #4bb8d7; +} +.modal-body.shipping-form table td .td-focus-top { + display: none; + position: absolute; + height: 1px; + top: -1px; + left: 0; + right: 0; + background: #4bb8d7; +} +.modal-body.shipping-form table input[type=text] { + padding: 8px 12px; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + font-size: 14px; + line-height: 24px; + border-color: transparent; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +.modal-body.shipping-form table td.focus { + border-color: #4bb8d7; + -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,0.075), 0 0 5px rgba(75,184,215,0.5); + -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,0.075), 0 0 5px rgba(75,184,215,0.5); + box-shadow: inset 0 1px 2px rgba(0,0,0,0.075), 0 0 5px rgba(75,184,215,0.5); +} +.modal-body.shipping-form table td.focus .td-focus-top { + display: block; +} .modal-actions { border-top: 1px solid #ddd; padding: 15px 30px; @@ -3312,6 +3473,23 @@ button.button.modal-button.full { width: 100%; margin: 0; } +button.button.modal-confirm { + position: relative; +} +button.button.modal-confirm.disabled { + opacity: 0.5; + cursor: pointer; +} +button.button.modal-back { + float: left; + margin-left: 0; +} +.modal-image img { + display: inherit; +} +.modal-options { + font-size: 13px; +} .modal-overlay { display: none; position: absolute; @@ -3705,7 +3883,7 @@ textarea.comment-input { position: relative; } .image-mosaic-wrap:hover img { - opacity: 0.98; + opacity: 0.8; } img.image-mosaic-play { position: absolute !important; @@ -3761,7 +3939,7 @@ span.image-mosaic-play-text { border-radius: 2px; } .post-instagram:hover { - opacity: 0.98; + opacity: 0.8; } .post .post-body { margin: 10px 0 0; @@ -5437,13 +5615,51 @@ input.import-input { position: relative; top: 2px; } -/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––ascent*/ +/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––ascent*/ .ascent-grades-histogram { width: 274px; height: 200px; margin-top: 20px; margin-bottom: 20px; } +/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––– –shipping*/ +.shipping-option-radio { + font-size: 16px; + display: block; + width: 10px; + cursor: pointer; +} +.shipping-summary-quantity { + display: block; +} +.shipping-summary-quantity input { + width: 30px; +} +.shipping-summary-thumb { + vertical-align: middle; +} +.shipping-option-title, +.shipping-summary-item { + display: block; + font-weight: bold; + font-size: 13px; +} +.shipping-option-details, +.shipping-summary-details { + color: #808080; + font-size: 12px; + white-space: normal; +} +.shipping-option-amount, +.shipping-summary-amount { + font-style: italic; + color: #396400; +} +.shipping-summary-total { + font-style: italic; + font-weight: bold; + color: #396400; +} /*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––other*/ a.popup-link { font-size: 16px; diff --git a/public/css/style.styl b/public/css/style.styl index 25504c6b..02099c10 100755 --- a/public/css/style.styl +++ b/public/css/style.styl @@ -386,7 +386,9 @@ h1.title-left line-height 40px color #404040 font-family standard_thin - // text-transform uppercase + +h1.title-left.no-image + margin-left 0 h1.title-left a, h1.title-left a:hover @@ -628,7 +630,6 @@ textarea resize none font-weight normal -webkit-font-smoothing antialiased - // padding 8px padding 9px 8px 7px border 1px solid bordergray color #404040 @@ -638,6 +639,7 @@ input[type=checkbox], input[type=radio] display inline input[type=text]:not(.text), +input[type=number], input[type=search], input[type=email], input[type=password] @@ -987,15 +989,15 @@ a.button.buy-button border 1px solid transparent background #b1dc36 font-size 12px - margin-top 12px + margin-top 17px margin-right 0 line-height 24px min-height 24px a.button.buy-button:hover:not(.disabled) - color #1a1a1a + color #2f5a00 background #b1dc36 - border 1px solid #1a1a1a + border 1px solid rgb(57, 100, 0) a.button.new-session-button, button.button.new-session-button, @@ -2463,21 +2465,37 @@ p.sidebar-tip span .sidebar-tick:last-child border-bottom 1px solid #f2f2f2 -.sidebar-broadcast +.sidebar-products + margin-top 10px !important + +.sidebar-broadcast, +.sidebar-product background #fcfcfc border 1px solid #f2f2f2 border-radius 3px padding 7px 0 margin-bottom 15px -.sidebar-broadcast:last-child +.sidebar-product + padding 0 + +.sidebar-broadcast:last-child, +.sidebar-product:last-child margin-bottom 0 -.sidebar-broadcast h1 +.sidebar-broadcast h1, +.sidebar-product h1 font-family standard_thin font-size 16px padding 0 7px 5px +.sidebar-product h1 + padding 10px + color #404040 + text-align center + border-bottom 1px solid #f2f2f2 + font-weight bold + .sidebar-broadcast h1 a background none @@ -2487,7 +2505,12 @@ p.sidebar-tip span .sidebar-broadcast h1 a i vertical-align 1px +.sidebar-product h1 a.buy-button + float right + margin -4px 0 0 0 + .sidebar-broadcast p +.sidebar-product p padding 0 10px color #666 font-family standard_thin @@ -2520,6 +2543,73 @@ a.sidebar-more a.sidebar-more:hover color blue +.sidebar-product-details + padding 0 + +.sidebar-product-images + height 83px + padding 10px + +.sidebar-product-images img + float left + font-size 0 + width 83px + margin 0 + padding 0 + border-right 1px solid transparent + +.sidebar-product-images img:hover + opacity 0.8 + +.sidebar-product-images img:last-child + border-right none + +.sidebar-product-picker + font-size 0 + height 25px + padding 10px + +.sidebar-product-picker a.button.buy-button + display block + float left + margin 0 + min-width 0 + width 50% + + box-sizing border-box + -moz-box-sizing border-box + -webkit-box-sizing border-box + +.sidebar-product-picker a.button.buy-button.buy-button-disabled + float none + width 100% + cursor default + background orange + color white + +a.button.buy-button-left + border-right 2px solid rgb(57, 100, 0) + border-radius 2px 0 0 2px + +a.button.buy-button-left:hover, +a.button.buy-button-left:focus + border-right 2px solid rgb(57, 100, 0) !important + +a.button.buy-button-right + border-radius 0 2px 2px 0 + +a.button.buy-button-right:hover, +a.button.buy-button-right:focus + border-left-color transparent !important + +a.button.empty-cart-button + display none + padding 0 10px + border-left-width 1px + +a.button.empty-cart-button:hover + border-left-width 1px !important + /*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––beta*/ .beta @@ -2529,6 +2619,7 @@ a.sidebar-more:hover font-family standard_thin font-size 16px line-height 24px + margin-bottom 15px /*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––instagrams*/ @@ -3257,6 +3348,9 @@ img.page-title-avatar width 500px border-radius 2px +.modal.modal-wide + width 650px + .modal-title display block background #f2f2f2 @@ -3323,6 +3417,69 @@ p.modal-message .modal-body ol li list-style inherit +.modal-body.shipping-form form + margin 10px 0 + +.modal-body.shipping-form table, +.modal-body.shipping-form table input[type=text] + width 100% + + box-sizing border-box + -moz-box-sizing border-box + -webkit-box-sizing border-box + +.modal-body.shipping-form table td + padding 0 + border 1px solid #cdcdcd + position relative + +.modal-body.table.shipping-form table tr.clickable + cursor pointer + +.modal-body.table.shipping-form table tr.clickable:hover + background #fcfcfc + +.modal-body.table.shipping-form table td + border 1px solid #e6e6e6 + border-left none + border-right none + padding 10px + font-size 13px + word-wrap break-word + +.modal-body.shipping-form table td.sibling-focus-right + border-right-color blue + +.modal-body.shipping-form table td .td-focus-top + display none + position absolute + height 1px + top -1px + left 0 + right 0 + background blue + +.modal-body.shipping-form table input[type=text] + padding 8px 12px + border-radius 0 + font-size 14px + line-height 24px + border-color transparent + + -webkit-box-shadow none + -moz-box-shadow none + box-shadow none + +.modal-body.shipping-form table td.focus + border-color blue + + -webkit-box-shadow inset 0 1px 2px rgba(0,0,0,0.075),0 0 5px rgba(75, 184, 215, 0.5) + -moz-box-shadow inset 0 1px 2px rgba(0,0,0,0.075),0 0 5px rgba(75, 184, 215, 0.5) + box-shadow inset 0 1px 2px rgba(0,0,0,0.075),0 0 5px rgba(75, 184, 215, 0.5) + +.modal-body.shipping-form table td.focus .td-focus-top + display block + .modal-actions border-top 1px solid #ddd padding 15px 30px @@ -3354,6 +3511,23 @@ button.button.modal-button.full width 100% margin 0 +button.button.modal-confirm + position relative + +button.button.modal-confirm.disabled + opacity 0.5 + cursor pointer + +button.button.modal-back + float left + margin-left 0 + +.modal-image img + display inherit + +.modal-options + font-size 13px + .modal-overlay display none position absolute @@ -3747,7 +3921,7 @@ textarea.comment-input position relative .image-mosaic-wrap:hover img - opacity 0.98 + opacity 0.8 img.image-mosaic-play position absolute !important @@ -3802,7 +3976,7 @@ span.image-mosaic-play-text border-radius 2px .post-instagram:hover - opacity 0.98 + opacity 0.8 .post .post-body margin 10px 0 0 @@ -5515,7 +5689,7 @@ input.import-input position relative top 2px -/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––ascent*/ +/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––ascent*/ .ascent-grades-histogram width: 274px @@ -5523,6 +5697,45 @@ input.import-input margin-top 20px margin-bottom 20px +/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––– –shipping*/ + +.shipping-option-radio + font-size 16px + display block + width 10px + cursor pointer + +.shipping-summary-quantity + display block + +.shipping-summary-quantity input + width 30px + +.shipping-summary-thumb + vertical-align middle + +.shipping-option-title, +.shipping-summary-item + display block + font-weight bold + font-size 13px + +.shipping-option-details, +.shipping-summary-details + color #808080 + font-size 12px + white-space normal + +.shipping-option-amount, +.shipping-summary-amount + font-style italic + color #396400 + +.shipping-summary-total + font-style italic + font-weight bold + color #396400 + /*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––other*/ a.popup-link diff --git a/public/font/config.json b/public/font/config.json index c2986048..b68917b3 100644 --- a/public/font/config.json +++ b/public/font/config.json @@ -216,6 +216,24 @@ "code": 59420, "src": "fontawesome" }, + { + "uid": "d862a10e1448589215be19702f98f2c1", + "css": "smile", + "code": 59446, + "src": "fontawesome" + }, + { + "uid": "06ddc67d609c477cd5524a7238d7850d", + "css": "frown", + "code": 59445, + "src": "fontawesome" + }, + { + "uid": "2c5055a9c9723725f49f0593a08535af", + "css": "meh", + "code": 59447, + "src": "fontawesome" + }, { "uid": "627abcdb627cb1789e009c08e2678ef9", "css": "twitter", @@ -252,6 +270,18 @@ "code": 59429, "src": "entypo" }, + { + "uid": "7f6916533c0842b6cec699fd773693d3", + "css": "hourglass", + "code": 59444, + "src": "entypo" + }, + { + "uid": "3a6f0140c3a390bdb203f56d1bfdefcb", + "css": "gauge", + "code": 59443, + "src": "entypo" + }, { "uid": "bczb7qup4axmc490xmuuv8qdhcnbgeyf", "css": "user", diff --git a/public/font/fontello.eot b/public/font/fontello.eot index 51a3892f..8b1755cb 100644 Binary files a/public/font/fontello.eot and b/public/font/fontello.eot differ diff --git a/public/font/fontello.svg b/public/font/fontello.svg index 45b6d70c..26090607 100644 --- a/public/font/fontello.svg +++ b/public/font/fontello.svg @@ -57,6 +57,11 @@ + + + + + \ No newline at end of file diff --git a/public/font/fontello.ttf b/public/font/fontello.ttf index a6d45c4d..a43f11a9 100644 Binary files a/public/font/fontello.ttf and b/public/font/fontello.ttf differ diff --git a/public/font/fontello.woff b/public/font/fontello.woff index 8ed9a8f0..0f8ef185 100644 Binary files a/public/font/fontello.woff and b/public/font/fontello.woff differ diff --git a/public/js/app.js b/public/js/app.js index 937c554c..307c990d 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -21,7 +21,8 @@ define([ avatar: 'https://s3.amazonaws.com/island.io/avatar_48.png', avatar_big: 'https://s3.amazonaws.com/island.io/avatar_325.png', banner: 'https://s3.amazonaws.com/island.io/banner_680.png', - banner_big: 'https://s3.amazonaws.com/island.io/banner_1024.png' + banner_big: 'https://s3.amazonaws.com/island.io/banner_1024.png', + store_avatar: 'https://s3.amazonaws.com/island.io/store_avatar.png' }; this.prefs = { @@ -47,8 +48,13 @@ define([ 'b6e0d7d608a14a578cf94763f70f1b49' }; this.facebook = { - clientId: window.__s ? 203397619757208:153015724883386 + clientId: window.__s ? 203397619757208: 153015724883386 }; + this.stripe = { + key: window.__s ? 'pk_live_p1Ojag00gWkn0MzgnF52RWFw': + 'pk_test_hUrz7pk2qdjqgIU1BDuHraVv' + }; + this.MAX_PRODUCT_QUANTITY_PER_ORDER = 20; if (window.__s === '') { window._rpc = rpc; diff --git a/public/js/rest.js b/public/js/rest.js index 1ab61803..ec5b2049 100644 --- a/public/js/rest.js +++ b/public/js/rest.js @@ -28,6 +28,7 @@ define([ member: err.member, content: err.content, message: err.error.message, + data: err.error.data, stack: err.error.stack, explain: err.error.explain, level: err.error.level, diff --git a/public/js/router.js b/public/js/router.js index a861ceac..17bbc65a 100644 --- a/public/js/router.js +++ b/public/js/router.js @@ -31,6 +31,7 @@ define([ 'views/ascent', 'views/settings', 'views/reset', + 'views/store', 'views/films', 'views/static', 'views/crags', @@ -45,7 +46,7 @@ define([ 'views/share' ], function ($, _, Backbone, Spin, mps, rest, util, Error, Header, Tabs, Footer, Flashes, Signin, Signup, Forgot, Notifications, Map, Profile, Post, Session, Tick, - Crag, Admin, ImportSearch, ImportInsert, Ascent, Settings, Reset, Films, Static, + Crag, Admin, ImportSearch, ImportInsert, Ascent, Settings, Reset, Store, Films, Static, Crags, Dashboard, Splash, Ticks, Medias, aboutTemp, privacyTemp, tipTemp, NewSession, Share ) { @@ -141,6 +142,7 @@ define([ this.route('privacy', 'privacy', this.privacy); this.route('about', 'about', this.about); this.route('films', 'films', this.films); + this.route('store', 'store', this.store); this.route('crags', 'crags', this.crags); this.route('signin', 'signin', this.signin); this.route('signup', 'signup', this.signup); @@ -259,8 +261,7 @@ define([ cb = cb || function(){}; // Check if a profile exists already. - var query = this.app.profile && - this.app.profile.notes ? {n: 0}: {}; + var query = this.app.profile && this.app.profile.notes ? {n: 0}: {}; _.extend(query, data); // Get a profile, if needed. @@ -492,6 +493,18 @@ define([ }, this)); }, + store: function () { + this.start(); + this.renderTabs(); + this.clearContainer(); + this.render('/service/store', _.bind(function (err) { + if (err) return; + this.page = new Store(this.app).render(); + this.renderTabs({html: this.page.title}); + this.stop(); + }, this)); + }, + films: function () { this.start(); this.renderTabs(); @@ -559,10 +572,11 @@ define([ this.start(); this.renderTabs(); this.clearContainer(); + var path, name = ''; if (this.app.state && this.app.state.import) { var target = this.app.state.import.target; - var path = this.app.state.import.userId + '-' + target - var name = this.app.state.import.name; + path = this.app.state.import.userId + '-' + target; + name = this.app.state.import.name; } delete this.app.state.import; this.render('/service/import/' + path, _.bind(function (err) { diff --git a/public/js/views/settings.js b/public/js/views/settings.js index d14bbe1a..c0f90a3d 100644 --- a/public/js/views/settings.js +++ b/public/js/views/settings.js @@ -359,8 +359,10 @@ define([ if (assembly.ok !== 'ASSEMBLY_COMPLETED') { this.bannerSpin.stop(); this.bannerDropZone.removeClass('uploading'); - mps.publish('flash/new', [{err: 'Upload failed. Please try again.', - level: 'error', type: 'popup'}]); + mps.publish('flash/new', [{ + err: 'Upload failed. Please try again.', + level: 'error', type: 'popup' + }]); return; } if (_.isEmpty(assembly.results)) { this.bannerSpin.stop(); @@ -383,7 +385,8 @@ define([ this.bannerSpin.stop(); this.bannerDropZone.removeClass('uploading'); - mps.publish('flash/new', [{err: err, level: 'error', type: 'popup'}]); + mps.publish('flash/new', [{err: err, level: 'error', + type: 'popup'}]); return; } @@ -566,8 +569,11 @@ define([ if (assembly.ok !== 'ASSEMBLY_COMPLETED') { this.avatarSpin.stop(); this.avatarDropZone.removeClass('uploading'); - mps.publish('flash/new', [{err: 'Upload failed. Please try again.', - level: 'error', type: 'popup'}]); + mps.publish('flash/new', [{ + err: 'Upload failed. Please try again.', + level: 'error', + type: 'popup' + }]); return; } if (_.isEmpty(assembly.results)) { this.avatarSpin.stop(); @@ -590,7 +596,8 @@ define([ this.avatarSpin.stop(); this.avatarDropZone.removeClass('uploading'); - mps.publish('flash/new', [{err: err, level: 'error', type: 'popup'}]); + mps.publish('flash/new', [{err: err, level: 'error', + type: 'popup'}]); return; } @@ -742,7 +749,8 @@ define([ rest.delete('/api/members/' + this.app.profile.member.username, {}, _.bind(function (err, data) { if (err) { - mps.publish('flash/new', [{err: err, level: 'error', type: 'popup'}]); + mps.publish('flash/new', [{err: err, level: 'error', + type: 'popup'}]); return; } @@ -773,7 +781,8 @@ define([ // Delete all ticks. rest.delete('/api/ticks/all', {}, _.bind(function (err, data) { if (err) { - mps.publish('flash/new', [{err: err, level: 'error', type: 'popup'}]); + mps.publish('flash/new', [{err: err, level: 'error', + type: 'popup'}]); return; } diff --git a/public/js/views/store.js b/public/js/views/store.js new file mode 100644 index 00000000..7c7a8430 --- /dev/null +++ b/public/js/views/store.js @@ -0,0 +1,579 @@ +/* + * Page view for films. + */ + +define([ + 'jQuery', + 'Underscore', + 'Backbone', + 'mps', + 'rest', + 'util', + 'Spin', + 'text!../../templates/store.html', + 'text!../../templates/store.title.html', + 'text!../../templates/shipping.cart.html', + 'text!../../templates/shipping.address.html', + 'text!../../templates/shipping.options.html', + 'text!../../templates/shipping.summary.html', + 'text!../../templates/shipping.processing.html', + 'views/lists/events', + 'views/lists/ticks' +], function ($, _, Backbone, mps, rest, util, Spin, template, title, + shippingCartTemp, shippingAddressTemp, shippingOptionsTemp, + shippingSummaryTemp, shippingProcessingTemp, Events, Ticks) { + + return Backbone.View.extend({ + + el: '.main', + + initialize: function (app) { + this.app = app; + this.subscriptions = [ + mps.subscribe('cart/checkout', _.bind(this.checkout, this)), + mps.subscribe('cart/empty', _.bind(this.emptyCart, this)) + ]; + this.on('rendered', this.setup, this); + }, + + render: function () { + this.app.title('The Island | Store'); + + this.template = _.template(template); + this.$el.html(this.template.call(this)); + this.title = _.template(title).call(this); + + this.trigger('rendered'); + + return this; + }, + + renderModal: function (template, opts) { + opts = opts || {}; + opts.member = this.app.profile.member; + + $.fancybox(_.template(template)(opts), { + openEffect: 'fade', + closeEffect: 'fade', + closeBtn: false, + padding: 0, + modal: true + }); + }, + + closeModal: function () { + $.fancybox.close(); + }, + + events: { + 'click .add-to-cart': 'addToCart', + 'click .buy-now': 'buyNow', + 'click .navigate': 'navigate' + }, + + setup: function () { + _.defer(function () { + mps.publish('cart/update'); + }); + + this.feed = new Events(this.app, {parentView: this, + reverse: true, filters: false}); + + this.stripeHandler = StripeCheckout.configure({ + key: this.app.stripe.key, + billingAddress: false + }); + + var fancyOpts = { + openEffect: 'fade', + closeEffect: 'fade', + closeBtn: false, + nextClick: true, + padding: 0 + }; + + this.$('a.fancybox').fancybox(fancyOpts); + + return this; + }, + + empty: function () { + this.$el.empty(); + return this; + }, + + destroy: function () { + _.each(this.subscriptions, function (s) { + mps.unsubscribe(s); + }); + this.feed.destroy(); + this.undelegateEvents(); + this.stopListening(); + this.empty(); + }, + + navigate: function (e) { + e.preventDefault(); + var path = $(e.target).closest('a').attr('href'); + if (path) { + this.app.router.navigate(path, {trigger: true}); + } + }, + + addToCart: function (e) { + var button = $(e.target).closest('.add-to-cart'); + var picker = button.parent(); + var sku = picker.data('sku'); + + var product = _.find(this.app.profile.content.products.items, + function (i) { + return i.sku === sku; + }); + if (!product) { + return; + } + + var cart = store.get('cart') || {}; + var cnt = (cart[sku] || 0) + 1; + if (cnt > this.app.MAX_PRODUCT_QUANTITY_PER_ORDER) { + return mps.publish('flash/new', [{ + message: 'Maximum quantity per order reached.', + level: 'alert', + type: 'popup' + }]); + } + cart[sku] = cnt; + + store.set('cart', cart); + mps.publish('cart/update'); + + mps.publish('flash/new', [{ + message: product.title + ' added to cart (' + cart[sku] + ' total).', + level: 'alert', + type: 'popup' + }]); + }, + + checkout: function (e) { + var summary = this.getOrderSummary(); + + if (summary.count <= 0) { + return; + } + + this.renderModal(shippingCartTemp, { + summary: summary, + max: this.app.MAX_PRODUCT_QUANTITY_PER_ORDER + }); + + var cancel = $('.modal-cancel'); + var confirm = $('.modal-confirm'); + + cancel.click(_.bind(this.closeModal, this)); + + confirm.click(_.bind(function (e) { + this.closeModal(); + this.getShippingOptions(); + }, this)); + + $('input[name$="-qnty"]').bind('change', _.bind(function (e) { + var input = $(e.target); + var cnt = Math.min(parseInt(input.val(), 10), + this.app.MAX_PRODUCT_QUANTITY_PER_ORDER); + var sku = input.data('sku'); + + var cart = store.get('cart') || {}; + cart[sku] = cnt; + + store.set('cart', cart); + mps.publish('cart/update'); + + this.closeModal(); + this.checkout(); + + $('input[name="' + sku + '-qnty"]').focus(); + + }, this)); + + return false; + }, + + buyNow: function (e) { + var button = $(e.target).closest('.buy-now'); + var picker = button.parent(); + var sku = picker.data('sku'); + var buyNow = {}; + buyNow[sku] = 1; + store.set('buyNow', buyNow); + + this.getShippingOptions(true); + }, + + getShippingOptions: function (buyNow) { + var cart = buyNow ? store.get('buyNow'): store.get('cart'); + + if (_.isEmpty(cart)) { + return false; + } + + var address; + var saveAddress; + var isValid = false; + + this.clearOrder(); + + this.renderModal(shippingAddressTemp, { + back: !buyNow + }); + + var cancel = $('.modal-cancel'); + var back = $('.modal-back'); + var confirm = $('.modal-confirm'); + + var spinner = new Spin($('.modal .button-spin'), { + color: '#808080', + lines: 13, + length: 3, + width: 2, + radius: 6, + }); + + cancel.click(_.bind(this.closeOrder, this)); + + back.click(_.bind(function (e) { + this.closeModal(); + this.checkout(); + }, this)); + + confirm.click(_.bind(function (e) { + if (!isValid) { + return false; + } + + spinner.start(); + confirm.addClass('spinning').attr('disabled', true); + + var username = this.app.profile.member ? + this.app.profile.member.username: false; + if (saveAddress && username) { + rest.put('/api/members/' + username, { + address: address + }, _.bind(function (err, data) { + if (err) { + mps.publish('flash/new', [{ + err: err, + level: 'error', + type: 'popup', + sticky: true + }]); + return false; + } + this.app.profile.member.address = address; + }, this)); + } + + // Get shipping options for sending the cart items to this address. + var payload = { + cart: cart, + address: address + }; + rest.post('/api/store/shipping', payload, _.bind(function (err, data) { + spinner.stop(); + confirm.removeClass('spinning').attr('disabled', false); + + if (err) { + mps.publish('flash/new', [{ + err: err, + level: 'error', + type: 'popup', + sticky: true + }]); + return false; + } + + store.set('shippingOptions', data.options); + store.set('shipTo', data.shipTo); + + this.closeModal(); + this.chooseShippingOption(buyNow); + }, this)); + }, this)); + + var form = $('.shipping-address-form'); + var inputs = $('.shipping-form input[type="text"]'); + var saveAddressBox = $('.modal-options input[name="saveAddress"]'); + + function _getAddress() { + address = form.serializeObject(); + _.each(address, function (v, k) { + if (v.trim() === '') { + address[k] = false; + } + }); + if (!address.name || !address.address || !address.city || + !address.zip || !address.country) { + confirm.addClass('disabled').attr('disabled', true); + isValid = false; + saveAddress = false; + } else { + confirm.removeClass('disabled').attr('disabled', false); + isValid = true; + saveAddress = saveAddressBox.is(':checked'); + } + + return isValid; + } + + inputs.focus(function (e) { + var el = $(e.target); + el.parent().addClass('focus'); + var sib = el.parent().prev(); + if (sib.length > 0) { + sib.addClass('sibling-focus-right'); + } + }); + + inputs.blur(function (e) { + $('.shipping-form td').removeClass('sibling-focus-right'); + var el = $(e.target); + el.parent().removeClass('focus'); + }); + + inputs.bind('keyup', function (e) { _getAddress(); }) + .bind('change', function (e) { _getAddress(); }); + _getAddress(); + + return false; + }, + + chooseShippingOption: function (buyNow) { + var cart = buyNow ? store.get('buyNow'): store.get('cart'); + var shipTo = store.get('shipTo'); + var shippingOptions = store.get('shippingOptions'); + var shipping = store.get('shipping'); + + if (_.isEmpty(cart) || !shipTo || !shippingOptions) { + return false; + } + + this.renderModal(shippingOptionsTemp, { + options: shippingOptions, + shipping: shipping + }); + + var cancel = $('.modal-cancel'); + var back = $('.modal-back'); + var confirm = $('.modal-confirm'); + + cancel.click(_.bind(this.closeOrder, this)); + + back.click(_.bind(function (e) { + this.closeModal(); + this.getShippingOptions(buyNow); + }, this)); + + confirm.click(_.bind(function (e) { + var optionCode = + $('.shipping-options-form input:radio[name="option"]:checked') + .val(); + var shipping = _.find(shippingOptions, function (o) { + return o.serviceLevelCode === optionCode; + }); + shipping.shipTo = shipTo; + store.set('shipping', shipping); + + this.closeModal(); + this.confirmShippingSummary(buyNow); + }, this)); + + $('.modal-body tr').click(function (e) { + var tr = $(e.target).closest('tr'); + var option = $('input[name="option"]', tr); + option.attr('checked', 'checked'); + }); + + return false; + }, + + getOrderSummary: function (buyNow, demandShipping) { + var cart = buyNow ? store.get('buyNow'): store.get('cart'); + var shipping = store.get('shipping'); + + if (_.isEmpty(cart)) { + return false; + } + + if (demandShipping && (!shipping || !shipping.shipTo)) { + return false; + } + + var items = {}; + var shipment = demandShipping ? shipping.shipments[0] : null; + var shippingAndHandlingCost = shipment ? shipment.cost.amount : 0; + var total = 0; + var count = 0; + + _.each(cart, _.bind(function (quantity, sku) { + var product = _.find(this.app.profile.content.products.items, + function (i) { + return i.sku === sku; + }); + if (!product) { + return; + } + var cost = quantity * product.price; + items[sku] = {product: product, quantity: quantity, cost: cost}; + total += cost; + count += quantity; + }, this)); + + var itemsTotal = total; + total += shippingAndHandlingCost * 100; + + var shippingAndHandling; + if (demandShipping) { + shippingAndHandling = shipping.serviceLevelName + ' (' + + shipment.carrier.description + ')
'; + shippingAndHandling += 'Ships ' + new Date(shipment.expectedShipDate) + .format('ddd, mmm d, h:MMtt Z') + '
'; + shippingAndHandling += 'Delivered by ' + + new Date(shipment.expectedDeliveryMaxDate) + .format('ddd, mmm d, h:MMtt Z'); + } + + return { + cart: cart, + shipping: shipping, + count: count, + items: items, + shippingAndHandling: shippingAndHandling, + shippingAndHandlingCost: shippingAndHandlingCost, + itemsTotal: itemsTotal, + total: total + }; + }, + + confirmShippingSummary: function (buyNow) { + var summary = this.getOrderSummary(buyNow, true); + + this.renderModal(shippingSummaryTemp, { + summary: summary + }); + + var cancel = $('.modal-cancel'); + var back = $('.modal-back'); + var confirm = $('.modal-confirm'); + + cancel.click(_.bind(this.closeOrder, this)); + + back.click(_.bind(function (e) { + this.closeModal(); + this.chooseShippingOption(buyNow); + }, this)); + + confirm.click(_.bind(function (e) { + this.closeModal(); + this.collectPayment(summary, buyNow); + }, this)); + + return false; + }, + + collectPayment: function (summary, buyNow) { + var itemsDescription = summary.count + ' item'; + if (summary.count !== 1) { + itemsDescription += 's'; + } + itemsDescription += ': $' + (summary.itemsTotal / 100).toFixed(2) + + ' (USD)'; + + var shippingDescription = 'Shipping & Handling: $' + + summary.shippingAndHandlingCost.toFixed(2) + ' (USD)'; + + this.stripeHandler.open({ + name: itemsDescription, + description: shippingDescription, + amount: summary.total, + image: this.app.images.store_avatar, + token: _.bind(function (token) { + var order = { + token: token, + cart: summary.cart, + shipping: summary.shipping, + description: itemsDescription + }; + this.placeOrder(order); + }, this) + }); + }, + + placeOrder: function (order) { + // Give 'em a random processing GIF. + rest.get('http://api.giphy.com/v1/gifs/random?api_key=' + + 'dc6zaTOxFJmzC&tag=processing', _.bind(function (err, res) { + loadingGIF = err ? null: res.data; + + this.renderModal(shippingProcessingTemp, { + loadingGIF: loadingGIF + }); + + rest.post('/api/store/checkout', order, _.bind(function (err, data) { + if (err) { + var errOpts = {level: 'error', type: 'popup', sticky: true}; + if (err.message === 'OVER_MAX_PRODUCT_QUANTITY_PER_ORDER' || + err.message === 'INSUFFICIENT_STOCK') { + _.each(err.data, function (p) { + var message = err.message + ': ' + p.name + ' ('; + if (p.allowed !== undefined) { + message += 'please limit your order to ' + p.allowed; + } + if (p.good !== undefined) { + message += p.good + ' remaining'; + } + message += ')'; + errOpts.err = {message: message}; + mps.publish('flash/new', [errOpts, true]); + }); + } else { + errOpts.err = err; + mps.publish('flash/new', [errOpts, true]); + } + + return false; + } + + this.emptyCart(); + mps.publish('cart/update'); + this.closeOrder(); + + mps.publish('flash/new', [{ + message: data.message, + level: 'alert', + type: 'block', + sticky: true + }, true]); + }, this)); + }, this)); + + return false; + }, + + emptyCart: function () { + store.set('cart', {}); + store.set('buyNow', {}); + }, + + clearOrder: function () { + store.set('shippingOptions', null); + store.set('shipTo', null); + store.set('shipping', null); + store.set('summary', null); + }, + + closeOrder: function () { + this.clearOrder(); + this.closeModal(); + } + + }); +}); diff --git a/public/js/views/tabs.js b/public/js/views/tabs.js index b127db09..a4575e41 100644 --- a/public/js/views/tabs.js +++ b/public/js/views/tabs.js @@ -28,6 +28,26 @@ define([ this.subscriptions = [ mps.subscribe('ascent/add', _.bind(function (opts) { this.add(null, opts); + }, this)), + mps.subscribe('cart/update', _.bind(function () { + var cart = store.get('cart'); + var count = 0; + _.each(cart, function (i) { + count += i; + }); + var countText = count + ' item'; + if (count !== 1) { + countText += 's'; + } + this.$('.cart-count').text(countText); + + if (count > 0) { + this.$('.cart-button').removeClass('disabled').attr('disabled', false); + this.$('.empty-cart-button').show(); + } else { + this.$('.cart-button').addClass('disabled').attr('disabled', true); + this.$('.empty-cart-button').hide(); + } }, this)) ]; }, @@ -74,7 +94,22 @@ define([ }, 'click .add-ascent': 'add', 'click .log-session': 'log', - 'click .clean-button': 'cleanLogs' + 'click .clean-button': 'cleanLogs', + 'click .cart-button': function () { + mps.publish('cart/checkout'); + }, + 'click .empty-cart-button': function () { + this.$('.cart-count').text('0 items'); + this.$('.empty-cart-button').hide(); + this.$('.cart-button').addClass('disabled').attr('disabled', true); + mps.publish('cart/empty'); + + mps.publish('flash/new', [{ + message: 'Cart emptied.', + level: 'alert', + type: 'popup' + }]); + } }, setup: function () { diff --git a/public/templates/crags.html b/public/templates/crags.html index 50d974b8..fb7f9142 100644 --- a/public/templates/crags.html +++ b/public/templates/crags.html @@ -15,7 +15,7 @@ <% } %> diff --git a/public/templates/privacy.html b/public/templates/privacy.html index 98ba492e..0303a72b 100644 --- a/public/templates/privacy.html +++ b/public/templates/privacy.html @@ -6,7 +6,7 @@ diff --git a/public/templates/settings.html b/public/templates/settings.html index e5f2abea..4e0b2844 100644 --- a/public/templates/settings.html +++ b/public/templates/settings.html @@ -59,6 +59,9 @@ var privacy = data.config.privacy; var prefs = data.prefs; + // Shipping + data.address = data.address || {}; + %>
@@ -66,13 +69,40 @@
+ + + + + + + + + - - - - + + + + + - + - + + + + + @@ -220,21 +282,21 @@

Preferences

@@ -411,7 +473,7 @@

Download My Data

@@ -423,7 +485,7 @@

Clear My Logs

@@ -440,10 +502,10 @@

Notification Settings

@@ -619,7 +681,7 @@

Danger Zone

+

Banner Image

+
+
+ +
+ + width=<%= w %> height=<%= h %> style=<%= t + l %> /> +
+ + +
+
+
+

Profile

+
@@ -99,107 +129,139 @@
- +
+ - - - - - - + + + + + + + + + + + +
+
+
+
+
+
+
+ +
+ +
+ +
+ +
- +
-
- -
- - width=<%= w %> height=<%= h %> style=<%= t + l %> /> -
- - -
-
+
+
- +
- +
- + +

Shipping Address (private)

- +
+ +
+
- + - +
- + + + +
- + + + + +
+ + +
- /> - /> - /> @@ -242,21 +304,21 @@

Preferences

- /> - /> - /> @@ -269,7 +331,7 @@

Preferences

- /> @@ -286,7 +348,7 @@

Preferences

- /> @@ -310,10 +372,10 @@

Privacy

<% if (privacy.mode === 0 || privacy.mode === '0') { %> - <% } else { %> - <% } %> @@ -332,10 +394,10 @@

Privacy

<% if (privacy.mode === 1 || privacy.mode === '1') { %> - <% } else { %> - <% } %> @@ -359,10 +421,10 @@

Privacy

<% if (!privacy.ticks || privacy.ticks === 0 || privacy.ticks === '0') { %> - <% } else { %> - <% } %> @@ -371,10 +433,10 @@

Privacy

<% if (privacy.ticks === 1 || privacy.ticks === '1') { %> - <% } else { %> - <% } %> @@ -383,10 +445,10 @@

Privacy

<% if (privacy.ticks === 2 || privacy.ticks === '2') { %> - <% } else { %> - <% } %> @@ -399,7 +461,7 @@

Import Scorecard from sites like - + Import

- + Download
- + Clear <% if (notes.comment.email === true || notes.comment.email === 'true') { %> + tabindex="34" checked="checked" /> <% } else { %> + tabindex="35" /> <% } %> @@ -457,10 +519,10 @@

Notification Settings

<% if (notes.hangten.email === true || notes.hangten.email === 'true') { %> + tabindex="36" checked="checked" /> <% } else { %> + tabindex="37" /> <% } %> @@ -474,10 +536,10 @@

Notification Settings

<% if (notes.follow.email === true || notes.follow.email === 'true') { %> + tabindex="38" checked="checked" /> <% } else { %> + tabindex="39" /> <% } %> @@ -491,10 +553,10 @@

Notification Settings

<% if (notes.request.email === true || notes.request.email === 'true') { %> + tabindex="40" checked="checked" /> <% } else { %> + tabindex="41" /> <% } %> @@ -508,10 +570,10 @@

Notification Settings

<% if (notes.accept.email === true || notes.accept.email === 'true') { %> + tabindex="42" checked="checked" /> <% } else { %> + tabindex="43" /> <% } %> @@ -527,12 +589,12 @@

Services

<% if (!data.googleId) { %> - <% } else if (data.provider !== 'google') { %> - @@ -545,12 +607,12 @@

Services


<% if (!data.facebookId) { %> - <% } else if (data.provider !== 'facebook') { %> - @@ -563,12 +625,12 @@

Services


<% if (!data.twitterId) { %> - <% } else if (data.provider !== 'twitter') { %> - @@ -581,12 +643,12 @@

Services


<% if (!data.instagramId) { %> - <% } else { %> - @@ -606,7 +668,7 @@

Security

-
- diff --git a/public/templates/shipping.address.html b/public/templates/shipping.address.html new file mode 100644 index 00000000..ff93d930 --- /dev/null +++ b/public/templates/shipping.address.html @@ -0,0 +1,67 @@ +<% + member = member || {}; + var address = member.address || {}; +%> + + diff --git a/public/templates/shipping.cart.html b/public/templates/shipping.cart.html new file mode 100644 index 00000000..82741aeb --- /dev/null +++ b/public/templates/shipping.cart.html @@ -0,0 +1,62 @@ + diff --git a/public/templates/shipping.options.html b/public/templates/shipping.options.html new file mode 100644 index 00000000..817f6107 --- /dev/null +++ b/public/templates/shipping.options.html @@ -0,0 +1,57 @@ +<% + var chosen = shipping ? shipping.serviceLevelCode: + options[0].serviceLevelCode; +%> + + diff --git a/public/templates/shipping.processing.html b/public/templates/shipping.processing.html new file mode 100644 index 00000000..bfdc25b5 --- /dev/null +++ b/public/templates/shipping.processing.html @@ -0,0 +1,13 @@ + diff --git a/public/templates/shipping.summary.html b/public/templates/shipping.summary.html new file mode 100644 index 00000000..d3a52f10 --- /dev/null +++ b/public/templates/shipping.summary.html @@ -0,0 +1,80 @@ + diff --git a/public/templates/splash.html b/public/templates/splash.html index 642da627..6fba57fe 100644 --- a/public/templates/splash.html +++ b/public/templates/splash.html @@ -89,7 +89,7 @@

Watch your favorite crags, boulder problems, and route diff --git a/public/templates/store.html b/public/templates/store.html new file mode 100644 index 00000000..d885ca99 --- /dev/null +++ b/public/templates/store.html @@ -0,0 +1,54 @@ +
+ +
+
+

+ Homegrown films: +Many thanks to everyone that has made these films happen. If you have a sales question or just need some help with something, please send us an email. +

+
+
+
+ Showing all. +
+
+
diff --git a/public/templates/store.title.html b/public/templates/store.title.html new file mode 100755 index 00000000..7c202fa8 --- /dev/null +++ b/public/templates/store.title.html @@ -0,0 +1,9 @@ + + + + + Checkout (0 items) + +
+

The Island Store

+
diff --git a/public/templates/tabs.html b/public/templates/tabs.html index 5c4bc75c..65d16060 100644 --- a/public/templates/tabs.html +++ b/public/templates/tabs.html @@ -4,9 +4,9 @@ <%= this.params.html %> <% } else { %> <% if (this.params.log) { %> - <% if (this.app.profile && this.app.profile.member - && this.app.profile.member.username !== 'island' - && this.app.profile.member.role !== 2) { %> + <% if (this.app.profile && this.app.profile.member && + this.app.profile.member.username !== 'island' && + this.app.profile.member.role !== 2) { %> Log @@ -19,9 +19,9 @@

<%= this.params.subtitle %>

<% } %> <% } else { %> - <% if (this.params.log - && this.app.profile.member.username !== 'island' - && this.app.profile.member.role !== 2) { %> + <% if (this.params.log && + this.app.profile.member.username !== 'island' && + this.app.profile.member.role !== 2) { %> Log @@ -29,7 +29,9 @@

<%= this.params.subtitle %>

    <% _.each(this.params.tabs, function (tab) { var klass = 'tab'; - if (tab.active) klass += ' active'; + if (tab.active) { + klass += ' active'; + } %>
  • <%= tab.title %> diff --git a/store.json b/store.json new file mode 100644 index 00000000..16cc8625 --- /dev/null +++ b/store.json @@ -0,0 +1,44 @@ +{ + "M1-Island-Brush": { + "name": "M1 Island Brush", + "title": "Island M1 Classic Brush", + "description": "Our version of the rock climbing toothbrush. Beech wood and boar's hair. Custom made in Bulgaria.", + "price": 750, + "images": [ + "https://s3.amazonaws.com/island.io/store/img/m1-1.jpg", + "https://s3.amazonaws.com/island.io/store/img/m1-2.jpg", + "https://s3.amazonaws.com/island.io/store/img/m1-3.jpg" + ], + "thumbs": [ + "https://s3.amazonaws.com/island.io/store/img/m1t-1.png", + "https://s3.amazonaws.com/island.io/store/img/m1t-2.png", + "https://s3.amazonaws.com/island.io/store/img/m1t-3.png" + ] + }, + "M1-Island-Case": { + "price": 75000 + }, + "M3-Island-Brush": { + "name": "M3 Island Brush", + "title": "Island M3 Scrub Brush", + "description": "Palm-sized scrubber for those bigger holds. Beech wood and boar's hair. Custom made in Bulgaria.", + "price": 1250, + "images": [ + "https://s3.amazonaws.com/island.io/store/img/m3-1.jpg", + "https://s3.amazonaws.com/island.io/store/img/m3-2.jpg", + "https://s3.amazonaws.com/island.io/store/img/m3-3.jpg" + ], + "thumbs": [ + "https://s3.amazonaws.com/island.io/store/img/m3t-1.png", + "https://s3.amazonaws.com/island.io/store/img/m3t-2.png", + "https://s3.amazonaws.com/island.io/store/img/m3t-3.png" + ] + }, + "M3-Island-Case": { + "price": 31250 + }, + + "TEST-NO-STOCK": { + "price": 200 + } +} diff --git a/test/server/member.js b/test/server/member.js index 1fa526cc..62521581 100644 --- a/test/server/member.js +++ b/test/server/member.js @@ -3,17 +3,18 @@ var assert = require('assert'); var request = require('supertest'); var url = 'localhost:8080'; -var user = 'testdummy5' +var user = 'testdummy5'; var cookies; -describe('members resource', function() { - it('check if service is up and user:' + user + ' doesn\'t exist', function(done) { +describe('Members', function() { + it('check if service is up and user:' + user + ' doesn\'t exist', + function(done) { request(url) .get('/api/members/' + user) - .expect(200) + .expect(404) .end(function(err, res) { - res.body.should.be.empty(); + res.body.error.message.should.be.exactly('member not found'); done(err); }); }); @@ -47,9 +48,8 @@ describe('members resource', function() { }); it('delete user: DELETE to /api/members', function(done) { - - var req = request(url).delete('/api/members/' + user) - req.cookies = cookies + var req = request(url).delete('/api/members/' + user); + req.cookies = cookies; req.expect(200) .end(function(err, res) { done(err); @@ -59,9 +59,9 @@ describe('members resource', function() { it('verify delete: GET to /api/members', function(done) { request(url) .get('/api/members/' + user) - .expect(200) + .expect(404) .end(function(err, res) { - res.body.should.be.empty(); + res.body.error.message.should.be.exactly('member not found'); done(err); }); }); diff --git a/test/server/service.js b/test/server/service.js index 4b1e876e..685355f4 100644 --- a/test/server/service.js +++ b/test/server/service.js @@ -52,11 +52,9 @@ describe('Service (not logged in)', function() { request(url) .get(route('ticks') + '/islandTest') .expect(200, function(err, res) { - console.log(res.body); res.body.content.page.ticks.should.be.empty(); done(err); }); }); - }); diff --git a/test/server/setupteardown.js b/test/server/setupteardown.js index 42759583..ab8c1fbc 100644 --- a/test/server/setupteardown.js +++ b/test/server/setupteardown.js @@ -14,32 +14,31 @@ function createMember(name, cb) { var profile = { username: name, password: name, - email: name + '@' + name + 'com' + email: name + '@' + name + '.com' }; - request(url) .get('/api/members/' + name) - .expect(200) + .expect(404) .end(function(err, res) { - if (!err && _.isEmpty(res.body)) { + if (!err && res.statusCode === 404) { console.log('creating user ' + name); request(url) .post('/api/members') .send(profile) .end(function(err, res) { return cb(err); - }) + }); } else { cb(err); } }); -}; +} function login(name, cb) { var profile = { username: name, password: name, - email: name + '@' + name + 'com' + email: name + '@' + name + '.com' }; request(url) .post('/api/members/auth') @@ -48,8 +47,8 @@ function login(name, cb) { .end(function(err, res) { cookies = res.headers['set-cookie'].pop().split(';')[0]; return cb(err); - }) -}; + }); +} function logout(name, cb) { var req = request(url).get('/service/logout'); @@ -61,7 +60,7 @@ function deleteMember(name, cb) { var profile = { username: name, password: name - } + }; request(url) .post('/api/members/auth') .send(profile) @@ -83,7 +82,7 @@ function createCrag(name, cb) { latitude: 37.7833, longitude: -122.4167 } - } + }; console.log('creating crag ' + name); var req = request(url).post('/api/crags'); req.cookies = cookies; @@ -101,7 +100,7 @@ function createAscent(name, type, grade, cragid, cb) { crag_id: cragid, type: type, grade: grade - } + }; console.log('creating ascent ' + name); var req = request(url).post('/api/ascents'); req.cookies = cookies; @@ -114,20 +113,19 @@ function createAscent(name, type, grade, cragid, cb) { }); } - -before('building a mini island database of users, ascents, crags', function(done) { +before('building a mini island database of users, ascents, crags', + function(done) { this.timeout(30000); async.waterfall([ - function(cb) { createMember('islandTest', cb) }, - function(cb) { login('islandTest', cb) }, - function(cb) { createCrag('crag1', cb) }, - function(res, cb) { createAscent('ascent1', 'b', 3, res.body._id, cb) } + function(cb) { createMember('islandTest', cb); }, + function(cb) { login('islandTest', cb); }, + function(cb) { createCrag('crag1', cb); }, + function(res, cb) { createAscent('ascent1', 'b', 3, res.body._id, cb); } ], done); }); after('clearing database', function(done) { async.parallel([ - function(cb) { deleteMember('islandTest', cb) } + function(cb) { deleteMember('islandTest', cb); } ], done); }); - diff --git a/test/server/store.js b/test/server/store.js new file mode 100644 index 00000000..3552238b --- /dev/null +++ b/test/server/store.js @@ -0,0 +1,537 @@ +var should = require('should'); +var assert = require('assert'); +var request = require('supertest'); +var _ = require('underscore'); +var store = require('../../lib/resources/store'); +var skus = Object.keys(require('../../store.json')); +var config = require('../../config.json'); + +var stripe = require('stripe')(config.STRIPE_SECRET_KEY); + +var shipwire = new (require('shipwire-node').Shipwire)({ + host: config.SHIPWIRE_HOST, + username: config.SHIPWIRE_USER, + password: config.SHIPWIRE_PASS +}); + +var url = 'localhost:8080'; + +var invalidAddress = {foo: 'bar'}; + +var nonExistingAddress = { + name: 'Whereis Waldo', + address: '123 Nowhere Rd', + city: 'Notarealcity', + state: 'ZZ', + zip: '99999', + country: 'Fakelandia' +}; + +var goodAddress = { + name: 'TEST GUY', + address: '530 N Montana Ave', + city: 'Bozeman', + state: 'MT', + zip: '59715', + country: 'United States' +}; + +var invalidCart = {'Not-A-Real-SKU': 3}; + +var overMaxCart = {'M3-Island-Brush': store.MAX_PRODUCT_QUANTITY_PER_ORDER + 1}; + +var outOfStockCart = {'TEST-NO-STOCK': 10}; + +var goodCart = {'M1-Island-Brush': 1}; + +var invalidToken = {id: 'canihazdollarbills'}; + +var goodToken; + +var shipping = { + serviceLevelCode: 'GD', + serviceLevelName: 'Ground', + shipTo: goodAddress, + shipments: [ + { + carrier: { + code: 'USPS FC', + name: 'USPS', + description: 'USPS First-Class Mail Parcel + Delivery Confirmation', + properties: [ + 'deliveryConfirmation' + ] + }, + cost: { + currency: 'USD', + type: 'total', + name: 'Total', + amount: 3.54, + converted: false, + originalCost: 3.54, + originalCurrency: 'USD' + }, + expectedDeliveryMaxDate: '2015-09-24T23:30:00-07:00', + expectedDeliveryMinDate: '2015-09-21T23:30:00-07:00', + expectedShipDate: '2015-09-18T01:30:00-05:00', + pieces: [ + { + contents: [ + { + quantity: 1, + sku: 'M1-Island-Brush' + } + ], + height: { + amount: 0.7, + units: 'in' + }, + length: { + amount: 9.5, + units: 'in' + }, + subweights: [ + { + amount: 0.05, + type: 'packaging', + units: 'lbs' + }, + { + amount: 0, + type: 'voidFill', + units: 'lbs' + }, + { + amount: 0.1, + type: 'products', + units: 'lbs' + } + ], + weight: { + amount: 0.15, + type: 'total', + units: 'lbs' + }, + width: { + amount: 5.5, + units: 'in' + } + } + ], + subtotals: [ + { + amount: 2.79, + converted: false, + currency: 'USD', + name: 'Shipping', + originalCost: 2.79, + originalCurrency: 'USD', + type: 'shipping' + }, + { + amount: 0.75, + converted: false, + currency: 'USD', + name: 'Insurance', + originalCost: 0.75, + originalCurrency: 'USD', + type: 'insurance' + }, + { + amount: 0, + converted: false, + currency: 'USD', + name: 'Packaging', + originalCost: 0, + originalCurrency: 'USD', + type: 'packaging' + }, + { + amount: 0, + converted: false, + currency: 'USD', + name: 'Handling', + originalCost: 0, + originalCurrency: 'USD', + type: 'handling' + } + ], + warehouseName: 'Chicago' + } + ] +}; + +var description = 'TEST ' + Date.now(); + +describe('Store', function() { + + describe('Shipping Rates', function() { + + it('request shipping rate with no address', function(done) { + request(url) + .post('/api/store/shipping') + .send({ + cart: goodCart + }) + .expect(403) + .end(function(err, res) { + should(res.body.error.message).be.exactly('Address invalid'); + done(err); + }); + }); + + it('request shipping rate with invalid address', function(done) { + request(url) + .post('/api/store/shipping') + .send({ + address: invalidAddress, + cart: goodCart + }) + .expect(403) + .end(function(err, res) { + should(res.body.error.message).be.exactly('Address invalid'); + done(err); + }); + }); + + it('request shipping rate with non-existing address', function(done) { + this.timeout(5000); + request(url) + .post('/api/store/shipping') + .send({ + address: nonExistingAddress, + cart: goodCart + }) + .expect(400) + .end(function(err, res) { + should(res.body.error.message).be.exactly( + 'No shipping options found for the specified address'); + done(err); + }); + }); + + it('request shipping rate with good address', function(done) { + this.timeout(5000); + request(url) + .post('/api/store/shipping') + .send({ + address: goodAddress, + cart: goodCart + }) + .expect(200) + .end(function(err, res) { + res.body.should.have.property('shipTo'); + res.body.should.have.property('options'); + done(err); + }); + }); + + it('request shipping rate with no cart', function(done) { + request(url) + .post('/api/store/shipping') + .send({ + address: goodAddress + }) + .expect(403) + .end(function(err, res) { + should(res.body.error.message).be.exactly('Cart invalid'); + done(err); + }); + }); + + it('request shipping rate with empty cart', function(done) { + request(url) + .post('/api/store/shipping') + .send({ + address: goodAddress, + cart: {} + }) + .expect(403) + .end(function(err, res) { + should(res.body.error.message).be.exactly('Cart invalid'); + done(err); + }); + }); + + it('request shipping rate with invalid cart', function(done) { + request(url) + .post('/api/store/shipping') + .send({ + address: goodAddress, + cart: invalidCart + }) + .expect(403) + .end(function(err, res) { + should(res.body.error.message).be.exactly('Cart invalid'); + done(err); + }); + }); + + it('request shipping rate with over max product quantity cart', + function(done) { + request(url) + .post('/api/store/shipping') + .send({ + address: goodAddress, + cart: overMaxCart + }) + .expect(403) + .end(function(err, res) { + should(res.body.error.message).be.exactly( + 'OVER_MAX_PRODUCT_QUANTITY_PER_ORDER'); + done(err); + }); + }); + + it('request shipping rate with good cart', function(done) { + this.timeout(5000); + request(url) + .post('/api/store/shipping') + .send({ + address: goodAddress, + cart: goodCart + }) + .expect(200) + .end(function(err, res) { + res.body.should.have.property('shipTo'); + res.body.should.have.property('options'); + done(err); + }); + }); + + }); + + describe('Stripe.js', function() { + + it('stripe token create', function(done) { + this.timeout(5000); + stripe.tokens.create({ + card: { + number: '4242424242424242', + exp_month: 12, + exp_year: 2016, + cvc: '123' + } + }, function (err, token) { + token.should.have.property('id'); + goodToken = token; + done(err); + }); + }); + + }); + + after(function () { + + describe('Checkout', function() { + + it('checkout with no stripe token', function(done) { + request(url) + .post('/api/store/checkout') + .send({ + cart: goodCart, + shipping: shipping, + description: description + }) + .expect(403) + .end(function(err, res) { + should(res.body.error.message).be.exactly('Token invalid'); + done(err); + }); + }); + + it('checkout with no cart', function(done) { + request(url) + .post('/api/store/checkout') + .send({ + token: goodToken, + shipping: shipping, + description: description + }) + .expect(403) + .end(function(err, res) { + should(res.body.error.message).be.exactly('Cart invalid'); + done(err); + }); + }); + + it('checkout with empty cart', function(done) { + request(url) + .post('/api/store/checkout') + .send({ + token: goodToken, + cart: {}, + shipping: shipping, + description: description + }) + .expect(403) + .end(function(err, res) { + should(res.body.error.message).be.exactly('Cart invalid'); + done(err); + }); + }); + + it('checkout with no shipping', function(done) { + request(url) + .post('/api/store/checkout') + .send({ + token: goodToken, + cart: goodCart, + description: description + }) + .expect(403) + .end(function(err, res) { + should(res.body.error.message).be.exactly('Shipping invalid'); + done(err); + }); + }); + + it('checkout with no shipping address', function(done) { + var _shipping = _.clone(shipping); + delete _shipping.shipTo; + request(url) + .post('/api/store/checkout') + .send({ + token: goodToken, + cart: goodCart, + shipping: _shipping, + description: description + }) + .expect(403) + .end(function(err, res) { + should(res.body.error.message).be.exactly('Shipping invalid'); + done(err); + }); + }); + + it('checkout with no shipment', function(done) { + var _shipping = _.clone(shipping); + delete _shipping.shipments; + request(url) + .post('/api/store/checkout') + .send({ + token: goodToken, + cart: goodCart, + shipping: _shipping, + description: description + }) + .expect(403) + .end(function(err, res) { + should(res.body.error.message).be.exactly('Shipping invalid'); + done(err); + }); + }); + + it('checkout with no description', function(done) { + request(url) + .post('/api/store/checkout') + .send({ + token: goodToken, + cart: goodCart, + shipping: shipping + }) + .expect(403) + .end(function(err, res) { + should(res.body.error.message).be.exactly('Description invalid'); + done(err); + }); + }); + + it('checkout with over max product quantity cart', function(done) { + request(url) + .post('/api/store/checkout') + .send({ + token: goodToken, + cart: overMaxCart, + shipping: shipping, + description: description + }) + .expect(403) + .end(function(err, res) { + should(res.body.error.message).be.exactly( + 'OVER_MAX_PRODUCT_QUANTITY_PER_ORDER'); + done(err); + }); + }); + + it('checkout with unknown product', function(done) { + this.timeout(5000); + request(url) + .post('/api/store/checkout') + .send({ + token: goodToken, + cart: invalidCart, + shipping: shipping, + description: description + }) + .expect(403) + .end(function(err, res) { + should(res.body.error.message).be.exactly('Cart invalid'); + done(err); + }); + }); + + it('checkout with insufficient stock', function(done) { + this.timeout(5000); + request(url) + .post('/api/store/checkout') + .send({ + token: goodToken, + cart: outOfStockCart, + shipping: shipping, + description: description + }) + .expect(403) + .end(function(err, res) { + should(res.body.error.message).be.exactly('INSUFFICIENT_STOCK'); + done(err); + }); + }); + + it('checkout with invalid token', function(done) { + this.timeout(5000); + request(url) + .post('/api/store/checkout') + .send({ + token: invalidToken, + cart: goodCart, + shipping: shipping, + description: description + }) + .expect(500) + .end(function(err, res) { + should(res.body.error.message).be.exactly( + 'No such token: canihazdollarbills'); + done(err); + }); + }); + + it('checkout with valid token', function(done) { + this.timeout(15000); + request(url) + .post('/api/store/checkout') + .send({ + token: goodToken, + cart: goodCart, + shipping: shipping, + description: description + }) + .expect(200) + .end(function(err, res) { + res.body.should.have.property('orderNo'); + res.body.should.have.property('orderId'); + + shipwire.orders.cancel({id: res.body.orderId}, + function (err, data) { + should(data.status).be.exactly(200); + should(data.message).be.exactly('Order cancelled'); + done(err); + }); + }); + }); + + }); + + }); + +}); diff --git a/views/header.jade b/views/header.jade index 32c5e4f2..f3b5db63 100644 --- a/views/header.jade +++ b/views/header.jade @@ -28,6 +28,7 @@ header.header a(class="navigate", href="/crags", alt="Search for a crag.") Crags li a(class="navigate", href="/films", alt="We\'re proud to bring you professional grade content. Many thanks to everyone that has made these films happen.") Films + //- a(class="navigate", href="/store", alt="Accessories and apparel.") Store - if (typeof member === 'undefined') li a(class="navigate", href="/media", alt="Recently uploaded photos and videos.") Recent Media diff --git a/views/layout.jade b/views/layout.jade index 83082b84..a914866e 100644 --- a/views/layout.jade +++ b/views/layout.jade @@ -164,6 +164,7 @@ html(lang="en", itemscope, itemtype="http://schema.org/#{typeof schema === 'unde script(type="text/javascript", src="https://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js") script(type="text/javascript", src="https://jwpsrv.com/library/1lrC0MMbEeKOnyIACqoQEQ.js") script(src="https://cartodb-libs.global.ssl.fastly.net/cartodb.js/v3/cartodb.js") + script(src="https://checkout.stripe.com/checkout.js") - if (process.env.NODE_ENV === 'production') script(type="text/javascript", src="#{root}/js/min.js") - else