From 82fb3408ee2eea99d2d8c5ea8905aff9281f4399 Mon Sep 17 00:00:00 2001 From: omaralvarez Date: Thu, 14 Aug 2014 21:00:10 +0200 Subject: [#1310] [Notifications] Add webui prefs page --- .../notifications/data/notifications.js | 519 +++++++++++++++++++-- .../plugins/notifications/notifications/webui.py | 23 +- deluge/plugins/notifications/setup.py | 6 +- 3 files changed, 476 insertions(+), 72 deletions(-) diff --git a/deluge/plugins/notifications/notifications/data/notifications.js b/deluge/plugins/notifications/notifications/data/notifications.js index 46384d0bc..392d26e71 100644 --- a/deluge/plugins/notifications/notifications/data/notifications.js +++ b/deluge/plugins/notifications/notifications/data/notifications.js @@ -1,50 +1,471 @@ -/* -Script: notifications.js - The client-side javascript code for the Notifications plugin. - -Copyright: - (C) Pedro Algarvio 2009 - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, write to: - The Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor - Boston, MA 02110-1301, USA. - - In addition, as a special exception, the copyright holders give - permission to link the code of portions of this program with the OpenSSL - library. - You must obey the GNU General Public License in all respects for all of - the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete - this exception statement from your version. If you delete this exception - statement from all source files in the program, then also delete it here. -*/ - -NotificationsPlugin = Ext.extend(Deluge.Plugin, { - constructor: function(config) { - config = Ext.apply({ - name: "Notifications" - }, config); - NotificationsPlugin.superclass.constructor.call(this, config); - }, - - onDisable: function() { - - }, - - onEnable: function() { - - } +/*! + * notifications.js + * + * Copyright (c) Omar Alvarez 2014 + * + * This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with + * the additional special exception to link portions of this program with the OpenSSL library. + * See LICENSE for more details. + * + */ + +Ext.ns('Deluge.ux.preferences'); + +/** + * @class Deluge.ux.preferences.NotificationsPage + * @extends Ext.Panel + */ +Deluge.ux.preferences.NotificationsPage = Ext.extend(Ext.Panel, { + + title: _('Notifications'), + layout: 'fit', + border: false, + + initComponent: function() { + Deluge.ux.preferences.NotificationsPage.superclass.initComponent.call(this); + + this.emailNotiFset = new Ext.form.FieldSet({ + xtype: 'fieldset', + border: false, + title: _('Email Notifications'), + autoHeight: true, + defaultType: 'textfield', + style: 'margin-top: 3px; margin-bottom: 0px; padding-bottom: 0px;', + width: '85%', + labelWidth: 1 + }); + + this.chkEnableEmail = this.emailNotiFset.add({ + fieldLabel: '', + labelSeparator: '', + name: 'enable_email', + xtype: 'checkbox', + boxLabel: _('Enabled'), + listeners: { + check: function(object, checked) { + this.setSmtpDisabled(!checked); + }, + scope: this + } + }); + + this.hBoxHost = this.emailNotiFset.add({ + fieldLabel: '', + labelSeparator: '', + name: 'host', + xtype: 'container', + layout: 'hbox', + disabled: true, + items: [{ + xtype: 'label', + text: _('Hostname:'), + margins: '6 0 0 6' + },{ + xtype: 'textfield', + margins: '2 0 0 3' + }] + }); + + this.hBoxPort = this.emailNotiFset.add({ + fieldLabel: '', + labelSeparator: '', + name: 'port', + xtype: 'container', + layout: 'hbox', + disabled: true, + items: [{ + xtype: 'label', + text: _('Port:'), + margins: '6 0 0 6' + },{ + xtype: 'spinnerfield', + margins: '2 0 0 31', + width: 128 + }] + }); + + this.hBoxUser = this.emailNotiFset.add({ + fieldLabel: '', + labelSeparator: '', + name: 'username', + xtype: 'container', + layout: 'hbox', + disabled: true, + items: [{ + xtype: 'label', + text: _('Username:'), + margins: '6 0 0 6' + },{ + xtype: 'textfield', + margins: '2 0 0 3' + }] + }); + + this.hBoxPassword = this.emailNotiFset.add({ + fieldLabel: '', + labelSeparator: '', + name: 'password', + xtype: 'container', + layout: 'hbox', + disabled: true, + items: [{ + xtype: 'label', + text: _('Password:'), + margins: '6 0 0 6' + },{ + xtype: 'textfield', + inputType: 'password', + margins: '2 0 0 5' + }] + }); + + this.hBoxFrom = this.emailNotiFset.add({ + fieldLabel: '', + labelSeparator: '', + name: 'from', + xtype: 'container', + layout: 'hbox', + disabled: true, + items: [{ + xtype: 'label', + text: _('From:'), + margins: '6 0 0 6' + },{ + xtype: 'textfield', + margins: '2 0 0 27' + }] + }); + + this.chkTLS = this.emailNotiFset.add({ + fieldLabel: '', + labelSeparator: '', + name: 'enable_tls_ssl', + xtype: 'checkbox', + disabled: true, + boxLabel: _('Server requires TLS/SSL') + }); + + this.recipientsFset = new Ext.form.FieldSet({ + xtype: 'fieldset', + border: false, + title: _('Recipients'), + autoHeight: true, + defaultType: 'editorgrid', + style: 'margin-top: 3px; margin-bottom: 0px; padding-bottom: 0px;', + autoWidth: true, + items: [{ + fieldLabel: '', + name: 'recipients', + margins: '2 0 5 5', + height: 130, + hideHeaders: true, + width: 260, + disabled: true, + autoExpandColumn: 'recipient', + bbar: { + items: [{ + text: _('Add'), + iconCls: 'icon-add', + handler: this.onAddClick, + scope: this + },{ + text: _('Remove'), + iconCls: 'icon-remove', + handler: this.onRemoveClick, + scope: this + }] + }, + viewConfig: { + emptyText: _('Add an recipient...'), + deferEmptyText: false + }, + colModel: new Ext.grid.ColumnModel({ + columns: [{ + id: 'recipient', + header: _('Recipient'), + dataIndex: 'recipient', + sortable: true, + hideable: false, + editable: true, + editor: { + xtype: 'textfield' + } + }] + }), + selModel: new Ext.grid.RowSelectionModel({ + singleSelect: false, + moveEditorOnEnter: false + }), + store: new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [{name: 'recipient'}] + }), + listeners: { + afteredit: function(e) { + e.record.commit(); + } + }, + setEmptyText: function(text) { + if (this.viewReady) { + this.getView().emptyText = text; + this.getView().refresh(); + } else { + Ext.apply(this.viewConfig, {emptyText: text}); + } + }, + loadData: function(data) { + this.getStore().loadData(data); + if (this.viewReady) { + this.getView().updateHeaders(); + } + } + }] + }); + + this.edGridSubs = new Ext.grid.EditorGridPanel({ + xtype: 'editorgrid', + autoHeight: true, + autoExpandColumn: 'event', + viewConfig: { + emptyText: _('Loading events...'), + deferEmptyText: false + }, + colModel: new Ext.grid.ColumnModel({ + defaults: { + renderer: function(value, meta, record, rowIndex, colIndex, store) { + if (Ext.isNumber(value) && parseInt(value) !== value) { + return value.toFixed(6); + } else if (Ext.isBoolean(value)) { + return '
 
'; + } + return value; + } + }, + columns: [{ + id: 'event', + header: 'Event', + dataIndex: 'event', + sortable: true, + hideable: false + },{ + id: 'email', + header: _('Email'), + dataIndex: 'email', + sortable: true, + hideable: false, + menuDisabled: true, + width: 40 + }] + }), + store: new Ext.data.ArrayStore({ + autoDestroy: true, + fields: [{ + name: 'event' + },{ + name: 'email' + }] + }), + listeners: { + cellclick: function(grid, rowIndex, colIndex, e) { + var record = grid.getStore().getAt(rowIndex); + var field = grid.getColumnModel().getDataIndex(colIndex); + var value = record.get(field); + + if (colIndex == 1) { + if (Ext.isBoolean(value)) { + record.set(field, !value); + record.commit(); + } + } + }, + beforeedit: function(e) { + if (Ext.isBoolean(e.value)) { + return false; + } + + return e.record.get('enabled'); + }, + afteredit: function(e) { + e.record.commit(); + } + }, + setEmptyText: function(text) { + if (this.viewReady) { + this.getView().emptyText = text; + this.getView().refresh(); + } else { + Ext.apply(this.viewConfig, {emptyText: text}); + } + }, + setSub: function(eventName) { + var store = this.getStore(); + var index = store.find('event',eventName); + store.getAt(index).set('email',true); + store.getAt(index).commit(); + }, + loadData: function(data) { + this.getStore().loadData(data); + if (this.viewReady) { + this.getView().updateHeaders(); + } + } + }); + + this.tabPanSettings = this.add({ + xtype: 'tabpanel', + activeTab: 0, + items: [{ + title: _('Settings'), + items: [this.emailNotiFset,this.recipientsFset], + autoScroll: true + },{ + title: _('Subscriptions'), + items: this.edGridSubs + }] + }); + + this.on('show', this.updateConfig, this); + }, + + updateConfig: function() { + deluge.client.notifications.get_handled_events({ + success: function(events) { + var data = []; + var keys = Ext.keys(events); + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + data.push([events[key][0], false]); + } + this.edGridSubs.loadData(data); + }, + scope: this + }); + deluge.client.notifications.get_config({ + success: function(config) { + this.chkEnableEmail.setValue(config['smtp_enabled']); + this.setSmtpDisabled(!config['smtp_enabled']); + + this.hBoxHost.getComponent(1).setValue(config['smtp_host']); + this.hBoxPort.getComponent(1).setValue(config['smtp_port']); + this.hBoxUser.getComponent(1).setValue(config['smtp_user']); + this.hBoxPassword.getComponent(1).setValue(config['smtp_pass']); + this.hBoxFrom.getComponent(1).setValue(config['smtp_from']); + this.chkTLS.setValue(config['smtp_tls']); + + var data = []; + var keys = Ext.keys(config['smtp_recipients']); + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + data.push([config['smtp_recipients'][key]]); + } + this.recipientsFset.getComponent(0).loadData(data); + + data = []; + keys = Ext.keys(config['subscriptions']['email']); + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + this.edGridSubs.setSub(config['subscriptions']['email'][key]); + } + }, + scope: this + }); + }, + + onApply: function() { + var config = {}; + + config['smtp_enabled'] = this.chkEnableEmail.getValue(); + config['smtp_host'] = this.hBoxHost.getComponent(1).getValue(); + config['smtp_port'] = this.hBoxPort.getComponent(1).getValue(); + config['smtp_user'] = this.hBoxUser.getComponent(1).getValue(); + config['smtp_pass'] = this.hBoxPassword.getComponent(1).getValue(); + config['smtp_from'] = this.hBoxFrom.getComponent(1).getValue(); + config['smtp_tls'] = this.chkTLS.getValue(); + + var recipientsList = []; + var store = this.recipientsFset.getComponent(0).getStore(); + + for (var i = 0; i < store.getCount(); i++) { + var record = store.getAt(i); + var recipient = record.get('recipient'); + recipientsList.push(recipient); + } + + config['smtp_recipients'] = recipientsList; + + var subscriptions = {}; + var eventList = []; + store = this.edGridSubs.getStore(); + + for (var i = 0; i < store.getCount(); i++) { + var record = store.getAt(i); + var ev = record.get('event'); + var email = record.get('email'); + if (email) { + eventList.push(ev); + } + } + + subscriptions['email'] = eventList; + config['subscriptions'] = subscriptions; + + deluge.client.notifications.set_config(config); + }, + + onOk: function() { + this.onApply(); + }, + + onAddClick: function() { + var store = this.recipientsFset.getComponent(0).getStore(); + var Recipient = store.recordType; + var i = new Recipient({ + recipient: '' + }); + this.recipientsFset.getComponent(0).stopEditing(); + store.insert(0, i); + this.recipientsFset.getComponent(0).startEditing(0, 0); + }, + + onRemoveClick: function() { + var selections = this.recipientsFset.getComponent(0).getSelectionModel().getSelections(); + var store = this.recipientsFset.getComponent(0).getStore(); + + this.recipientsFset.getComponent(0).stopEditing(); + for (var i = 0; i < selections.length; i++) + store.remove(selections[i]); + store.commitChanges(); + }, + + setSmtpDisabled: function(disable) { + this.hBoxHost.setDisabled(disable); + this.hBoxPort.setDisabled(disable); + this.hBoxUser.setDisabled(disable); + this.hBoxPassword.setDisabled(disable); + this.hBoxFrom.setDisabled(disable); + this.chkTLS.setDisabled(disable); + this.recipientsFset.getComponent(0).setDisabled(disable); + }, + + onDestroy: function() { + deluge.preferences.un('show', this.updateConfig, this); + + Deluge.ux.preferences.NotificationsPage.superclass.onDestroy.call(this); + } + }); -new NotificationsPlugin(); + +Deluge.plugins.NotificationsPlugin = Ext.extend(Deluge.Plugin, { + name: 'Notifications', + + onDisable: function() { + deluge.preferences.removePage(this.prefsPage); + }, + + onEnable: function() { + this.prefsPage = deluge.preferences.addPage(new Deluge.ux.preferences.NotificationsPage()); + } +}); + +Deluge.registerPlugin('Notifications', Deluge.plugins.NotificationsPlugin); diff --git a/deluge/plugins/notifications/notifications/webui.py b/deluge/plugins/notifications/notifications/webui.py index 3abf447a9..f5522c7f1 100644 --- a/deluge/plugins/notifications/notifications/webui.py +++ b/deluge/plugins/notifications/notifications/webui.py @@ -37,37 +37,18 @@ # statement from all source files in the program, then also delete it here. # -from twisted.internet import defer from deluge.log import LOG as log from deluge.ui.client import client from deluge import component from deluge.plugins.pluginbase import WebPluginBase -import deluge.configmanager - -# Relative imports from common import get_resource -DEFAULT_PREFS = { - # FLASH - "flash_enabled": False, - # Subscriptions - "subscriptions": { - "flash": [] - } -} - -class WebUI(WebPluginBase, component.Component): +class WebUI(WebPluginBase): scripts = [get_resource("notifications.js")] - - def __init__(self, plugin_name): - WebPluginBase.__init__(self, plugin_name) - component.Component.__init__(self, "Notifications") + debug_scripts = scripts def enable(self): - self.config = deluge.configmanager.ConfigManager( - "notifications-web.conf", DEFAULT_PREFS - ) log.debug("Enabling Web UI notifications") def disable(self): diff --git a/deluge/plugins/notifications/setup.py b/deluge/plugins/notifications/setup.py index 890314a84..9a9ac156d 100755 --- a/deluge/plugins/notifications/setup.py +++ b/deluge/plugins/notifications/setup.py @@ -50,7 +50,7 @@ __long_description__ = """ Plugin which provides notifications to Deluge Email, Popup, Blink and Sound notifications - + The plugin also allows other plugins to make use of itself for their own custom notifications """ @@ -74,5 +74,7 @@ setup( %s = %s:CorePlugin [deluge.plugin.gtkui] %s = %s:GtkUIPlugin - """ % ((__plugin_name__, __plugin_name__.lower())*2) + [deluge.plugin.web] + %s = %s:WebUIPlugin + """ % ((__plugin_name__, __plugin_name__.lower())*3) ) -- cgit