diff options
18 files changed, 182 insertions, 62 deletions
diff --git a/module/AccountManager.py b/module/AccountManager.py index 45b4eef95..d90c957c3 100644 --- a/module/AccountManager.py +++ b/module/AccountManager.py @@ -100,7 +100,7 @@ class AccountManager: if plugin in self.accounts and user in self.accounts[plugin]: del self.accounts[plugin][user] self.core.db.removeAccount(plugin, user) - self.core.eventManager.dispatchEvent("accountDeleted", plugin, user) + self.core.eventManager.dispatchEvent("account:deleted", plugin, user) else: self.core.log.debug("Remove non existing account %s %s" % (plugin, user)) @@ -137,4 +137,4 @@ class AccountManager: acc.getAccountInfo(True) def sendChange(self, plugin, name): - self.core.eventManager.dispatchEvent("accountUpdated", plugin, name)
\ No newline at end of file + self.core.eventManager.dispatchEvent("account:updated", plugin, name)
\ No newline at end of file diff --git a/module/plugins/addons/MultiHoster.py b/module/plugins/addons/MultiHoster.py index 05d25b958..825085df8 100644 --- a/module/plugins/addons/MultiHoster.py +++ b/module/plugins/addons/MultiHoster.py @@ -66,7 +66,7 @@ class MultiHoster(Addon): - @AddEventListener("accountDeleted") + @AddEventListener("account:deleted") def refreshAccounts(self, plugin=None, user=None): self.plugins = {} @@ -75,7 +75,7 @@ class MultiHoster(Addon): if isinstance(account, MultiHosterAccount) and account.isUsable(): self.addHoster(account) - @AddEventListener("accountUpdated") + @AddEventListener("account:updated") def refreshAccount(self, plugin, user): account = self.core.accountManager.getAccount(plugin, user) diff --git a/module/remote/apitypes.py b/module/remote/apitypes.py index 83eb19450..e81c960c8 100644 --- a/module/remote/apitypes.py +++ b/module/remote/apitypes.py @@ -127,16 +127,15 @@ class AddonService(BaseObject): self.media = media class ConfigHolder(BaseObject): - __slots__ = ['name', 'label', 'description', 'long_description', 'items', 'info', 'handler'] + __slots__ = ['name', 'label', 'description', 'long_description', 'items', 'info'] - def __init__(self, name=None, label=None, description=None, long_description=None, items=None, info=None, handler=None): + def __init__(self, name=None, label=None, description=None, long_description=None, items=None, info=None): self.name = name self.label = label self.description = description self.long_description = long_description self.items = items self.info = info - self.handler = handler class ConfigInfo(BaseObject): __slots__ = ['name', 'label', 'description', 'category', 'user_context', 'activated'] diff --git a/module/remote/apitypes_debug.py b/module/remote/apitypes_debug.py index 6909464d4..7b1b5e7f3 100644 --- a/module/remote/apitypes_debug.py +++ b/module/remote/apitypes_debug.py @@ -21,7 +21,7 @@ classes = { 'AccountInfo' : [basestring, basestring, int, bool, int, int, int, bool, bool, bool, (dict, basestring, basestring)], 'AddonInfo' : [basestring, basestring, basestring], 'AddonService' : [basestring, basestring, (list, basestring), (None, int)], - 'ConfigHolder' : [basestring, basestring, basestring, basestring, (list, ConfigItem), (None, (list, AddonInfo)), (None, (list, InteractionTask))], + 'ConfigHolder' : [basestring, basestring, basestring, basestring, (list, ConfigItem), (None, (list, AddonInfo))], 'ConfigInfo' : [basestring, basestring, basestring, basestring, bool, (None, bool)], 'ConfigItem' : [basestring, basestring, basestring, Input, basestring, basestring], 'DownloadInfo' : [basestring, basestring, basestring, int, basestring, basestring], diff --git a/module/remote/pyload.thrift b/module/remote/pyload.thrift index 76e755de0..2aeb54091 100644 --- a/module/remote/pyload.thrift +++ b/module/remote/pyload.thrift @@ -250,7 +250,6 @@ struct ConfigHolder { 4: string long_description, 5: list<ConfigItem> items, 6: optional list<AddonInfo> info, - 7: optional list<InteractionTask> handler, // if null plugin is not loaded } struct ConfigInfo { diff --git a/module/remote/wsbackend/AsyncHandler.py b/module/remote/wsbackend/AsyncHandler.py index b40f0ea4e..d9e302fbb 100644 --- a/module/remote/wsbackend/AsyncHandler.py +++ b/module/remote/wsbackend/AsyncHandler.py @@ -80,6 +80,7 @@ class AsyncHandler(AbstractHandler): for req in self.clients: # filter events that these user is no owner of # TODO: events are security critical, this should be revised later + # TODO: permissions? interaction etc if not req.api.user.isAdmin(): skip = False for arg in args: diff --git a/module/web/static/js/default.js b/module/web/static/js/default.js index afe624ff9..44c8842fa 100644 --- a/module/web/static/js/default.js +++ b/module/web/static/js/default.js @@ -1,4 +1,4 @@ -define('default', ['require', 'jquery', 'app', 'views/headerView', 'views/dashboardView'], +define('default', ['require', 'jquery', 'app', 'views/headerView', 'views/dashboard/dashboardView'], function(require, $, App, HeaderView, DashboardView) { App.init = function() { diff --git a/module/web/static/js/views/abstract/modalView.js b/module/web/static/js/views/abstract/modalView.js index d3ac34bd6..1e45e942b 100644 --- a/module/web/static/js/views/abstract/modalView.js +++ b/module/web/static/js/views/abstract/modalView.js @@ -31,47 +31,57 @@ define(['jquery', 'backbone', 'underscore', 'omniwindow'], function($, Backbone, }, + // TODO: whole modal stuff is not very elegant render: function() { this.$el.html(this.template(this.renderContent())); - this.$el.addClass('modal hide'); - this.$el.css({opacity: 0, scale: 0.7}); - $("body").append(this.el); - - var self = this; - - this.dialog = this.$el.omniWindow({ - overlay: { - selector: '#modal-overlay', - hideClass: 'hide', - animations: { - hide: function(subjects, internalCallback) { - subjects.overlay.transition({opacity: 'hide', delay: 100}, 300, function() { + this.onRender(); + + if (this.dialog === null) { + this.$el.addClass('modal hide'); + this.$el.css({opacity: 0, scale: 0.7}); + + var self = this; + $("body").append(this.el); + this.dialog = this.$el.omniWindow({ + overlay: { + selector: '#modal-overlay', + hideClass: 'hide', + animations: { + hide: function(subjects, internalCallback) { + subjects.overlay.transition({opacity: 'hide', delay: 100}, 300, function() { + internalCallback(subjects); + self.onHide(); + if (self.onHideDestroy) + self.destroy(); + }); + }, + show: function(subjects, internalCallback) { + subjects.overlay.fadeIn(300); internalCallback(subjects); - if (self.onHideDestroy) - self.destroy(); - }); - }, - show: function(subjects, internalCallback) { - subjects.overlay.fadeIn(300); - internalCallback(subjects); - }}}, - modal: { - hideClass: 'hide', - animations: { - hide: function(subjects, internalCallback) { - subjects.modal.transition({opacity: 'hide', scale: 0.7}, 300); - internalCallback(subjects); - }, - - show: function(subjects, internalCallback) { - subjects.modal.transition({opacity: 'show', scale: 1, delay: 100}, 300, function() { + }}}, + modal: { + hideClass: 'hide', + animations: { + hide: function(subjects, internalCallback) { + subjects.modal.transition({opacity: 'hide', scale: 0.7}, 300); internalCallback(subjects); - }); - }} - }}); + }, + + show: function(subjects, internalCallback) { + subjects.modal.transition({opacity: 'show', scale: 1, delay: 100}, 300, function() { + internalCallback(subjects); + }); + }} + }}); + } return this; }, + + onRender: function() { + + }, + renderContent: function() { return {content: $('<h1>Content!</h1>').html()}; }, @@ -91,7 +101,6 @@ define(['jquery', 'backbone', 'underscore', 'omniwindow'], function($, Backbone, hide: function() { this.dialog.trigger('hide'); - this.onHide(); }, onHide: function() { diff --git a/module/web/static/js/views/dashboardView.js b/module/web/static/js/views/dashboard/dashboardView.js index 58a50777c..c888214df 100644 --- a/module/web/static/js/views/dashboardView.js +++ b/module/web/static/js/views/dashboard/dashboardView.js @@ -1,5 +1,5 @@ define(['jquery', 'backbone', 'underscore', 'app', 'models/TreeCollection', - 'views/packageView', 'views/fileView', 'views/selectionView', 'views/filterView', 'select2'], + './packageView', './fileView', './selectionView', './filterView', 'select2'], function($, Backbone, _, App, TreeCollection, packageView, fileView, selectionView, filterView) { // Renders whole dashboard diff --git a/module/web/static/js/views/fileView.js b/module/web/static/js/views/dashboard/fileView.js index c673041b5..c673041b5 100644 --- a/module/web/static/js/views/fileView.js +++ b/module/web/static/js/views/dashboard/fileView.js diff --git a/module/web/static/js/views/filterView.js b/module/web/static/js/views/dashboard/filterView.js index 14968f2cc..14968f2cc 100644 --- a/module/web/static/js/views/filterView.js +++ b/module/web/static/js/views/dashboard/filterView.js diff --git a/module/web/static/js/views/packageView.js b/module/web/static/js/views/dashboard/packageView.js index 547c1470d..547c1470d 100644 --- a/module/web/static/js/views/packageView.js +++ b/module/web/static/js/views/dashboard/packageView.js diff --git a/module/web/static/js/views/selectionView.js b/module/web/static/js/views/dashboard/selectionView.js index 546cda847..546cda847 100644 --- a/module/web/static/js/views/selectionView.js +++ b/module/web/static/js/views/dashboard/selectionView.js diff --git a/module/web/static/js/views/input/inputLoader.js b/module/web/static/js/views/input/inputLoader.js new file mode 100644 index 000000000..5ccf07695 --- /dev/null +++ b/module/web/static/js/views/input/inputLoader.js @@ -0,0 +1,7 @@ +define(['./textInput'], function(textInput) { + + // selects appropriate input element + return function(input, value, default_value, description) { + return textInput; + }; +});
\ No newline at end of file diff --git a/module/web/static/js/views/input/inputView.js b/module/web/static/js/views/input/inputView.js new file mode 100644 index 000000000..15dc71aad --- /dev/null +++ b/module/web/static/js/views/input/inputView.js @@ -0,0 +1,55 @@ +define(['jquery', 'backbone', 'underscore'], function($, Backbone, _) { + + // Renders input elements + return Backbone.View.extend({ + + tagName: 'input', + + model: null, + value: null, + default_value: null, + description: null, + + initialize: function(model, value, default_value, description) { + this.model = model; + this.value = value; + this.default_value = default_value; + this.description = description; + }, + + render: function() { + return this; + }, + + destroy: function() { + this.undelegateEvents(); + this.unbind(); + if (this.onDestroy) { + this.onDestroy(); + } + this.$el.removeData().unbind(); + this.remove(); + }, + + // focus the input element + focus: function() { + this.$el.focus(); + }, + + // Clear the input + clear: function() { + + }, + + // retrieve value of the input + getVal: function() { + return this.value; + }, + + // the child class must call this when the value changed + setVal: function(value) { + this.value = value; + this.trigger('change', value); + } + }); +});
\ No newline at end of file diff --git a/module/web/static/js/views/input/textInput.js b/module/web/static/js/views/input/textInput.js new file mode 100644 index 000000000..7252ce289 --- /dev/null +++ b/module/web/static/js/views/input/textInput.js @@ -0,0 +1,33 @@ +define(['jquery', 'backbone', 'underscore', './inputView'], function($, Backbone, _, inputView) { + + return inputView.extend({ + + // TODO + tagName: 'input', + events: { + 'keypress': 'onChange' + }, + + render: function() { + this.$el.attr('type', 'text'); + this.$el.attr('name', 'textInput'); + + if (this.default_value) + this.$el.attr('placeholder', this.default_value); + + if (this.value) + this.$el.val(this.value); + + return this; + }, + + clear: function() { + this.$el.val(''); + }, + + onChange: function(e) { + this.setVal(this.$el.val()); + } + + }); +});
\ No newline at end of file diff --git a/module/web/static/js/views/queryModal.js b/module/web/static/js/views/queryModal.js index 5d1585a0d..86fd5b78b 100644 --- a/module/web/static/js/views/queryModal.js +++ b/module/web/static/js/views/queryModal.js @@ -1,15 +1,18 @@ -define(['jquery', 'underscore', 'app', 'views/abstract/modalView', 'text!tpl/default/queryDialog.html'], - function($, _, App, modalView, template) { +define(['jquery', 'underscore', 'app', 'views/abstract/modalView', './input/inputLoader', 'text!tpl/default/queryDialog.html'], + function($, _, App, modalView, load_input, template) { return modalView.extend({ events: { 'click .btn-success': 'submit', 'submit form': 'submit' }, + template: _.compile(template), - model: null, + // the notificationView parent: null, - template: _.compile(template), + + model: null, + input: null, initialize: function() { // Inherit parent events @@ -23,32 +26,42 @@ define(['jquery', 'underscore', 'app', 'views/abstract/modalView', 'text!tpl/def description: this.model.get('description') }; + var input = this.model.get('input').data; if (this.model.isCaptcha()) { - var input = this.model.get('input').data; data.captcha = input[0]; data.type = input[1]; } - return data; }, + onRender: function() { + // instantiate the input + var input = this.model.get('input'); + var inputView = load_input(input); + this.input = new inputView(input); + // only renders after wards + this.$('#inputField').append(this.input.render().el); + }, + submit: function(e) { e.stopPropagation(); - // TODO: different input types // TODO: load next task - this.model.set('result', this.$('input').val()); + this.model.set('result', this.input.getVal()); var self = this; this.model.save({success: function() { self.hide(); }}); - this.$('input').val(''); + this.input.clear(); }, onShow: function() { - this.$('input').focus(); - } + this.input.focus(); + }, + onHide: function() { + this.input.destroy(); + } }); });
\ No newline at end of file diff --git a/module/web/templates/default/backbone/queryDialog.html b/module/web/templates/default/backbone/queryDialog.html index a37ac6256..eb05c20e2 100755 --- a/module/web/templates/default/backbone/queryDialog.html +++ b/module/web/templates/default/backbone/queryDialog.html @@ -10,12 +10,16 @@ <legend><% description %></legend> <div class="control-group"> <%= if captcha %> - <label class="control-label" for="inputText"><img src="data:image/<% type %>;base64,<% captcha %>"></label> - <div class="controls"> - <input type="text" id="inputText" name="captcha"> - </div> + <label class="control-label" for="inputField"> + <img src="data:image/<% type %>;base64,<% captcha %>"> + </label> + <% else %> + <label class="control-label" for="inputField"> + <% content %> + </label> <%/if%> - <% content %> + <div class="controls" id="inputField"> + </div> </div> </form> {% endblock %} |