Grid.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /**
  2. * @class SimpleTasks.view.tasks.List
  3. * @extends Ext.grid.Panel
  4. * The tasks list view. A grid that displays a list of tasks.
  5. */
  6. Ext.define('SimpleTasks.view.tasks.Grid', {
  7. extend: 'Ext.grid.Panel',
  8. xtype: 'taskGrid',
  9. requires: [
  10. 'SimpleTasks.ux.DragDrop',
  11. 'SimpleTasks.ux.CheckColumn',
  12. 'SimpleTasks.ux.ReminderColumn',
  13. 'Ext.grid.plugin.CellEditing',
  14. 'Ext.grid.column.Action',
  15. 'Ext.grid.column.Date',
  16. 'Ext.grid.feature.Grouping',
  17. 'Ext.grid.plugin.DragDrop',
  18. 'Ext.ux.TreePicker'
  19. ],
  20. store: 'Tasks',
  21. viewConfig: {
  22. plugins: {
  23. ptype: 'gridviewdragdrop',
  24. ddGroup: 'task',
  25. dragText: 'Drag task to change list',
  26. enableDrop: false
  27. },
  28. getRowClass: function(record, rowIndex, rowParams, store){
  29. var due = record.get('due');
  30. if(record.get('done')) {
  31. return 'tasks-completed-task';
  32. } else if(due && (due < Ext.Date.clearTime(new Date()))) {
  33. return 'tasks-overdue-task';
  34. }
  35. }
  36. },
  37. dockedItems: [
  38. {
  39. xtype: 'taskForm',
  40. dock: 'top',
  41. // the grid's column headers are a docked item with a weight of 100.
  42. // giving this a weight of 101 causes it to be docked under the column headers
  43. weight: 101,
  44. bodyStyle: {
  45. 'background-color': '#E4E5E7'
  46. }
  47. }
  48. ],
  49. initComponent: function() {
  50. var me = this,
  51. cellEditingPlugin = Ext.create('Ext.grid.plugin.CellEditing'),
  52. groupingFeature = Ext.create('Ext.grid.feature.Grouping', {
  53. groupHeaderTpl: [
  54. '{groupValue:this.renderDueDate}',
  55. {
  56. renderDueDate: me.renderDueDate
  57. }
  58. ],
  59. enableGroupingMenu: false
  60. });
  61. me.plugins = [cellEditingPlugin];
  62. me.features = [groupingFeature];
  63. me.columns = {
  64. defaults: {
  65. draggable: false,
  66. resizable: false,
  67. hideable: false
  68. },
  69. items: [
  70. {
  71. xtype: 'checkcolumn',
  72. dataIndex: 'done',
  73. cls: 'tasks-icon-column-header tasks-done-column-header',
  74. width: 24,
  75. align: 'center',
  76. menuDisabled: true,
  77. sortable: false,
  78. listeners: {
  79. 'checkchange': Ext.bind(me.handleCheckChange, me)
  80. }
  81. },
  82. {
  83. text: 'Title',
  84. dataIndex: 'title',
  85. flex: 1,
  86. emptyCellText: '',
  87. editor: {
  88. xtype: 'textfield',
  89. selectOnFocus: true
  90. }
  91. },
  92. {
  93. text: 'List',
  94. dataIndex: 'list_id',
  95. width: 200,
  96. editor: {
  97. xtype: 'treepicker',
  98. displayField: 'name',
  99. store: Ext.create('SimpleTasks.store.Lists', {storeId: 'Lists-TaskGrid' })
  100. },
  101. renderer: me.renderList
  102. },
  103. {
  104. xtype: 'datecolumn',
  105. text: 'Due Date',
  106. dataIndex: 'due',
  107. width: 90,
  108. editor: 'datefield',
  109. format: 'n/j/Y',
  110. emptyCellText: ''
  111. },
  112. {
  113. xtype: 'remindercolumn',
  114. dataIndex: 'reminder',
  115. cls: 'tasks-icon-column-header tasks-reminder-column-header',
  116. width: 24,
  117. tooltip: 'Set Reminder',
  118. menuPosition: 'tr-br',
  119. menuDisabled: true,
  120. sortable: false,
  121. emptyCellText: '',
  122. listeners: {
  123. select: Ext.bind(me.handleReminderSelect, me)
  124. }
  125. },
  126. {
  127. xtype: 'actioncolumn',
  128. cls: 'tasks-icon-column-header tasks-edit-column-header',
  129. width: 24,
  130. icon: 'resources/images/edit_task.png',
  131. iconCls: 'x-hidden',
  132. tooltip: 'Edit',
  133. menuDisabled: true,
  134. sortable: false,
  135. handler: Ext.bind(me.handleEditClick, me)
  136. },
  137. {
  138. xtype: 'actioncolumn',
  139. cls: 'tasks-icon-column-header tasks-delete-column-header',
  140. width: 24,
  141. icon: 'resources/images/delete.png',
  142. iconCls: 'x-hidden',
  143. tooltip: 'Delete',
  144. menuDisabled: true,
  145. sortable: false,
  146. handler: Ext.bind(me.handleDeleteClick, me)
  147. }
  148. ]
  149. };
  150. me.callParent(arguments);
  151. me.addEvents(
  152. /**
  153. * @event editclick
  154. * Fires when an edit icon is clicked
  155. * @param {Ext.grid.View} view
  156. * @param {Number} rowIndex
  157. * @param {Number} colIndex
  158. * @param {Ext.grid.column.Action} column
  159. * @param {EventObject} e
  160. */
  161. 'editclick',
  162. /**
  163. * @event deleteclick
  164. * Fires when a delete icon is clicked
  165. * @param {Ext.grid.View} view
  166. * @param {Number} rowIndex
  167. * @param {Number} colIndex
  168. * @param {Ext.grid.column.Action} column
  169. * @param {EventObject} e
  170. */
  171. 'deleteclick',
  172. /**
  173. * @event edit
  174. * Fires when a record is edited using the CellEditing plugin or the checkcolumn
  175. * @param {SimpleTasks.model.Task} task The task record that was edited
  176. */
  177. 'recordedit',
  178. /**
  179. * @event reminderselect
  180. * Fires when a reminder time is selected from the reminder column's dropdown menu
  181. * @param {SimpleTasks.model.Task} task the underlying record of the row that was clicked to show the reminder menu
  182. * @param {String|Number} value The value that was selected
  183. */
  184. 'reminderselect'
  185. );
  186. cellEditingPlugin.on('edit', me.handleCellEdit, this);
  187. },
  188. /**
  189. * Handles a click on the edit icon
  190. * @private
  191. * @param {Ext.grid.View} gridView
  192. * @param {Number} rowIndex
  193. * @param {Number} colIndex
  194. * @param {Ext.grid.column.Action} column
  195. * @param {EventObject} e
  196. */
  197. handleEditClick: function(gridView, rowIndex, colIndex, column, e) {
  198. // Fire a "deleteclick" event with all the same args as this handler
  199. this.fireEvent('editclick', gridView, rowIndex, colIndex, column, e);
  200. },
  201. /**
  202. * Handles a click on a delete icon
  203. * @private
  204. * @param {Ext.grid.View} gridView
  205. * @param {Number} rowIndex
  206. * @param {Number} colIndex
  207. * @param {Ext.grid.column.Action} column
  208. * @param {EventObject} e
  209. */
  210. handleDeleteClick: function(gridView, rowIndex, colIndex, column, e) {
  211. // Fire a "deleteclick" event with all the same args as this handler
  212. this.fireEvent('deleteclick', gridView, rowIndex, colIndex, column, e);
  213. },
  214. /**
  215. * Handles a "checkchange" event on the "done" column
  216. * @private
  217. * @param {SimpleTasks.ux.CheckColumn} column
  218. * @param {Number} rowIndex
  219. * @param {Boolean} checked
  220. */
  221. handleCheckChange: function(column, rowIndex, checked) {
  222. this.fireEvent('recordedit', this.store.getAt(rowIndex));
  223. },
  224. /**
  225. * Handles a "select" event on the reminder column
  226. * @private
  227. * @param {SimpleTasks.model.Task} task the underlying record of the row that was clicked to show the reminder menu
  228. * @param {String|Number} value The value that was selected
  229. */
  230. handleReminderSelect: function(task, value) {
  231. this.fireEvent('reminderselect', task, value);
  232. },
  233. /**
  234. * Handles the CellEditing plugin's "edit" event
  235. * @private
  236. * @param {Ext.grid.plugin.CellEditing} editor
  237. * @param {Object} e an edit event object
  238. */
  239. handleCellEdit: function(editor, e) {
  240. this.fireEvent('recordedit', e.record);
  241. },
  242. /**
  243. * Reapplies the store's current filters. This is needed because when data in the store is modified
  244. * after filters have been applied, the filters do not automatically get applied to the new data.
  245. */
  246. refreshFilters: function() {
  247. var store = this.store,
  248. filters = store.filters;
  249. // save a reference to the existing task filters before clearing them
  250. filters = filters.getRange(0, filters.getCount() - 1);
  251. // clear the tasks store's filters and reapply them.
  252. store.clearFilter();
  253. store.filter(filters);
  254. },
  255. /**
  256. * Renderer for the list column
  257. * @private
  258. * @param {Number} value
  259. * @param {Object} metaData
  260. * @param {SimpleTasks.model.Task} task
  261. * @param {Number} rowIndex
  262. * @param {Number} colIndex
  263. * @param {SimpleTasks.store.Tasks} store
  264. * @param {Ext.grid.View} view
  265. */
  266. renderList: function(value, metaData, task, rowIndex, colIndex, store, view) {
  267. var listsStore = Ext.getStore('Lists'),
  268. node = value ? listsStore.getNodeById(value) : listsStore.getRootNode();
  269. return node.get('name');
  270. },
  271. /**
  272. * Renderer for the group headers
  273. * @private
  274. * @param {Date} date
  275. */
  276. renderDueDate: function(date) {
  277. var today = Ext.Date.clearTime(new Date()),
  278. todayTime = today.getTime(),
  279. dueDateTime;
  280. if(!date) {
  281. return '(No Date)';
  282. }
  283. dueDateTime = Ext.Date.clearTime(date).getTime();
  284. if(dueDateTime === todayTime) {
  285. return 'Today';
  286. }
  287. if(dueDateTime > todayTime) {
  288. if(dueDateTime === Ext.Date.add(today, Ext.Date.DAY, 1).getTime()) {
  289. // due date is current date + 1 day
  290. return 'Tomorrow';
  291. }
  292. if(dueDateTime < Ext.Date.add(today, Ext.Date.DAY, 7).getTime()) {
  293. // if the due date is less than one week in the future, return the day of the week.
  294. return Ext.Date.format(date, 'l');
  295. }
  296. } else {
  297. if(dueDateTime === Ext.Date.add(today, Ext.Date.DAY, -1).getTime()) {
  298. // due date is current date - 1 day.
  299. return 'Yesterday';
  300. }
  301. if(dueDateTime > Ext.Date.add(today, Ext.Date.DAY, -7).getTime()) {
  302. // if the due date is less than one week past, return 'Last' + the day of the week.
  303. return 'Last '+ Ext.Date.format(date, 'l');
  304. }
  305. }
  306. return date.getFullYear() === today.getFullYear() ? Ext.Date.format(date, 'D m/d') : Ext.Date.format(date, 'D m/d/Y');
  307. }
  308. });