Skip to content

Commit 67610c2

Browse files
author
Suvajit Gupta
committed
Refactored statistics to use Sai
1 parent 354235a commit 67610c2

12 files changed

+351
-202
lines changed

Buildfile

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
config :scui, :required => [:foundation, :calendar, :dashboard, :drawing, :linkit]
22
config :'core-tasks', :required => [:sproutcore, :scuds, :'scuds/local']
3-
config :tasks, :required => [:'core-tasks', :sproutcore, :scui],:title=>"Tasks:Dev"
4-
# config :tasks, :required => [:'core-tasks', :sproutcore, :scui],:title=>"Tasks:Demo"
5-
# config :tasks, :required => [:'core-tasks', :sproutcore, :scui],:title=>"Tasks:SproutCore"
6-
# config :tasks, :required => [:'core-tasks', :sproutcore, :scui],:title=>"Tasks:Greenhouse"
7-
# config :tasks, :required => [:'core-tasks', :sproutcore, :scui],:title=>"Tasks:TPG"
8-
# config :tasks, :required => [:'core-tasks', :sproutcore, :scui],:title=>"Todos:Eloqua"
3+
config :tasks, :required => [:'core-tasks', :sproutcore, :scui, :sai, :'sai/graphs'],:title=>"Tasks:Dev"
4+
# config :tasks, :required => [:'core-tasks', :sproutcore, :scui, :sai, :'sai/graphs'],:title=>"Tasks:Demo"
5+
# config :tasks, :required => [:'core-tasks', :sproutcore, :scui, :sai, :'sai/graphs'],:title=>"Todos:Eloqua"
6+
# config :tasks, :required => [:'core-tasks', :sproutcore, :scui, :sai, :'sai/graphs'],:title=>"Tasks:SproutCore"
7+
# config :tasks, :required => [:'core-tasks', :sproutcore, :scui, :sai, :'sai/graphs'],:title=>"Tasks:TPG"
8+
# config :tasks, :required => [:'core-tasks', :sproutcore, :scui, :sai, :'sai/graphs'],:title=>"Tasks:Greenhouse"
99

1010
# Local Persevere back end - prod instance
1111
proxy '/tasks-server', :to => 'localhost:8088', :protocol => 'http'

README

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ cd frameworks
1616

1717
git clone git://github.com/etgryphon/sproutcore-ui.git scui
1818
git clone git://github.com/etgryphon/sproutcore-uds.git scuds
19+
git clone http://github.com/etgryphon/sai.git
1920

2021
git clone git://github.com/suvajitgupta/sproutcore.git
2122

apps/tasks/controllers/assignments.js

