'use strict'; pandora.ui.tasksDialog = function(options) { options = Ox.extend({ tasks: 'all' }, options || {}); var canceling = [], clientItems = [], serverItems = [], listItems = [], clientTimeout, serverTimeout, $list = Ox.TableList({ columns: [ { id: 'id', title: Ox._('ID'), visible: false }, { format: function(value) { return Ox.encodeHTMLEntities(value); }, id: 'user', operator: '+', title: Ox._('User'), visible: false, width: 144 }, { format: function(value) { return Ox.encodeHTMLEntities(value); }, id: 'title', operator: '+', title: Ox._('Title'), visible: true, width: 288 }, { format: function(value) { return Ox.formatDate(value, '%Y-%m-%d %H:%M:%S'); }, id: 'started', operator: '-', title: Ox._('Started'), visible: true, width: 144 }, { format: function(value) { return value ? Ox.formatDate(value, '%Y-%m-%d %H:%M:%S') : ''; }, id: 'ended', operator: '-', sort: function(value, data) { return value || 1e13 + data.started; }, title: Ox._('Ended'), visible: true, width: 144 }, { format: function(value, data) { return { 'pending': 'Uploading (Queued)', 'uploading': 'Uploading' + ( data.progress === void 0 ? '' : ' (' + ( data.progress === 0 ? 'Queued' : data.progress + '%' ) + ')' ), 'queued': $tasksSelect.value() == 'all' ? 'Processing (Queued)' : 'Finished', 'processing': 'Processing', 'canceled': 'Canceled', 'failed': 'Failed', 'finished': 'Finished' }[value] || value; }, id: 'status', operator: '+', sort: function(value) { return [ 'pending', 'uploading', 'queued', 'processing', 'canceled', 'failed', 'finished' ].indexOf(value); }, title: Ox._('Status'), visible: true, width: 176 - Ox.SCROLLBAR_SIZE }, { id: 'progress', title: Ox._('Progress'), visible: false } ], columnsVisible: true, items: listItems, scrollbarVisible: true, sort: [{key: 'ended', operator: '-'}], unique: 'id' }).bindEvent({ select: updateButton, open: function(data) { var item; if (data.ids.length == 1) { item = listItems.filter(function(item) { return item.id == data.ids[0]; })[0]; if (item && item.item) { that.close(); pandora.UI.set({ item: item.item, itemView: 'info' }); } } } }), $sidebar = Ox.Element().css({ margin: '4px' }), $tasksSelect = Ox.Select({ items: [ {id: 'uploads', title: Ox._('Show Uploads')}, {id: 'all', title: Ox._('Show All Tasks')} ], value: options.tasks, width: 128 }).css({ margin: '4px' }).bindEvent({ change: updateList }) .appendTo($sidebar), $usersSelect = Ox.Select({ items: [ {id: 'my', title: Ox._('Show My Tasks')}, {id: 'all', title: Ox._('Show All Users')} ], width: 128 }).css({ display: pandora.hasCapability('canSeeAllTasks') ? 'block' : 'none', margin: '8px 4px 4px 4px' }).bindEvent({ change: function(data) { $list[data.value == 'all' ? 'addColumn' : 'removeColumn']('user'); $list.resizeColumn('title', data.value == 'all' ? 144 : 288); setTimeout(updateList); } }) .appendTo($sidebar), $button = Ox.Button({ disabled: true, title: Ox._('Cancel Task'), width: 128 }).css({ margin: '4px', }).bindEvent({ click: function() { $button.options({disabled: true}); var ids = $list.options('selected').filter(canBeCanceled); canceling.push(ids); ids.forEach(function(id) { if (Ox.contains( ['pending', 'uploading'], $list.value(id, 'status') )) { pandora.uploadQueue.remove(id); } }) pandora.api.cancelTask({ id: ids }, function() { canceling = canceling.filter(function(id) { return !Ox.contains(ids, id); }); getServerItems(); }); } }).appendTo($sidebar), $panel = Ox.SplitPanel({ elements: [ { element: $list, size: 752 }, { element: $sidebar, } ], orientation: 'horizontal' }), that = Ox.Dialog({ buttons: [ Ox.Button({ id: 'done', title: Ox._('Done') }).bindEvent({ click: function() { that.close(); } }) ], closeButton: true, content: $panel, height: 384, removeOnClose: true, title: Ox._('Tasks'), width: 896 }) .bindEvent({ close: function() { clientTimeout && clearTimeout(clientTimeout); serverTimeout && clearTimeout(serverTimeout); }, open: function() { getClientItems(); getServerItems(); } }); function canBeCanceled(id) { return !Ox.contains( ['cancelled', 'failed', 'finished'], $list.value(id, 'status') ) && !Ox.contains(canceling, id); } function getClientItems(callback) { clearTimeout(clientTimeout); var uploads = pandora.uploadQueue.get(); var uploadsById = {}; uploads.forEach(function(upload) { uploadsById[upload.item.id] = ( uploadsById[upload.item.id] || [] ).concat(upload); }); clientItems = [] Ox.forEach(uploadsById, function(uploads, id) { // FIXME: include upload.file.size var progress = Math.round(Ox.sum(uploads.map(function(upload) { return upload.data.progress / uploads.length; })) * 100); var status = uploads.map(function(upload) { return upload.data.status; }); clientItems.push({ ended: uploads.every(function(upload) { return upload.data.ended; }) ? Ox.max(uploads.map(function(upload) { return upload.data.ended; })) : '', id: id, progress: progress, started: Ox.min(uploads.map(function(upload) { return upload.data.started; })), status: Ox.contains(status, 'uploading') ? 'uploading' : Ox.contains(status, 'pending') ? 'pending' : Ox.contains(status, 'canceled') ? 'canceled' : 'queued', title: uploads[0].item.title, user: pandora.user.username }); }); clientTimeout = setTimeout(getClientItems, 1000); updateValues(); callback && callback(); } function getListItems() { var allTasks = $tasksSelect.value() == 'all', uploading = allTasks ? ['pending', 'uploading'] : ['pending', 'uploading', 'queued'], items = clientItems.filter(function(item) { return Ox.contains(uploading, item.status); }), items = serverItems.filter(function(item) { return allTasks ? ( Ox.getIndex(items, 'id', item.item) == -1 || item.user != pandora.user.username ) : ( Ox.getIndex(items, 'id', item.item) == -1 && Ox.getIndex(clientItems, 'id', item.item) > -1 ); }).concat(items); return items; } function getServerItems(callback) { clearTimeout(serverTimeout); pandora.api.getTasks($usersSelect.value() == 'all' ? {} : { user: pandora.user.username }, function(result) { serverItems = result.data.items; serverTimeout = setTimeout(getServerItems, 10000); getClientItems(callback); }); } function updateButton() { var ids = $list.options('selected').filter(canBeCanceled); $button.options({ disabled: ids.length == 0, title: ids.length < 2 ? 'Cancel Task' : 'Cancel Tasks' }); } function updateList() { getServerItems(function() { listItems= getListItems(); $list.options({items: listItems}); updateButton(); }); } function updateValues() { var currentListItems = getListItems(), hasNewItems = currentListItems.length != listItems.length; !hasNewItems && currentListItems.forEach(function(item) { if (Ox.getIndexById(listItems, item.id) == -1) { hasNewItems = true; } else if (!hasNewItems) { ['progress', 'status'].concat( item.ended ? ['ended'] : [] ).forEach(function(key) { $list.value(item.id, key, item[key]); }); } }); hasNewItems && updateList(); } return that; };