Merge pull request #1072 from taigaio/us/4316/show-points-per-role
show points per role in milestonestable
commit
0128aee9f0
|
@ -12,6 +12,7 @@
|
|||
- Display the current user (me) at first in assignment lightbox (thanks to [@mikaoelitiana](https://github.com/mikaoelitiana))
|
||||
- Divide the user dashboard in two columns in large screens,
|
||||
- Upvote and downvote issues from the issues list.
|
||||
- Show points per role in statsection of the taskboard panel.
|
||||
- Comments:
|
||||
- Add a new permissions to allow add comments instead of use the existent modify permission for this purpose.
|
||||
- Ability to edit comments, view edition history and redesign comments module UI.
|
||||
|
|
|
@ -220,6 +220,7 @@ class TaskboardController extends mixOf(taiga.Controller, taiga.PageMixin)
|
|||
|
||||
return promise.then(=> @.loadProject())
|
||||
.then(=> @.loadTaskboard())
|
||||
.then(=> @.setRolePoints())
|
||||
|
||||
refreshTasksOrder: (tasks) ->
|
||||
items = @.resortTasks(tasks)
|
||||
|
@ -273,6 +274,33 @@ class TaskboardController extends mixOf(taiga.Controller, taiga.PageMixin)
|
|||
editTaskAssignedTo: (task) ->
|
||||
@rootscope.$broadcast("assigned-to:add", task)
|
||||
|
||||
setRolePoints: () ->
|
||||
computableRoles = _.filter(@scope.project.roles, "computable")
|
||||
|
||||
getRole = (roleId) =>
|
||||
roleId = parseInt(roleId, 10)
|
||||
return _.find computableRoles, (role) -> role.id == roleId
|
||||
|
||||
getPoint = (pointId) =>
|
||||
poitnId = parseInt(pointId, 10)
|
||||
return _.find @scope.project.points, (point) -> point.id == pointId
|
||||
|
||||
pointsByRole = _.reduce @scope.userstories, (result, us, key) =>
|
||||
_.forOwn us.points, (pointId, roleId) ->
|
||||
role = getRole(roleId)
|
||||
point = getPoint(pointId)
|
||||
|
||||
if !result[role.id]
|
||||
result[role.id] = role
|
||||
result[role.id].points = 0
|
||||
|
||||
result[role.id].points += point.value
|
||||
|
||||
return result
|
||||
, {}
|
||||
|
||||
@scope.pointsByRole = Object.keys(pointsByRole).map (key) -> return pointsByRole[key]
|
||||
|
||||
module.controller("TaskboardController", TaskboardController)
|
||||
|
||||
|
||||
|
|
|
@ -1151,7 +1151,8 @@
|
|||
"CLOSED_TASKS": "closed<br />tasks",
|
||||
"IOCAINE_DOSES": "iocaine<br />doses",
|
||||
"SHOW_STATISTICS_TITLE": "Show statistics",
|
||||
"TOGGLE_BAKLOG_GRAPH": "Show/Hide burndown graph"
|
||||
"TOGGLE_BAKLOG_GRAPH": "Show/Hide burndown graph",
|
||||
"POINTS_PER_ROLE": "Points per role"
|
||||
},
|
||||
"SUMMARY": {
|
||||
"PROJECT_POINTS": "project<br />points",
|
||||
|
|
|
@ -1,29 +1,44 @@
|
|||
div.summary.large-summary
|
||||
div.large-summary-wrapper
|
||||
div.summary-progress-wrapper
|
||||
.summary-progress-wrapper
|
||||
div.summary-progress-bar(tg-progress-bar="stats.completedPercentage")
|
||||
div.data
|
||||
span.number(ng-bind="stats.completedPercentage + '%'")
|
||||
|
||||
div.summary-stats
|
||||
.stats-wrapper(ng-class="{'show-role-points': showRolePoints}")
|
||||
.main-summary-stats
|
||||
span.summary-stats.toggle-points-per-role(ng-click="showRolePoints = true")
|
||||
tg-svg(svg-icon="icon-arrow-down")
|
||||
span.number(ng-bind="stats.totalPointsSum|default:'--'")
|
||||
span.description(translate="BACKLOG.SPRINT_SUMMARY.TOTAL_POINTS")
|
||||
div.summary-stats
|
||||
div.summary-stats.summary-completed-points
|
||||
span.number(ng-bind="stats.completedPointsSum|default:'--'")
|
||||
span.description(translate="BACKLOG.SPRINT_SUMMARY.COMPLETED_POINTS")
|
||||
|
||||
div.summary-stats
|
||||
div.summary-stats.summary-open-tasks
|
||||
tg-svg(svg-icon="icon-bulk")
|
||||
span.number(ng-bind="stats.openTasks|default:'--'")
|
||||
span.description(translate="BACKLOG.SPRINT_SUMMARY.OPEN_TASKS")
|
||||
div.summary-stats
|
||||
div.summary-stats.summary-closed-tasks
|
||||
span.number(ng-bind="stats.completed_tasks|default:'--'")
|
||||
span.description(translate="BACKLOG.SPRINT_SUMMARY.CLOSED_TASKS")
|
||||
|
||||
div.summary-stats(title="{{'COMMON.IOCAINE_TEXT' | translate}}")
|
||||
div.summary-stats.summary-iocaine(title="{{'COMMON.IOCAINE_TEXT' | translate}}")
|
||||
tg-svg(svg-icon="icon-iocaine")
|
||||
span.number(ng-bind="stats.iocaine_doses|default:'--'")
|
||||
span.description(translate="BACKLOG.SPRINT_SUMMARY.IOCAINE_DOSES")
|
||||
|
||||
.points-per-role-stats.toggle-points-per-role(
|
||||
ng-click="showRolePoints = false"
|
||||
)
|
||||
span.points-per-role-stats-title
|
||||
tg-svg(svg-icon="icon-arrow-up")
|
||||
span(translate="BACKLOG.SPRINT_SUMMARY.POINTS_PER_ROLE")
|
||||
|
||||
.points-per-role-stats-content
|
||||
.summary-stats(ng-repeat="rolePoint in pointsByRole")
|
||||
span.number {{rolePoint.points}}
|
||||
span.role {{rolePoint.name}}
|
||||
|
||||
div.stats.toggle-analytics-visibility(title="{{'BACKLOG.SPRINT_SUMMARY.SHOW_STATISTICS_TITLE' | translate}}")
|
||||
tg-svg(svg-icon="icon-graph")
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
header(tg-backlog-sprint-header, ng-model="sprint")
|
||||
|
||||
div.sprint-progress-bar(tg-progress-bar="100 * sprint.closed_points / sprint.total_points")
|
||||
.summary-progress-wrapper
|
||||
div.sprint-progress-bar(tg-progress-bar="100 * sprint.closed_points / sprint.total_points")
|
||||
|
||||
div.sprint-table(tg-bind-scope, ng-class="{'sprint-empty-wrapper': !sprint.user_stories.length}")
|
||||
div.sprint-empty(ng-if="!sprint.user_stories.length")
|
||||
|
|
|
@ -2,14 +2,18 @@ $summary-background: $grayer;
|
|||
|
||||
.summary {
|
||||
align-content: center;
|
||||
align-items: center;
|
||||
background: $summary-background;
|
||||
color: $white;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
height: 65px;
|
||||
justify-content: flex-start;
|
||||
margin-bottom: 2rem;
|
||||
padding: 1em;
|
||||
overflow: hidden;
|
||||
padding: 1rem;
|
||||
.summary-stats {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
margin: 0 .5rem;
|
||||
}
|
||||
|
@ -20,7 +24,7 @@ $summary-background: $grayer;
|
|||
}
|
||||
.number {
|
||||
@include font-size(xlarge);
|
||||
@include font-type(bold);
|
||||
@include font-type(light);
|
||||
line-height: .9;
|
||||
margin-right: .3rem;
|
||||
}
|
||||
|
@ -69,6 +73,21 @@ $summary-background: $grayer;
|
|||
transition: fill .2s;
|
||||
}
|
||||
}
|
||||
.main-summary-stats {
|
||||
display: flex;
|
||||
transform: translateY(0);
|
||||
transition: all .2s ease-in-out;
|
||||
}
|
||||
|
||||
|
||||
.show-role-points {
|
||||
.points-per-role-stats {
|
||||
transform: translateY(-35px);
|
||||
}
|
||||
.main-summary-stats {
|
||||
transform: translateY(-65px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.summary-progress-bar {
|
||||
|
@ -102,7 +121,12 @@ $summary-background: $grayer;
|
|||
}
|
||||
|
||||
.large-summary {
|
||||
align-items: stretch;
|
||||
justify-content: space-between;
|
||||
padding: .75rem 1rem;
|
||||
.stats-wrapper {
|
||||
padding-top: .35rem;
|
||||
}
|
||||
.large-summary-wrapper {
|
||||
align-content: center;
|
||||
display: flex;
|
||||
|
@ -110,6 +134,7 @@ $summary-background: $grayer;
|
|||
justify-content: flex-start;
|
||||
}
|
||||
.summary-progress-wrapper {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
.summary-progress-bar {
|
||||
|
@ -122,13 +147,23 @@ $summary-background: $grayer;
|
|||
border: 0;
|
||||
margin: 0;
|
||||
}
|
||||
&.summary-completed-points,
|
||||
&.summary-closed-tasks {
|
||||
border-right: 1px solid $blackish;
|
||||
margin-right: 0;
|
||||
padding-right: 1rem;
|
||||
+.summary-stats {
|
||||
border-left: 1px solid $gray;
|
||||
margin-left: 0;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.icon {
|
||||
@include svg-size(1.3rem);
|
||||
fill: currentColor;
|
||||
height: 1.5rem;
|
||||
margin-right: .4rem;
|
||||
vertical-align: middle;
|
||||
width: 1.5rem;
|
||||
&.icon-stats {
|
||||
color: $primary;
|
||||
float: right;
|
||||
|
@ -146,6 +181,33 @@ $summary-background: $grayer;
|
|||
}
|
||||
}
|
||||
}
|
||||
.points-per-role-stats-content {
|
||||
display: flex;
|
||||
padding-left: 1rem;
|
||||
.summary-stats {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
.toggle-points-per-role {
|
||||
color: $white;
|
||||
cursor: pointer;
|
||||
svg {
|
||||
@include svg-size();
|
||||
}
|
||||
}
|
||||
.points-per-role-stats {
|
||||
margin-left: .5rem;
|
||||
transform: translateY(35px);
|
||||
transition: all .2s ease-in-out;
|
||||
.number {
|
||||
@include font-size(large);
|
||||
@include font-type(normal);
|
||||
}
|
||||
.role {
|
||||
@include font-size(xsmall);
|
||||
@include font-type(light);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.empty-burndown {
|
||||
|
|
Loading…
Reference in New Issue