+1-164
Original file line numberDiff line numberDiff line change
@@ -683,169 +683,6 @@ Tasks.assignmentsController = SC.ArrayController.create(
683683

684684
return ret;
685685

686-
}.property('assignedTasks'),
687-
688-
statistics: '',
689-
690-
computeStatistics: function() {
691-
692-
var submitters = {};
693-
var notLoadedAssigneesCount = 0, underloadedAssigneesCount = 0,
694-
properlyLoadedAssigneesCount = 0, overloadedAssigneesCount = 0;
695-
var finishedTasksCount = 0, leftTasksCount = 0;
696-
var riskyTasksCount = 0, failedTasksCount = 0;
697-
var featureCount = 0, bugCount = 0, otherCount = 0;
698-
var highCount = 0, mediumCount = 0, lowCount = 0;
699-
var plannedCount = 0, activeCount = 0, doneCount = 0, riskyCount = 0;
700-
var untestedCount = 0, passedCount = 0, failedCount = 0;
701-
702-
var assigneesCount = 0;
703-
var assignmentNodes = this.getPath('assignedTasks.treeItemChildren');
704-
if(assignmentNodes) assigneesCount = assignmentNodes.get('length');
705-
var tasksCount, totalTasksCount = 0;
706-
for(var i=0; i < assigneesCount; i++) {
707-
var assignmentNode = assignmentNodes.objectAt(i);
708-
finishedTasksCount += assignmentNode.get('finishedTasksCount');
709-
leftTasksCount += assignmentNode.get('leftTasksCount');
710-
var loading = assignmentNode.get('loading');
711-
switch(loading) {
712-
case CoreTasks.USER_NOT_LOADED: notLoadedAssigneesCount++; break;
713-
case CoreTasks.USER_UNDER_LOADED: underloadedAssigneesCount++; break;
714-
case CoreTasks.USER_PROPERLY_LOADED: properlyLoadedAssigneesCount++; break;
715-
case CoreTasks.USER_OVER_LOADED: overloadedAssigneesCount++; break;
716-
}
717-
riskyTasksCount += assignmentNode.get('riskyTasksCount');
718-
failedTasksCount += assignmentNode.get('failedTasksCount');
719-
tasksCount = assignmentNode.get('tasksCount');
720-
totalTasksCount += tasksCount;
721-
var tasks = assignmentNode.get('treeItemChildren');
722-
for(var j=0; tasks && j<tasksCount; j++) {
723-
var task = tasks.objectAt(j);
724-
var submitter = task.get('submitter');
725-
if(submitter) {
726-
var submitterName = submitter.get('loginName');
727-
if(submitters[submitterName]) submitters[submitterName]++;
728-
else submitters[submitterName] = 1;
729-
}
730-
731-
switch(task.get('type')) {
732-
case CoreTasks.TASK_TYPE_FEATURE: featureCount++; break;
733-
case CoreTasks.TASK_TYPE_BUG: bugCount++; break;
734-
case CoreTasks.TASK_TYPE_OTHER: otherCount++; break;
735-
}
736-
switch(task.get('priority')) {
737-
case CoreTasks.TASK_PRIORITY_HIGH: highCount++; break;
738-
case CoreTasks.TASK_PRIORITY_MEDIUM: mediumCount++; break;
739-
case CoreTasks.TASK_PRIORITY_LOW: lowCount++; break;
740-
}
741-
switch(task.get('developmentStatus')) {
742-
case CoreTasks.STATUS_PLANNED: plannedCount++; break;
743-
case CoreTasks.STATUS_ACTIVE: activeCount++; break;
744-
case CoreTasks.STATUS_DONE: doneCount++;
745-
switch(task.get('validation')) {
746-
case CoreTasks.TASK_VALIDATION_UNTESTED: untestedCount++; break;
747-
case CoreTasks.TASK_VALIDATION_PASSED: passedCount++; break;
748-
case CoreTasks.TASK_VALIDATION_FAILED: failedCount++; break;
749-
}
750-
break;
751-
case CoreTasks.STATUS_RISKY: riskyCount++; break;
752-
}
753-
}
754-
}
755-
var submittersCount = 0;
756-
for(var s in submitters) {
757-
submittersCount++;
758-
}
759-
760-
return {
761-
submittersCount: submittersCount,
762-
finishedTasksCount: finishedTasksCount, leftTasksCount: leftTasksCount,
763-
notLoadedAssigneesCount: notLoadedAssigneesCount,
764-
underloadedAssigneesCount: underloadedAssigneesCount,
765-
properlyLoadedAssigneesCount: properlyLoadedAssigneesCount,
766-
overloadedAssigneesCount: overloadedAssigneesCount,
767-
riskyTasksCount: riskyTasksCount, failedTasksCount: failedTasksCount, tasksCount: totalTasksCount,
768-
featureCount: featureCount, bugCount: bugCount, otherCount: otherCount,
769-
highCount: highCount, mediumCount: mediumCount, lowCount: lowCount,
770-
plannedCount: plannedCount, activeCount: activeCount, doneCount: doneCount, riskyCount: riskyCount,
771-
untestedCount: untestedCount, passedCount: passedCount, failedCount: failedCount
772-
};
773-
774-
},
775-
776-
displayStatistics: function() {
777-
var stats = this.computeStatistics();
778-
var ret = '';
779-
var blank = sc_static('blank');
780-
if(stats.tasksCount > 0) {
781-
if(this.get('displayMode') === Tasks.DISPLAY_MODE_TASKS) {
782-
ret += '<table width="100%">';
783-
if(Tasks.softwareMode) {
784-
ret += '<tr class="even">';
785-
ret += ('<td class="title"><span>' + "_Type".loc() + '</td>');
786-
ret += ('<td><img src="' + blank + '" class="task-icon-feature"/>&nbsp;' + "_Feature".loc() + ': ' + stats.featureCount + ' (' + Math.round(100*stats.featureCount/stats.tasksCount) + '%)' + '</td>');
787-
ret += ('<td><img src="' + blank + '" class="task-icon-bug"/>&nbsp;' + "_Bug".loc() + ': ' + stats.bugCount + ' (' + Math.round(100*stats.bugCount/stats.tasksCount) + '%)' + '</td>');
788-
ret += ('<td><img src="' + blank + '" class="task-icon-other"/>&nbsp;' + "_Other".loc() + ': ' + stats.otherCount + ' (' + Math.round(100*stats.otherCount/stats.tasksCount) + '%)' + '</td>');
789-
ret += '<td></td></tr>';
790-
}
791-
ret += '<tr class="odd">';
792-
ret += ('<td class="title"><span>' + "_Priority".loc() + '</td>');
793-
ret += ('<td><span class="task-priority-high">' + "_High".loc() + ':</span> ' + stats.highCount + ' (' + Math.round(100*stats.highCount/stats.tasksCount) + '%)' + '</td>');
794-
ret += ('<td><span class="task-priority-medium">' + "_Medium".loc() + ':</span> ' + stats.mediumCount + ' (' + Math.round(100*stats.mediumCount/stats.tasksCount) + '%)' + '</td>');
795-
ret += ('<td><span class="task-priority-low">' + "_Low".loc() + ':</span> ' + stats.lowCount + ' (' + Math.round(100*stats.lowCount/stats.tasksCount) + '%)' + '</td>');
796-
ret += '<td></td></tr>';
797-
ret += '<tr class="even">';
798-
ret += ('<td class="title"><span>' + "_Status".loc() + '</td>');
799-
ret += ('<td><span class="status-planned">' + "_Planned".loc() + ':</span> ' + stats.plannedCount + ' (' + Math.round(100*stats.plannedCount/stats.tasksCount) + '%)' + '</td>');
800-
ret += ('<td><span class="status-active">' + "_Active".loc() + ':</span> ' + stats.activeCount + ' (' + Math.round(100*stats.activeCount/stats.tasksCount) + '%)' + '</td>');
801-
ret += ('<td><span class="status-done">' + "_Done".loc() + ':</span> ' + stats.doneCount + ' (' + Math.round(100*stats.doneCount/stats.tasksCount) + '%)' + '</td>');
802-
ret += ('<td><span class="status-risky">' + "_Risky".loc() + ':</span> ' + stats.riskyCount + ' (' + Math.round(100*stats.riskyCount/stats.tasksCount) + '%)' + '</td>');
803-
ret += '</tr>';
804-
if(Tasks.softwareMode) {
805-
ret += '<tr class="odd">';
806-
ret += ('<td class="title"><span>' + "_Validation".loc() + '</td>');
807-
ret += ('<td><span class="task-validation-untested">' + "_Untested".loc() + ':</span> ' + stats.untestedCount + ' (' + Math.round(100*stats.untestedCount/stats.tasksCount) + '%)' + '</td>');
808-
ret += ('<td><span class="task-validation-passed">' + "_Passed".loc() + ':</span> ' + stats.passedCount + ' (' + Math.round(100*stats.passedCount/stats.tasksCount) + '%)' + '</td>');
809-
ret += ('<td><span class="task-validation-failed">' + "_Failed".loc() + ':</span> ' + stats.failedCount + ' (' + Math.round(100*stats.failedCount/stats.tasksCount) + '%)' + '</td>');
810-
ret += '<td></td></tr>';
811-
}
812-
ret += '</table><br>';
813-
ret += "_Submitters:".loc() + stats.submittersCount;
814-
}
815-
else { // displayMode === Tasks.DISPLAY_MODE_TEAM
816-
ret += '<table width="100%">';
817-
ret += '<tr class="even">';
818-
ret += ('<td class="title"><img src="' + blank + '" class="sc-icon-group-16"/>&nbsp;<span>' + "_Assignees:".loc() + '</td>');
819-
ret += ('<td><span class="assignee-not-loaded">' + "_AssigneeNotLoaded".loc() + ':</span> ' + stats.notLoadedAssigneesCount + '</td>');
820-
ret += ('<td><span class="assignee-under-loaded">' + "_AssigneeUnderLoaded".loc() + ':</span> ' + stats.underloadedAssigneesCount + '</td>');
821-
ret += ('<td><span class="assignee-properly-loaded">' + "_AssigneeProperlyLoaded".loc() + ':</span> ' + stats.properlyLoadedAssigneesCount + '</td>');
822-
ret += ('<td><span class="assignee-overloaded">' + "_AssigneeOverloaded".loc() + ':</span> ' + stats.overloadedAssigneesCount + '</td>');
823-
ret += '</tr>';
824-
ret += '<tr class="odd">';
825-
ret += ('<td class="title"><img src="' + blank + '" class="red-flag-icon"/>&nbsp;<span>' + "_RedFlags:".loc() + '</td>');
826-
ret += ('<td><span class="status-risky">' + "_Risky".loc() + ':</span> ' + stats.riskyTasksCount + '</td>');
827-
ret += ('<td><span class="task-validation-failed">' + "_Failed".loc() + ':</span> ' + stats.failedTasksCount + '</td>');
828-
ret += '<td></td><td></td></tr>';
829-
ret += '</table><br>';
830-
ret += "_Summary:".loc() + stats.finishedTasksCount + ' ' + "_finished".loc() + ', ' + stats.leftTasksCount + ' ' + "_left".loc();
831-
}
832-
}
833-
this.set('statistics', ret);
834-
},
835-
836-
showStatistics: function() {
837-
this.displayStatistics();
838-
// HACK: [SG] Creating/destroying panel so that text label refreshes, which is wasn't on quilmes
839-
this._panel = Tasks.getPath('statisticsPane').create();
840-
if(this._panel) this._panel.append();
841-
},
842-
843-
closePanel: function() {
844-
if(this._panel) {
845-
this._panel.destroy();
846-
this._panel = null;
847-
this.set('statistics', '');
848-
}
849-
}
686+
}.property('assignedTasks')
850687

