]> git.proxmox.com Git - extjs.git/blob - extjs/examples/classic/simple-tasks/app/controller/Tasks.js
add extjs 6.0.1 sources
[extjs.git] / extjs / examples / classic / simple-tasks / app / controller / Tasks.js
1 /**
2 * @class SimpleTasks.controller.Tasks
3 * @extends Ext.app.Controller
4 */
5 Ext.define('SimpleTasks.controller.Tasks', {
6 extend: 'Ext.app.Controller',
7
8 models: ['Task'],
9 stores: ['Tasks'],
10
11 views: [
12 'tasks.Grid',
13 'tasks.Form',
14 'tasks.EditWindow',
15 'tasks.DefaultTimeWindow',
16 'tasks.ReminderWindow',
17 'tasks.ContextMenu'
18 ],
19
20 refs: [
21 {
22 ref: 'listTree',
23 selector: 'listTree'
24 },
25 {
26 ref: 'taskForm',
27 selector: 'taskForm'
28 },
29 {
30 ref: 'taskGrid',
31 selector: 'taskGrid'
32 },
33 {
34 ref: 'tasksToolbar',
35 selector: 'tasksToolbar'
36 },
37 {
38 ref: 'taskEditWindow',
39 selector: 'taskEditWindow',
40 xtype: 'taskEditWindow',
41 autoCreate: true
42 },
43 {
44 ref: 'defaultTimeWindow',
45 selector: 'defaultTimeWindow',
46 xtype: 'defaultTimeWindow',
47 autoCreate: true
48 },
49 {
50 ref: 'reminderWindow',
51 selector: 'reminderWindow',
52 xtype: 'reminderWindow',
53 forceCreate: true
54 },
55 {
56 ref: 'contextMenu',
57 selector: 'tasksContextMenu',
58 xtype: 'tasksContextMenu',
59 autoCreate: true
60 }
61 ],
62
63 init: function() {
64 var me = this;
65 me.control(
66 {
67 'taskForm textfield': {
68 specialkey: me.handleSpecialKey
69 },
70 '[iconCls=tasks-new]': {
71 click: me.focusTaskForm
72 },
73 '#delete-task-btn': {
74 click: me.handleDeleteClick
75 },
76 '#delete-task-item': {
77 click: me.handleDeleteClick
78 },
79 '#mark-complete-item': {
80 click: me.markComplete
81 },
82 '#mark-complete-btn': {
83 click: me.markComplete
84 },
85 '#mark-active-item': {
86 click: me.markActive
87 },
88 '#mark-active-btn': {
89 click: me.markActive
90 },
91 '#show-all-btn': {
92 click: me.filterAll
93 },
94 '#show-active-btn': {
95 click: me.filterActive
96 },
97 '#show-complete-btn': {
98 click: me.filterComplete
99 },
100 '#edit-task-item': {
101 click: me.handleEditItemClick
102 },
103 'taskGrid': {
104 recordedit: me.updateTask,
105 deleteclick: me.handleDeleteIconClick,
106 editclick: me.handleEditIconClick,
107 reminderselect: me.setReminder,
108 itemmouseenter: me.showActions,
109 itemmouseleave: me.hideActions,
110 selectionchange: me.toggleButtons,
111 columnresize: me.syncTaskFormFieldWidth,
112 itemcontextmenu: me.showContextMenu
113 },
114 'tasksToolbar': {
115 afterrender: me.initShowAll
116 },
117 'taskEditWindow [name=has_reminder]': {
118 change: me.toggleReminderFields
119 },
120 '#cancel-task-edit-btn': {
121 click: me.hideEditWindow
122 },
123 '#save-task-edit-btn': {
124 click: me.handleSaveTaskClick
125 },
126 'taskEditWindow [name=reminder_date]': {
127 change: me.syncReminderField
128 },
129 'taskEditWindow [name=reminder_time]': {
130 change: me.syncReminderField
131 },
132 '#toggle-complete-btn': {
133 click: me.toggleCompleteField
134 },
135 '#delete-task-window-btn': {
136 click: me.deleteTaskAndCloseEditWindow
137 },
138 'defaultTimeWindow [name=default_time]': {
139
140 },
141 '#cancel-default-time-edit-btn': {
142 click: me.hideDefaultTimeWindow
143 },
144 '#save-default-time-btn': {
145 click: me.saveDefaultTime
146 },
147 '[cls=snooze-btn]': {
148 click: me.snooze
149 },
150 '[cls=dismiss-reminder-btn]': {
151 click: me.dismissReminder
152 }
153 }
154 );
155
156 me.initReminderInterval();
157 },
158
159 /**
160 * Handles a "specialkey" event on an field on the task form.
161 * Creates a new task if the enter key is pressed.
162 * @param {Ext.form.field.Text} field
163 * @param {Ext.EventObject} e
164 */
165 handleSpecialKey: function(field, e) {
166 if(e.getKey() === e.ENTER) {
167 this.newTask();
168 }
169 },
170
171 /**
172 * Creates a new task based on the data currently contained in the task form.
173 * Saves the new task to the server and adds it to the task list view.
174 */
175 newTask: function() {
176 var me = this,
177 form = me.getTaskForm(),
178 basicForm = form.getForm(),
179 formEl = form.getEl(),
180 titleField = form.getForm().findField('title'),
181 task = Ext.create('SimpleTasks.model.Task');
182
183 // require title field to have a value
184 if(!titleField.getValue()) {
185 return;
186 }
187
188 // update the new task record with the data from the form.
189 basicForm.updateRecord(task);
190
191 // try to blur all of this form's items to make sure that the user can't type into a field while saving
192 form.items.each(function(item) {
193 var inputEl = item.getEl().down('input');
194 if(inputEl) {
195 inputEl.blur();
196 }
197 });
198
199 // mask the form element while saving
200 formEl.mask('saving . . .');
201 // save the task to the server
202 task.save({
203 success: function(task, operation) {
204 me.getTasksStore().add(task);
205 me.refreshListTree();
206 me.getTasksStore().sort();
207 titleField.reset();
208 titleField.focus();
209 formEl.unmask();
210 },
211 failure: function(task, operation) {
212 var error = operation.getError(),
213 msg = Ext.isObject(error) ? error.status + ' ' + error.statusText : error;
214
215 Ext.MessageBox.show({
216 title: 'Add Task Failed',
217 msg: msg,
218 icon: Ext.Msg.ERROR,
219 buttons: Ext.Msg.OK
220 });
221 formEl.unmask();
222 }
223 });
224 },
225
226 /**
227 * Handles the task list's "recordedit" event.
228 * Updates the task on the server whenever a task is updated using the task grid's cell editor
229 * @param {SimpleTasks.model.Task} task The task record that was edited
230 */
231 updateTask: function(task) {
232 var me = this;
233
234 if (task.modified && task.modified.done === false) {
235 task.set('reminder', null);
236 }
237 task.save({
238 success: function(task, operation) {
239 me.refreshListTree();
240 me.getTasksStore().sort();
241 },
242 failure: function(task, operation) {
243 var error = operation.getError(),
244 msg = Ext.isObject(error) ? error.status + ' ' + error.statusText : error;
245
246 Ext.MessageBox.show({
247 title: 'Update Task Failed',
248 msg: msg,
249 icon: Ext.Msg.ERROR,
250 buttons: Ext.Msg.OK
251 });
252 }
253 });
254 },
255
256 /**
257 * Handles a click on a delete icon in the task grid.
258 * @param {Ext.grid.View} view
259 * @param {Number} rowIndex
260 * @param {Number} colIndex
261 * @param {Ext.grid.column.Action} column
262 * @param {EventObject} e
263 */
264 handleDeleteIconClick: function(view, rowIndex, colIndex, column, e) {
265 this.deleteTask(this.getTasksStore().getAt(rowIndex));
266 },
267
268 /**
269 * Handles a click on the "delete task" button or context menu item
270 * @param {Ext.button.Button} button
271 * @param {Ext.EventObject} e
272 */
273 handleDeleteClick: function(button, e) {
274 this.deleteTask(this.getTaskGrid().getSelectionModel().getSelection()[0]);
275 },
276
277 /**
278 * Deletes the task from the server and updates the view.
279 * @param {SimpleTasks.model.Task} task
280 * @param {Function} successCallback A function to call after the task has been deleted successfully
281 */
282 deleteTask: function(task, successCallback) {
283 var me = this;
284
285 Ext.Msg.show({
286 title: 'Delete Task?',
287 msg: 'Are you sure you want to delete this task?',
288 buttons: Ext.Msg.YESNO,
289 fn: function(response) {
290 if(response === 'yes') {
291 task.erase({
292 success: function(task, operation) {
293 me.getTasksStore().remove(task);
294 me.refreshListTree();
295 if(successCallback) {
296 successCallback();
297 }
298 },
299 failure: function(task, operation) {
300 var error = operation.getError(),
301 msg = Ext.isObject(error) ? error.status + ' ' + error.statusText : error;
302
303 Ext.MessageBox.show({
304 title: 'Delete Task Failed',
305 msg: msg,
306 icon: Ext.Msg.ERROR,
307 buttons: Ext.Msg.OK
308 });
309 }
310 });
311 }
312 }
313 });
314 },
315
316 /**
317 * Refreshes the task grid's list filter, and the task counts in the list tree
318 */
319 refreshListTree: function() {
320 // refresh the lists list view so that the task counts will be correct
321 this.getListTree().refreshView();
322 },
323
324 /**
325 * Handles a click on the "Edit" context menu item
326 * @param {Ext.menu.Item} item
327 * @param {EventObject} e
328 */
329 handleEditItemClick: function(item, e) {
330 this.showEditWindow(this.getContextMenu().getTask());
331 },
332
333 /**
334 * Handles a click on the "Edit Task" action column
335 * @param {Ext.grid.View} view
336 * @param {Number} rowIndex
337 * @param {Number} colIndex
338 * @param {Ext.grid.column.Action} column
339 * @param {EventObject} e
340 */
341 handleEditIconClick: function(view, rowIndex, colIndex, column, e) {
342 this.showEditWindow(view.getRecord(view.findTargetByEvent(e)));
343 },
344
345 /**
346 * Handles the task grid's "selectionchange" event.
347 * Disables or enables the task-related toolbar buttons depending on whether or not there is a selection.
348 * @param {Ext.selection.RowModel} selModel
349 * @param {SimpleTasks.model.Task[]} tasks
350 */
351 toggleButtons: function(selModel, tasks) {
352 var deleteTaskBtn = Ext.getCmp('delete-task-btn'),
353 markCompleteBtn = Ext.getCmp('mark-complete-btn'),
354 markActiveBtn = Ext.getCmp('mark-active-btn');
355
356 if(tasks.length === 0) {
357 deleteTaskBtn.disable();
358 markCompleteBtn.disable();
359 markActiveBtn.disable();
360 } else {
361 deleteTaskBtn.enable();
362 markCompleteBtn.enable();
363 markActiveBtn.enable();
364 }
365 },
366
367 /**
368 * Handles a click on the "New Task" button or context menu item
369 * focuses the title field on the new task form
370 * @param {Ext.Component} component
371 * @param {Ext.EventObject} e
372 */
373 focusTaskForm: function(component, e) {
374 this.getTaskForm().query('[name=title]')[0].focus();
375 },
376
377 /**
378 * Handles a click on the "Mark Complete" button or menu item
379 * Sets the selected task's "done" field to true
380 * @param {Ext.Component} component
381 * @param {Ext.EventObject} e
382 */
383 markComplete: function(component, e) {
384 var contextMenu = this.getContextMenu(),
385 task = contextMenu.isVisible() ? contextMenu.getTask() : this.getTaskGrid().getSelectionModel().getSelection()[0];
386
387 task.set('done', true);
388 task.set('reminder', null);
389 task.save({
390 failure: function(task, operation) {
391 var error = operation.getError(),
392 msg = Ext.isObject(error) ? error.status + ' ' + error.statusText : error;
393
394 Ext.MessageBox.show({
395 title: 'Mark Complete Failed',
396 msg: msg,
397 icon: Ext.Msg.ERROR,
398 buttons: Ext.Msg.OK
399 });
400 }
401 });
402 this.refreshListTree();
403 },
404
405 /**
406 * Handles a click on the "Mark Active" button
407 * Sets the selected task's "done" field to false
408 * @param {Ext.button.Button} button
409 * @param {Ext.EventObject} e
410 */
411 markActive: function(button, e) {
412 var contextMenu = this.getContextMenu(),
413 task = contextMenu.isVisible() ? contextMenu.getTask() : this.getTaskGrid().getSelectionModel().getSelection()[0];
414
415 task.set('done', false);
416 task.save({
417 failure: function(task, operation) {
418 var error = operation.getError(),
419 msg = Ext.isObject(error) ? error.status + ' ' + error.statusText : error;
420
421 Ext.MessageBox.show({
422 title: 'Mark Active Failed',
423 msg: msg,
424 icon: Ext.Msg.ERROR,
425 buttons: Ext.Msg.OK
426 });
427 }
428 });
429 this.refreshListTree();
430 },
431
432 /**
433 * Handles the task grid columnresize event.
434 * Synchronizes the width the column's associated form field with the width of the column
435 * @param {Ext.grid.header.Container} headerContainer
436 * @param {Ext.column.Column} column
437 * @param {Number} width The new column width
438 */
439 syncTaskFormFieldWidth: function(headerContainer, column, width) {
440 var field = this.getTaskForm().query('[name=' + column.dataIndex + ']')[0];
441 if (field) {
442 field.setWidth(width - 5);
443 }
444 },
445
446 /**
447 * Handles a click on the "Show All" button. Removes any filter on the done field so that all tasks will be displayed
448 * @param {Ext.button.Button} button
449 * @param {Ext.EventObject} e
450 */
451 filterAll: function(button, e) {
452 this.getTasksStore().clearFilter();
453 this.refreshListTree();
454 },
455
456 /**
457 * Handles a click on the "Show Active" button. Filters tasks by done = false
458 * @param {Ext.button.Button} button
459 * @param {Ext.EventObject} e
460 */
461 filterActive: function(button, e) {
462 this.getTasksStore().addFilter({
463 property: 'done',
464 value: false
465 });
466 this.refreshListTree();
467 },
468
469 /**
470 * Handles a click on the "Show Complete" button. Filters tasks by done = true.
471 * @param {Ext.button.Button} button
472 * @param {Ext.EventObject} e
473 */
474 filterComplete: function(button, e) {
475 this.getTasksStore().addFilter({
476 property: 'done',
477 value: true
478 });
479 this.refreshListTree();
480 },
481
482 /**
483 * Handles the tasks toolbar's render event
484 * Initializes the "Show All" Button to the pressed state
485 * @param {SimpleTasks.view.Toolbar} toolbar
486 */
487 initShowAll: function(toolbar) {
488 toolbar.getComponent('show-all-btn').toggle();
489 },
490
491 /**
492 * Handles a mouseenter event on a task grid item.
493 * Shows the item's action icons.
494 * @param {Ext.grid.View} view
495 * @param {SimpleTasks.model.Task} task
496 * @param {HTMLElement} node
497 * @param {Number} rowIndex
498 * @param {Ext.EventObject} e
499 */
500 showActions: function(view, task, node, rowIndex, e) {
501 var icons = Ext.fly(node).query('.x-action-col-icon');
502 Ext.each(icons, function(icon){
503 Ext.get(icon).removeCls('x-hidden');
504 });
505 },
506
507 /**
508 * Handles a mouseleave event on a task grid item.
509 * Hides the item's action icons.
510 * @param {Ext.grid.View} view
511 * @param {SimpleTasks.model.Task} task
512 * @param {HTMLElement} node
513 * @param {Number} rowIndex
514 * @param {Ext.EventObject} e
515 */
516 hideActions: function(view, task, node, rowIndex, e) {
517 var icons = Ext.fly(node).query('.x-action-col-icon');
518 Ext.each(icons, function(icon){
519 Ext.get(icon).addCls('x-hidden');
520 });
521 },
522
523 /**
524 * Handles the task grid's itemcontextmenu event
525 * Shows the task context menu.
526 * @param {Ext.grid.View} view
527 * @param {SimpleTasks.model.Task} task
528 * @param {HTMLElement} node
529 * @param {Number} rowIndex
530 * @param {Ext.EventObject} e
531 */
532 showContextMenu: function(view, task, node, rowIndex, e) {
533 var contextMenu = this.getContextMenu(),
534 markCompleteItem = Ext.getCmp('mark-complete-item'),
535 markActiveItem = Ext.getCmp('mark-active-item');
536
537 if(task.get('done')) {
538 markCompleteItem.hide();
539 markActiveItem.show();
540 } else {
541 markCompleteItem.show();
542 markActiveItem.hide();
543 }
544 contextMenu.setTask(task);
545 contextMenu.showAt(e.getX(), e.getY());
546 e.preventDefault();
547 },
548
549 /**
550 * Shows the "Edit Task" window
551 * @param {SimpleTasks.model.Task} task the task to edit
552 */
553 showEditWindow: function(task) {
554 var me = this,
555 taskEditWindow = me.getTaskEditWindow(),
556 form = taskEditWindow.down('form').getForm(),
557 reminderCheckbox = form.findField('has_reminder'),
558 dateField = form.findField('reminder_date'),
559 timeField = form.findField('reminder_time'),
560 reminder = task.get('reminder');
561
562 // Set the tasks title as the title of the edit window
563 taskEditWindow.setTitle('Edit Task - ' + task.get('title'));
564 // load the task data into the form
565 taskEditWindow.down('form').loadRecord(task);
566 // set the text of the toggle-complete button depending on the tasks "done" value
567 Ext.getCmp('toggle-complete-btn').setText(task.get('done') ? 'Mark Active' : 'Mark Complete');
568 taskEditWindow.show();
569
570 if(task.get('reminder')) {
571 // if the task already has a reminder set check the reminder checkbox and populate the reminder date and reminder time fields
572 reminderCheckbox.setValue(true);
573 dateField.setValue(Ext.Date.clearTime(reminder, true));
574 timeField.setValue(Ext.Date.format(reminder, timeField.format));
575 } else {
576 // if the task does not have a reminder set uncheck the reminder checkbox and set the reminder date and time fields to null
577 reminderCheckbox.setValue(false);
578 dateField.setValue(null);
579 timeField.setValue(null);
580 }
581
582 if(task.get('done')) {
583 // if the task is done disable the reminder checkbox (reminders cannot be set on completed tasks)
584 reminderCheckbox.disable();
585 } else {
586 reminderCheckbox.enable();
587 }
588
589 },
590
591 /**
592 * Handles a click on the "Edit Task" window's cancel button
593 * Hides the "Edit Task" window
594 * @param {Ext.Button} button
595 * @param {Ext.EventObject} e
596 */
597 hideEditWindow: function(button, e) {
598 this.getTaskEditWindow().close();
599 },
600
601 /**
602 * Handles the change event on the task edit window's "has_reminder" checkbox
603 * Toggles the visibility of the reminder date and time fields
604 * @param {Ext.form.field.Checkbox} checkbox
605 * @param {Boolean} newValue
606 * @param {Boolean} oldValue
607 */
608 toggleReminderFields: function(checkbox, newValue, oldValue) {
609 var taskEditWindow = this.getTaskEditWindow(),
610 windowEl = taskEditWindow.getEl(),
611 form = taskEditWindow.down('form').getForm(),
612 task = form.getRecord(),
613 dateField = form.findField('reminder_date'),
614 timeField = form.findField('reminder_time'),
615 defaultTimeDate, defaultTimeMilliseconds;
616
617 if(newValue) { // if the "has reminder" checkbox was checked
618 windowEl.mask('loading');
619 // get the default reminder time from the server or cache
620 this.getDefaultReminderTime(function(defaultTime) {
621 // enable the date and time fields
622 dateField.enable();
623 timeField.enable();
624 if(!dateField.getValue()) {
625 // if the reminder date has not already been set, default the reminder date to the task's due date
626 // or the current date if the task does not have a due date
627 dateField.setValue(task.get('due') || Ext.Date.clearTime(new Date()));
628 timeField.setValue(defaultTime);
629 }
630 // set the form's hidden reminder field by combining the reminder date and time fields
631 defaultTimeDate = timeField.getValue();
632 defaultTimeMilliseconds = defaultTimeDate - Ext.Date.clearTime(defaultTimeDate, true);
633 form.findField('reminder').setValue(new Date(dateField.getValue().getTime() + defaultTimeMilliseconds));
634 windowEl.unmask();
635 }, timeField.format);
636 } else { // if the "has reminder" checkbox was unchecked
637 // nullify the form's hidden reminder field and disable the reminder date and time fields
638 form.findField('reminder').setValue(null);
639 dateField.disable();
640 timeField.disable();
641 }
642 },
643
644 /**
645 * Handles a click on the "Task Edit" window's save button.
646 * @param {Ext.button.Button} button
647 * @param {Ext.EventObject} e
648 */
649 handleSaveTaskClick: function(button, e) {
650 this.saveEditWindow();
651 },
652
653 /**
654 * Updates the task record with the form data from the edit window and saves the task to the server.
655 */
656 saveEditWindow: function() {
657 var taskEditWindow = this.getTaskEditWindow(),
658 listTree = this.getListTree(),
659 windowEl = taskEditWindow.getEl(),
660 form = taskEditWindow.down('form').getForm(),
661 task = form.getRecord();
662
663 if (form.isValid()) {
664 windowEl.mask('saving');
665 form.updateRecord(task);
666 if (task.modified && task.modified.done === false) {
667 task.set('reminder', null);
668 }
669 task.save({
670 success: function(task, operation) {
671 windowEl.unmask();
672 taskEditWindow.close();
673 listTree.view.refresh();
674 },
675 failure: function(task, operation) {
676 var error = operation.getError(),
677 msg = Ext.isObject(error) ? error.status + ' ' + error.statusText : error;
678
679 Ext.MessageBox.show({
680 title: 'Edit Task Failed',
681 msg: msg,
682 icon: Ext.Msg.ERROR,
683 buttons: Ext.Msg.OK
684 });
685 windowEl.unmask();
686 }
687 });
688 } else {
689 Ext.Msg.alert('Invalid Data', 'Please correct form errors');
690 }
691 },
692
693 /**
694 * Syncronizes the value of the edit window's hidden reminder field whenever "reminder_date", or "reminder_time" is changed
695 * @param {Ext.form.field.Picker} field the date or time picker
696 * @param {Date} oldValue
697 * @param {Date} newValue
698 */
699 syncReminderField: function(field, oldValue, newValue) {
700 var form = this.getTaskEditWindow().down('form').getForm(),
701 reminderField = form.findField('reminder'),
702 date = form.findField('reminder_date').getValue(),
703 timeDate = form.findField('reminder_time').getValue(),
704 time, reminderDate;
705
706 if(date && timeDate) {
707 time = timeDate - Ext.Date.clearTime(timeDate, true);
708 reminderDate = new Date(date.getTime() + time);
709 reminderField.setValue(reminderDate);
710 }
711 },
712
713 /**
714 * Toggles the edit window's "done" field to true when the "Mark Complete" or "Mark Active" button on the edit window is clicked
715 * @param {Ext.button.Button} button
716 * @param {Ext.EventObject} e
717 */
718 toggleCompleteField: function(button, e) {
719 var taskEditWindow = this.getTaskEditWindow(),
720 doneField = taskEditWindow.down('form').getForm().findField('done');
721
722 if(doneField.getValue() === 'true') {
723 doneField.setValue(false);
724 } else {
725 doneField.setValue(true);
726 }
727 this.saveEditWindow();
728 },
729
730 /**
731 * Handles a click on the "Delete" button on the edit window.
732 * Deletes the task and closes the edit window
733 * @param {Ext.button.Button} button
734 * @param {Ext.EventObject} e
735 */
736 deleteTaskAndCloseEditWindow: function(button, e) {
737 var me = this,
738 taskEditWindow = me.getTaskEditWindow(),
739 task = taskEditWindow.down('form').getRecord();
740
741 me.deleteTask(task, function() {
742 me.getTaskEditWindow().close();
743 });
744 },
745
746 /**
747 * Handles the Task Grid's `reminderselect` event
748 * Sets a task's reminder
749 * @param {SimpleTasks.model.Task} task the underlying record of the row that was clicked to show the reminder menu
750 * @param {String|Number} value The value that was selected
751 */
752 setReminder: function(task, value) {
753 var me = this,
754 defaultTimeWindow = me.getDefaultTimeWindow(),
755 defaultTimeField = defaultTimeWindow.down('form').getForm().findField('default_time'),
756 defaultTimeDate, defaultTimeMilliseconds;
757
758 me.getDefaultReminderTime(function(defaultTime) {
759 if(value === 'set') {
760 // if the user selected "Set Default Time", show the default time window.
761 defaultTimeField.setValue(defaultTime);
762 defaultTimeWindow.show();
763 } else {
764 if(Ext.isNumber(value)) {
765 // if the user selected a reminder time, set the reminder by adding the user selected value to the due date
766 defaultTimeDate = Ext.Date.parse(defaultTime, defaultTimeField.format);
767 defaultTimeMilliseconds = defaultTimeDate - Ext.Date.clearTime(defaultTimeDate, true);
768 task.set('reminder', new Date(task.get('due').getTime() - (value * 86400000) + defaultTimeMilliseconds));
769 } else {
770 // if the user selected "No Reminder" set the reminder field to null
771 task.set('reminder', null);
772 }
773 task.save({
774 failure: function(task, operation) {
775 var error = operation.getError(),
776 msg = Ext.isObject(error) ? error.status + ' ' + error.statusText : error;
777
778 Ext.MessageBox.show({
779 title: 'Set Reminder Failed',
780 msg: msg,
781 icon: Ext.Msg.ERROR,
782 buttons: Ext.Msg.OK
783 });
784 }
785 });
786 }
787 }, defaultTimeField.format);
788 },
789
790 /**
791 * Gets the default reminder time and passes it to the callback function.
792 * Retrieves default reminder time from the server on the first call, then caches it for future calls.
793 * @param {Function} callback
794 * @param {String} timeFormat, the time format used to encode the time: the time format of the destination TimeField
795 */
796 getDefaultReminderTime: function(callback, timeFormat) {
797 var me = this,
798 defaultReminderTime;
799
800 if(me.defaultReminderTime) {
801 callback(me.defaultReminderTime);
802 } else {
803 me.defaultReminderTime = Ext.Date.format(Ext.Date.parse('8', 'g'), timeFormat || "g:i A"); // the default time if no value can be retrieved from storage
804 if (SimpleTasks.Settings.useLocalStorage) {
805 defaultReminderTime = localStorage.getItem('SimpleTasks-defaultReminderTime');
806 if (defaultReminderTime && Ext.Date.parse(defaultReminderTime, timeFormat)) {
807 me.defaultReminderTime = defaultReminderTime;
808 }
809 callback(me.defaultReminderTime);
810 } else {
811 Ext.Ajax.request({
812 url: 'php/config/read.php',
813 params: {
814 key: 'default.reminder.time'
815 },
816 success: function(response, options) {
817 var responseData = Ext.decode(response.responseText);
818 if(responseData.success && responseData.value && Ext.Date.parse(responseData.value, timeFormat)) {
819 me.defaultReminderTime = responseData.value;
820 }
821 callback(me.defaultReminderTime);
822 },
823 failure: function(response, options) {
824 callback(me.defaultReminderTime);
825 }
826 });
827 }
828 }
829 },
830
831 /**
832 * Hides the default reminder time window when the cancel button is clicked
833 * @param {Ext.button.Button} button
834 * @param {Ext.EventObject} e
835 */
836 hideDefaultTimeWindow: function(button, e) {
837 this.getDefaultTimeWindow().close();
838 },
839
840 /**
841 * Saves the default reminder time to the server when the OK button is clicked
842 * @param {Ext.button.Button} button
843 * @param {Ext.EventObject} e
844 */
845 saveDefaultTime: function(button, e) {
846 var me = this,
847 defaultTimeWindow = me.getDefaultTimeWindow(),
848 windowEl = defaultTimeWindow.getEl(),
849 field = defaultTimeWindow.down('form').getForm().findField('default_time'),
850 time = field.getRawValue();
851
852 if (!field.isValid()) {
853 return;
854 }
855
856 if (SimpleTasks.Settings.useLocalStorage) {
857 localStorage.setItem('SimpleTasks-defaultReminderTime', time);
858 me.defaultReminderTime = time;
859 defaultTimeWindow.close();
860 } else {
861 windowEl.mask('saving');
862 Ext.Ajax.request({
863 url: 'php/config/update.php',
864 params: {
865 key: 'default.reminder.time',
866 value: time
867 },
868 success: function(response, options) {
869 var responseData = Ext.decode(response.responseText);
870
871 if(responseData.success) {
872 me.defaultReminderTime = time;
873 defaultTimeWindow.close();
874 } else {
875 Ext.MessageBox.show({
876 title: 'Set Default Time Failed',
877 msg: responseData.message,
878 icon: Ext.Msg.ERROR,
879 buttons: Ext.Msg.OK
880 });
881 }
882 windowEl.unmask();
883 },
884 failure: function(response, options) {
885 Ext.MessageBox.show({
886 title: 'Set Default Time Failed',
887 msg: response.status + ' ' + response.statusText,
888 icon: Ext.Msg.ERROR,
889 buttons: Ext.Msg.OK
890 });
891 windowEl.unmask();
892 }
893 });
894 }
895 },
896
897 /**
898 * Initializes checking for tasks that have passed their reminder date at 10 second intervals.
899 */
900 initReminderInterval: function() {
901 var me = this,
902 now, reminderDate;
903
904 setInterval(function() {
905 now = new Date();
906 me.getTasksStore().each(function(task) {
907 reminderDate = task.get('reminder');
908 if(reminderDate && reminderDate < now && !task.get('done')) {
909 me.showReminderWindow(task);
910 }
911 });
912 }, 10000);
913 },
914
915 /**
916 * Shows the reminder window for a given task
917 * @param {SimpleTasks.model.Task} task
918 */
919 showReminderWindow: function(task) {
920 var reminderWindow = this.getReminderWindow(),
921 reminderDetailsBox = reminderWindow.down('[cls=tasks-reminder-details]'),
922 title = task.get('title');
923
924 task.set('reminder', null);
925 task.save({
926 failure: function(task, operation) {
927 var error = operation.getError(),
928 msg = Ext.isObject(error) ? error.status + ' ' + error.statusText : error;
929
930 Ext.MessageBox.show({
931 title: 'Clear Reminder Failed',
932 msg: msg,
933 icon: Ext.Msg.ERROR,
934 buttons: Ext.Msg.OK
935 });
936 }
937 });
938 reminderWindow.setTask(task);
939 reminderWindow.setTitle('Reminder - ' + title);
940 reminderDetailsBox.update({
941 title: title,
942 due: task.get('due')
943 });
944 reminderWindow.show();
945 },
946
947
948 /**
949 * Handles a click on the snooze button on the reminder window.
950 * Sets the task's reminder date to the current date plus snooze time selected
951 * @param {Ext.button.Button} button
952 * @param {Ext.EventObject} e
953 */
954 snooze: function(button, e) {
955 var reminderWindow = button.findParentByType('window'),
956 task = reminderWindow.getTask(),
957 snoozeMilliseconds = reminderWindow.down('[name=snooze_time]').getValue() * 60000,
958 reminderDate = new Date(new Date().getTime() + snoozeMilliseconds);
959
960 task.set('reminder', reminderDate);
961 task.save({
962 failure: function(task, operation) {
963 var error = operation.getError(),
964 msg = Ext.isObject(error) ? error.status + ' ' + error.statusText : error;
965
966 Ext.MessageBox.show({
967 title: 'Set Reminder Failed',
968 msg: msg,
969 icon: Ext.Msg.ERROR,
970 buttons: Ext.Msg.OK
971 });
972 }
973 });
974 reminderWindow.close();
975 },
976
977 /**
978 * Handle's a click on the reminder window's dismiss button.
979 * Hides the reminder window.
980 * @param {Ext.button.Button} button
981 * @param {Ext.EventObject} e
982 */
983 dismissReminder: function(button, e) {
984 button.findParentByType('window').close();
985 }
986
987 });