Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add non-dev time comparisons #4

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
104 changes: 103 additions & 1 deletion client/helpers.js.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ closedTicketStatuses = ['Closed', 'Delivery QA', 'Deployed', 'Review']
unless _(allBugs).isEmpty()
drawDonutChart(getGroupedData(allBugs, 'status'), 'bugs-by-status', 0.40, 283, true)

allTimeSpent = getAllTimeSpent()
unless _(allTimeSpent).isEmpty()
drawDonutChart(allTimeSpent, 'all-logged-work', 0.40, 450, true)

openBugs = getOpenBugs()
unless _(openBugs).isEmpty()
drawDonutChart(getGroupedData(openBugs, 'priority'), 'open-bugs-by-priority', 0.40, 283, true)
Expand All @@ -60,6 +64,10 @@ closedTicketStatuses = ['Closed', 'Delivery QA', 'Deployed', 'Review']
true
)

NonDevTasksTimeSpent = getNonDevTasksTimeSpent()
unless _(NonDevTasksTimeSpent).isEmpty()
drawDonutChart(NonDevTasksTimeSpent, 'non-dev-tickets', 0.40, 450, false)

@drawDonutChart = (data, domId, ratio, size, showLegend) ->
nv.addGraph ->
chart = nv.models.pieChart()
Expand All @@ -69,7 +77,7 @@ closedTicketStatuses = ['Closed', 'Delivery QA', 'Deployed', 'Review']
.height(size)
.showLabels(false)
.showLegend(showLegend)
.tooltipContent((key, y, e) -> "<h3> #{key} </h3> <p> #{Math.round(y)} </p>")
.tooltipContent((key, y, e) -> "<h3> #{key} </h3> <p> #{y} </p>")
.width(size)
.x((d) -> d.label)
.y((d) -> d.value)
Expand All @@ -90,6 +98,61 @@ closedTicketStatuses = ['Closed', 'Delivery QA', 'Deployed', 'Review']
{ fields: { 'points': 0 } }
).fetch()

@getAllTimeSpent = ->
bugsTime = 0
featureTime = 0
nonDevTime = 0
bugAddition = getAllBugs().forEach((ticket) ->
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to use reduce() for these functions - http://underscorejs.org/#reduce

workForticket = ticket.worklog.forEach((log) ->
if log.date <= getEndDate() and log.date >= getStartDate()
bugsTime += log.time
)
)
featureAddition = getFeatureTickets().forEach((ticket) ->
workForticket = ticket.worklog.forEach((log) ->
if log.date <= getEndDate() and log.date >= getStartDate()
featureTime += log.time
)
)
nonDevAddition = getNonDevTasks().forEach((ticket) ->
workForticket = ticket.worklog.forEach((log) ->
if log.date <= getEndDate() and log.date >= getStartDate()
nonDevTime += log.time
)
)
allTime =
Bugs: bugsTime
NewDevelopment: featureTime
NonDev: nonDevTime
aggregatedData = _(allTime).map((value, key) ->
label: key
value: value
)
aggregatedData

@getAllTimeSpentRecently = ->
bugsTime = 0
featureTime = 0
nonDevTime = 0
bugAddition = getAllBugs().forEach((ticket) ->
bugsTime += ticket.timespent
)
featureAddition = getFeatureTickets().forEach((ticket) ->
featureTime += ticket.timespent
)
nonDevAddition = getNonDevTasks().forEach((ticket) ->
nonDevTime += ticket.timespent
)
allTime =
Bugs: bugsTime
Features: featureTime
NonDev: nonDevTime
aggregatedData = _(allTime).map((value, key) ->
label: key
value: value
)
aggregatedData

@getClosedBugs = ->
Tickets.find(
status: $in: closedTicketStatuses
Expand Down Expand Up @@ -126,6 +189,13 @@ closedTicketStatuses = ['Closed', 'Delivery QA', 'Deployed', 'Review']
)
aggregatedData

@getEndDate = ->
settings = getSettings()
if settings.analysisEndDate
moment(settings.analysisEndDate).toDate()
else
moment().toDate()

@getEstimatedCompletionDate = ->
settings = getSettings()
unless settings is undefined
Expand All @@ -149,10 +219,35 @@ closedTicketStatuses = ['Closed', 'Delivery QA', 'Deployed', 'Review']

addWeekdaysToToday(calendarDaysRemaining)

@getFeatureTickets = ->
Tickets.find(
labels: $ne: 'ExcludeFromKanburn'
type: $ne: 'Bug'
)

@getGroupedData = (data, grouping) ->
groupedData = _(data).groupBy(grouping)
_(groupedData).map((value, key) -> { label: key, value: Math.round(value.length) })

@getNonDevTasks = ->
Tickets.find(
labels: 'ExcludeFromKanburn'
status: $nin: closedTicketStatuses
type: 'Task'
).fetch()

@getNonDevTasksTimeSpent = ->
nonDevTasksTimeSpentData = getNonDevTasks().map((value, key) ->
totalTime = 0
workForticket = value.worklog.forEach((log) ->
if log.date <= getEndDate() and log.date >= getStartDate()
totalTime += log.time
)
label: value.title
value: if totalTime? then totalTime else 0
)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't need these parens

nonDevTasksTimeSpentData
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also don't think this variable or return are needed.


@getOpenBugs = ->
Tickets.find(
status: $nin: closedTicketStatuses
Expand Down Expand Up @@ -180,6 +275,13 @@ closedTicketStatuses = ['Closed', 'Delivery QA', 'Deployed', 'Review']
{ name: 'Measures', activeClass: isActiveSquad('Measures') }
]