851688
});

apps/tasks/controllers/statistics.js

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
// ==========================================================================
2+
// Tasks.statisticsController
3+
// ==========================================================================
4+
/*globals CoreTasks Tasks sc_require */
5+
6+
sc_require('core');
7+
8+
/** @static
9+
10+
@extends SC.ObjectController
11+
@author Suvajit Gupta
12+
13+
Controller for computing statistics.
14+
*/
15+
Tasks.statisticsController = SC.ObjectController.create(
16+
/** @scope Tasks.loginController.prototype */ {
17+
18+
statistics: '', // Stores statistics computed by function below
19+
computeStatistics: function() {
20+
21+
var submitters = {};
22+
var notLoadedAssigneesCount = 0, underloadedAssigneesCount = 0,
23+
properlyLoadedAssigneesCount = 0, overloadedAssigneesCount = 0;
24+
var finishedTasksCount = 0, leftTasksCount = 0;
25+
var riskyTasksCount = 0, failedTasksCount = 0;
26+
var featureCount = 0, bugCount = 0, otherCount = 0;
27+
var highCount = 0, mediumCount = 0, lowCount = 0;
28+
var plannedCount = 0, activeCount = 0, doneCount = 0, riskyCount = 0;
29+
var untestedCount = 0, passedCount = 0, failedCount = 0;
30+
31+
var assigneesCount = 0;
32+
var assignmentNodes = Tasks.assignmentsController.getPath('assignedTasks.treeItemChildren');
33+
if(assignmentNodes) assigneesCount = assignmentNodes.get('length');
34+
var tasksCount, totalTasksCount = 0;
35+
for(var i=0; i < assigneesCount; i++) {
36+
var assignmentNode = assignmentNodes.objectAt(i);
37+
finishedTasksCount += assignmentNode.get('finishedTasksCount');
38+
leftTasksCount += assignmentNode.get('leftTasksCount');
39+
var loading = assignmentNode.get('loading');
40+
switch(loading) {
41+
case CoreTasks.USER_NOT_LOADED: notLoadedAssigneesCount++; break;
42+
case CoreTasks.USER_UNDER_LOADED: underloadedAssigneesCount++; break;
43+
case CoreTasks.USER_PROPERLY_LOADED: properlyLoadedAssigneesCount++; break;
44+
case CoreTasks.USER_OVER_LOADED: overloadedAssigneesCount++; break;
45+
}
46+
riskyTasksCount += assignmentNode.get('riskyTasksCount');
47+
failedTasksCount += assignmentNode.get('failedTasksCount');
48+
tasksCount = assignmentNode.get('tasksCount');
49+
totalTasksCount += tasksCount;
50+
var tasks = assignmentNode.get('treeItemChildren');
51+
for(var j=0; tasks && j<tasksCount; j++) {
52+
var task = tasks.objectAt(j);
53+
var submitter = task.get('submitter');
54+
if(submitter) {
55+
var submitterName = submitter.get('loginName');
56+
if(submitters[submitterName]) submitters[submitterName]++;
57+
else submitters[submitterName] = 1;
58+
}
59+
60+
switch(task.get('type')) {
61+
case CoreTasks.TASK_TYPE_FEATURE: featureCount++; break;
62+
case CoreTasks.TASK_TYPE_BUG: bugCount++; break;
63+
case CoreTasks.TASK_TYPE_OTHER: otherCount++; break;
64+
}
65+
switch(task.get('priority')) {
66+
case CoreTasks.TASK_PRIORITY_HIGH: highCount++; break;
67+
case CoreTasks.TASK_PRIORITY_MEDIUM: mediumCount++; break;
68+
case CoreTasks.TASK_PRIORITY_LOW: lowCount++; break;
69+
}
70+
switch(task.get('developmentStatus')) {
71+
case CoreTasks.STATUS_PLANNED: plannedCount++; break;
72+
case CoreTasks.STATUS_ACTIVE: activeCount++; break;
73+
case CoreTasks.STATUS_DONE: doneCount++;
74+
switch(task.get('validation')) {
75+
case CoreTasks.TASK_VALIDATION_UNTESTED: untestedCount++; break;
76+
case CoreTasks.TASK_VALIDATION_PASSED: passedCount++; break;
77+
case CoreTasks.TASK_VALIDATION_FAILED: failedCount++; break;
78+
}
79+
break;
80+
case CoreTasks.STATUS_RISKY: riskyCount++; break;
81+
}
82+
}
83+
}
84+
var submittersCount = 0;
85+
for(var s in submitters) {
86+
submittersCount++;
87+
}
88+
89+
var stats = {
90+
tasksCount: tasksCount, submittersCount: submittersCount,
91+
finishedTasksCount: finishedTasksCount, leftTasksCount: leftTasksCount,
92+
notLoadedAssigneesCount: notLoadedAssigneesCount,
93+
underloadedAssigneesCount: underloadedAssigneesCount,
94+
properlyLoadedAssigneesCount: properlyLoadedAssigneesCount,
95+
overloadedAssigneesCount: overloadedAssigneesCount,
96+
riskyTasksCount: riskyTasksCount, failedTasksCount: failedTasksCount, tasksCount: totalTasksCount,
97+
featureCount: featureCount, bugCount: bugCount, otherCount: otherCount,
98+
highCount: highCount, mediumCount: mediumCount, lowCount: lowCount,
99+
plannedCount: plannedCount, activeCount: activeCount, doneCount: doneCount, riskyCount: riskyCount,
100+
untestedCount: untestedCount, passedCount: passedCount, failedCount: failedCount
101+
};
102+
// console.log('DEBUG: computeStatistics() ' + JSON.stringify(stats));
103+
this.set('statistics', stats);
104+
105+
},
106+
107+
showStatistics: function() {
108+
this.computeStatistics();
109+
// HACK: [SG] Creating/destroying panel so that text label refreshes, which wasn't on quilmes
110+
this._panel = Tasks.statisticsPane.create();
111+
if(this._panel) this._panel.append();
112+
},
113+
114+
closePanel: function() {
115+
this.set('statistics', '');
116+
if(this._panel) {
117+
this._panel.remove();
118+
this._panel.destroyLayer();
119+
this._panel = null;
120+
}
121+
}
122+
123+
});

