task-manager 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +4 -0
  3. data/Rakefile +27 -0
  4. data/app/assets/images/task-manager/icons/add.png +0 -0
  5. data/app/assets/images/task-manager/icons/delete.png +0 -0
  6. data/app/assets/images/task-manager/icons/edit.png +0 -0
  7. data/app/assets/javascripts/task-manager/application.js +43 -0
  8. data/app/assets/javascripts/task-manager/extjs/app/controller/Plans.js +359 -0
  9. data/app/assets/javascripts/task-manager/extjs/app/controller/Tasks.js +56 -0
  10. data/app/assets/javascripts/task-manager/extjs/app/helper/application_helper.js +24 -0
  11. data/app/assets/javascripts/task-manager/extjs/app/model/Assignee.js +19 -0
  12. data/app/assets/javascripts/task-manager/extjs/app/model/Plan.js +195 -0
  13. data/app/assets/javascripts/task-manager/extjs/app/model/Task.js +23 -0
  14. data/app/assets/javascripts/task-manager/extjs/app/store/Assignees.js +53 -0
  15. data/app/assets/javascripts/task-manager/extjs/app/store/AssigneesTree.js +3 -0
  16. data/app/assets/javascripts/task-manager/extjs/app/store/Booleans.js +9 -0
  17. data/app/assets/javascripts/task-manager/extjs/app/store/Days.js +38 -0
  18. data/app/assets/javascripts/task-manager/extjs/app/store/Hours.js +31 -0
  19. data/app/assets/javascripts/task-manager/extjs/app/store/Minutes.js +67 -0
  20. data/app/assets/javascripts/task-manager/extjs/app/store/Months.js +19 -0
  21. data/app/assets/javascripts/task-manager/extjs/app/store/Plans.js +6 -0
  22. data/app/assets/javascripts/task-manager/extjs/app/store/QuarterlyMonths.js +10 -0
  23. data/app/assets/javascripts/task-manager/extjs/app/store/Statuses.js +11 -0
  24. data/app/assets/javascripts/task-manager/extjs/app/store/Tasks.js +6 -0
  25. data/app/assets/javascripts/task-manager/extjs/app/store/Types.js +12 -0
  26. data/app/assets/javascripts/task-manager/extjs/app/store/WeekDays.js +14 -0
  27. data/app/assets/javascripts/task-manager/extjs/app/view/plan/AssignablesWindow.js +23 -0
  28. data/app/assets/javascripts/task-manager/extjs/app/view/plan/Edit.js +189 -0
  29. data/app/assets/javascripts/task-manager/extjs/app/view/plan/EditWindow.js +21 -0
  30. data/app/assets/javascripts/task-manager/extjs/app/view/plan/Grid.js +92 -0
  31. data/app/assets/javascripts/task-manager/extjs/app/view/plan/Index.js +24 -0
  32. data/app/assets/javascripts/task-manager/extjs/app/view/plan/New.js +190 -0
  33. data/app/assets/javascripts/task-manager/extjs/app/view/plan/Search.js +132 -0
  34. data/app/assets/javascripts/task-manager/extjs/app/view/plan/SelectAssignables.js +22 -0
  35. data/app/assets/javascripts/task-manager/extjs/app/view/plan/SelectAssignablesGrid.js +22 -0
  36. data/app/assets/javascripts/task-manager/extjs/app/view/plan/SelectAssignablesTree.js +9 -0
  37. data/app/assets/javascripts/task-manager/extjs/app/view/plan/Window.js +21 -0
  38. data/app/assets/javascripts/task-manager/extjs/app/view/task/Grid.js +62 -0
  39. data/app/assets/javascripts/task-manager/extjs/app/view/task/Index.js +21 -0
  40. data/app/assets/javascripts/task-manager/extjs/app/view/task/Search.js +148 -0
  41. data/app/assets/javascripts/task-manager/extjs/lib/ux/MultiSelectablePagingGrid.js +20 -0
  42. data/app/assets/javascripts/task-manager/extjs/lib/ux/RowExpander.js +230 -0
  43. data/app/assets/stylesheets/task-manager/application.css.scss +13 -0
  44. data/app/assets/stylesheets/task-manager/extjs.css.scss +43 -0
  45. data/app/controllers/task_manager/api/v1/plans_controller.rb +251 -0
  46. data/app/controllers/task_manager/api/v1/tasks_controller.rb +82 -0
  47. data/app/controllers/task_manager/application_controller.rb +4 -0
  48. data/app/helpers/task_manager/application_helper.rb +4 -0
  49. data/app/models/task_manager/assignable.rb +10 -0
  50. data/app/models/task_manager/callable.rb +10 -0
  51. data/app/models/task_manager/plan.rb +114 -0
  52. data/app/models/task_manager/task.rb +81 -0
  53. data/app/serializers/task_manager/plan_serializer.rb +8 -0
  54. data/app/serializers/task_manager/task_serializer.rb +8 -0
  55. data/app/views/layouts/task-manager/application.html.erb +14 -0
  56. data/config/routes.rb +8 -0
  57. data/db/migrate/20121102054723_setup_hstore.rb +9 -0
  58. data/db/migrate/20121102055137_create_task_manager_plans.rb +16 -0
  59. data/db/migrate/20121102142657_create_task_manager_assignables.rb +13 -0
  60. data/db/migrate/20121102150720_create_task_manager_callables.rb +13 -0
  61. data/db/migrate/20121105170602_create_task_manager_tasks.rb +18 -0
  62. data/lib/task-manager.rb +37 -0
  63. data/lib/task-manager/api_constraints.rb +12 -0
  64. data/lib/task-manager/deadline_calculator.rb +22 -0
  65. data/lib/task-manager/deadline_validator.rb +27 -0
  66. data/lib/task-manager/engine.rb +5 -0
  67. data/lib/task-manager/version.rb +3 -0
  68. data/lib/tasks/task-manager_tasks.rake +4 -0
  69. metadata +327 -0
