From e471d652e5ac37f4ea1a9929d78b720189bd2edd Mon Sep 17 00:00:00 2001 From: Matt Lott <mattlott@live.com> Date: Mon, 22 Feb 2016 12:05:29 -0800 Subject: [PATCH] Add more year long dashboard graphs --- app/templates/admin/analytics.jade | 40 ++++--- app/views/admin/AnalyticsView.coffee | 160 ++++++++++++--------------- 2 files changed, 97 insertions(+), 103 deletions(-) diff --git a/app/templates/admin/analytics.jade b/app/templates/admin/analytics.jade index afbe31362..741bc5971 100644 --- a/app/templates/admin/analytics.jade +++ b/app/templates/admin/analytics.jade @@ -8,28 +8,28 @@ block content .container-fluid .row .col-md-5.big-stat.active-classes + div.description Monthly Active Classes if activeClasses.length > 0 - div.description Monthly Active Classes div.count= activeClasses[0].groups[activeClasses[0].groups.length - 1] .col-md-5.big-stat.recurring-revenue + div.description Monthly Recurring Revenue if revenue.length > 0 - div.description Monthly Recurring Revenue div.count $#{Math.round((revenue[0].groups[revenue[0].groups.length - 1]) / 100)} .col-md-5.big-stat.classroom-active-users + div.description Classroom Monthly Active Users if activeUsers.length > 0 - var classroomBigMAU = 0; each count, event in activeUsers[0].events if event.indexOf('MAU classroom') >= 0 - classroomBigMAU += count; - div.description Classroom Monthly Active Users div.count= classroomBigMAU .col-md-5.big-stat.campaign-active-users + div.description Campaign Monthly Active Users if activeUsers.length > 0 - var campaignBigMAU = 0; each count, event in activeUsers[0].events if event.indexOf('MAU campaign') >= 0 - campaignBigMAU += count; - div.description Campaign Monthly Active Users div.count= campaignBigMAU ul.nav.nav-tabs @@ -62,7 +62,10 @@ block content .small Paid class: at least one paid student in the classroom .small Trial class: not paid, at least one trial student in classroom .small Free class: not paid, not trial - .active-classes-chart.line-chart-container + .active-classes-chart-90.line-chart-container + + h3 Active Classes 365 days + .active-classes-chart-365.line-chart-container h1#active-classes-table Active Classes table.table.table-striped.table-condensed @@ -93,7 +96,7 @@ block content h1#recurring-revenue-table Recurring Revenue table.table.table-striped.table-condensed tr - th Day + th(style='min-width:85px;') Day for group in revenueGroups th= group.replace('DRR ', 'Daily ').replace('MRR ', 'Monthly ') each entry in revenue @@ -107,10 +110,16 @@ block content .small Paid student: user.coursePrepaidID set and prepaid.properties.trialRequestID NOT set .small Trial student: user.coursePrepaidID set and prepaid.properties.trialRequestID set .small Free student: not paid, not trial - .classroom-daily-active-users-chart.line-chart-container + .classroom-daily-active-users-chart-90.line-chart-container h3#classroom-maus-graph Classroom Monthly Active Users 90 days - .classroom-monthly-active-users-chart.line-chart-container + .classroom-monthly-active-users-chart-90.line-chart-container + + h3#classroom-daus-graph Classroom Daily Active Users 365 days + .classroom-daily-active-users-chart-365.line-chart-container + + h3#classroom-maus-graph Classroom Monthly Active Users 365 days + .classroom-monthly-active-users-chart-365.line-chart-container h3#enrollments-graph Enrollments Issued and Redeemed 90 days .paid-courses-chart.line-chart-container @@ -199,13 +208,19 @@ block content td 0 .tab-pane#tab_campaign - h3#campaign-daus-graph Campaign Daily Active Users 90 days + h3 Campaign Daily Active Users 90 days .small Paid user: had monthly or yearly sub on given day .small Free user: not paid - .campaign-daily-active-users-chart.line-chart-container + .campaign-daily-active-users-chart-90.line-chart-container - h3#campaign-maus-graph Campaign Monthly Active Users 90 days - .campaign-monthly-active-users-chart.line-chart-container + h3 Campaign Monthly Active Users 90 days + .campaign-monthly-active-users-chart-90.line-chart-container + + h3 Campaign Daily Active Users 365 days + .campaign-daily-active-users-chart-365.line-chart-container + + h3 Campaign Monthly Active Users 365 days + .campaign-monthly-active-users-chart-365.line-chart-container h1#active-users-table Active Users if activeUsers.length > 0 @@ -236,7 +251,6 @@ block content .campaign-vs-classroom-monthly-active-users-recent-chart.line-chart-container h3#campaign-vs-classroom-paid-maus-graph Campaign vs Classroom Paid Monthly Active Users 365 days - .small TODO: aggregate active user data from last year .campaign-vs-classroom-monthly-active-users-chart.line-chart-container h1#active-users-table Active Users diff --git a/app/views/admin/AnalyticsView.coffee b/app/views/admin/AnalyticsView.coffee index 0ba3ba279..66a4e7111 100644 --- a/app/views/admin/AnalyticsView.coffee +++ b/app/views/admin/AnalyticsView.coffee @@ -287,11 +287,16 @@ module.exports = class AnalyticsView extends RootView visibleWidth = $('.kpi-recent-chart').width() d3Utils.createLineChart('.kpi-recent-chart', @kpiRecentChartLines, visibleWidth) d3Utils.createLineChart('.kpi-chart', @kpiChartLines, visibleWidth) - d3Utils.createLineChart('.active-classes-chart', @activeClassesChartLines, visibleWidth) - d3Utils.createLineChart('.classroom-daily-active-users-chart', @classroomDailyActiveUsersChartLines, visibleWidth) - d3Utils.createLineChart('.classroom-monthly-active-users-chart', @classroomMonthlyActiveUsersChartLines, visibleWidth) - d3Utils.createLineChart('.campaign-daily-active-users-chart', @campaignDailyActiveUsersChartLines, visibleWidth) - d3Utils.createLineChart('.campaign-monthly-active-users-chart', @campaignMonthlyActiveUsersChartLines, visibleWidth) + d3Utils.createLineChart('.active-classes-chart-90', @activeClassesChartLines90, visibleWidth) + d3Utils.createLineChart('.active-classes-chart-365', @activeClassesChartLines365, visibleWidth) + d3Utils.createLineChart('.classroom-daily-active-users-chart-90', @classroomDailyActiveUsersChartLines90, visibleWidth) + d3Utils.createLineChart('.classroom-monthly-active-users-chart-90', @classroomMonthlyActiveUsersChartLines90, visibleWidth) + d3Utils.createLineChart('.classroom-daily-active-users-chart-365', @classroomDailyActiveUsersChartLines365, visibleWidth) + d3Utils.createLineChart('.classroom-monthly-active-users-chart-365', @classroomMonthlyActiveUsersChartLines365, visibleWidth) + d3Utils.createLineChart('.campaign-daily-active-users-chart-90', @campaignDailyActiveUsersChartLines90, visibleWidth) + d3Utils.createLineChart('.campaign-monthly-active-users-chart-90', @campaignMonthlyActiveUsersChartLines90, visibleWidth) + d3Utils.createLineChart('.campaign-daily-active-users-chart-365', @campaignDailyActiveUsersChartLines365, visibleWidth) + d3Utils.createLineChart('.campaign-monthly-active-users-chart-365', @campaignMonthlyActiveUsersChartLines365, visibleWidth) d3Utils.createLineChart('.campaign-vs-classroom-monthly-active-users-recent-chart.line-chart-container', @campaignVsClassroomMonthlyActiveUsersRecentChartLines, visibleWidth) d3Utils.createLineChart('.campaign-vs-classroom-monthly-active-users-chart.line-chart-container', @campaignVsClassroomMonthlyActiveUsersChartLines, visibleWidth) d3Utils.createLineChart('.paid-courses-chart', @enrollmentsChartLines, visibleWidth) @@ -393,9 +398,9 @@ module.exports = class AnalyticsView extends RootView showYScale: true updateActiveClassesChartData: -> - @activeClassesChartLines = [] + @activeClassesChartLines90 = [] + @activeClassesChartLines365 = [] return unless @activeClasses?.length - days = d3Utils.createContiguousDays(90) groupDayMap = {} for entry in @activeClasses @@ -404,35 +409,42 @@ module.exports = class AnalyticsView extends RootView groupDayMap[@activeClassGroups[i]][entry.day] ?= 0 groupDayMap[@activeClassGroups[i]][entry.day] += count - lines = [] - colorIndex = 0 - totalMax = 0 - for group, entries of groupDayMap - data = [] - for day, count of entries - data.push - day: day - value: count - data.reverse() - points = @createLineChartPoints(days, data) - @activeClassesChartLines.push - points: points - description: group.replace('Active classes ', '') - lineColor: @lineColors[colorIndex++ % @lineColors.length] - strokeWidth: 1 - min: 0 - showYScale: group is 'Total' - totalMax = _.max(points, 'y').y if group is 'Total' - line.max = totalMax for line in @activeClassesChartLines + createActiveClassesChartLines = (lines, numDays) => + days = d3Utils.createContiguousDays(numDays) + colorIndex = 0 + totalMax = 0 + for group, entries of groupDayMap + data = [] + for day, count of entries + data.push + day: day + value: count + data.reverse() + points = @createLineChartPoints(days, data) + lines.push + points: points + description: group.replace('Active classes ', '') + lineColor: @lineColors[colorIndex++ % @lineColors.length] + strokeWidth: 1 + min: 0 + showYScale: group is 'Total' + totalMax = _.max(points, 'y').y if group is 'Total' + line.max = totalMax for line in lines + + createActiveClassesChartLines(@activeClassesChartLines90, 90) + createActiveClassesChartLines(@activeClassesChartLines365, 365) updateActiveUsersChartData: -> # Create chart lines for the active user events returned by active_users in analytics_perday_handler - @campaignDailyActiveUsersChartLines = [] - @campaignMonthlyActiveUsersChartLines = [] - @classroomDailyActiveUsersChartLines = [] - @classroomMonthlyActiveUsersChartLines = [] + @campaignDailyActiveUsersChartLines90 = [] + @campaignMonthlyActiveUsersChartLines90 = [] + @campaignDailyActiveUsersChartLines365 = [] + @campaignMonthlyActiveUsersChartLines365 = [] + @classroomDailyActiveUsersChartLines90 = [] + @classroomMonthlyActiveUsersChartLines90 = [] + @classroomDailyActiveUsersChartLines365 = [] + @classroomMonthlyActiveUsersChartLines365 = [] return unless @activeUsers?.length - days = d3Utils.createContiguousDays(90) # Separate day/value arrays by event eventDataMap = {} @@ -444,65 +456,33 @@ module.exports = class AnalyticsView extends RootView day: entry.day value: count - # Build chart lines for each event - eventLineMap = - 'DAU campaign': {max: 0, colorIndex: 0} - 'MAU campaign': {max: 0, colorIndex: 0} - 'DAU classroom': {max: 0, colorIndex: 0} - 'MAU classroom': {max: 0, colorIndex: 0} - for event, data of eventDataMap - data.reverse() - points = @createLineChartPoints(days, data) - max = _.max(points, 'y').y - if event.indexOf('DAU campaign') >= 0 - chartLines = @campaignDailyActiveUsersChartLines - eventLineMap['DAU campaign'].max = Math.max(eventLineMap['DAU campaign'].max, max) - lineColor = @lineColors[eventLineMap['DAU campaign'].colorIndex++ % @lineColors.length] - else if event.indexOf('MAU campaign') >= 0 - chartLines = @campaignMonthlyActiveUsersChartLines - eventLineMap['MAU campaign'].max = Math.max(eventLineMap['MAU campaign'].max, max) - lineColor = @lineColors[eventLineMap['MAU campaign'].colorIndex++ % @lineColors.length] - else if event.indexOf('DAU classroom') >= 0 - chartLines = @classroomDailyActiveUsersChartLines - eventLineMap['DAU classroom'].max = Math.max(eventLineMap['DAU classroom'].max, max) - lineColor = @lineColors[eventLineMap['DAU classroom'].colorIndex++ % @lineColors.length] - else if event.indexOf('MAU classroom') >= 0 - chartLines = @classroomMonthlyActiveUsersChartLines - eventLineMap['MAU classroom'].max = Math.max(eventLineMap['MAU classroom'].max, max) - lineColor = @lineColors[eventLineMap['MAU classroom'].colorIndex++ % @lineColors.length] - chartLines.push - points: points - description: event - lineColor: lineColor - strokeWidth: 1 - min: 0 - showYScale: false + createActiveUsersChartLines = (lines, numDays, eventPrefix) => + days = d3Utils.createContiguousDays(numDays) + colorIndex = 0 + lineMax = 0 + showYScale = true + for event, data of eventDataMap + continue unless event.indexOf(eventPrefix) >= 0 + points = @createLineChartPoints(days, _.cloneDeep(data).reverse()) + lineMax = Math.max(_.max(points, 'y').y, lineMax) + lines.push + points: points + description: event + lineColor: @lineColors[colorIndex++ % @lineColors.length] + strokeWidth: 1 + min: 0 + showYScale: showYScale + showYScale = false + line.max = lineMax for line in lines - # Update line Y scales and maxes - showYScaleSet = false - for line in @campaignDailyActiveUsersChartLines - line.max = eventLineMap['DAU campaign'].max - unless showYScaleSet - line.showYScale = true - showYScaleSet = true - showYScaleSet = false - for line in @campaignMonthlyActiveUsersChartLines - line.max = eventLineMap['MAU campaign'].max - unless showYScaleSet - line.showYScale = true - showYScaleSet = true - showYScaleSet = false - for line in @classroomDailyActiveUsersChartLines - line.max = eventLineMap['DAU classroom'].max - unless showYScaleSet - line.showYScale = true - showYScaleSet = true - showYScaleSet = false - for line in @classroomMonthlyActiveUsersChartLines - line.max = eventLineMap['MAU classroom'].max - unless showYScaleSet - line.showYScale = true - showYScaleSet = true + createActiveUsersChartLines(@campaignDailyActiveUsersChartLines90, 90, 'DAU campaign') + createActiveUsersChartLines(@campaignMonthlyActiveUsersChartLines90, 90, 'MAU campaign') + createActiveUsersChartLines(@classroomDailyActiveUsersChartLines90, 90, 'DAU classroom') + createActiveUsersChartLines(@classroomMonthlyActiveUsersChartLines90, 90, 'MAU classroom') + createActiveUsersChartLines(@campaignDailyActiveUsersChartLines365, 365, 'DAU campaign') + createActiveUsersChartLines(@campaignMonthlyActiveUsersChartLines365, 365, 'MAU campaign') + createActiveUsersChartLines(@classroomDailyActiveUsersChartLines365, 365, 'DAU classroom') + createActiveUsersChartLines(@classroomMonthlyActiveUsersChartLines365, 365, 'MAU classroom') updateCampaignVsClassroomActiveUsersChartData: -> @campaignVsClassroomMonthlyActiveUsersRecentChartLines = []