apps/tasks/core_actions.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ Tasks.mixin({
126126
SC.RunLoop.begin();
127127
CoreTasks.store.loadRecords(CoreTasks.User, response);
128128
SC.RunLoop.end();
129-
currentUser = CoreTasks.store.find(CoreTasks.User, response[0].id);
129+
currentUser = CoreTasks.getUserByLoginName(response[0].loginName);
130130
}
131131

132132
// Greet user and save login session information
@@ -552,7 +552,7 @@ Tasks.mixin({
552552
* Popup Project Statistics panel.
553553
*/
554554
viewStatistics: function() {
555-
Tasks.assignmentsController.showStatistics();
555+
Tasks.statisticsController.showStatistics();
556556
},
557557

558558
/**

apps/tasks/core_routes.js

+5-8
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,12 @@ Tasks.mixin( /** @scope Tasks */ {
5050
viewRoute: function(params) {
5151
// console.log('DEBUG: viewRoute() search=' + params.search);
5252
Tasks._closeMainPage();
53-
if(SC.none(params.search) || params.search === '') {
54-
console.warn('Missing task search for URL routing');
55-
}
56-
else {
57-
// Enter the statechart.
58-
Tasks.goState('a', 1);
59-
Tasks.authenticate('guest', '');
53+
if(!SC.none(params.search) && params.search !== '') {
6054
Tasks.assignmentsController.set('searchFilter', params.search);
6155
}
56+
// Enter the statechart.
57+
Tasks.goState('a', 1);
58+
Tasks.authenticate('guest', '');
6259
},
6360

6461
/**
@@ -132,7 +129,7 @@ Tasks.mixin( /** @scope Tasks */ {
132129
The catch-all case when no routes are specified
133130
*/
134131
defaultRoute: function(params) {
135-
if(CoreTasks.loginTime) {
132+
if(CoreTasks.loginTime && SC.none(Tasks.state.a)) {
136133
// Enter the statechart.
137134
Tasks.goState('a', 1);
138135
Tasks.loginController.openPanel();

apps/tasks/core_states.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Tasks.mixin({
2323
Tasks.loadData();
2424
},
2525

26-
// Project/Task Management
26+
// GUI Running
2727
goStateA4: function() {
2828
}
2929

apps/tasks/english.lproj/default_theme/statistics_pane.css

+1-3
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@
77
*/
88

99
.statistics-pane table {
10-
border: 1px solid gray !important;
11-
border-collapse: separate !important;
12-
margin: 0px !important;
10+
margin-top: 5px !important;
1311
}
1412

1513
.statistics-pane td.title {

0 commit comments

Comments
 (0)