MODx.grid.Trash = function (config) { config = config || {}; this.sm = new Ext.grid.CheckboxSelectionModel(); Ext.applyIf(config, { url: MODx.config.connector_url, baseParams: { action: 'resource/trash/getlist' }, fields: [ 'id', 'pagetitle', 'longtitle', 'published', 'context_key', 'context_name', 'parentPath', 'deletedon', 'deletedby', 'deletedby_name', 'cls' ], paging: true, autosave: true, save_action: 'resource/updatefromgrid', save_callback: this.refreshEverything, remoteSort: true, sm: this.sm, columns: [this.sm, { header: _('id'), dataIndex: 'id', width: 20, sortable: true }, { header: _('pagetitle'), dataIndex: 'pagetitle', width: 80, sortable: true, renderer: this.renderTooltip }, { header: _('trash.context_title'), dataIndex: 'context_name', width: 60, sortable: false }, { header: _('published'), dataIndex: 'published', width: 40, sortable: true, editor: {xtype: 'combo-boolean', renderer: 'boolean'} }, { header: _('trash.deletedon_title'), dataIndex: 'deletedon', width: 75, sortable: true }, { header: _('trash.deletedbyUser_title'), dataIndex: 'deletedby', width: 75, sortable: true, renderer: function (value, metaData, record) { return record.data.deletedby_name; } }], tbar: [{ text: _('bulk_actions'), menu: [{ text: _('trash.selected_purge'), handler: this.purgeSelected, scope: this }, { text: _('trash.selected_restore'), handler: this.restoreSelected, scope: this }] }, { xtype: 'button', text: _('trash.purge_all'), id: 'modx-purge-all', cls: 'x-btn-purge-all', listeners: { 'click': {fn: this.purgeAll, scope: this} } }, { xtype: 'button', text: _('trash.restore_all'), id: 'modx-restore-all', cls: 'x-btn-restore-all', listeners: { 'click': {fn: this.restoreAll, scope: this} } }, '->', { xtype: 'modx-combo-context', id: 'modx-trash-context', emptyText: _('context'), exclude: 'mgr', listeners: { 'select': {fn: this.searchContext, scope: this} } },{ xtype: 'textfield', id: 'modx-trash-search', cls: 'x-form-filter', emptyText: _('search_ellipsis'), listeners: { 'change': {fn: this.search, scope: this}, 'render': { fn: function (cmp) { new Ext.KeyMap(cmp.getEl(), { key: Ext.EventObject.ENTER, fn: this.blur, scope: cmp }); }, scope: this } } }, { xtype: 'button', text: _('filter_clear'), id: 'modx-filter-clear', cls: 'x-form-filter-clear', listeners: { 'click': {fn: this.clearFilter, scope: this} } }] }); MODx.grid.Trash.superclass.constructor.call(this, config); }; Ext.extend(MODx.grid.Trash, MODx.grid.Grid, { getMenu: function () { var r = this.getSelectionModel().getSelected(); var p = r.data.cls; var m = []; if (this.getSelectionModel().getCount() > 1) { m.push({ text: _('trash.selected_purge'), handler: this.purgeSelected, scope: this }); m.push({ text: _('trash.selected_restore'), handler: this.restoreSelected, scope: this }); } else { if (p.indexOf('trashpurge') !== -1) { m.push({ text: _('trash.purge'), handler: this.purgeResource }); } if (p.indexOf('trashundelete') !== -1) { m.push({ text: _('trash.restore'), handler: this.restoreResource }); } } if (m.length > 0) { this.addContextMenuItem(m); } }, search: function (tf, newValue) { var nv = newValue || tf; this.getStore().baseParams.query = Ext.isEmpty(nv) || Ext.isObject(nv) ? '' : nv; this.getBottomToolbar().changePage(1); this.refresh(); return true; }, searchContext: function (tf) { this.getStore().baseParams.context = !Ext.isEmpty(tf) ? tf.value : ''; this.getBottomToolbar().changePage(1); this.refresh(); return true; }, clearFilter: function () { this.getStore().baseParams.query = ''; this.getStore().baseParams.context = ''; Ext.getCmp('modx-trash-search').reset(); Ext.getCmp('modx-trash-context').reset(); this.getBottomToolbar().changePage(1); this.refresh(); }, purgeResource: function () { MODx.msg.confirm({ title: _('trash.purge_confirm_title'), text: _('trash.purge_confirm_message', { 'list': this.listResources('') }), url: this.config.url, params: { action: 'resource/trash/purge', ids: this.menu.record.id }, listeners: { 'success': { fn: function (data) { this.refreshEverything(data.total); }, scope: this }, 'error': { fn: function (data) { MODx.msg.status({ title: _('error'), message: data.message }); }, scope: this } } }); }, restoreResource: function () { var withPublish = ''; if (this.menu.record.published) { withPublish = '_with_publish'; } MODx.msg.confirm({ title: _('trash.restore_confirm_title'), text: _('trash.restore_confirm_message' + withPublish, { 'list': this.listResources('') }), url: this.config.url, params: { action: 'resource/undelete', id: this.menu.record.id }, listeners: { 'success': { fn: function (data) { this.refreshEverything(data.total); }, scope: this }, 'error': { fn: function (data) { MODx.msg.status({ title: _('error'), message: data.message }); }, scope: this } } }); }, purgeSelected: function () { var cs = this.getSelectedAsList(); if (cs === false) return false; MODx.msg.confirm({ title: _('trash.purge_confirm_title'), text: _('trash.purge_confirm_message', { 'list': this.listResources('') }), url: this.config.url, params: { action: 'resource/trash/purge', ids: cs }, listeners: { 'success': { fn: function (data) { this.getSelectionModel().clearSelections(true); this.refreshEverything(data.total); }, scope: this }, 'error': { fn: function (data) { MODx.msg.status({ title: _('error'), message: data.message }); }, scope: this } } }); return true; }, restoreSelected: function () { var cs = this.getSelectedAsList(); if (cs === false) return false; MODx.msg.confirm({ title: _('trash.restore_confirm_title'), text: _('trash.restore_confirm_message', { 'list': this.listResources('') }), url: this.config.url, params: { action: 'resource/trash/restore', ids: cs }, listeners: { 'success': { fn: function (data) { this.refreshEverything(data.total); }, scope: this }, 'error': { fn: function (data) { MODx.msg.status({ title: _('error'), message: data.message }); }, scope: this } } }); return true; }, purgeAll: function () { var sm = this.getSelectionModel(); sm.selectAll(); var cs = this.getSelectedAsList(); if (cs === false) return false; MODx.msg.confirm({ title: _('trash.purge_confirm_title'), text: _('trash.purge_all_confirm_message', { 'count': sm.selections.length, 'list': this.listResources('') }), url: this.config.url, params: { action: 'resource/trash/purge', // we can't just purge everything, because it might happen that in // the meantime something was deleted by another user which is not yet // shown in the trash manager list because of missing reload. // in that case we would purge something unreviewed/blindly. // therefore we have to pass all ids which are shown in our list here ids: cs }, listeners: { 'success': { fn: function (data) { MODx.msg.status({ title: _('success'), message: data.message }); if (data.object.count_success > 0) { this.refreshEverything(data.total); // no need to refresh if nothing was purged this.fireEvent('emptyTrash'); } }, scope: this }, 'error': { fn: function (data) { MODx.msg.status({ title: _('error'), message: data.message }); }, scope: this } } }) }, restoreAll: function () { var sm = this.getSelectionModel(); sm.selectAll(); var cs = this.getSelectedAsList(); if (cs === false) return false; MODx.msg.confirm({ title: _('trash.restore_confirm_title'), text: _('trash.restore_all_confirm_message', { 'count': sm.selections.length, 'list': this.listResources('') }), url: this.config.url, params: { action: 'resource/trash/restore', // we can't just restore everything, because it might happen that in // the meantime something was deleted by another user which is not yet // shown in the trash manager list because of missing reload. // in that case we would restore something unreviewed/blindly. // therefore we have to pass all ids which are shown in our list here ids: cs }, listeners: { 'success': { fn: function (data) { MODx.msg.status({ title: _('success'), message: data.message }); if (data.object.count_success > 0) { this.refreshEverything(data.total); // no need to refresh if nothing was purged this.fireEvent('emptyTrash'); } }, scope: this }, 'error': { fn: function (data) { MODx.msg.status({ title: _('error'), message: data.message }); }, scope: this } } }) }, refreshTree: function () { var t = Ext.getCmp('modx-resource-tree'); t.refresh(); this.refreshRecycleBinButton(); }, refreshEverything: function (total) { this.refresh(); this.refreshTree(); this.refreshRecycleBinButton(total); }, refreshRecycleBinButton: function (total) { var t = Ext.getCmp('modx-resource-tree'); var trashButton = t.getTopToolbar().findById('emptifier'); if (total !== undefined) { // if no resource is deleted, we disable the icon. // otherwise we have to update the tooltip if (total = 0) { trashButton.disable(); trashButton.setTooltip(_('trash.manage_recycle_bin_tooltip')); } else { trashButton.enable(); trashButton.setTooltip(_('trash.manage_recycle_bin_tooltip', total)); } } }, listResources: function (separator) { separator = separator || ''; // creates a textual representation of the selected resources // we create a textlist of the resources here to show them again in the confirmation box var selections = this.getSelectionModel().getSelections(); var text = [], t; selections.forEach(function (selection) { //t = selection.data.pagetitle + " (" + selection.data.id + ")"; t = selection.data.parentPath + "" + selection.data.pagetitle + " (" + selection.data.id + ")" + ""; if (selection.data.published) { t = '' + t + ''; } t = "
" + t + "
"; text.push(t); }); return text.join(separator); }, renderTooltip: function (value, metadata, record) { if (value) { var preview = ((record.json.pagetitle) ? '

' + _('pagetitle') + ': ' + record.json.pagetitle + '

' : '') + ((record.json.longtitle) ? '

' + _('long_title') + ': ' + record.json.longtitle + '

' : '') + ((record.data.parentPath) ? '

' + _('trash.parent_path') + ': ' + record.data.parentPath + '

' : '') + ((record.json.content) ? '

' + _('content') + ': ' + Ext.util.Format.ellipsis(record.json.content.replace(/<\/?[^>]+>/gi, ''), 100) + '

' : ''); preview = Ext.util.Format.htmlEncode(preview); return '
' + value + '
'; } else { return ''; } } }); Ext.reg('modx-grid-trash', MODx.grid.Trash);