From a645f2d16e9b920856bb4b6c1e2a3928ff3e8418 Mon Sep 17 00:00:00 2001 From: Cyril Fluck Date: Thu, 19 Sep 2013 22:07:37 -0700 Subject: [PATCH] Use Conductor Analytics card --- app/initializers/conductor_analytics.js | 32 + app/initializers/conductor_services.js | 2 + app/main.js | 2 + app/views/footer.js | 2 +- public/index.html | 7 +- stylesheets/_footer.scss | 7 +- test/index.html | 1 + vendor/analytics.js | 189 ------ vendor/conductor-analytics/card.js | 575 ++++++++++++++++++ .../conductor-analytics-bootstrap.js | 47 ++ .../conductor-analytics.css | 66 ++ vendor/conductor-analytics/ember-data.js | 1 + vendor/conductor-analytics/ember.js | 1 + vendor/conductor-analytics/handlebars.js | 1 + vendor/conductor-analytics/jquery.js | 1 + vendor/conductor/conductor.amd.js | 2 +- 16 files changed, 739 insertions(+), 197 deletions(-) create mode 100644 app/initializers/conductor_analytics.js delete mode 100644 vendor/analytics.js create mode 100644 vendor/conductor-analytics/card.js create mode 100644 vendor/conductor-analytics/conductor-analytics-bootstrap.js create mode 100644 vendor/conductor-analytics/conductor-analytics.css create mode 120000 vendor/conductor-analytics/ember-data.js create mode 120000 vendor/conductor-analytics/ember.js create mode 120000 vendor/conductor-analytics/handlebars.js create mode 120000 vendor/conductor-analytics/jquery.js diff --git a/app/initializers/conductor_analytics.js b/app/initializers/conductor_analytics.js new file mode 100644 index 0000000..e3f3562 --- /dev/null +++ b/app/initializers/conductor_analytics.js @@ -0,0 +1,32 @@ +import analyticsCardBootstrap from "conductor/analytics/bootstrap"; + +var analyticsCard; + +var initializer = { + name: 'conductorAnalytics', + before: 'conductorServices', + + initialize: function (container, application) { + var sk = window.StarterKit; + + if(sk) { + sk.wiretapCard = function(card) { + analyticsCard.track( card ); + }; + + sk.initializeAnalytics = function(conductor) { + analyticsCard = analyticsCardBootstrap.initializeConductorAnalytics( + conductor, + '/vendor/conductor-analytics/card.js' + ); + }; + + sk.insertAnalytics = function($analytics) { + analyticsCard.appendTo( $analytics ); + analyticsCard.render(); + }; + } + } +}; + +export default initializer; diff --git a/app/initializers/conductor_services.js b/app/initializers/conductor_services.js index 77ceb84..be5187a 100644 --- a/app/initializers/conductor_services.js +++ b/app/initializers/conductor_services.js @@ -27,6 +27,8 @@ var initializer = { conductor.removeDefaultCapability('height'); application.register('conductor:main', conductor, { instantiate: false }); + if( window.StarterKit ) window.StarterKit.initializeAnalytics(conductor); + Ember.keys(requirejs._eak_seen).forEach(function (moduleName) { var match = /^glazier\/services\/(.+)/.exec(moduleName); diff --git a/app/main.js b/app/main.js index 48c7f02..d338430 100644 --- a/app/main.js +++ b/app/main.js @@ -8,6 +8,7 @@ import Dashboard from 'glazier/models/dashboard'; import PaneView from 'glazier/views/pane'; import conductorServicesInitializer from 'glazier/initializers/conductor_services'; +import conductorAnalyticsInitializer from 'glazier/initializers/conductor_analytics'; import injectionsInitializer from 'glazier/initializers/injections'; if (requirejs._eak_seen.ziniki) { @@ -49,6 +50,7 @@ Glazier.PaneView = PaneView; Glazier.env = (/github\.glazier\.io/.test(window.location.hostname)) ? 'prod' : 'dev'; Application.initializer(injectionsInitializer); +Application.initializer(conductorAnalyticsInitializer); Application.initializer(conductorServicesInitializer); Ember.RSVP.configure('onerror', function(error) { diff --git a/app/views/footer.js b/app/views/footer.js index 16bd5a1..cbc09c2 100644 --- a/app/views/footer.js +++ b/app/views/footer.js @@ -2,7 +2,7 @@ var FooterView = Ember.View.extend({ elementId: "footer", classNameBindings: ['controller.isDrawerOpen'], didInsertElement: function() { - StarterKit.initializeAnalytics(this.$('.analytics')); + if( window.StarterKit ) StarterKit.insertAnalytics(this.$('.analytics .output')[0]); } }); diff --git a/public/index.html b/public/index.html index adefccf..3da77c8 100644 --- a/public/index.html +++ b/public/index.html @@ -14,6 +14,7 @@ + - - - diff --git a/stylesheets/_footer.scss b/stylesheets/_footer.scss index 329541f..cec045d 100644 --- a/stylesheets/_footer.scss +++ b/stylesheets/_footer.scss @@ -113,6 +113,11 @@ background-color: rgba(0,0,0,0.8); } + .analytics, + .output { + height: inherit; + } + &.is-drawer-open { bottom:0; } @@ -155,4 +160,4 @@ color: #333; } } -} \ No newline at end of file +} diff --git a/test/index.html b/test/index.html index bcac558..c2777f2 100644 --- a/test/index.html +++ b/test/index.html @@ -17,6 +17,7 @@ + diff --git a/vendor/analytics.js b/vendor/analytics.js deleted file mode 100644 index 1444638..0000000 --- a/vendor/analytics.js +++ /dev/null @@ -1,189 +0,0 @@ -/*global StarterKit*/ - -(function() { - "use strict"; - - addStringExtensions(); - - function addStringExtensions() { - var stringProto = String.prototype; - - function fmt(str, formats) { - // first, replace any ORDERED replacements. - var idx = 0; // the current index for non-numerical replacements - return str.replace(/%@([0-9]+)?/g, function(s, argIndex) { - argIndex = (argIndex) ? parseInt(argIndex,0) - 1 : idx++ ; - s = formats[argIndex]; - return ((s === null) ? '(null)' : (s === undefined) ? '' : s).toString(); - }) ; - } - - stringProto.fmt = function() { - return fmt(this, arguments); - }; - - function extend(prop, getter) { - Object.defineProperty(stringProto, prop, { - get: getter - }); - } - - extend('p', function() { - return '

'+this+'

'; - }); - - extend('bold', function() { - return ''+this+''; - }); - - var colors = { - red: '#a00', - green: '#0a0', - blue: '#4866ff', - yellow: '#aa0', - teal: '#0aa', - magenta: '#a0a', - lightGrey: '#aaa', - veryLightGrey: '#666' - }; - - Object.keys(colors).forEach(function(color) { - extend(color, function() { - return ""+this+""; - }); - }); - } -})(); - -(function() { - "use strict"; - - // Add analytics functionality to the - // Starter Kit - $.extend(StarterKit, { - - wiretapCard: function(card) { - card.wiretap(this.printWiretapEvent, this); - }, - - initializeAnalytics: function($analytics) { - $analytics.find('.tab').on('click', function() { - $analytics.toggleClass('showing'); - }); - - this.$analytics = $analytics; - - this.print("✔ Analytics monitoring active".green); - this.print(""); - this.print("%@ %@ %@ %@".fmt(padLeft("Service", 11).blue.bold, "↔".teal.bold, pad("Event", 14).magenta.bold, "Data".lightGrey.bold)); - this.print(""); - }, - - printWiretapEvent: function(service, event) { - if (service === "nestedWiretapping") { - this.printNestedWiretapEvent(service, event); - } else { - this.printNonNestedWiretapEvent(service, event); - } - }, - - printNonNestedWiretapEvent: function(service, event) { - var direction = (event.direction === "sent" ? "→" : "←"); - var data = JSON.stringify(event.data) || ""; - - this.print("%@ %@ %@ %@".fmt(padLeft(service, 11).blue, direction.teal, pad(event.type, 14).magenta, htmlEscape(data).lightGrey)); - }, - - printNestedWiretapEvent: function (service, event) { - var i, data, dataStr, direction; - - for(i = 1, data = event.data; - data.service === "nestedWiretapping"; - data = data.data, ++i); - - direction = (data.direction === "sent" ? "→" : "←"); - this.print("%@ %@ %@ %@ %@ %@".fmt( - padLeft(i + "/" + data.service, 11).blue, - direction.teal, - pad(event.type, 14).magenta, - data.url.veryLightGrey, - data.id.veryLightGrey)); - - if (data.data) { - dataStr = JSON.stringify(data.data); - this.print("%@ %@".fmt(padLeft("", 28).lightGrey, htmlEscape(dataStr).lightGrey)); - } - }, - - print: function(string) { - var $output = this.$analytics.find('.output'), - atBottom; - - // Determine if the output is scrolled to the bottom, - // or if the user has scrolled up to see older log - // messages. We only want to auto-scroll if it won't - // disrupt the user. - atBottom = ($output.scrollTop() === ($output[0].scrollHeight - $output.height())); - - // Append the new message - $output.append("

%@%@

".fmt(timestamp().yellow, string)); - - if (atBottom) { - // Scroll the div to show the new message - $output.scrollTop($output[0].scrollHeight); - } - } - }); - - // Pad a string with spaces to a maximum length. - // For example, calling pad("foo", 5) would return - // "foo " (the original string plus two spaces to - // bring it to five characters). - function pad(string, max) { - while (string.length < max) { - string = string+" "; - } - - return string; - } - - // Pad a string with spaces, but prepend the necessary - // spaces instead of appending them. - function padLeft(string, max) { - while (string.length < max) { - string = " "+string; - } - - return string; - } - - // Pad a single-digit number with a zero, if necessary. - // zeroPad(3) => "03" - // zeroPad(10) => "10" - function zeroPad(number) { - number = number+''; - if (number.length === 1) { - return "0"+number; - } - return number; - } - - // Returns a new human-readable timestamp for the current time. - // timestamp() => "2013-03-14 10:55" - function timestamp() { - var date = new Date(), - year = date.getFullYear(), - month = zeroPad(date.getMonth()+1), - day = zeroPad(date.getDate()), - hour = zeroPad(date.getHours()), - minute = zeroPad(date.getMinutes()); - - return "%@-%@-%@ %@:%@ ".fmt(year, month, day, hour, minute); - } - - function htmlEscape(str) { - return str.replace(/ "03" + // zeroPad(10) => "10" + function zeroPad(number) { + number = number+''; + if (number.length === 1) { + return "0"+number; + } + return number; + } + + var Event = DS.Model.extend({ + eventType: DS.belongsTo('eventType'), + card: DS.belongsTo('card'), + direction: DS.attr(), + data: DS.attr(), + time: DS.attr('date'), + + formattedTime: function() { + var date = this.get('time'), + year = date.getFullYear(), + month = zeroPad(date.getMonth()+1), + day = zeroPad(date.getDate()), + hour = zeroPad(date.getHours()), + minute = zeroPad(date.getMinutes()); + + return "%@-%@-%@ %@:%@ ".fmt(year, month, day, hour, minute); + }.property('time') + }); + + + return Event; + }); +define("conductor/analytics/card/models/event_type", + [], + function() { + "use strict"; + var EventType = DS.Model.extend({ + isVisible: DS.attr('boolean', true), + service: DS.belongsTo('service'), + events: DS.hasMany('event') + }); + + + return EventType; + }); +define("conductor/analytics/card/models/service", + [], + function() { + "use strict"; + var Service = DS.Model.extend({ + isVisible: DS.attr('boolean', true), + eventTypes: DS.hasMany('eventType') + }); + + + return Service; + }); +define("conductor/analytics/card/routes/events", + [], + function() { + "use strict"; + var EventsRoute = Ember.Route.extend({ + model: function() { + return this.store.filter('event', function(event) { + var eventType = event.get('eventType'); + + return eventType.get('isVisible') && eventType.get('service.isVisible') && event.get('card.isVisible'); + }); + }, + + actions: { + switchRoutes: function() { + this.transitionTo('filters'); + } + } + }); + + + return EventsRoute; + }); +define("conductor/analytics/card/routes/filters", + [], + function() { + "use strict"; + var FiltersRoute = Ember.Route.extend({ + setupController: function() { + this.controllerFor('services').set('model', this.store.all('service') ); + this.controllerFor('cards').set('model', this.store.all('card') ); + }, + + renderTemplate: function() { + this.render(); + + this.render('services', { + into: 'filters', + outlet: 'services', + controller: 'services' + }); + + this.render('cards', { + into: 'filters', + outlet: 'cards', + controller: 'cards' + }); + }, + + actions: { + switchRoutes: function() { + this.transitionTo('events'); + } + } + }); + + + return FiltersRoute; + }); +define("conductor/analytics/card/routes/index", + [], + function() { + "use strict"; + var IndexRoute = Ember.Route.extend({ + redirect: function() { + this.transitionTo('events'); + } + }); + + + return IndexRoute; + }); +define("conductor/analytics/card/views/event", + [], + function() { + "use strict"; + var EventView = Ember.View.extend({ + templateName: 'event', + tagName: 'tr', + classNames: ['event'], + + eventData: function() { + return this.get('content.data').slice(0, 100); + }.property('content.data'), + + direction: function() { + return (this.get('content.direction') === "sent" ? "→" : "←"); + }.property('content.direction') + }); + + + return EventView; + }); +define("conductor/analytics/card/views/events", + ["conductor/analytics/card/views/event"], + function(EventView) { + "use strict"; + /*global $ */ + + var EventsView = Ember.CollectionView.extend({ + tagName: 'tbody', + itemViewClass: EventView, + autoScroll: true, + + arrayWillChange: function() { + var $body = $('body'), //TODO: this should not be here + atBottom = ($body.scrollTop() === ($body[0].scrollHeight - $body.height())); + + this.set('autoScroll', atBottom); + + this._super.apply(this, arguments); + }, + + arrayDidChange: function() { + Ember.run.scheduleOnce( + 'afterRender', + this, + 'resetScroll' + ); + + this._super.apply(this, arguments); + }, + + resetScroll: function (scrollHeight) { + var $body; //TODO: this should not be here + + if( this.get('autoScroll') ) { + $body = $('body'); + + $('body').scrollTop( $body[0].scrollHeight ); + } + } + }); + + + return EventsView; + }); +define("conductor/analytics/card/templates", + [], + function() { + "use strict"; + Ember.TEMPLATES["application"] = Ember.Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) { + this.compilerInfo = [4,'>= 1.0.0']; + helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {}; + var buffer = '', hashContexts, hashTypes, escapeExpression=this.escapeExpression; + + + data.buffer.push("
\n Filters\n
\n\n"); + hashTypes = {}; + hashContexts = {}; + data.buffer.push(escapeExpression(helpers._triageMustache.call(depth0, "outlet", {hash:{},contexts:[depth0],types:["ID"],hashContexts:hashContexts,hashTypes:hashTypes,data:data}))); + data.buffer.push("\n"); + return buffer; + + }); + + Ember.TEMPLATES["cards"] = Ember.Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) { + this.compilerInfo = [4,'>= 1.0.0']; + helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {}; + var buffer = '', stack1, hashTypes, hashContexts, helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, self=this; + + function program1(depth0,data) { + + var buffer = '', stack1, hashContexts, hashTypes, options; + data.buffer.push("\n \n "); + hashContexts = {'type': depth0,'name': depth0,'checked': depth0}; + hashTypes = {'type': "STRING",'name': "ID",'checked': "ID"}; + options = {hash:{ + 'type': ("checkbox"), + 'name': ("card.id"), + 'checked': ("card.isVisible") + },contexts:[],types:[],hashContexts:hashContexts,hashTypes:hashTypes,data:data}; + data.buffer.push(escapeExpression(((stack1 = helpers.input || depth0.input),stack1 ? stack1.call(depth0, options) : helperMissing.call(depth0, "input", options)))); + data.buffer.push("\n "); + hashTypes = {}; + hashContexts = {}; + data.buffer.push(escapeExpression(helpers._triageMustache.call(depth0, "card.id", {hash:{},contexts:[depth0],types:["ID"],hashContexts:hashContexts,hashTypes:hashTypes,data:data}))); + data.buffer.push("\n \n "); + return buffer; + } + + data.buffer.push("\n \n \n \n \n \n \n "); + hashTypes = {}; + hashContexts = {}; + stack1 = helpers.each.call(depth0, "card", "in", "controller", {hash:{},inverse:self.noop,fn:self.program(1, program1, data),contexts:[depth0,depth0,depth0],types:["ID","ID","ID"],hashContexts:hashContexts,hashTypes:hashTypes,data:data}); + if(stack1 || stack1 === 0) { data.buffer.push(stack1); } + data.buffer.push("\n \n
Card
\n"); + return buffer; + + }); + + Ember.TEMPLATES["event"] = Ember.Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) { + this.compilerInfo = [4,'>= 1.0.0']; + helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {}; + var buffer = '', hashTypes, hashContexts, escapeExpression=this.escapeExpression; + + + data.buffer.push(""); + hashTypes = {}; + hashContexts = {}; + data.buffer.push(escapeExpression(helpers._triageMustache.call(depth0, "view.content.formattedTime", {hash:{},contexts:[depth0],types:["ID"],hashContexts:hashContexts,hashTypes:hashTypes,data:data}))); + data.buffer.push("\n"); + hashTypes = {}; + hashContexts = {}; + data.buffer.push(escapeExpression(helpers._triageMustache.call(depth0, "view.content.eventType.service.id", {hash:{},contexts:[depth0],types:["ID"],hashContexts:hashContexts,hashTypes:hashTypes,data:data}))); + data.buffer.push("\n"); + hashTypes = {}; + hashContexts = {}; + data.buffer.push(escapeExpression(helpers._triageMustache.call(depth0, "view.direction", {hash:{},contexts:[depth0],types:["ID"],hashContexts:hashContexts,hashTypes:hashTypes,data:data}))); + data.buffer.push("\n"); + hashTypes = {}; + hashContexts = {}; + data.buffer.push(escapeExpression(helpers._triageMustache.call(depth0, "view.content.eventType.id", {hash:{},contexts:[depth0],types:["ID"],hashContexts:hashContexts,hashTypes:hashTypes,data:data}))); + data.buffer.push("\n"); + hashTypes = {}; + hashContexts = {}; + data.buffer.push(escapeExpression(helpers._triageMustache.call(depth0, "view.eventData", {hash:{},contexts:[depth0],types:["ID"],hashContexts:hashContexts,hashTypes:hashTypes,data:data}))); + data.buffer.push("\n"); + return buffer; + + }); + + Ember.TEMPLATES["events"] = Ember.Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) { + this.compilerInfo = [4,'>= 1.0.0']; + helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {}; + var buffer = '', stack1, hashContexts, hashTypes, options, helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; + + + data.buffer.push("
\n \n \n \n \n \n \n \n \n \n \n "); + hashContexts = {'contentBinding': depth0}; + hashTypes = {'contentBinding': "STRING"}; + options = {hash:{ + 'contentBinding': ("controller") + },contexts:[depth0],types:["ID"],hashContexts:hashContexts,hashTypes:hashTypes,data:data}; + data.buffer.push(escapeExpression(((stack1 = helpers.collection || depth0.collection),stack1 ? stack1.call(depth0, "App.EventsIndexView", options) : helperMissing.call(depth0, "collection", "App.EventsIndexView", options)))); + data.buffer.push("\n
TimeServiceEventData
\n
\n"); + return buffer; + + }); + + Ember.TEMPLATES["filters"] = Ember.Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) { + this.compilerInfo = [4,'>= 1.0.0']; + helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {}; + var buffer = '', stack1, hashTypes, hashContexts, options, helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; + + + data.buffer.push("
\n
\n "); + hashTypes = {}; + hashContexts = {}; + options = {hash:{},contexts:[depth0],types:["STRING"],hashContexts:hashContexts,hashTypes:hashTypes,data:data}; + data.buffer.push(escapeExpression(((stack1 = helpers.outlet || depth0.outlet),stack1 ? stack1.call(depth0, "services", options) : helperMissing.call(depth0, "outlet", "services", options)))); + data.buffer.push("\n
\n\n
\n "); + hashTypes = {}; + hashContexts = {}; + options = {hash:{},contexts:[depth0],types:["STRING"],hashContexts:hashContexts,hashTypes:hashTypes,data:data}; + data.buffer.push(escapeExpression(((stack1 = helpers.outlet || depth0.outlet),stack1 ? stack1.call(depth0, "cards", options) : helperMissing.call(depth0, "outlet", "cards", options)))); + data.buffer.push("\n
\n
\n"); + return buffer; + + }); + + Ember.TEMPLATES["services"] = Ember.Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) { + this.compilerInfo = [4,'>= 1.0.0']; + helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {}; + var buffer = '', stack1, hashTypes, hashContexts, helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, self=this; + + function program1(depth0,data) { + + var buffer = '', stack1, stack2, hashContexts, hashTypes, options; + data.buffer.push("\n \n "); + hashContexts = {'type': depth0,'name': depth0,'checked': depth0}; + hashTypes = {'type': "STRING",'name': "ID",'checked': "ID"}; + options = {hash:{ + 'type': ("checkbox"), + 'name': ("service.id"), + 'checked': ("service.isVisible") + },contexts:[],types:[],hashContexts:hashContexts,hashTypes:hashTypes,data:data}; + data.buffer.push(escapeExpression(((stack1 = helpers.input || depth0.input),stack1 ? stack1.call(depth0, options) : helperMissing.call(depth0, "input", options)))); + data.buffer.push("\n "); + hashTypes = {}; + hashContexts = {}; + data.buffer.push(escapeExpression(helpers._triageMustache.call(depth0, "service.id", {hash:{},contexts:[depth0],types:["ID"],hashContexts:hashContexts,hashTypes:hashTypes,data:data}))); + data.buffer.push("\n \n \n "); + hashTypes = {}; + hashContexts = {}; + stack2 = helpers.each.call(depth0, "eventType", "in", "service.eventTypes", {hash:{},inverse:self.noop,fn:self.program(2, program2, data),contexts:[depth0,depth0,depth0],types:["ID","ID","ID"],hashContexts:hashContexts,hashTypes:hashTypes,data:data}); + if(stack2 || stack2 === 0) { data.buffer.push(stack2); } + data.buffer.push("\n
\n \n \n "); + return buffer; + } + function program2(depth0,data) { + + var buffer = '', stack1, hashContexts, hashTypes, options; + data.buffer.push("\n \n "); + hashContexts = {'type': depth0,'name': depth0,'checked': depth0}; + hashTypes = {'type': "STRING",'name': "ID",'checked': "ID"}; + options = {hash:{ + 'type': ("checkbox"), + 'name': ("eventType.id"), + 'checked': ("eventType.isVisible") + },contexts:[],types:[],hashContexts:hashContexts,hashTypes:hashTypes,data:data}; + data.buffer.push(escapeExpression(((stack1 = helpers.input || depth0.input),stack1 ? stack1.call(depth0, options) : helperMissing.call(depth0, "input", options)))); + data.buffer.push("\n "); + hashTypes = {}; + hashContexts = {}; + data.buffer.push(escapeExpression(helpers._triageMustache.call(depth0, "eventType.id", {hash:{},contexts:[depth0],types:["ID"],hashContexts:hashContexts,hashTypes:hashTypes,data:data}))); + data.buffer.push("\n \n "); + return buffer; + } + + data.buffer.push("\n \n \n \n \n \n \n \n "); + hashTypes = {}; + hashContexts = {}; + stack1 = helpers.each.call(depth0, "service", "in", "controller", {hash:{},inverse:self.noop,fn:self.program(1, program1, data),contexts:[depth0,depth0,depth0],types:["ID","ID","ID"],hashContexts:hashContexts,hashTypes:hashTypes,data:data}); + if(stack1 || stack1 === 0) { data.buffer.push(stack1); } + data.buffer.push("\n \n
Service Event Type
\n"); + return buffer; + + }); + }); +/*global Conductor, oasis */ + +Conductor.require('jquery.js'); +Conductor.require('handlebars.js'); +Conductor.require('ember.js'); +Conductor.require('ember-data.js'); +Conductor.requireCSS('conductor-analytics.css'); + +var RSVP = Conductor.Oasis.RSVP; + +Conductor.card( { + App: null, + + initializeDOM: function () { + var analyticsDiv = document.createElement('div'); + analyticsDiv.setAttribute('id', 'analytics'); + document.body.appendChild( analyticsDiv ); + this.App.advanceReadiness(); + }, + + activate: function() { + var heightConsumer = this.consumers.height; + + if( heightConsumer ) { + heightConsumer.autoUpdate = false; + } + + oasis.configure('eventCallback', Ember.run); + this.App = require('conductor/analytics/card/application'); + }, + + consumers: { + analytics: Conductor.Oasis.Consumer.extend({ + events: { + printWiretapEvent: function(data) { + var card = this.card, + service = data.service, + event = data.event, + cardId = data.card, + time = data.time; + + card.waitForActivation().then( function() { + card.App.then( function() { + card.App.createEvent(time, service, event, cardId); + }).fail(RSVP.rethrow); + }).fail(RSVP.rethrow); + } + } + }) + } +} ); diff --git a/vendor/conductor-analytics/conductor-analytics-bootstrap.js b/vendor/conductor-analytics/conductor-analytics-bootstrap.js new file mode 100644 index 0000000..41d612a --- /dev/null +++ b/vendor/conductor-analytics/conductor-analytics-bootstrap.js @@ -0,0 +1,47 @@ +define("conductor/analytics/bootstrap", + ["exports"], + function(__exports__) { + "use strict"; + function initializeAnalyticsTab() { + var $analytics = $('.analytics'); + + $analytics.find('.tab').on('click', function() { + $analytics.toggleClass('showing'); + }); + } + + function initializeConductorAnalytics( conductor, card_path ) { + var analyticsCard = conductor.load(card_path, 1, { + capabilities: ['analytics'], + services: { + analytics: Conductor.Oasis.Service + } + }); + + var printWiretapEvent = function( service, messageEvent ) { + var timestamp = new Date(), + cardName = this.sandbox.name(); + + analyticsCard.waitForLoad().then( function() { + analyticsCard.sandbox.capabilities.analytics.send( + 'printWiretapEvent', + { + service: service, + event: messageEvent, + card: cardName, + time: timestamp + } + ); + }, Conductor.Oasis.RSVP.rethrow); + }; + + analyticsCard.track = function(card) { + card.wiretap( printWiretapEvent, card ); + }; + + return analyticsCard; + } + + __exports__.initializeAnalyticsTab = initializeAnalyticsTab; + __exports__.initializeConductorAnalytics = initializeConductorAnalytics; + }); \ No newline at end of file diff --git a/vendor/conductor-analytics/conductor-analytics.css b/vendor/conductor-analytics/conductor-analytics.css new file mode 100644 index 0000000..bc2a1df --- /dev/null +++ b/vendor/conductor-analytics/conductor-analytics.css @@ -0,0 +1,66 @@ +#analytics { + height: 240px; + background-color: black; +} + +#events { + overflow-y: hidden; + overflow-x: auto; +} + +.time { + color: #aa0; + white-space: nowrap; + min-width: 120px; +} + +.service { + text-align: right; + color: #4866ff; + min-width: 60px; + vertical-align: top; +} + +.direction { + text-align: center; + color: #0aa; + min-width: 20px; +} + +.event { + text-align: left; + color: #a0a; + min-width: 100px; +} + +.data { + text-align: left; + color: #aaa; + white-space: nowrap; +} + +.menu { + position: fixed; + top: 0px; + right: 20px; + margin: 5px; + width: 70px; + color: red; + background-color: black; + text-align: center; +} + +/* This shouldn't be needed if href=true would work */ +.menu a { + text-decoration: underline; + cursor: pointer; +} + +.filter { + display: inline-block; + vertical-align: top; +} + +.filter table { + color: white; +} diff --git a/vendor/conductor-analytics/ember-data.js b/vendor/conductor-analytics/ember-data.js new file mode 120000 index 0000000..eb6d454 --- /dev/null +++ b/vendor/conductor-analytics/ember-data.js @@ -0,0 +1 @@ +../ember-data-latest.js \ No newline at end of file diff --git a/vendor/conductor-analytics/ember.js b/vendor/conductor-analytics/ember.js new file mode 120000 index 0000000..1d90a1c --- /dev/null +++ b/vendor/conductor-analytics/ember.js @@ -0,0 +1 @@ +../ember-latest.js \ No newline at end of file diff --git a/vendor/conductor-analytics/handlebars.js b/vendor/conductor-analytics/handlebars.js new file mode 120000 index 0000000..c3ccad1 --- /dev/null +++ b/vendor/conductor-analytics/handlebars.js @@ -0,0 +1 @@ +../handlebars.js \ No newline at end of file diff --git a/vendor/conductor-analytics/jquery.js b/vendor/conductor-analytics/jquery.js new file mode 120000 index 0000000..9014be5 --- /dev/null +++ b/vendor/conductor-analytics/jquery.js @@ -0,0 +1 @@ +../jquery.js \ No newline at end of file diff --git a/vendor/conductor/conductor.amd.js b/vendor/conductor/conductor.amd.js index cfd78be..fefdbec 100644 --- a/vendor/conductor/conductor.amd.js +++ b/vendor/conductor/conductor.amd.js @@ -1403,4 +1403,4 @@ define("conductor/xhr_service", return XhrService; - }); \ No newline at end of file + });