task-manager 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.md +4 -0
- data/Rakefile +27 -0
- data/app/assets/images/task-manager/icons/add.png +0 -0
- data/app/assets/images/task-manager/icons/delete.png +0 -0
- data/app/assets/images/task-manager/icons/edit.png +0 -0
- data/app/assets/javascripts/task-manager/application.js +43 -0
- data/app/assets/javascripts/task-manager/extjs/app/controller/Plans.js +359 -0
- data/app/assets/javascripts/task-manager/extjs/app/controller/Tasks.js +56 -0
- data/app/assets/javascripts/task-manager/extjs/app/helper/application_helper.js +24 -0
- data/app/assets/javascripts/task-manager/extjs/app/model/Assignee.js +19 -0
- data/app/assets/javascripts/task-manager/extjs/app/model/Plan.js +195 -0
- data/app/assets/javascripts/task-manager/extjs/app/model/Task.js +23 -0
- data/app/assets/javascripts/task-manager/extjs/app/store/Assignees.js +53 -0
- data/app/assets/javascripts/task-manager/extjs/app/store/AssigneesTree.js +3 -0
- data/app/assets/javascripts/task-manager/extjs/app/store/Booleans.js +9 -0
- data/app/assets/javascripts/task-manager/extjs/app/store/Days.js +38 -0
- data/app/assets/javascripts/task-manager/extjs/app/store/Hours.js +31 -0
- data/app/assets/javascripts/task-manager/extjs/app/store/Minutes.js +67 -0
- data/app/assets/javascripts/task-manager/extjs/app/store/Months.js +19 -0
- data/app/assets/javascripts/task-manager/extjs/app/store/Plans.js +6 -0
- data/app/assets/javascripts/task-manager/extjs/app/store/QuarterlyMonths.js +10 -0
- data/app/assets/javascripts/task-manager/extjs/app/store/Statuses.js +11 -0
- data/app/assets/javascripts/task-manager/extjs/app/store/Tasks.js +6 -0
- data/app/assets/javascripts/task-manager/extjs/app/store/Types.js +12 -0
- data/app/assets/javascripts/task-manager/extjs/app/store/WeekDays.js +14 -0
- data/app/assets/javascripts/task-manager/extjs/app/view/plan/AssignablesWindow.js +23 -0
- data/app/assets/javascripts/task-manager/extjs/app/view/plan/Edit.js +189 -0
- data/app/assets/javascripts/task-manager/extjs/app/view/plan/EditWindow.js +21 -0
- data/app/assets/javascripts/task-manager/extjs/app/view/plan/Grid.js +92 -0
- data/app/assets/javascripts/task-manager/extjs/app/view/plan/Index.js +24 -0
- data/app/assets/javascripts/task-manager/extjs/app/view/plan/New.js +190 -0
- data/app/assets/javascripts/task-manager/extjs/app/view/plan/Search.js +132 -0
- data/app/assets/javascripts/task-manager/extjs/app/view/plan/SelectAssignables.js +22 -0
- data/app/assets/javascripts/task-manager/extjs/app/view/plan/SelectAssignablesGrid.js +22 -0
- data/app/assets/javascripts/task-manager/extjs/app/view/plan/SelectAssignablesTree.js +9 -0
- data/app/assets/javascripts/task-manager/extjs/app/view/plan/Window.js +21 -0
- data/app/assets/javascripts/task-manager/extjs/app/view/task/Grid.js +62 -0
- data/app/assets/javascripts/task-manager/extjs/app/view/task/Index.js +21 -0
- data/app/assets/javascripts/task-manager/extjs/app/view/task/Search.js +148 -0
- data/app/assets/javascripts/task-manager/extjs/lib/ux/MultiSelectablePagingGrid.js +20 -0
- data/app/assets/javascripts/task-manager/extjs/lib/ux/RowExpander.js +230 -0
- data/app/assets/stylesheets/task-manager/application.css.scss +13 -0
- data/app/assets/stylesheets/task-manager/extjs.css.scss +43 -0
- data/app/controllers/task_manager/api/v1/plans_controller.rb +251 -0
- data/app/controllers/task_manager/api/v1/tasks_controller.rb +82 -0
- data/app/controllers/task_manager/application_controller.rb +4 -0
- data/app/helpers/task_manager/application_helper.rb +4 -0
- data/app/models/task_manager/assignable.rb +10 -0
- data/app/models/task_manager/callable.rb +10 -0
- data/app/models/task_manager/plan.rb +114 -0
- data/app/models/task_manager/task.rb +81 -0
- data/app/serializers/task_manager/plan_serializer.rb +8 -0
- data/app/serializers/task_manager/task_serializer.rb +8 -0
- data/app/views/layouts/task-manager/application.html.erb +14 -0
- data/config/routes.rb +8 -0
- data/db/migrate/20121102054723_setup_hstore.rb +9 -0
- data/db/migrate/20121102055137_create_task_manager_plans.rb +16 -0
- data/db/migrate/20121102142657_create_task_manager_assignables.rb +13 -0
- data/db/migrate/20121102150720_create_task_manager_callables.rb +13 -0
- data/db/migrate/20121105170602_create_task_manager_tasks.rb +18 -0
- data/lib/task-manager.rb +37 -0
- data/lib/task-manager/api_constraints.rb +12 -0
- data/lib/task-manager/deadline_calculator.rb +22 -0
- data/lib/task-manager/deadline_validator.rb +27 -0
- data/lib/task-manager/engine.rb +5 -0
- data/lib/task-manager/version.rb +3 -0
- data/lib/tasks/task-manager_tasks.rake +4 -0
- metadata +327 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
Ext.define('TM.view.task.Index', {
|
2
|
+
extend: 'Ext.panel.Panel',
|
3
|
+
xtype: 'task_index',
|
4
|
+
|
5
|
+
requires: ['TM.view.task.Search'],
|
6
|
+
title: '任务管理',
|
7
|
+
closable: true,
|
8
|
+
|
9
|
+
// store: '',
|
10
|
+
layout: {
|
11
|
+
type: 'vbox',
|
12
|
+
align: 'stretch'
|
13
|
+
},
|
14
|
+
|
15
|
+
items: [{
|
16
|
+
xtype: 'task_search'
|
17
|
+
}, {
|
18
|
+
xtype: 'task_grid',
|
19
|
+
flex: 1
|
20
|
+
}]
|
21
|
+
})
|
@@ -0,0 +1,148 @@
|
|
1
|
+
Ext.define('TM.view.task.Search', {
|
2
|
+
extend: 'Ext.form.Panel',
|
3
|
+
xtype: 'task_search',
|
4
|
+
|
5
|
+
border: 0,
|
6
|
+
bodyPadding: '5 5 0',
|
7
|
+
|
8
|
+
items: [{
|
9
|
+
xtype: 'fieldset',
|
10
|
+
id: 'fieldset',
|
11
|
+
title: '查询',
|
12
|
+
|
13
|
+
layout: {
|
14
|
+
type: 'form',
|
15
|
+
border: 0,
|
16
|
+
margin: 2
|
17
|
+
},
|
18
|
+
items: [{
|
19
|
+
border: 0,
|
20
|
+
items: [{
|
21
|
+
layout: 'column',
|
22
|
+
border: 0,
|
23
|
+
defaults: {
|
24
|
+
xtype: 'textfield',
|
25
|
+
id: 'textfield',
|
26
|
+
labelAlign: 'right',
|
27
|
+
width: 300,
|
28
|
+
labelWidth: 130
|
29
|
+
},
|
30
|
+
items: [{
|
31
|
+
fieldLabel: '名称',
|
32
|
+
name: 'q[name_cont]'
|
33
|
+
}, {
|
34
|
+
fieldLabel: '类型',
|
35
|
+
editable: false,
|
36
|
+
xtype: 'combo',
|
37
|
+
id: 'types',
|
38
|
+
store: 'TM.store.Types',
|
39
|
+
valueField: 'value',
|
40
|
+
name: 'q[task_type_eq]'
|
41
|
+
}, {
|
42
|
+
fieldLabel: '状态',
|
43
|
+
xtype: 'combo',
|
44
|
+
editable: false,
|
45
|
+
valueField: 'value',
|
46
|
+
store: 'TM.store.Statuses',
|
47
|
+
name: 'q[status_eq]'
|
48
|
+
}]
|
49
|
+
}, {
|
50
|
+
layout: 'column',
|
51
|
+
border: 0,
|
52
|
+
defaults: {
|
53
|
+
border: 0,
|
54
|
+
labelAlign: 'right',
|
55
|
+
width: 300,
|
56
|
+
labelWidth: 130
|
57
|
+
},
|
58
|
+
items: [{
|
59
|
+
layout: 'column',
|
60
|
+
border: 0,
|
61
|
+
defaults: {
|
62
|
+
xtype: 'datefield',
|
63
|
+
id: 'datefield',
|
64
|
+
labelAlign: 'right',
|
65
|
+
width: 300,
|
66
|
+
labelWidth: 130
|
67
|
+
},
|
68
|
+
items: [{
|
69
|
+
fieldLabel: '完成时间 从',
|
70
|
+
format: 'Y-m-d',
|
71
|
+
editable: false,
|
72
|
+
name: 'q[finished_at_gteq]',
|
73
|
+
id: 'last_task'
|
74
|
+
}, {
|
75
|
+
fieldLabel: '截至时间 从',
|
76
|
+
format: 'Y-m-d',
|
77
|
+
xtype: 'datefield',
|
78
|
+
editable: false,
|
79
|
+
name: 'q[deadline_gteq]'
|
80
|
+
}]
|
81
|
+
}, {
|
82
|
+
layout: 'column',
|
83
|
+
border: 0,
|
84
|
+
defaults: {
|
85
|
+
xtype: 'datefield',
|
86
|
+
labelAlign: 'right',
|
87
|
+
width: 300,
|
88
|
+
labelWidth: 130
|
89
|
+
},
|
90
|
+
items: [{
|
91
|
+
fieldLabel: '至',
|
92
|
+
format: 'Y-m-d',
|
93
|
+
editable: false,
|
94
|
+
name: 'q[finished_at_lteq]'
|
95
|
+
}, {
|
96
|
+
fieldLabel: '至',
|
97
|
+
format: 'Y-m-d',
|
98
|
+
xtype: 'datefield',
|
99
|
+
editable: false,
|
100
|
+
name: 'q[deadline_lteq]'
|
101
|
+
}]
|
102
|
+
}, {
|
103
|
+
layout: 'hbox',
|
104
|
+
margin: '20 0 0 60',
|
105
|
+
items: [{
|
106
|
+
xtype: 'button',
|
107
|
+
formBind: true,
|
108
|
+
width: 60,
|
109
|
+
text: '查询',
|
110
|
+
action: 'query'
|
111
|
+
}, {
|
112
|
+
xtype: 'button',
|
113
|
+
margin: '0 0 0 20',
|
114
|
+
width: 60,
|
115
|
+
text: '重置',
|
116
|
+
action: 'reset'
|
117
|
+
}]
|
118
|
+
}]
|
119
|
+
}],
|
120
|
+
}]
|
121
|
+
}],
|
122
|
+
|
123
|
+
// buttons: [{
|
124
|
+
// formBind: true,
|
125
|
+
// width: 60,
|
126
|
+
// text: '查询',
|
127
|
+
// action: 'query'
|
128
|
+
// }, {
|
129
|
+
// margin: '0 0 0 20',
|
130
|
+
// width: 60,
|
131
|
+
// text: '重置',
|
132
|
+
// action: 'reset'
|
133
|
+
// }],
|
134
|
+
|
135
|
+
hasQueryParams: function() {
|
136
|
+
var hasParams = false;
|
137
|
+
Ext.Object.each(this.getValues(), function(key, value) {
|
138
|
+
if(value) {
|
139
|
+
hasParams = true;
|
140
|
+
|
141
|
+
// Break each
|
142
|
+
return false;
|
143
|
+
}
|
144
|
+
});
|
145
|
+
|
146
|
+
return hasParams;
|
147
|
+
}
|
148
|
+
});
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Ext.define('Ext.ux.MultiSelectablePagingGrid', {
|
2
|
+
extend: 'Ext.grid.Panel',
|
3
|
+
selType: 'checkboxmodel',
|
4
|
+
selModel: {
|
5
|
+
mode: 'MULTI',
|
6
|
+
allowDeselect: true,
|
7
|
+
checkOnly: true
|
8
|
+
},
|
9
|
+
|
10
|
+
initComponent: function() {
|
11
|
+
this.dockedItems = [{
|
12
|
+
xtype: 'pagingtoolbar',
|
13
|
+
store: this.store,
|
14
|
+
dock: 'bottom',
|
15
|
+
displayInfo: true
|
16
|
+
}];
|
17
|
+
|
18
|
+
this.callParent(arguments);
|
19
|
+
}
|
20
|
+
});
|
@@ -0,0 +1,230 @@
|
|
1
|
+
// feature idea to enable Ajax loading and then the content
|
2
|
+
// cache would actually make sense. Should we dictate that they use
|
3
|
+
// data or support raw html as well?
|
4
|
+
|
5
|
+
/**
|
6
|
+
* @class Ext.ux.RowExpander
|
7
|
+
* @extends Ext.AbstractPlugin
|
8
|
+
* Plugin (ptype = 'rowexpander') that adds the ability to have a Column in a grid which enables
|
9
|
+
* a second row body which expands/contracts. The expand/contract behavior is configurable to react
|
10
|
+
* on clicking of the column, double click of the row, and/or hitting enter while a row is selected.
|
11
|
+
*
|
12
|
+
* @ptype rowexpander
|
13
|
+
*/
|
14
|
+
Ext.define('Ext.ux.RowExpander', {
|
15
|
+
extend: 'Ext.AbstractPlugin',
|
16
|
+
|
17
|
+
requires: [
|
18
|
+
'Ext.grid.feature.RowBody',
|
19
|
+
'Ext.grid.feature.RowWrap'
|
20
|
+
],
|
21
|
+
|
22
|
+
alias: 'plugin.rowexpander',
|
23
|
+
|
24
|
+
rowBodyTpl: null,
|
25
|
+
|
26
|
+
/**
|
27
|
+
* @cfg {Boolean} expandOnEnter
|
28
|
+
* <tt>true</tt> to toggle selected row(s) between expanded/collapsed when the enter
|
29
|
+
* key is pressed (defaults to <tt>true</tt>).
|
30
|
+
*/
|
31
|
+
expandOnEnter: true,
|
32
|
+
|
33
|
+
/**
|
34
|
+
* @cfg {Boolean} expandOnDblClick
|
35
|
+
* <tt>true</tt> to toggle a row between expanded/collapsed when double clicked
|
36
|
+
* (defaults to <tt>true</tt>).
|
37
|
+
*/
|
38
|
+
expandOnDblClick: true,
|
39
|
+
|
40
|
+
/**
|
41
|
+
* @cfg {Boolean} selectRowOnExpand
|
42
|
+
* <tt>true</tt> to select a row when clicking on the expander icon
|
43
|
+
* (defaults to <tt>false</tt>).
|
44
|
+
*/
|
45
|
+
selectRowOnExpand: false,
|
46
|
+
|
47
|
+
rowBodyTrSelector: '.x-grid-rowbody-tr',
|
48
|
+
rowBodyHiddenCls: 'x-grid-row-body-hidden',
|
49
|
+
rowCollapsedCls: 'x-grid-row-collapsed',
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
renderer: function(value, metadata, record, rowIdx, colIdx) {
|
54
|
+
if (colIdx === 0) {
|
55
|
+
metadata.tdCls = 'x-grid-td-expander';
|
56
|
+
}
|
57
|
+
return '<div class="x-grid-row-expander"> </div>';
|
58
|
+
},
|
59
|
+
|
60
|
+
/**
|
61
|
+
* @event expandbody
|
62
|
+
* <b<Fired through the grid's View</b>
|
63
|
+
* @param {HTMLElement} rowNode The <tr> element which owns the expanded row.
|
64
|
+
* @param {Ext.data.Model} record The record providing the data.
|
65
|
+
* @param {HTMLElement} expandRow The <tr> element containing the expanded data.
|
66
|
+
*/
|
67
|
+
/**
|
68
|
+
* @event collapsebody
|
69
|
+
* <b<Fired through the grid's View.</b>
|
70
|
+
* @param {HTMLElement} rowNode The <tr> element which owns the expanded row.
|
71
|
+
* @param {Ext.data.Model} record The record providing the data.
|
72
|
+
* @param {HTMLElement} expandRow The <tr> element containing the expanded data.
|
73
|
+
*/
|
74
|
+
|
75
|
+
constructor: function() {
|
76
|
+
this.callParent(arguments);
|
77
|
+
var grid = this.getCmp();
|
78
|
+
this.recordsExpanded = {};
|
79
|
+
// <debug>
|
80
|
+
if (!this.rowBodyTpl) {
|
81
|
+
Ext.Error.raise("The 'rowBodyTpl' config is required and is not defined.");
|
82
|
+
}
|
83
|
+
// </debug>
|
84
|
+
// TODO: if XTemplate/Template receives a template as an arg, should
|
85
|
+
// just return it back!
|
86
|
+
var rowBodyTpl = Ext.create('Ext.XTemplate', this.rowBodyTpl),
|
87
|
+
features = [{
|
88
|
+
ftype: 'rowbody',
|
89
|
+
columnId: this.getHeaderId(),
|
90
|
+
recordsExpanded: this.recordsExpanded,
|
91
|
+
rowBodyHiddenCls: this.rowBodyHiddenCls,
|
92
|
+
rowCollapsedCls: this.rowCollapsedCls,
|
93
|
+
getAdditionalData: this.getRowBodyFeatureData,
|
94
|
+
getRowBodyContents: function(data) {
|
95
|
+
return rowBodyTpl.applyTemplate(data);
|
96
|
+
}
|
97
|
+
},{
|
98
|
+
ftype: 'rowwrap'
|
99
|
+
}];
|
100
|
+
|
101
|
+
if (grid.features) {
|
102
|
+
grid.features = features.concat(grid.features);
|
103
|
+
} else {
|
104
|
+
grid.features = features;
|
105
|
+
}
|
106
|
+
|
107
|
+
// NOTE: features have to be added before init (before Table.initComponent)
|
108
|
+
},
|
109
|
+
|
110
|
+
init: function(grid) {
|
111
|
+
this.callParent(arguments);
|
112
|
+
|
113
|
+
// Columns have to be added in init (after columns has been used to create the
|
114
|
+
// headerCt). Otherwise, shared column configs get corrupted, e.g., if put in the
|
115
|
+
// prototype.
|
116
|
+
grid.headerCt.insert(0, this.getHeaderConfig());
|
117
|
+
grid.on('render', this.bindView, this, {single: true});
|
118
|
+
},
|
119
|
+
|
120
|
+
getHeaderId: function() {
|
121
|
+
if (!this.headerId) {
|
122
|
+
this.headerId = Ext.id();
|
123
|
+
}
|
124
|
+
return this.headerId;
|
125
|
+
},
|
126
|
+
|
127
|
+
getRowBodyFeatureData: function(data, idx, record, orig) {
|
128
|
+
var o = Ext.grid.feature.RowBody.prototype.getAdditionalData.apply(this, arguments),
|
129
|
+
id = this.columnId;
|
130
|
+
o.rowBodyColspan = o.rowBodyColspan - 1;
|
131
|
+
o.rowBody = this.getRowBodyContents(data);
|
132
|
+
o.rowCls = this.recordsExpanded[record.internalId] ? '' : this.rowCollapsedCls;
|
133
|
+
o.rowBodyCls = this.recordsExpanded[record.internalId] ? '' : this.rowBodyHiddenCls;
|
134
|
+
o[id + '-tdAttr'] = ' valign="top" rowspan="2" ';
|
135
|
+
if (orig[id+'-tdAttr']) {
|
136
|
+
o[id+'-tdAttr'] += orig[id+'-tdAttr'];
|
137
|
+
}
|
138
|
+
return o;
|
139
|
+
},
|
140
|
+
|
141
|
+
bindView: function() {
|
142
|
+
var view = this.getCmp().getView(),
|
143
|
+
viewEl;
|
144
|
+
|
145
|
+
if (!view.rendered) {
|
146
|
+
view.on('render', this.bindView, this, {single: true});
|
147
|
+
} else {
|
148
|
+
viewEl = view.getEl();
|
149
|
+
if (this.expandOnEnter) {
|
150
|
+
this.keyNav = Ext.create('Ext.KeyNav', viewEl, {
|
151
|
+
'enter' : this.onEnter,
|
152
|
+
scope: this
|
153
|
+
});
|
154
|
+
}
|
155
|
+
if (this.expandOnDblClick) {
|
156
|
+
view.on('itemdblclick', this.onDblClick, this);
|
157
|
+
}
|
158
|
+
this.view = view;
|
159
|
+
}
|
160
|
+
},
|
161
|
+
|
162
|
+
onEnter: function(e) {
|
163
|
+
var view = this.view,
|
164
|
+
ds = view.store,
|
165
|
+
sm = view.getSelectionModel(),
|
166
|
+
sels = sm.getSelection(),
|
167
|
+
ln = sels.length,
|
168
|
+
i = 0,
|
169
|
+
rowIdx;
|
170
|
+
|
171
|
+
for (; i < ln; i++) {
|
172
|
+
rowIdx = ds.indexOf(sels[i]);
|
173
|
+
this.toggleRow(rowIdx);
|
174
|
+
}
|
175
|
+
},
|
176
|
+
|
177
|
+
toggleRow: function(rowIdx) {
|
178
|
+
var rowNode = this.view.getNode(rowIdx),
|
179
|
+
row = Ext.get(rowNode),
|
180
|
+
nextBd = Ext.get(row).down(this.rowBodyTrSelector),
|
181
|
+
record = this.view.getRecord(rowNode),
|
182
|
+
grid = this.getCmp();
|
183
|
+
|
184
|
+
if (row.hasCls(this.rowCollapsedCls)) {
|
185
|
+
row.removeCls(this.rowCollapsedCls);
|
186
|
+
nextBd.removeCls(this.rowBodyHiddenCls);
|
187
|
+
this.recordsExpanded[record.internalId] = true;
|
188
|
+
this.view.fireEvent('expandbody', rowNode, record, nextBd.dom);
|
189
|
+
} else {
|
190
|
+
row.addCls(this.rowCollapsedCls);
|
191
|
+
nextBd.addCls(this.rowBodyHiddenCls);
|
192
|
+
this.recordsExpanded[record.internalId] = false;
|
193
|
+
this.view.fireEvent('collapsebody', rowNode, record, nextBd.dom);
|
194
|
+
}
|
195
|
+
},
|
196
|
+
|
197
|
+
onDblClick: function(view, cell, rowIdx, cellIndex, e) {
|
198
|
+
|
199
|
+
this.toggleRow(rowIdx);
|
200
|
+
},
|
201
|
+
|
202
|
+
getHeaderConfig: function() {
|
203
|
+
var me = this,
|
204
|
+
toggleRow = Ext.Function.bind(me.toggleRow, me),
|
205
|
+
selectRowOnExpand = me.selectRowOnExpand;
|
206
|
+
|
207
|
+
return {
|
208
|
+
id: this.getHeaderId(),
|
209
|
+
width: 24,
|
210
|
+
sortable: false,
|
211
|
+
resizable: false,
|
212
|
+
draggable: false,
|
213
|
+
hideable: false,
|
214
|
+
menuDisabled: true,
|
215
|
+
cls: Ext.baseCSSPrefix + 'grid-header-special',
|
216
|
+
renderer: function(value, metadata) {
|
217
|
+
metadata.tdCls = Ext.baseCSSPrefix + 'grid-cell-special';
|
218
|
+
|
219
|
+
return '<div class="' + Ext.baseCSSPrefix + 'grid-row-expander"> </div>';
|
220
|
+
},
|
221
|
+
processEvent: function(type, view, cell, recordIndex, cellIndex, e) {
|
222
|
+
if (type == "mousedown" && e.getTarget('.x-grid-row-expander')) {
|
223
|
+
var row = e.getTarget('.x-grid-row');
|
224
|
+
toggleRow(row);
|
225
|
+
return selectRowOnExpand;
|
226
|
+
}
|
227
|
+
}
|
228
|
+
};
|
229
|
+
}
|
230
|
+
});
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
9
|
+
* compiled file, but it's generally better to create a new file per style scope.
|
10
|
+
*
|
11
|
+
*= require_self
|
12
|
+
*= require ./extjs
|
13
|
+
*/
|
@@ -0,0 +1,43 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
9
|
+
* compiled file, but it's generally better to create a new file per style scope.
|
10
|
+
*
|
11
|
+
*= require_self
|
12
|
+
*/
|
13
|
+
.btn-add-icon {
|
14
|
+
background: url(image_path('task-manager/icons/add.png')) no-repeat;
|
15
|
+
}
|
16
|
+
.btn-edit-icon {
|
17
|
+
background: url(image_path('task-manager/icons/edit.png')) no-repeat;
|
18
|
+
}
|
19
|
+
.btn-delete-icon {
|
20
|
+
background: url(image_path('task-manager/icons/delete.png')) no-repeat;
|
21
|
+
}
|
22
|
+
table.data {
|
23
|
+
border: 1px solid #aaa;
|
24
|
+
width: 100%;
|
25
|
+
margin: 5px;
|
26
|
+
margin-left: 60px;
|
27
|
+
tr {
|
28
|
+
td.title {
|
29
|
+
font-weight: bold;
|
30
|
+
font-size: 14px;
|
31
|
+
border-right: 1px solid #aaa;
|
32
|
+
text-align: center;
|
33
|
+
width: 100px;
|
34
|
+
}
|
35
|
+
td.name {
|
36
|
+
text-align: right;
|
37
|
+
width: 70px;
|
38
|
+
}
|
39
|
+
td {
|
40
|
+
padding: 3px;
|
41
|
+
}
|
42
|
+
}
|
43
|
+
}
|