task-manager 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. data/README.md +136 -1
  2. data/Rakefile +3 -17
  3. data/app/assets/javascripts/task-manager/{application.js → extjs.js} +3 -9
  4. data/app/assets/javascripts/task-manager/extjs/app/controller/Plans.js +29 -264
  5. data/app/assets/javascripts/task-manager/extjs/app/helper/{application_helper.js → ApplicationHelper.js} +0 -0
  6. data/app/assets/javascripts/task-manager/extjs/app/model/Assignee.js +16 -0
  7. data/app/assets/javascripts/task-manager/extjs/app/model/Plan.js +18 -156
  8. data/app/assets/javascripts/task-manager/extjs/app/store/Assignees.js +37 -30
  9. data/app/assets/javascripts/task-manager/extjs/app/view/assignee/TreeCombo.js +48 -0
  10. data/app/assets/javascripts/task-manager/extjs/app/view/plan/Form.js +290 -0
  11. data/app/assets/javascripts/task-manager/extjs/app/view/plan/{Window.js → FormWindow.js} +7 -5
  12. data/app/assets/javascripts/task-manager/extjs/lib/ux/Model.js +14 -0
  13. data/app/assets/javascripts/task-manager/extjs/lib/ux/TreeCombo.js +276 -0
  14. data/app/controllers/task_manager/api/v1/plans_controller.rb +3 -3
  15. data/app/controllers/task_manager/api/v1/tasks_controller.rb +1 -1
  16. data/app/models/task_manager/plan.rb +48 -37
  17. data/lib/task-manager/deadline_validator.rb +23 -14
  18. data/lib/task-manager/version.rb +1 -1
  19. metadata +27 -16
  20. data/app/assets/javascripts/task-manager/extjs/app/store/AssigneesTree.js +0 -3
  21. data/app/assets/javascripts/task-manager/extjs/app/view/plan/AssignablesWindow.js +0 -23
  22. data/app/assets/javascripts/task-manager/extjs/app/view/plan/Edit.js +0 -189
  23. data/app/assets/javascripts/task-manager/extjs/app/view/plan/EditWindow.js +0 -21
  24. data/app/assets/javascripts/task-manager/extjs/app/view/plan/New.js +0 -190
  25. data/app/assets/javascripts/task-manager/extjs/app/view/plan/SelectAssignables.js +0 -22
  26. data/app/assets/javascripts/task-manager/extjs/app/view/plan/SelectAssignablesGrid.js +0 -22
  27. data/app/assets/javascripts/task-manager/extjs/app/view/plan/SelectAssignablesTree.js +0 -9
  28. data/app/assets/stylesheets/task-manager/application.css.scss +0 -13
@@ -15,5 +15,21 @@ Ext.define('TM.model.Assignee', {
15
15
  root: 'assignees',
16
16
  totalProperty: 'total'
17
17
  }
18
+ },
19
+
20
+ getId: function(detailed) {
21
+ if(detailed) {
22
+ return this.get('class_name') + '-' + this.get('id');
23
+ } else {
24
+ return this.get('id');
25
+ }
26
+ },
27
+
28
+ getParentId: function(detailed) {
29
+ if(this.get('parent_id') && detailed) {
30
+ return this.get('class_name') + '-' + this.get('parent_id');
31
+ } else {
32
+ return this.get('parent_id');
33
+ }
18
34
  }
19
35
  });