@@ -0,0 +1,24 @@
1
+ Ext.define('TM.view.plan.Index', {
2
+ extend: 'Ext.panel.Panel',
3
+ xtype: 'plan_index',
4
+
5
+ requires: ['TM.view.plan.Search'],
6
+
7
+ title: '计划管理',
8
+ closable: true,
9
+
10
+ store: 'TM.store.Plans',
11
+
12
+ layout: {
13
+ type: 'vbox',
14
+ align: 'stretch'
15
+ },
16
+
17
+ items: [{
18
+ xtype: 'plan_search',
19
+ width: 50
20
+ }, {
21
+ xtype: 'plan_grid',
22
+ flex: 1,
23
+ }]
24
+ });
@@ -0,0 +1,190 @@
1
+ Ext.define('TM.view.plan.New', {
2
+ extend: 'Ext.form.Panel',
3
+ xtype: 'plan_new',
4
+
5
+ defaults: {
6
+ xtype: 'fieldset',
7
+ margin: '5 10'
8
+ },
9
+
10
+ assignees: [],
11
+
12
+ items: [{
13
+ id: 'fillField',
14
+ title: '基本信息',
15
+ layout: {
16
+ type: 'table',
17
+ columns: 1
18
+ },
19
+ defaults: {
20
+ xtype: 'textfield',
21
+ labelAlign: 'right',
22
+ margin: '10 0',
23
+ width: 510
24
+ },
25
+
26
+ items: [{
27
+ fieldLabel: '计划名称',
28
+ name: 'name',
29
+ allowBlank: false
30
+ },{
31
+ fieldLabel: '计划执行人',
32
+ name: 'assignables',
33
+ id: 'assignables',
34
+ readOnly: true
35
+ }, {
36
+ fieldLabel: '计划类型',
37
+ name: 'plan_type',
38
+ store: 'TM.store.Types',
39
+ editable: false,
40
+ valueField: 'value',
41
+ xtype: 'combo',
42
+ blankText: '请选择计划类型!',
43
+ allowBlank: false
44
+ }, {
45
+ fieldLabel: '横向指标',
46
+ name: 'dataX'
47
+ }, {
48
+ fieldLabel: '纵向指标',
49
+ name: 'dataY'
50
+ }, {
51
+ fieldLabel: '生效时间',
52
+ xtype: 'datefield',
53
+ editable: false,
54
+ anchor: '100%',
55
+ format: 'Y/m/d',
56
+ name: 'enabled_at',
57
+ id: 'enabled_at',
58
+ minValue: new Date()
59
+ }, {
60
+ fieldLabel: '完成前几天提醒',
61
+ id: 'new_begin_to_remind',
62
+ emptyText: '计划完成前多少天开始提醒,此处为倒计时。',
63
+ value: '0',
64
+ name: 'begin_to_remind'
65
+ }, {
66
+ fieldLabel: '是否自动完成',
67
+ xtype: 'checkbox',
68
+ name: 'autocompletable'
69
+ }]
70
+ }, {
71
+ xtype: 'fieldset',
72
+ id: 'selectField',
73
+ title: '计划完成截至时限',
74
+ layout: {
75
+ type: 'table',
76
+ columns: 2
77
+ },
78
+ defaults: {
79
+ labelAlign: 'right',
80
+ },
81
+ items: [{
82
+ fieldLabel: '月',
83
+ id: 'new_quarterly_month',
84
+ name: 'quarterly_month',
85
+ xtype: 'combo',
86
+ store: 'TM.store.QuarterlyMonths',
87
+ valueField: 'value',
88
+ editable: false
89
+ }, {
90
+ fieldLabel: '月',
91
+ id: 'new_month',
92
+ name: 'month',
93
+ xtype: 'combo',
94
+ store: 'TM.store.Months',
95
+ valueField: 'value',
96
+ editable: false
97
+ }, {
98
+ fieldLabel: '日',
99
+ id: 'new_weekly_day',
100
+ name: 'weekly_day',
101
+ store: 'TM.store.WeekDays',
102
+ valueField: 'value',
103
+ xtype: 'combo',
104
+ editable: false
105
+ }, {
106
+ fieldLabel: '日',
107
+ id: 'new_day',
108
+ name: 'day',
109
+ store: 'TM.store.Days',
110
+ valueField: 'value',
111
+ xtype: 'combo',
112
+ editable: false
113
+ }, {
114
+ fieldLabel: '时',
115
+ id: 'new_hour',
116
+ name: 'hour',
117
+ store: 'TM.store.Hours',
118
+ valueField: 'value',
119
+ xtype: 'combo',
120
+ editable: false
121
+ }, {
122
+ fieldLabel: '分',
123
+ id: 'new_minute',
124
+ name: 'minute',
125
+ store: 'TM.store.Minutes',
126
+ valueField: 'value',
127
+ xtype: 'combo',
128
+ editable: false
129
+ }]
130
+ }],
131
+
132
+ buttons: [{
133
+ text: '保存',
134
+ formBind: true,
135
+ action: 'save'
136
+ }, {
137
+ text: '重置',
138
+ action: 'reset'
139
+ }],
140
+
141
+ showYearlyField: function() {
142
+ var fieldSet = this.getComponent('selectField');
143
+ fieldSet.getComponent('new_quarterly_month').hide();
144
+ fieldSet.getComponent('new_weekly_day').hide();
145
+ fieldSet.getComponent('new_month').show();
146
+ fieldSet.getComponent('new_day').show();
147
+ fieldSet.getComponent('new_hour').show();
148
+ fieldSet.getComponent('new_minute').show();
149
+ },
150
+
151
+ showMonthlyField: function() {
152
+ var fieldSet = this.getComponent('selectField');
153
+ fieldSet.getComponent('new_quarterly_month').hide();
154
+ fieldSet.getComponent('new_weekly_day').hide();
155
+ fieldSet.getComponent('new_month').hide();
156
+ fieldSet.getComponent('new_day').show();
157
+ fieldSet.getComponent('new_hour').show();
158
+ fieldSet.getComponent('new_minute').show();
159
+ },
160
+
161
+ showQuarterlyField: function() {
162
+ var fieldSet = this.getComponent('selectField');
163
+ fieldSet.getComponent('new_quarterly_month').show();
164
+ fieldSet.getComponent('new_weekly_day').hide();
165
+ fieldSet.getComponent('new_month').hide();
166
+ fieldSet.getComponent('new_day').show();
167
+ fieldSet.getComponent('new_hour').show();
168
+ fieldSet.getComponent('new_minute').show();
169
+ },
170
+
171
+ showWeeklyField: function() {
172
+ var fieldSet = this.getComponent('selectField');
173
+ fieldSet.getComponent('new_quarterly_month').hide();
174
+ fieldSet.getComponent('new_weekly_day').show();
175
+ fieldSet.getComponent('new_month').hide();
176
+ fieldSet.getComponent('new_day').hide();
177
+ fieldSet.getComponent('new_hour').show();
178
+ fieldSet.getComponent('new_minute').show();
179
+ },
180
+
181
+ showDailyField: function() {
182
+ var fieldSet = this.getComponent('selectField');
183
+ fieldSet.getComponent('new_quarterly_month').hide();
184
+ fieldSet.getComponent('new_weekly_day').hide();
185
+ fieldSet.getComponent('new_month').hide();
186
+ fieldSet.getComponent('new_day').hide();
187
+ fieldSet.getComponent('new_hour').show();
188
+ fieldSet.getComponent('new_minute').show();
189
+ }
190
+ });
@@ -0,0 +1,132 @@
1
+ Ext.define('TM.view.plan.Search', {
2
+ extend: 'Ext.form.Panel',
3
+ xtype: 'plan_search',
4
+
5
+ border: 0,
6
+ bodyPadding: '5 5 0',
7
+
8
+ items: [{
9
+ xtype: 'fieldset',
10
+ title: '查询',
11
+
12
+ layout: {
13
+ type: 'form',
14
+ border: 0,
15
+ margin: 2
16
+ },
17
+
18
+ items: [{
19
+ border: 0,
20
+ items: [{
21
+ layout: 'column',
22
+ border: 0,
23
+ defaults: {
24
+ xtype: 'textfield',
25
+ labelAlign: 'right',
26
+ width: 300,
27
+ labelWidth: 130
28
+ },
29
+ items: [{
30
+ fieldLabel: '名称',
31
+ name: 'q[name_cont]'
32
+ }, {
33
+ fieldLabel: '类型',
34
+ editable: false,
35
+ xtype: 'combo',
36
+ store: 'TM.store.Types',
37
+ valueField: 'value',
38
+ name: 'q[plan_type_eq]'
39
+ }, {
40
+ fieldLabel: '是否自动完成',
41
+ xtype: 'combo',
42
+ editable: false,
43
+ valueField: 'value',
44
+ store: 'TM.store.Booleans',
45
+ name: 'q[autocompletable_eq]'
46
+ }]
47
+ }, {
48
+ layout: 'column',
49
+ border: 0,
50
+ defaults: {
51
+ border: 0,
52
+ labelAlign: 'right',
53
+ width: 300,
54
+ labelWidth: 130
55
+ },
56
+ items: [{
57
+ layout: 'column',
58
+ border: 0,
59
+ defaults: {
60
+ xtype: 'datefield',
61
+ labelAlign: 'right',
62
+ width: 300,
63
+ labelWidth: 130
64
+ },
65
+ items: [{
66
+ //fieldLabel: '生成时间 从',
67
+ //format: 'Y-m-d',
68
+ //editable: false,
69
+ //name: 'q[last_task_created_at_gteq]'
70
+ //}, {
71
+ fieldLabel: '生效时间 从',
72
+ format: 'Y-m-d',
73
+ xtype: 'datefield',
74
+ editable: false,
75
+ name: 'q[enabled_at_gteq]'
76
+ }]
77
+ }, {
78
+ layout: 'column',
79
+ border: 0,
80
+ defaults: {
81
+ xtype: 'datefield',
82
+ labelAlign: 'right',
83
+ width: 300,
84
+ labelWidth: 130
85
+ },
86
+ items: [{
87
+ //fieldLabel: '至',
88
+ //format: 'Y-m-d',
89
+ //editable: false,
90
+ //name: 'q[last_task_created_at_lteq]'
91
+ //}, {
92
+ fieldLabel: '至',
93
+ format: 'Y-m-d',
94
+ xtype: 'datefield',
95
+ editable: false,
96
+ name: 'q[enabled_at_lteq]'
97
+ }]
98
+ }, {
99
+ layout: 'hbox',
100
+ margin: '5 0 0 60',
101
+ items: [{
102
+ xtype: 'button',
103
+ formBind: true,
104
+ width: 60,
105
+ text: '查询',
106
+ action: 'query'
107
+ }, {
108
+ xtype: 'button',
109
+ margin: '0 0 0 20',
110
+ width: 60,
111
+ text: '重置',
112
+ action: 'reset'
113
+ }]
114
+ }]
115
+ }],
116
+ }]
117
+ }],
118
+
119
+ hasQueryParams: function() {
120
+ var hasParams = false;
121
+ Ext.Object.each(this.getValues(), function(key, value) {
122
+ if(value) {
123
+ hasParams = true;
124
+
125
+ // Break each
126
+ return false;
127
+ }
128
+ });
129
+
130
+ return hasParams;
131
+ }
132
+ });
@@ -0,0 +1,22 @@
1
+ Ext.define('TM.view.plan.SelectAssignables', {
2
+ extend: 'Ext.panel.Panel',
3
+ xtype: 'plan_selectassignables',
4
+
5
+ requires: [
6
+ //'TM.view.plan.SelectAssignablesGrid',
7
+ 'TM.view.plan.SelectAssignablesTree'
8
+ ],
9
+
10
+ items: [{
11
+ xtype: 'plan_selectassignablestree',
12
+ flex: 1
13
+ }],
14
+
15
+ buttons: [{
16
+ text: '确定',
17
+ action: 'save'
18
+ }, {
19
+ text: '取消',
20
+ action: 'cancel'
21
+ }]
22
+ });
@@ -0,0 +1,22 @@
1
+ Ext.define('TM.view.plan.SelectAssignablesGrid', {
2
+ extend: 'Ext.grid.Panel',
3
+ xtype: 'plan_selectassignablesgrid',
4
+
5
+ store: 'TM.store.Assignees',
6
+ height: 490,
7
+
8
+ border: 0,
9
+
10
+ selType: 'checkboxmodel',
11
+ selModel: {
12
+ mode: 'MULTI',
13
+ allowDeselect: true,
14
+ checkOnly: true
15
+ },
16
+
17
+ columns: [{
18
+ text: '名称',
19
+ flex: 1,
20
+ dataIndex: 'name'
21
+ }]
22
+ });
@@ -0,0 +1,9 @@
1
+ Ext.define('TM.view.plan.SelectAssignablesTree', {
2
+ extend: 'Ext.tree.Panel',
3
+ xtype: 'plan_selectassignablestree',
4
+
5
+ store: 'TM.store.AssigneesTree',
6
+ height: 490,
7
+ rootVisible: false,
8
+ border: 0
9
+ });
@@ -0,0 +1,21 @@
1
+ Ext.define('TM.view.plan.Window', {
2
+ extend: 'Ext.window.Window',
3
+ requires: ['TM.view.plan.New'],
4
+ xtype: 'plan_window',
5
+
6
+ title: '添加计划',
7
+ modal: true,
8
+
9
+ width: 600,
10
+ height: 550,
11
+
12
+ layout: {
13
+ type: 'fit',
14
+ align: 'stretch'
15
+ },
16
+
17
+ items: [{
18
+ xtype: 'plan_new',
19
+ border: false
20
+ }]
21
+ });
@@ -0,0 +1,62 @@
1
+ Ext.define('TM.view.task.Grid', {
2
+ extend: 'Ext.ux.MultiSelectablePagingGrid',
3
+ xtype: 'task_grid',
4
+
5
+ mixins: [
6
+ 'TM.helper.ApplicationHelper'
7
+ ],
8
+ store: 'TM.store.Tasks',
9
+
10
+ requires: [
11
+ 'Ext.ux.RowExpander'
12
+ ],
13
+
14
+ plugins: [{
15
+ ptype: 'rowexpander',
16
+ rowBodyTpl: [
17
+ '<table class="data">',
18
+ '<tr>',
19
+ '<td class="name">横向指标:</td>',
20
+ '<td class="value">{[values.data.x == null ? "" : values.data.x]}</td>',
21
+ '</tr>',
22
+ '<tr>',
23
+ '<td class="name">纵向指标:</td>',
24
+ '<td class="value">{[values.data.y == null ? "" : values.data.y]}</td>',
25
+ '</tr>',
26
+ '</table>'
27
+ ]
28
+ }],
29
+
30
+ tbar: [ {
31
+ text: '删除',
32
+ iconCls: 'btn-delete-icon',
33
+ action: 'delete'
34
+ }],
35
+
36
+ columns: [{
37
+ text: '名称',
38
+ dataIndex: 'name',
39
+ flex: 2
40
+ }, {
41
+ text: '类型',
42
+ dataIndex: 'task_type',
43
+ renderer: function(v, m, record) {
44
+ return this.translateType(v);
45
+ },
46
+ flex: 2
47
+ }, {
48
+ text: '状态',
49
+ dataIndex: 'status',
50
+ renderer: function(v, m, record) {
51
+ return this.translateStatus(v);
52
+ },
53
+ flex:2
54
+ }, {
55
+ text: '截至时间',
56
+ dataIndex: 'deadline',
57
+ renderer: function(v, m, record) {
58
+ return Ext.Date.format(v, 'Y年m月j日 H:i:s');
59
+ },
60
+ flex:2
61
+ }]
62
+ });