@getStartDate = ->
settings = getSettings()
if settings.analysisStartDate
moment(settings.analysisStartDate).toDate()
else
moment('7/20/2015').toDate()

@getTicketsOnHold = ->
Tickets.find(
title: /\bhold/i
Expand Down
9 changes: 9 additions & 0 deletions client/home.js.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,15 @@ Template.home.helpers
daysRemaining: ->
calculateDays(getOpenTicketsWithEstimates(), getOpenBugs())

endDate: ->
moment(getEndDate()).format('M/D/YY')

isLoading: ->
Session.get('loading')

nonDevTasks: ->
getNonDevTasks()

onHold: ->
getTicketsOnHold()

Expand All @@ -30,6 +36,9 @@ Template.home.helpers
releaseDate = adjustForTimezone(release.releaseDate)
estimatedCompletionDate <= releaseDate

startDate: ->
moment(getStartDate()).format('M/D/YY')

thereAreBugs: ->
not _(getAllBugs()).isEmpty()

Expand Down
8 changes: 7 additions & 1 deletion client/views/cards/ticket-list.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
{{ #unless excludePoints }}
<th>Story Points</th>
{{ /unless }}
{{ #if showLoggedTime }}
<th>Logged Time</th>
{{ /if }}
</tr>
</thead>
<tbody>
Expand All @@ -21,9 +24,12 @@
<td>{{ title }}</td>
<td>{{ priority }}</td>
<td>{{ status }}</td>
{{ #unless excludePoints }}
{{ #unless ../excludePoints }}
<td>{{ points }}</td>
{{ /unless }}
{{ #if ../showLoggedTime }}
<td>{{ timespent }}</td>
{{ /if }}
</tr>
{{ /each }}
</tbody>
Expand Down
65 changes: 54 additions & 11 deletions client/views/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,11 @@ <h3>
</div>
<div class="item">
<div class="row">
<div class="col-md-4">
<div class="col-md-6">
<div class="card">
<div id="tickets-by-points">
<div id="all-logged-work">
<div class="card-header">
Open Tickets, by Estimate (Points)
All Hours Between {{ startDate }} and {{ endDate }}
</div>
<div class="card-content">
<svg></svg>
Expand All @@ -90,20 +90,63 @@ <h3>
</div>
</div>

<div class="col-md-8">
<div class="card">
<div class="col-md-6">
<div class="card">
<div id="non-dev-tickets">
<div class="card-header">
Non-Dev Hours Between {{ startDate }} and {{ endDate }}
</div>
<div class="card-content">
<svg></svg>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="item">
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">
Non-Dev Tasks
</div>
<div class="card-content">
{{> ticketList tickets=nonDevTasks excludePoints=true showLoggedTime=true }}
</div>
</div>
</div>
</div>
</div>
<div class="item">
<div class="row">
<div class="col-md-4">
<div class="card">
<div id="tickets-by-points">
<div class="card-header">
Critical Defects
Open Tickets, by Estimate (Points)
</div>
<div class="card-content">
{{ #if thereAreCriticalBugs }}
{{> ticketList tickets=criticalBugs excludePoints=true}}
{{ else }}
<p>No critical defects</p>
{{ /if }}
<svg></svg>
</div>
</div>
</div>
</div>

<div class="col-md-8">
<div class="card">
<div class="card-header">
Critical Defects
</div>
<div class="card-content">
{{ #if thereAreCriticalBugs }}
{{> ticketList tickets=criticalBugs excludePoints=true}}
{{ else }}
<p>No critical defects</p>
{{ /if }}
</div>
</div>
</div>
</div>
</div>
{{ #if thereAreTicketsWithoutEstimates }}
Expand Down
8 changes: 8 additions & 0 deletions collections/settings.js.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,12 @@ Settings.attachSchema(new SimpleSchema(
min: 0
decimal: true
optional: false
analysisStartDate:
type: Date
label: "Start Date for Time Analysis"
optional: true
analysisEndDate:
type: Date
label: "End Date for Time Analysis"
optional: true
))
10 changes: 9 additions & 1 deletion server/publications.js.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Meteor.publish 'tickets', (selectedSquad) ->
headerValue = CryptoJS.enc.Utf8.parse("#{username}:#{password}")
authorizationHeader = "Basic #{CryptoJS.enc.Base64.stringify(headerValue)}"
baseUrl = 'https://jira.arcadiasolutions.com/rest/api/latest/search?jql='
fields = 'components,customfield_10002,issuetype,labels,priority,status,summary'
fields = 'components,customfield_10002,issuetype,labels,priority,status,summary,timespent,worklog'

apiRoute = (filterId) ->
"#{baseUrl}filter=#{filterId}&fields=#{fields}&maxResults=1000"
Expand Down Expand Up @@ -60,15 +60,23 @@ Meteor.publish 'tickets', (selectedSquad) ->
ticketsForSelectedSquad = nonBugTickets.concat(bugTickets).concat(ticketsWithoutComponents)

formattedTickets = _(ticketsForSelectedSquad).forEach (issue) ->
worklog = issue.fields.worklog.worklogs.map (worklog) ->
{
time: worklog.timeSpentSeconds/3600
date: moment(worklog.started).toDate()
}
doc =
component: if issue.fields.components[0] then issue.fields.components[0].name else ''
id: issue.key
points: issue.fields.customfield_10002 or ''
priority: issue.fields.priority.name
labels: issue.fields.labels
status: issue.fields.status.name
timespent: issue.fields.timespent/3600
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to see if we can use moment to do some nice formatting here. At the very least some rounding would be nice.

title: issue.fields.summary
type: issue.fields.issuetype.name
worklog: worklog


self.added 'tickets', Random.id(), doc

Expand Down