diff --git a/README.md b/README.md index 276767e..da62583 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ + [![Build Status](https://secure.travis-ci.org/ApiEngine/apiengine-client.png?branch=master)](http://travis-ci.org/ApiEngine/apiengine-client) @@ -17,3 +18,5 @@ When privacy is paramount we have you covered. Switch between private & public a ## PUBLIC APIs WITH GREAT POTENTIAL Build your community & start a dialogue with yo + +[http://stats.pingdom.com/wyvr99zdb86k](Pingdom Uptime) \ No newline at end of file diff --git a/build/README.md b/build/README.md new file mode 100644 index 0000000..8c1e954 --- /dev/null +++ b/build/README.md @@ -0,0 +1,14 @@ +## Build + +Some build notes will go here eventually + + + + Usage: build.js [options] + + Options: + + -h, --help output usage information + -V, --version output the version number + -e, --environment [environment] Which enviroment, development, vagrant, stage or production? Changes where assets are pulled from + -s, --server [server] Is there a custom server url for this build? (https://*) Changes what API server you use diff --git a/build/build.js b/build/build.js index cd6fe73..92735e4 100644 --- a/build/build.js +++ b/build/build.js @@ -4,26 +4,92 @@ var http = require('http-get'); var rjs = require('requirejs'); var knox = require('knox'); var glob = require("glob") +var clc = require('cli-color'); -console.log(process.argv); +// CONFIG -var cloudfront = 'https://d3oqwi49u9bqjg.cloudfront.net'; +var cloudfront_production = 'https://d50sg51l36z7c.cloudfront.net'; +var cloudfront_stage = 'https://d51ivijxlr7mx.cloudfront.net'; +var cloudfront_vagrant = 'https://vagrant-client.apiengine.io:40443'; -if(process.argv[2] === 'stage') { - var cloudfront = 'https://d51ivijxlr7mx.cloudfront.net'; +var server_production = 'https://x.apiengine.io'; +var server_staging = 'https://s.apiengine.io'; + +// Logging helpers + +var types = { + default: clc.black, + error: clc.red.bold, + warn: clc.yellow, + heading: clc.blue.bold.underline, + label: clc.blue.bold, + action: clc.xterm(8).italic +}; + +var log = function (message, _type) { + var type = _type || types.default; + console.log(type(message) + '\n'); +} + +// Start build +var program = require('commander'); + +program + .version('0.0.1') + .option('-e, --environment [environment]', 'Which enviroment, development, vagrant, stage or production? Changes where assets are pulled from', 'develop') + .option('-s, --server [server]', 'Is there a custom server url for this build? (https://*) Changes what API server you use') + .parse(process.argv); + + + +log('Api Engine Client Builder', types.heading) + +var server = null; +var cloudfront = null; + +if(program.environment === 'stage') { + cloudfront = cloudfront_stage; + log('Staging enviroment selected', types.label) + server = server_staging; + +} else if (program.environment === 'production' ) { + log('Production enviroment selected', types.label) + cloudfront = cloudfront_production; + server = server_production; + +} else if(program.environment === 'vagrant') { + var cloudfront = cloudfront_vagrant; + server = server_staging; + log('Vagrant enviroment selected', types.label) + +} else { + server = server_staging; + log('Development enviroment selected', types.label) +} + +if(program.server) { + log('Custom server url selected', types.label) + + server = program.server; } var version = Date.now(); var outputFolder = 'output/version/' + version -console.log('Building client'); +log('Starting build'); var startTime = Date.now(); +log('Create output folders', types.action); + fs.removeSync('output'); fs.mkdirSync('output'); fs.mkdirSync('output/version'); fs.mkdirSync(outputFolder); + + var rootPath = '..'; +log('Running require.js optimizer', types.action) + rjs.optimize({ dir: outputFolder + '/js', mainConfigFile: rootPath + '/js/main.js', @@ -32,8 +98,8 @@ var rootPath = '..'; paths: { 'jquery': 'empty:', 'mustache': 'empty:', - 'underscore': 'empty:', - 'addthis': 'empty:' + 'backbone': 'empty:', + 'underscore': 'empty:' }, modules: [ { @@ -61,10 +127,24 @@ var rootPath = '..'; } ] }); +log('Optimization finished', types.action) +log('Editing index.html to contain new enviroment variables', types.action) + var index = fs.readFileSync(rootPath + '/index.html', 'ascii'); -index = index.replace('css/styles.css', cloudfront + '/version/' + version + '/css/styles.css'); index = index.replace('', ''); -index = index.replace(' data-main="js/main"', ' data-main="' + cloudfront + '/version/' + version + '/js/main"'); +if(cloudfront) { + index = index.replace('css/styles.css', cloudfront + '/version/' + version + '/css/styles.css'); + index = index.replace(' data-main="js/main"', ' data-main="' + cloudfront + '/version/' + version + '/js/main"'); +} else { + index = index.replace('css/styles.css', 'version/' + version + '/css/styles.css'); + index = index.replace(' data-main="js/main"', ' data-main="version/' + version + '/js/main"'); +} + +index = index.replace('', '') + + +log('Optimization css with require.js', types.action) + fs.writeFileSync('output/index.html', index); rjs.optimize({ cssIn: rootPath + '/css/styles.css', @@ -89,6 +169,7 @@ function cssIncImages(cssFile) { fs.writeFileSync(cssFile, css, 'utf-8'); // you can overwrite the original file with this line return css; } +log('Copying accross more needed files', types.action) fs.copy(rootPath + '/googleaa49fe030680ef6c.html', 'output/googleaa49fe030680ef6c.html', function (){ fs.copy(rootPath + '/site.xml', 'output/site.xml', function (){ @@ -97,11 +178,14 @@ function cssIncImages(cssFile) { fs.copy(rootPath + '/css/img', outputFolder +'/css/img', function () { fs.copy(rootPath + '/img', outputFolder +'/img', function () { fs.copy(rootPath + '/css/fonts', outputFolder +'/css/fonts', function () { +log('Embedding images into CSS', types.action) cssIncImages(outputFolder + '/css/styles.css'); fs.copy('output', 'relic', function () { - var endTime = (Date.now() - startTime) / 1000; +log('Build finished!', types.heading) +log('Finished in ' + endTime + ' seconds', types.label) + }); }); }); diff --git a/build/package.json b/build/package.json index 95b9b4b..3ab847b 100644 --- a/build/package.json +++ b/build/package.json @@ -8,6 +8,8 @@ "knox": "~0.3.0", "http-get": "~0.4.2", "glob": "~3.1.12", - "chimney": "~0.2.0" + "chimney": "~0.2.0", + "cli-color": "~0.2.2", + "commander": "~1.1.1" } } diff --git a/index.html b/index.html index 294835b..c324741 100644 --- a/index.html +++ b/index.html @@ -1,20 +1,21 @@ - - API Engine - Great apps start with great apis - - - - + ga('create', 'UA-39509998-1', 'apiengine.io'); + ga('send', 'pageview'); + diff --git a/js/extensions.js b/js/extensions.js index a09292f..2056e7c 100644 --- a/js/extensions.js +++ b/js/extensions.js @@ -10,7 +10,21 @@ define(['jquery'], function ($) { + pad(this.getUTCSeconds()) + 'Z'; }; } - + $.fn.serializeObject = function() { + var o = {}; + var a = this.serializeArray(); + $.each(a, function() { + if (o[this.name] !== undefined) { + if (!o[this.name].push) { + o[this.name] = [o[this.name]]; + } + o[this.name].push(this.value || ''); + } else { + o[this.name] = this.value || ''; + } + }); + return o; + }; (function($) { var supportedCSS,styles=document.getElementsByTagName("head")[0].style,toCheck="transformProperty WebkitTransform OTransform msTransform MozTransform".split(" "); for (var a=0;a= 500 && res.status <= 600) { + var responseJSON = xhr.responseText; + try { + responseJSON = JSON.parse(xhr.responseText); + } catch (e) {} + + var error = new ErrorModel(); + error.save({ + "page": window.location.href, + "context": req.type + ' ' + req.url, + "code": res.status, + "error": "Internal API error", + "payload": { + sent : req.data, + received : responseJSON + } + }, {}); + } + }); + }; + return { + setup: setup + } +}) \ No newline at end of file diff --git a/js/setup/setup.js b/js/setup/setup.js new file mode 100644 index 0000000..c958eab --- /dev/null +++ b/js/setup/setup.js @@ -0,0 +1,11 @@ +define([ + 'setup/logging' +], function (Logging){ + var setup = function () { + Logging.setup(); + } + return { + setup: setup + } + +}); \ No newline at end of file diff --git a/js/views/apis/list.js b/js/views/apis/list.js index 7ac284b..40b7b0d 100644 --- a/js/views/apis/list.js +++ b/js/views/apis/list.js @@ -3,14 +3,13 @@ define([ 'underscore', 'backbone', 'mustache', - 'addthis', 'models/session', 'text!templates/apis/list.html', 'text!templates/apis/list-item.html', 'collections/apis', 'models/api', 'models/follower' -], function($, _, Backbone, Mustache, unused, Session, apisListTemplate, apisListItemTemplate, ApisCollection, ApiModel, FollowerModel){ +], function($, _, Backbone, Mustache, Session, apisListTemplate, apisListItemTemplate, ApisCollection, ApiModel, FollowerModel){ var ApisPage = Backbone.View.extend({ el: '.private-container', initialize: function () { @@ -107,10 +106,12 @@ define([ }; apis.fetch({ success: function (collection) { - that.$el.html(Mustache.render(apisListTemplate, {authed: Session.get('auth'), currentUser: that.options.currentUser, _:_, is_public: that.options.is_public, apis: collection.models, username: Session.get('login'), location: that.options.location}, {listtemplate: apisListItemTemplate})); - + that.$el.hide() + .html(Mustache.render(apisListTemplate, {authed: Session.get('auth'), currentUser: that.options.currentUser, _:_, is_public: that.options.is_public, apis: collection.models, username: Session.get('login'), location: that.options.location}, {listtemplate: apisListItemTemplate})) + .fadeIn(350); + // activate the share buttons - _.each(collection.models, function(model) { + /*_.each(collection.models, function(model) { addthis.button('#' + model.get('user') + '-' + model.get('name'), { services_compact : "facebook,twitter,digg,pinterest,email", ui_click : true @@ -118,7 +119,7 @@ define([ url: Backbone.router.getBaseUrl() + model.get('user') + '/' + model.get('name'), title: model.get('name') + ' on API Engine' }); - }); + });*/ } }); diff --git a/js/views/apis/page.js b/js/views/apis/page.js index ad9fd50..09498d4 100644 --- a/js/views/apis/page.js +++ b/js/views/apis/page.js @@ -76,6 +76,7 @@ define([ this.$el.html(Mustache.render(apiDetailsTemplate, {api: this.model, owner: Session.get('login') === this.model.get('user')})); // activate addThis share button for the API + /* addthis.button('#' + this.model.get('username') + '-' + this.model.get('apiname'), { services_compact : "facebook,twitter,digg,pinterest,email", ui_click : true @@ -83,7 +84,7 @@ define([ url: Backbone.router.getBaseUrl() + this.model.get('username') + '/' + this.model.get('apiname'), title: this.model.get('apiname') + ' on API Engine' }); - + */ // switch on active tab from router if(this.options.collaborators) { var collaboratorsView = Vm.create(this, 'apipage', CollaboratorsView, _.extend({parent : this}, this.options)); diff --git a/js/views/app.js b/js/views/app.js index 0c9cefc..d7aaca4 100644 --- a/js/views/app.js +++ b/js/views/app.js @@ -19,72 +19,14 @@ define([ var AppView = Backbone.View.extend({ el: 'body', initialize: function () { - // log all 500 error codes with the server. We may also log others - this is done in libs/form/form.js - // when no UI elements are found for handling a valid server error condition. - EventBus.on('all', function (event) { - console.log('gaaa'); - ga('send', { - hitType: 'event', - eventCategory: 'app', - eventAction: event - }) - }); - EventBus.trigger(Events.NEW_USER); - $("body").ajaxError(function(ev, res, req) { - if(res.status >= 500 && res.status <= 600) { - var responseJSON = xhr.responseText; - try { - responseJSON = JSON.parse(xhr.responseText); - } catch (e) {} - - var error = new ErrorModel(); - error.save({ - "page": window.location.href, - "context": req.type + ' ' + req.url, - "code": res.status, - "error": "Internal API error", - "payload": { - sent : req.data, - received : responseJSON - } - }, {}); - } - console.log(arguments); - }); - - // This snipper should usually be loaded elsewhere - // It simply takes a
and converts its values to an object - $.fn.serializeObject = function() { - var o = {}; - var a = this.serializeArray(); - $.each(a, function() { - if (o[this.name] !== undefined) { - if (!o[this.name].push) { - o[this.name] = [o[this.name]]; - } - o[this.name].push(this.value || ''); - } else { - o[this.name] = this.value || ''; - } - }); - return o; - }; + var that = this; - $.ajaxPrefilter( function( options, originalOptions, jqXHR ) { - // Your server goes below - if(options.url.indexOf('proxino') === -1) { - if(window.location.host === 'apiengine.io') { - options.url = 'https://x.apiengine.io' + options.url; - } else { - options.url = 'https://s.apiengine.io' + options.url; + $.ajaxPrefilter( function( options, originalOptions, jqXHR ) { + if(options.url.indexOf('proxino') === -1) { + options.url = $('[data-server-url]').attr('data-server-url') + options.url; } - //options.url = 'http://192.168.2.111:3000' + options.url; - }// else { - //options.url = 'http://d3gscmgl75g1oq.cloudfront.net' + options.url; - - // }; }); }, @@ -110,25 +52,23 @@ define([ 'hitType': 'pageview', 'page': $(this).attr('href') }); - // mixpanel.track_pageview(); Backbone.router.navigate($(this).attr('href'), true); - $(document).scrollTop(0); + //$(document).scrollTop(0); return false; } }); var notifications = new Notifications(); - var root = '/'; - if(window.location.hostname === 'localhost') { + var root = '/'; + if(window.location.hostname === 'localhost' && window.location.pathname.indexOf('relic') !== -1) { + root = '/repos/apiengine-client/build/relic'; + + } else if(window.location.hostname === 'localhost') { root = '/repos/apiengine-client/'; } Backbone.history.start({pushState: true, root: root}); }); - -//$.ajax('http://d3gscmgl75g1oq.cloudfront.net/user/thomasdavis/api/ApiEngine/1/resource/8', { - //success: function () {console.log(arguments);} -//}); }, events: { 'click .js-feedback': 'openFeedback' diff --git a/js/views/header/header.js b/js/views/header/header.js index 0b0f94e..97440b7 100644 --- a/js/views/header/header.js +++ b/js/views/header/header.js @@ -19,7 +19,7 @@ define([ }); }, render: function () { - this.$el.hide().fadeIn(250); + this.$el.hide().fadeIn(500); this.$el.html(Mustache.render(headerLayoutTemplate, {username: Session.get('login')})); var mainMenu = new MainMenuView(); mainMenu.render(); diff --git a/js/views/header/main-menu.js b/js/views/header/main-menu.js index 43df38a..6f66374 100644 --- a/js/views/header/main-menu.js +++ b/js/views/header/main-menu.js @@ -34,6 +34,14 @@ define([ $('.logo-cog').rotate({ duration:2000, animateTo:value}); }); + + $.ajaxPrefilter( function( options, originalOptions, jqXHR ) { + + value +=180; + $('.logo-cog').rotate({ duration:4000, animateTo:value}); + + }); + var accountMenu = Vm.create(this, 'accountmenu', AccountMenuView, {}); accountMenu.render(); }, diff --git a/js/views/home/register.js b/js/views/home/register.js index e419168..6e1ff5d 100644 --- a/js/views/home/register.js +++ b/js/views/home/register.js @@ -63,8 +63,7 @@ define([ return text; } - creds.login = 'beta' + makeid(); - creds.password = makeid(); + //creds.password = makeid(); user.save(creds, { success: function (data) { diff --git a/js/views/profile/page.js b/js/views/profile/page.js index 0ad1cc8..2d3a2f8 100644 --- a/js/views/profile/page.js +++ b/js/views/profile/page.js @@ -93,7 +93,9 @@ define([ if(Session.get('login') === that.options.username ) { currentUser = true; } - that.$el.html(Mustache.render(profileTemplate, {user: that.userModel, currentUser: currentUser})); + that.$el.hide() + .html(Mustache.render(profileTemplate, {user: that.userModel, currentUser: currentUser})) + .fadeIn(700); $('.timeago').timeago(); this.renderSettings(); }, diff --git a/js/views/settings/billing.js b/js/views/settings/billing.js index 787d35e..d6f000f 100644 --- a/js/views/settings/billing.js +++ b/js/views/settings/billing.js @@ -5,18 +5,42 @@ define([ 'router', 'vm', 'models/session', - 'text!templates/settings/billing.html' -], function($, _, Backbone, Router, Vm, Session, settingTemplate){ + 'text!templates/settings/billing.html', + 'models/billing/card' +], function($, _, Backbone, Router, Vm, Session, settingTemplate, Card){ var SettingPage = Backbone.View.extend({ el: '.settings-page-container', initialize: function () { }, events: { + 'submit .billing-form': 'updateCreditCard' }, render: function (options) { $('.settings-menu a').removeClass('active'); $('.settings-menu .billing').addClass('active'); this.$el.html(settingTemplate); + }, + updateCreditCard: function (ev) { + var formData = $(ev.currentTarget).serializeObject(); + var cardData = { + card_number: formData.card_number, + expiry: { + month: formData.expiry_month, + year: formData.expiry_year + }, + ccv: formData.ccv, + name: formData.name + } + var card = new Card(); + card.login = Session.get('login'); + card.save(cardData, { + success: function () { + console.log(arguments) + } + }) + + return false; + } }); return SettingPage; diff --git a/js/views/settings/page.js b/js/views/settings/page.js index a0da1cb..b6508bc 100644 --- a/js/views/settings/page.js +++ b/js/views/settings/page.js @@ -21,7 +21,10 @@ define([ render: function (options) { $('.tabs-container li').removeClass('active'); $('.tabs-container .settings').addClass('active'); - this.$el.html(_.template(pageTemplate, {user: Session.get('user')})); + if($('.settings-container').length === 0) { + + this.$el.hide().html(_.template(pageTemplate, {user: Session.get('user')})).fadeIn(350); + } switch(options.setting){ case 'profile': var profileView = new ProfileView(); diff --git a/package.json b/package.json index 77b568a..325c0d8 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "w3cjs": "0.1.6" }, "dependencies": { - "superagent": "~0.8.1" + "superagent": "~0.8.1", + "commander": "~1.1.1" } } diff --git a/templates/header/account-menu.html b/templates/header/account-menu.html index f0962b8..8643a93 100644 --- a/templates/header/account-menu.html +++ b/templates/header/account-menu.html @@ -17,9 +17,8 @@ <% } else { %> -
  • - +
  • <% }; %> diff --git a/templates/modals/register.html b/templates/modals/register.html index ed8e481..614785b 100644 --- a/templates/modals/register.html +++ b/templates/modals/register.html @@ -9,12 +9,9 @@
    - +
    - +
    YOUR SECURITY IS OUR SECURITY

    We ensure that all API Engine payment details and transactions adhere to Payment Card Industry Data Security Standards (PCI-DSS) Procedures.

    - - + + - + + + + + + +