Grid.js 11.3 KB
/**
 * @class SimpleTasks.view.tasks.List
 * @extends Ext.grid.Panel
 * The tasks list view.  A grid that displays a list of tasks.
 */
Ext.define('SimpleTasks.view.tasks.Grid', {
    extend: 'Ext.grid.Panel',
    xtype: 'taskGrid',
    requires: [
        'SimpleTasks.ux.DragDrop',
        'SimpleTasks.ux.CheckColumn',
        'SimpleTasks.ux.ReminderColumn',
        'Ext.grid.plugin.CellEditing',
        'Ext.grid.column.Action',
        'Ext.grid.column.Date',
        'Ext.grid.feature.Grouping',
        'Ext.grid.plugin.DragDrop',
        'Ext.ux.TreePicker'
    ],
    store: 'Tasks',

    viewConfig: {
        plugins: {
            ptype: 'gridviewdragdrop',
            ddGroup: 'task',
            dragText: 'Drag task to change list',
            enableDrop: false
        },
        getRowClass: function(record, rowIndex, rowParams, store){
            var due = record.get('due');
            if(record.get('done')) {
                return 'tasks-completed-task';
            } else if(due && (due < Ext.Date.clearTime(new Date()))) {
                return 'tasks-overdue-task';
            }
        }
    },

    dockedItems: [
        {
            xtype: 'taskForm',
            dock: 'top',
            // the grid's column headers are a docked item with a weight of 100.
            // giving this a weight of 101 causes it to be docked under the column headers
            weight: 101,
            bodyStyle: {
                'background-color': '#E4E5E7'
            }
        }
    ],

    initComponent: function() {
        var me = this,
            cellEditingPlugin = Ext.create('Ext.grid.plugin.CellEditing'),
            groupingFeature = Ext.create('Ext.grid.feature.Grouping', {
                groupHeaderTpl: [
                    '{groupValue:this.renderDueDate}',
                    {
                        renderDueDate: me.renderDueDate
                    }
                ],
                enableGroupingMenu: false
            });

        me.plugins = [cellEditingPlugin];

        me.features = [groupingFeature];

        me.columns = {
            defaults: {
                draggable: false,
                resizable: false,
                hideable: false
            },
            items: [
                {
                    xtype: 'checkcolumn',
                    dataIndex: 'done',
                    cls: 'tasks-icon-column-header tasks-done-column-header',
                    width: 24,
                    align: 'center',
                    menuDisabled: true,
                    sortable: false,
                    listeners: {
                        'checkchange': Ext.bind(me.handleCheckChange, me)
                    }
                },
                {
                    text: 'Title',
                    dataIndex: 'title',
                    flex: 1,
                    emptyCellText: '',
                    editor: {
                        xtype: 'textfield',
                        selectOnFocus: true
                    }
                },
                {
                    text: 'List',
                    dataIndex: 'list_id',
                    width: 200,
                    editor: {
                        xtype: 'treepicker',
                        displayField: 'name',
                        store: Ext.create('SimpleTasks.store.Lists', {storeId: 'Lists-TaskGrid' })
                    },
                    renderer: me.renderList
                },
                {
                    xtype: 'datecolumn',
                    text: 'Due Date',
                    dataIndex: 'due',
                    width: 90,
                    editor: 'datefield',
                    format: 'n/j/Y',
                    emptyCellText: ''
                },
                {
                    xtype: 'remindercolumn',
                    dataIndex: 'reminder',
                    cls: 'tasks-icon-column-header tasks-reminder-column-header',
                    width: 24,
                    tooltip: 'Set Reminder',
                    menuPosition: 'tr-br',
                    menuDisabled: true,
                    sortable: false,
                    emptyCellText: '',
                    listeners: {
                        select: Ext.bind(me.handleReminderSelect, me)
                    }
                },
                {
                    xtype: 'actioncolumn',
                    cls: 'tasks-icon-column-header tasks-edit-column-header',
                    width: 24,
                    icon: 'resources/images/edit_task.png',
                    iconCls: 'x-hidden',
                    tooltip: 'Edit',
                    menuDisabled: true,
                    sortable: false,
                    handler: Ext.bind(me.handleEditClick, me)
                },
                {
                    xtype: 'actioncolumn',
                    cls: 'tasks-icon-column-header tasks-delete-column-header',
                    width: 24,
                    icon: 'resources/images/delete.png',
                    iconCls: 'x-hidden',
                    tooltip: 'Delete',
                    menuDisabled: true,
                    sortable: false,
                    handler: Ext.bind(me.handleDeleteClick, me)
                }
            ]
        };

        me.callParent(arguments);

        me.addEvents(
            /**
             * @event editclick
             * Fires when an edit icon is clicked
             * @param {Ext.grid.View} view
             * @param {Number} rowIndex
             * @param {Number} colIndex
             * @param {Ext.grid.column.Action} column
             * @param {EventObject} e
             */
            'editclick',

            /**
             * @event deleteclick
             * Fires when a delete icon is clicked
             * @param {Ext.grid.View} view
             * @param {Number} rowIndex
             * @param {Number} colIndex
             * @param {Ext.grid.column.Action} column
             * @param {EventObject} e
             */
            'deleteclick',

            /**
             * @event edit
             * Fires when a record is edited using the CellEditing plugin or the checkcolumn
             * @param {SimpleTasks.model.Task} task     The task record that was edited
             */
            'recordedit',
            
            /**
             * @event reminderselect
             * Fires when a reminder time is selected from the reminder column's dropdown menu
             * @param {SimpleTasks.model.Task} task    the underlying record of the row that was clicked to show the reminder menu
             * @param {String|Number} value      The value that was selected
             */
            'reminderselect'
        );

        cellEditingPlugin.on('edit', me.handleCellEdit, this);

    },

    /**
     * Handles a click on the edit icon
     * @private
     * @param {Ext.grid.View} gridView
     * @param {Number} rowIndex
     * @param {Number} colIndex
     * @param {Ext.grid.column.Action} column
     * @param {EventObject} e
     */
    handleEditClick: function(gridView, rowIndex, colIndex, column, e) {
        // Fire a "deleteclick" event with all the same args as this handler
        this.fireEvent('editclick', gridView, rowIndex, colIndex, column, e);
    },

    /**
     * Handles a click on a delete icon
     * @private
     * @param {Ext.grid.View} gridView
     * @param {Number} rowIndex
     * @param {Number} colIndex
     * @param {Ext.grid.column.Action} column
     * @param {EventObject} e
     */
    handleDeleteClick: function(gridView, rowIndex, colIndex, column, e) {
        // Fire a "deleteclick" event with all the same args as this handler
        this.fireEvent('deleteclick', gridView, rowIndex, colIndex, column, e);
    },

    /**
     * Handles a "checkchange" event on the "done" column
     * @private
     * @param {SimpleTasks.ux.CheckColumn} column
     * @param {Number} rowIndex
     * @param {Boolean} checked
     */
    handleCheckChange: function(column, rowIndex, checked) {
        this.fireEvent('recordedit', this.store.getAt(rowIndex));
    },

    /**
     * Handles a "select" event on the reminder column
     * @private
     * @param {SimpleTasks.model.Task} task    the underlying record of the row that was clicked to show the reminder menu
     * @param {String|Number} value      The value that was selected
     */
    handleReminderSelect: function(task, value) {
        this.fireEvent('reminderselect', task, value);
    },

    /**
     * Handles the CellEditing plugin's "edit" event
     * @private
     * @param {Ext.grid.plugin.CellEditing} editor
     * @param {Object} e                                an edit event object
     */
    handleCellEdit: function(editor, e) {
        this.fireEvent('recordedit', e.record);
    },

    /**
     * Reapplies the store's current filters. This is needed because when data in the store is modified
     * after filters have been applied, the filters do not automatically get applied to the new data.
     */
    refreshFilters: function() {
        var store = this.store,
            filters = store.filters;

        // save a reference to the existing task filters before clearing them
        filters = filters.getRange(0, filters.getCount() - 1);

        // clear the tasks store's filters and reapply them.
        store.clearFilter();
        store.filter(filters);
    },

    /**
     * Renderer for the list column
     * @private
     * @param {Number} value
     * @param {Object} metaData
     * @param {SimpleTasks.model.Task} task
     * @param {Number} rowIndex
     * @param {Number} colIndex
     * @param {SimpleTasks.store.Tasks} store
     * @param {Ext.grid.View} view
     */
    renderList: function(value, metaData, task, rowIndex, colIndex, store, view) {
        var listsStore = Ext.getStore('Lists'),
            node = value ? listsStore.getNodeById(value) : listsStore.getRootNode();

        return node.get('name');
    },

    /**
     * Renderer for the group headers
     * @private
     * @param {Date} date
     */
    renderDueDate: function(date) {
        var today = Ext.Date.clearTime(new Date()),
            todayTime = today.getTime(),
            dueDateTime;

        if(!date) {
            return '(No Date)';
        }
        dueDateTime = Ext.Date.clearTime(date).getTime();
        if(dueDateTime === todayTime) {
            return 'Today';
        }
        if(dueDateTime > todayTime) {
            if(dueDateTime === Ext.Date.add(today, Ext.Date.DAY, 1).getTime()) {
                // due date is current date + 1 day
                return 'Tomorrow';
            }
            if(dueDateTime < Ext.Date.add(today, Ext.Date.DAY, 7).getTime()) {
                // if the due date is less than one week in the future, return the day of the week.
                return Ext.Date.format(date, 'l');
            }
        } else {
            if(dueDateTime === Ext.Date.add(today, Ext.Date.DAY, -1).getTime()) {
                // due date is current date - 1 day.
                return 'Yesterday';
            }
            if(dueDateTime > Ext.Date.add(today, Ext.Date.DAY, -7).getTime()) {
                // if the due date is less than one week past, return 'Last' + the day of the week.
                return 'Last '+ Ext.Date.format(date, 'l');
            }
        }
        return date.getFullYear() === today.getFullYear() ? Ext.Date.format(date, 'D m/d') : Ext.Date.format(date, 'D m/d/Y');
    }

});