@@ -2,39 +2,11 @@ Ext.define('TM.model.Plan', {
2
2
  extend: 'Ext.data.Model',
3
3
 
4
4
  fields: [
5
- { name: 'id', type: 'int' },
5
+ { name: 'id', type: 'int', persist: false },
6
6
 
7
7
  { name: 'name' },
8
8
  { name: 'plan_type' },
9
9
  { name: 'data', type: 'auto' },
10
- { name: 'dataX', convert: function(v, record) {
11
- return record.get('data').x;
12
- }},
13
- { name: 'dataY', convert: function(v, record) {
14
- return record.get('data').y;
15
- }},
16
- { name: 'quarterly_month', convert: function(v, record) {
17
- if (record.get('plan_type') == 'quarterly') return record.get('data').deadline_month;
18
- return null;
19
- }},
20
- { name: 'month', convert: function(v, record) {
21
- if (record.get('plan_type') == 'yearly') return record.get('data').deadline_month;
22
- return null;
23
- }},
24
- { name: 'weekly_day', convert: function(v, record) {
25
- if (record.get('plan_type') == 'weekly') return record.get('data').deadline_day;
26
- return null;
27
- }},
28
- { name: 'day', convert: function(v, record) {
29
- if (record.get('plan_type') != 'weekly') return record.get('data').deadline_day;
30
- return null;
31
- }},
32
- { name: 'hour', convert: function(v, record) {
33
- return record.get('data').deadline_hour;
34
- }},
35
- { name: 'minute', convert: function(v, record) {
36
- return record.get('data').deadline_minute;
37
- }},
38
10
  { name: 'autocompletable', type: 'boolean' },
39
11
 
40
12
  { name: 'begin_to_remind', type: 'int' },
@@ -43,10 +15,12 @@ Ext.define('TM.model.Plan', {
43
15
  { name: 'last_task_created_at', type: 'date' },
44
16
 
45
17
 
46
- { name: 'created_at', type: 'date' },
47
- { name: 'updated_at', type: 'date' },
18
+ { name: 'created_at', type: 'date', persist: false },
19
+ { name: 'updated_at', type: 'date', persist: false },
48
20
 
49
- { name: 'assignees', type: 'auto' }
21
+ { name: 'assignees', type: 'auto', persist: false, defaultValue: [] },
22
+ { name: 'assignables_attributes', type: 'auto', defaultValue: [] },
23
+ { name: 'callables_attributes', type: 'auto', defaultValue: [] }
50
24
  ],
51
25
 
52
26
  proxy: {
@@ -58,132 +32,20 @@ Ext.define('TM.model.Plan', {
58
32
  }
59
33
  },
60
34
 
61
- set: function() {
62
- if (typeof arguments[0] === 'object') {
63
- this.callParent(arguments);
64
-
65
- obj = arguments[0];
66
- if (obj.data) {
67
- this.set('dataX', obj.data.x);
68
- this.set('dataY', obj.data.y);
69
- this.set('quarterly_month', obj.data.deadline_month);
70
- this.set('month', obj.data.deadline_month);
71
- this.set('weekly_day', obj.data.deadline_day);
72
- this.set('day', obj.data.deadline_day);
73
- this.set('hour', obj.data.deadline_hour);
74
- this.set('minute', obj.data.deadline_minute);
35
+ save: function(opts) {
36
+ var self = this;
37
+ opts = opts || {};
38
+ var success = opts.success;
39
+ opts.success = function(record, operation) {
40
+ self.set(Ext.JSON.decode(operation.response.responseText).plan);
41
+ self.commit();
42
+ if (operation.action === 'create') {
43
+ Ext.getStore('TM.store.Plans').insert(0, self);
75
44
  }
76
- } else {
77
- this.callParent(arguments);
78
- }
79
- },
80
-
81
- update: function(attrs, opts) {
82
- var self = this;
83
- var plan = Ext.create('TM.model.Plan', attrs);
84
-
85
- opts = opts || {};
86
- var success = opts.success;
87
-
88
- var assignables_attributes = new Array();
89
- Ext.Array.forEach(attrs.assignees, function(node, index, assignees) {
90
- var record = Ext.getStore('TM.store.Assignees').getById(node.get('id'));
91
- assignables_attributes.push({
92
- assignee_id: record.get('id'),
93
- assignee_type: record.get('class_name')
94
- });
95
- });
96
-
97
- var callables_attributes = new Array();
98
-
99
- Ext.apply(opts, {
100
- url: '/task-manager/api/plans/'+this.get('id'),
101
- method: 'PUT',
102
- jsonData: {
103
- plan: {
104
- data: {
105
- x: attrs.dataX,
106
- y: attrs.dataY,
107
- deadline_month: attrs.plan_type == 'quarterly' ? attrs.quarterly_month : (attrs.plan_type == 'yearly' ? attrs.month : null),
108
- deadline_day: attrs.plan_type == 'weekly' ? attrs.weekly_day : (attrs.plan_type == 'daily' ? null : attrs.day),
109
- deadline_hour: attrs.hour,
110
- deadline_minute: attrs.minute
111
- },
112
- name: attrs.name,
113
- plan_type: attrs.plan_type,
114
- enabled_at: attrs.enabled_at,
115
- begin_to_remind: attrs.begin_to_remind,
116
- autocompletable: attrs.autocompletable,
117
- assignables_attributes: assignables_attributes,
118
- callables_attributes: callables_attributes
119
- }
120
- },
121
- success: function(response) {
122
- var obj = Ext.JSON.decode(response.responseText);
123
- self.set(obj.plan);
124
- self.commit();
125
-
126
- if(success) success.call(opts.scope || this);
127
- }
128
- });
129
- Ext.Ajax.request(opts);
45
+ if(success) success.call(self);
46
+ };
130
47
 
131
- return plan;
132
- },
133
-
134
- statics: {
135
- create: function(attrs, opts) {
136
- var plan = Ext.create('TM.model.Plan', attrs);
137
-
138
- opts = opts || {};
139
- var success = opts.success;
140
-
141
- var assignables_attributes = new Array();
142
- Ext.Array.forEach(attrs.assignees, function(node, index, assignees) {
143
- var record = Ext.getStore('TM.store.Assignees').getById(node.get('id'));
144
- assignables_attributes.push({
145
- assignee_id: record.get('id'),
146
- assignee_type: record.get('class_name')
147
- })
148
- });
149
-
150
- var callables_attributes = new Array();
151
-
152
- Ext.apply(opts, {
153
- url: '/task-manager/api/plans',
154
- method: 'POST',
155
- jsonData: {
156
- plan: {
157
- data: {
158
- x: attrs.dataX,
159
- y: attrs.dataY,
160
- deadline_month: attrs.plan_type == 'quarterly' ? attrs.quarterly_month : (attrs.plan_type == 'yearly' ? attrs.month : null),
161
- deadline_day: attrs.plan_type == 'weekly' ? attrs.weekly_day : (attrs.plan_type == 'daily' ? null : attrs.day),
162
- deadline_hour: attrs.hour,
163
- deadline_minute: attrs.minute
164
- },
165
- name: attrs.name,
166
- plan_type: attrs.plan_type,
167
- enabled_at: attrs.enabled_at,
168
- begin_to_remind: attrs.begin_to_remind,
169
- autocompletable: attrs.autocompletable,
170
- assignables_attributes: assignables_attributes,
171
- callables_attributes: callables_attributes
172
- }
173
- },
174
- success: function(response) {
175
- var obj = Ext.JSON.decode(response.responseText);
176
- plan.set(obj.plan);
177
- //plan.set('dataX', obj.plan.data.x);
178
- plan.commit();
179
-
180
- if(success) success.call(opts.scope || this);
181
- }
182
- });
183
- Ext.Ajax.request(opts);
184
-
185
- return plan;
186
- }
48
+ this.callParent([opts]);
187
49
  },
188
50
 
189
51
  destroy: function() {
@@ -4,50 +4,57 @@ Ext.define('TM.store.Assignees', {
4
4
  autoLoad: true,
5
5
  model: 'TM.model.Assignee',
6
6
 
7
- toTreeStore: function() {
7
+ listeners: {
8
+ load: {
9
+ fn: function(store) {
10
+ store.refreshRootNode();
11
+ }
12
+ }
13
+ },
8
14
 
9
- var self = this;
10
- var store = {
15
+ toTreeStore: function() {
16
+ this._treeStore = this._treeStore || Ext.create('Ext.data.TreeStore', {
11
17
  root: {
12
18
  expanded: true,
19
+ checked: false,
20
+ text: '全部',
21
+ id: 'root',
13
22
  children: []
14
23
  }
15
- };
16
-
17
- self.each(function(assignee) {
18
- self.addChild(self.getPositionById(store.root,
19
- assignee.get('parent_id')), assignee);
20
24
  });
21
25
 
22
- return store;
26
+ return this._treeStore;
23
27
  },
24
28
 
25
29
  // @private
26
- getPositionById: function(root, id) {
27
- if (id == null || id == 0) return root;
28
- if (root.id == id) return root;
29
-
30
- var childrenLength = root.children ? root.children.length : 0;
31
- for (var i = 0; i < childrenLength; i++) {
32
- var result = this.getPositionById(root.children[i], id);
33
- if (result != null) return result;
34
- }
35
-
36
- return null;
30
+ getRootNode: function() {
31
+ return this.toTreeStore().getRootNode();
37
32
  },
38
33
 
39
- addChild: function(root, record) {
40
- if (root.children == null) root.children = [];
34
+ // @private
35
+ refreshRootNode: function() {
36
+ this.each(function(assignee) {
37
+ var parent = this.getNodeById(assignee.getParentId(true)) || this.getRootNode();
38
+ var node = parent.findChild('id', assignee.getId(true));
39
+
40
+ if(!node) this.appendChildNode(parent, assignee);
41
+ }, this);
42
+ },
41
43
 
42
- root.children.push({
43
- id: record.get('id'),
44
- text: record.get('name'),
44
+ // @private
45
+ appendChildNode: function(parent, assignee) {
46
+ parent.set('leaf', false);
47
+ parent.appendChild(parent.createNode({
48
+ id: assignee.getId(true),
49
+ text: assignee.get('name'),
45
50
  checked: false,
46
- leaf: true
47
- });
51
+ leaf: true,
52
+ record: assignee
53
+ }));
54
+ },
48
55
 
49
- if (root.leaf != null) {
50
- root.leaf == true ? root.leaf = false : null;
51
- }
56
+ // @private
57
+ getNodeById: function(id) {
58
+ return this.toTreeStore().getNodeById(id);
52
59
  }
53
60
  });
@@ -0,0 +1,48 @@
1
+ Ext.define('TM.view.assignee.TreeCombo', {
2
+ xtype: 'assignee_treecombo',
3
+ extend: 'Ext.ux.TreeCombo',
4
+
5
+ setValue: function(valueInit) {
6
+ if(typeof valueInit === 'object') {
7
+ var value = [];
8
+ valueInit.forEach(function(i) {
9
+ value.push(i.assignee_type + '-' + i.assignee_id);
10
+ });
11
+ valueInit = value.join(',');
12
+ }
13
+
14
+ this.callParent([valueInit]);
15
+ },
16
+
17
+ getSubmitValue: function() {
18
+ var value = [];
19
+ if(!this.value) return value;
20
+
21
+ var objs = this.value.split(',');
22
+ objs.forEach(function(i) {
23
+ var node = this.tree.getStore().getNodeById(i);
24
+ if(node) {
25
+ var assignee = node.raw.record;
26
+ var attrs = {
27
+ assignee_id: assignee.get('id'),
28
+ assignee_type: assignee.get('class_name')
29
+ };
30
+ value.push(attrs);
31
+ }
32
+ }, this);
33
+
34
+ return value;
35
+ },
36
+
37
+ // @protected
38
+ initComponent: function() {
39
+ this.callParent(arguments);
40
+
41
+ this.on('show', this.unCheckNodes);
42
+ },
43
+
44
+ // @private
45
+ unCheckNodes: function() {
46
+ this.setValue('');
47
+ }
48
+ });
@@ -0,0 +1,290 @@
1
+ Ext.define('TM.view.plan.Form', {
2
+ requires: ['Ext.ux.TreeCombo'],
3
+ extend: 'Ext.form.Panel',
4
+ xtype: 'plan_form',
5
+
6
+ defaultPlanType: 'yearly',
7
+ defaultBeginToRemind: 0,
8
+
9
+ defaults: {
10
+ xtype: 'fieldset',
11
+ margin: '5 10'
12
+ },
13
+
14
+ items: [{
15
+ itemId: 'base-info',
16
+ title: '基本信息',
17
+ layout: {
18
+ type: 'table',
19
+ columns: 1
20
+ },
21
+ defaults: {
22
+ xtype: 'textfield',
23
+ labelAlign: 'right',
24
+ margin: '10 0',
25
+ width: 510
26
+ },
27
+
28
+ items: [{
29
+ fieldLabel: '计划名称',
30
+ name: 'name',
31
+ allowBlank: false
32
+ }, {
33
+ xtype: 'assignee_treecombo',
34
+ fieldLabel: '计划执行人',
35
+ name: 'assignables_attributes',
36
+ store: Ext.getStore('TM.store.Assignees').toTreeStore()
37
+ }, {
38
+ fieldLabel: '计划类型',
39
+ name: 'plan_type',
40
+ store: 'TM.store.Types',
41
+ editable: false,
42
+ valueField: 'value',
43
+ xtype: 'combo',
44
+ blankText: '请选择计划类型!',
45
+ allowBlank: false
46
+ }, {
47
+ fieldLabel: '横向指标',
48
+ name: 'data.x'
49
+ }, {
50
+ fieldLabel: '纵向指标',
51
+ name: 'data.y'
52
+ }, {
53
+ fieldLabel: '生效时间',
54
+ xtype: 'datefield',
55
+ editable: false,
56
+ anchor: '100%',
57
+ format: 'Y/m/d',
58
+ name: 'enabled_at'
59
+ }, {
60
+ fieldLabel: '完成前几天提醒',
61
+ emptyText: '计划完成前多少天开始提醒,此处为倒计时。',
62
+ name: 'begin_to_remind'
63
+ }, {
64
+ fieldLabel: '是否自动完成',
65
+ xtype: 'checkbox',
66
+ name: 'autocompletable'
67
+ }]
68
+ }, {
69
+ xtype: 'fieldset',
70
+ itemId: 'deadline',
71
+ title: '计划完成截至时限',
72
+ layout: {
73
+ type: 'table',
74
+ columns: 2
75
+ },
76
+ defaults: {
77
+ labelAlign: 'right',
78
+ },
79
+ items: [{
80
+ fieldLabel: '月',
81
+ name: 'data.deadline_month',
82
+ xtype: 'combo',
83
+ store: 'TM.store.Months',
84
+ valueField: 'value',
85
+ editable: false
86
+ }, {
87
+ fieldLabel: '日',
88
+ name: 'data.deadline_day',
89
+ store: 'TM.store.Days',
90
+ valueField: 'value',
91
+ xtype: 'combo',
92
+ editable: false
93
+ }, {
94
+ fieldLabel: '时',
95
+ name: 'data.deadline_hour',
96
+ store: 'TM.store.Hours',
97
+ valueField: 'value',
98
+ xtype: 'combo',
99
+ editable: false
100
+ }, {
101
+ fieldLabel: '分',
102
+ name: 'data.deadline_minute',
103
+ store: 'TM.store.Minutes',
104
+ valueField: 'value',
105
+ xtype: 'combo',
106
+ editable: false
107
+ }]
108
+ }],
109
+
110
+ buttons: [{
111
+ text: '保存',
112
+ formBind: true,
113
+ action: 'save'
114
+ }, {
115
+ text: '取消',
116
+ action: 'cancel'
117
+ }],
118
+
119
+ getValues: function() {
120
+ var values = this.callParent();
121
+
122
+ values.data = {};
123
+ ['month', 'day', 'hour', 'minute'].forEach(function(name) {
124
+ values.data['deadline_' + name] = this.getDeadlineCombo('data.deadline_' + name).getValue();
125
+ delete values['data.deadline_' + name];
126
+ }, this);
127
+
128
+ ['x', 'y'].forEach(function(name) {
129
+ values.data[name] = this.query('textfield[name="data.' + name + '"]')[0].getValue();
130
+ delete values['data.' + name];
131
+ }, this);
132
+
133
+ return values;
134
+ },
135
+
136
+ loadRecord: function(record) {
137
+ this.callParent(arguments);
138
+
139
+ this.refreshDeadline(record.get('plan_type'));
140
+
141
+ ['month', 'day', 'hour', 'minute'].forEach(function(name) {
142
+ this.getDeadlineCombo('data.deadline_' + name).setValue(record.get('data')['deadline_' + name]);
143
+ }, this);
144
+
145
+ ['x', 'y'].forEach(function(name) {
146
+ this.query('textfield[name="data.' + name + '"]')[0].setValue(record.get('data')[name]);
147
+ }, this);
148
+
149
+ this.checkSelectedAssignees(record.get('assignees'));
150
+ },
151
+
152
+ // @protected
153
+ initComponent: function() {
154
+ this.callParent(arguments);
155
+
156
+ var planTypeCombo = this.query('fieldset combo[name="plan_type"]')[0];
157
+ planTypeCombo.setValue(this.defaultPlanType);
158
+ planTypeCombo.on('change', this.onPlanTypeChange, this);
159
+
160
+ var beginToRemindField = this.query('fieldset textfield[name="begin_to_remind"]')[0];
161
+ beginToRemindField.setValue(this.defaultBeginToRemind);
162
+
163
+ this.refreshDeadline(this.defaultPlanType);
164
+ },
165
+
166
+ // @private
167
+ checkSelectedAssignees: function(assignees) {
168
+ if(typeof assignees === 'undefined') return;
169
+
170
+ var values = [];
171
+ assignees.forEach(function(a) {
172
+ var node = this.getAssigneesTreeCombo().tree.getRootNode().findChildBy(function(node) {
173
+ with(node.raw) {
174
+ return record.get('id') == a.id &&
175
+ record.get('name') == a.name
176
+ }
177
+ }, this, true);
178
+
179
+ if(node) {
180
+ values.push({
181
+ assignee_id: node.raw.record.get('id'),
182
+ assignee_type: node.raw.record.get('class_name')
183
+ });
184
+ }
185
+ }, this);
186
+
187
+ console.log(values);
188
+ this.getAssigneesTreeCombo().setValue(values);
189
+ },
190
+
191
+ //@private
192
+ onPlanTypeChange: function(combo, newValue) {
193
+ this.refreshDeadline(newValue);
194
+ },
195
+
196
+ // @private
197
+ refreshDeadline: function(planType) {
198
+ switch(planType) {
199
+ case 'yearly':
200
+ this.showYearlyDeadlineCombos();
201
+ break;
202
+ case 'quarterly':
203
+ this.showQuarterlyDeadlineCombos();
204
+ break;
205
+ case 'monthly':
206
+ this.showMonthlyDeadlineCombos();
207
+ break;
208
+ case 'weekly':
209
+ this.showWeeklyDeadlineCombos();
210
+ break;
211
+ case 'daily':
212
+ this.showDailyDeadlineCombos();
213
+ break;
214
+ default:
215
+ throw 'Invalid plan_type ' + planType;
216
+ }
217
+
218
+ ['month', 'day', 'hour', 'minute'].forEach(function(name) {
219
+ this.getDeadlineCombo('data.deadline_' + name).setValue(null);
220
+ }, this);
221
+ },
222
+
223
+ // @private
224
+ showYearlyDeadlineCombos: function() {
225
+ this.getDeadlineCombo('data.deadline_month').
226
+ bindStore(Ext.getStore('TM.store.Months'));
227
+ this.getDeadlineCombo('data.deadline_day').
228
+ bindStore(Ext.getStore('TM.store.Days'));
229
+
230
+ this.showDeadlineCombos(["month", "day", "hour", "minute"]);
231
+ },
232
+
233
+ // @private
234
+ showQuarterlyDeadlineCombos: function() {
235
+ this.getDeadlineCombo('data.deadline_month').
236
+ bindStore(Ext.getStore('TM.store.QuarterlyMonths'));
237
+ this.getDeadlineCombo('data.deadline_day').
238
+ bindStore(Ext.getStore('TM.store.Days'));
239
+
240
+ this.showDeadlineCombos(["month", "day", "hour", "minute"]);
241
+ },
242
+
243
+ // @private
244
+ showMonthlyDeadlineCombos: function() {
245
+ this.getDeadlineCombo('data.deadline_day').
246
+ bindStore(Ext.getStore('TM.store.Days'));
247
+
248
+ this.showDeadlineCombos(["day", "hour", "minute"]);
249
+ this.hideDeadlineCombos(["month"]);
250
+ },
251
+
252
+ // @private
253
+ showWeeklyDeadlineCombos: function() {
254
+ this.getDeadlineCombo('data.deadline_day').
255
+ bindStore(Ext.getStore('TM.store.WeekDays'));
256
+
257
+ this.showDeadlineCombos(["day", "hour", "minute"]);
258
+ this.hideDeadlineCombos(["month"]);
259
+ },
260
+
261
+ // @private
262
+ showDailyDeadlineCombos: function() {
263
+ this.showDeadlineCombos(["hour", "minute"]);
264
+ this.hideDeadlineCombos(["month", "day"]);
265
+ },
266
+
267
+ // @private
268
+ getDeadlineCombo: function(name) {
269
+ return this.query('#deadline combo[name="' + name + '"]')[0];
270
+ },
271
+
272
+ // @private
273
+ showDeadlineCombos: function(combos) {
274
+ combos.forEach(function(c) {
275
+ this.getDeadlineCombo('data.deadline_' + c).show();
276
+ }, this);
277
+ },
278
+
279
+ // @private
280
+ hideDeadlineCombos: function(combos) {
281
+ combos.forEach(function(c) {
282
+ this.getDeadlineCombo('data.deadline_' + c).hide();
283
+ }, this);
284
+ },
285
+
286
+ // @private
287
+ getAssigneesTreeCombo: function() {
288
+ return this.query('assignee_treecombo')[0];
289
+ }
290
+ });