summaryrefslogtreecommitdiffstats
path: root/module
diff options
context:
space:
mode:
Diffstat (limited to 'module')
-rw-r--r--module/api/CoreApi.py6
-rw-r--r--module/datatypes/PyFile.py38
-rw-r--r--module/remote/wsbackend/AsyncHandler.py13
-rw-r--r--module/threads/ThreadManager.py19
-rw-r--r--module/web/static/js/models/Progress.js18
-rw-r--r--module/web/static/js/views/abstract/modalView.js11
-rw-r--r--module/web/static/js/views/fileView.js1
-rw-r--r--module/web/static/js/views/headerView.js40
-rw-r--r--module/web/static/js/views/linkGrabberModal.js98
-rw-r--r--module/web/static/js/views/progressView.js30
-rw-r--r--module/web/templates/default/base.html77
11 files changed, 203 insertions, 148 deletions
diff --git a/module/api/CoreApi.py b/module/api/CoreApi.py
index a86197813..d75fe6ad6 100644
--- a/module/api/CoreApi.py
+++ b/module/api/CoreApi.py
@@ -39,8 +39,8 @@ class CoreApi(ApiComponent):
self.core.threadManager.pause,
self.core.config['reconnect']['activated'] and self.isTimeReconnect())
- # TODO multi user
- for pyfile in self.core.threadManager.getActiveDownloads():
+
+ for pyfile in self.core.threadManager.getActiveDownloads(self.primaryUID):
serverStatus.speed += pyfile.getSpeed() #bytes/s
return serverStatus
@@ -51,7 +51,7 @@ class CoreApi(ApiComponent):
:rtype: list of :class:`ProgressInfo`
"""
- pass
+ return self.core.threadManager.getProgressList(self.primaryUID)
def pauseServer(self):
"""Pause server: It won't start any new downloads, but nothing gets aborted."""
diff --git a/module/datatypes/PyFile.py b/module/datatypes/PyFile.py
index d6270acaa..14baa68ab 100644
--- a/module/datatypes/PyFile.py
+++ b/module/datatypes/PyFile.py
@@ -40,7 +40,8 @@ statusMap = {
"processing": 14,
"custom": 15,
"unknown": 16,
- }
+}
+
class PyFile(object):
"""
@@ -54,7 +55,7 @@ class PyFile(object):
@staticmethod
def fromInfoData(m, info):
f = PyFile(m, info.fid, info.name, info.size, info.status, info.media, info.added, info.fileorder,
- "", "", "", DownloadStatus.NA, "", info.package, info.owner)
+ "", "", "", DownloadStatus.NA, "", info.package, info.owner)
if info.download:
f.url = info.download.url
f.pluginname = info.download.plugin
@@ -179,7 +180,7 @@ class PyFile(object):
def toInfoData(self):
return FileInfo(self.fid, self.getName(), self.packageid, self.ownerid, self.getSize(), self.filestatus,
- self.media, self.added, self.fileorder, DownloadInfo(
+ self.media, self.added, self.fileorder, DownloadInfo(
self.url, self.pluginname, self.hash, self.status, self.getStatusName(), self.error
)
)
@@ -218,18 +219,6 @@ class PyFile(object):
def checkIfProcessed(self):
self.m.checkAllLinksProcessed(self.id)
- def formatWait(self):
- """ formats and return wait time in humanreadable format """
- return format_time(self.waitUntil - time())
-
- def formatSize(self):
- """ formats size to readable format """
- return format_size(self.getSize())
-
- def formatETA(self):
- """ formats eta to readable format """
- return format_time(self.getETA())
-
def getSpeed(self):
""" calculates speed """
try:
@@ -258,16 +247,6 @@ class PyFile(object):
except:
return 0
- def getPercent(self):
- """ get % of download """
- if self.status == DownloadStatus.Downloading:
- try:
- return self.plugin.req.percent
- except:
- return 0
- else:
- return self.progress
-
def getSize(self):
""" get size of download """
try:
@@ -278,10 +257,7 @@ class PyFile(object):
except:
return self.size
- def notifyChange(self):
- self.m.core.eventManager.dispatchEvent("linkUpdated", self.id, self.packageid)
-
def getProgressInfo(self):
- return ProgressInfo(self.plugin, self.name, self.statusname, self.getETA(), self.formatETA(),
- self.getBytesArrived(), self.getSize(),
- DownloadProgress(self.fid, self.packageid, self.getSpeed(), self.status))
+ return ProgressInfo(self.pluginname, self.name, self.getStatusName(), self.getETA(),
+ self.getBytesArrived(), self.getSize(),
+ DownloadProgress(self.fid, self.packageid, self.getSpeed(), self.status))
diff --git a/module/remote/wsbackend/AsyncHandler.py b/module/remote/wsbackend/AsyncHandler.py
index 5c08aa96d..99ffe9894 100644
--- a/module/remote/wsbackend/AsyncHandler.py
+++ b/module/remote/wsbackend/AsyncHandler.py
@@ -19,6 +19,7 @@
import re
from Queue import Queue, Empty
from threading import Lock
+from time import time
from mod_pywebsocket.msgutil import receive_message
@@ -58,6 +59,7 @@ class AsyncHandler(AbstractHandler):
req.interval = self.PROGRESS_INTERVAL
req.events = self.EVENT_PATTERN
req.mode = Mode.STANDBY
+ req.t = time() # time when update should be pushed
self.clients.append(req)
@lock
@@ -120,6 +122,7 @@ class AsyncHandler(AbstractHandler):
def mode_running(self, req):
""" Listen for events, closes socket when returning True """
try:
+ # block length of update interval if necessary
ev = req.queue.get(True, req.interval)
try:
self.send(req, ev)
@@ -130,9 +133,15 @@ class AsyncHandler(AbstractHandler):
self.send(req, ev)
except Empty:
+ pass
+
+ if req.t <= time():
# TODO: server status is not enough
# modify core api to include progress? think of other needed information to show
+ # eta is quite wrong currently
# notifications
-
self.send(req, self.api.getServerStatus())
- self.send(req, self.api.getProgressInfo()) \ No newline at end of file
+ self.send(req, self.api.getProgressInfo())
+
+ # update time for next update
+ req.t = time() + req.interval \ No newline at end of file
diff --git a/module/threads/ThreadManager.py b/module/threads/ThreadManager.py
index a0ece3463..f67179d08 100644
--- a/module/threads/ThreadManager.py
+++ b/module/threads/ThreadManager.py
@@ -118,9 +118,23 @@ class ThreadManager:
def setInfoResults(self, rid, result):
self.infoResults[rid].update(result)
- def getActiveDownloads(self):
+ def getActiveDownloads(self, user=None):
+ # TODO: user context
return [x.active for x in self.threads if x.active and isinstance(x.active, PyFile)]
+ def getProgressList(self, user=None):
+ info = []
+
+ # TODO: local threads can create multiple progresses
+ for thread in self.threads + self.localThreads:
+ # skip if not belong to current user
+ if user and thread.user != user: continue
+
+ progress = thread.getProgress()
+ if progress: info.append(progress)
+
+ return info
+
def getActiveFiles(self):
active = self.getActiveDownloads()
@@ -133,9 +147,6 @@ class ThreadManager:
"""get a id list of all pyfiles processed"""
return [x.id for x in self.getActiveFiles()]
- def allProgressInfo(self):
- pass #TODO
-
def work(self):
"""run all task which have to be done (this is for repetetive call by core)"""
try:
diff --git a/module/web/static/js/models/Progress.js b/module/web/static/js/models/Progress.js
index ebbe34862..c6a2fc4d1 100644
--- a/module/web/static/js/models/Progress.js
+++ b/module/web/static/js/models/Progress.js
@@ -2,10 +2,11 @@ define(['jquery', 'backbone', 'underscore'], function($, Backbone, _) {
return Backbone.Model.extend({
-// TODO
-// idAttribute: 'fid',
+ // generated, not submitted
+ idAttribute: 'pid',
defaults: {
+ pid: -1,
plugin: null,
name: null,
statusmsg: -1,
@@ -15,7 +16,6 @@ define(['jquery', 'backbone', 'underscore'], function($, Backbone, _) {
download: null
},
-
// Model Constructor
initialize: function() {
@@ -26,8 +26,18 @@ define(['jquery', 'backbone', 'underscore'], function($, Backbone, _) {
},
+ toJSON: function(options) {
+ var obj = Backbone.Model.prototype.toJSON.call(this, options);
+ if (obj.total > 0)
+ obj.percent = Math.round(obj.done * 100 / obj.total);
+ else
+ obj.percent = 0;
+
+ return obj;
+ },
+
isDownload : function() {
- return this.has('download')
+ return this.has('download');
}
});
diff --git a/module/web/static/js/views/abstract/modalView.js b/module/web/static/js/views/abstract/modalView.js
index e0542d552..8f5a7ed0c 100644
--- a/module/web/static/js/views/abstract/modalView.js
+++ b/module/web/static/js/views/abstract/modalView.js
@@ -82,11 +82,20 @@ define(['jquery', 'backbone', 'underscore', 'omniwindow'], function($, Backbone,
this.dialog.trigger('show');
- // TODO: set focus on first element
+ this.onShow();
+ },
+
+ onShow: function() {
+
},
hide: function() {
this.dialog.trigger('hide');
+ this.onHide();
+ },
+
+ onHide: function() {
+
},
confirm: function() {
diff --git a/module/web/static/js/views/fileView.js b/module/web/static/js/views/fileView.js
index 2459b6cd6..68e8df176 100644
--- a/module/web/static/js/views/fileView.js
+++ b/module/web/static/js/views/fileView.js
@@ -6,7 +6,6 @@ define(['jquery', 'backbone', 'underscore', 'app', 'utils/apitypes', 'views/abst
tagName: 'li',
className: 'file-view row-fluid',
-// template: _.template($("#template-file").html()),
template: _.compile($("#template-file").html()),
events: {
'click .checkbox': 'select',
diff --git a/module/web/static/js/views/headerView.js b/module/web/static/js/views/headerView.js
index 35df06003..dddae4705 100644
--- a/module/web/static/js/views/headerView.js
+++ b/module/web/static/js/views/headerView.js
@@ -1,5 +1,5 @@
-define(['jquery', 'underscore', 'backbone', 'app', 'models/ServerStatus', 'flot'],
- function($, _, Backbone, App, ServerStatus) {
+define(['jquery', 'underscore', 'backbone', 'app', 'models/ServerStatus', 'collections/ProgressList', 'views/progressView', 'flot'],
+ function($, _, Backbone, App, ServerStatus, ProgressList, ProgressView) {
// Renders the header with all information
return Backbone.View.extend({
@@ -11,23 +11,34 @@ define(['jquery', 'underscore', 'backbone', 'app', 'models/ServerStatus', 'flot'
'click .btn-grabber': 'open_grabber'
},
+ // todo: maybe combine these
templateStatus: _.compile($('#template-header-status').html()),
- templateProgress: _.compile($('#template-header-progress').html()),
+ templateHeader: _.compile($('#template-header').html()),
// Will hold the link grabber
grabber: null,
notifications: null,
+ header: null,
+ progress: null,
ws: null,
// Status model
status: null,
+ progressList: null,
initialize: function() {
+ var self = this;
this.notifications = this.$('#notification-area').calculateHeight().height(0);
this.status = new ServerStatus();
this.listenTo(this.status, 'change', this.render);
+ this.progress = this.$('.progress-list');
+ this.progressList = new ProgressList();
+ this.listenTo(this.progressList, 'add', function(model) {
+ self.progress.appendWithAnimation(new ProgressView({model: model}).render().el);
+ });
+
// TODO: button to start stop refresh
var ws = App.openWebSocket('/async');
ws.onopen = function() {
@@ -108,8 +119,19 @@ define(['jquery', 'underscore', 'backbone', 'app', 'models/ServerStatus', 'flot'
this.templateStatus(this.status.toJSON())
);
- // TODO: render progress
- this.$('.progress-list');
+ var data = {tasks: 0, downloads: 0, speed: 0};
+ this.progressList.each(function(progress) {
+ if (progress.isDownload()) {
+ data.downloads += 1;
+ data.speed += progress.get('download').speed;
+ } else
+ data.tasks++;
+ });
+
+ this.$('#progress-info').html(
+ this.templateHeader(data)
+ );
+ return this;
},
toggle_taskList: function() {
@@ -147,7 +169,15 @@ define(['jquery', 'underscore', 'backbone', 'app', 'models/ServerStatus', 'flot'
},
onProgressUpdate: function(progress) {
+ _.each(progress, function(prog) {
+ if (prog.download)
+ prog.pid = prog.download.fid;
+ else
+ prog.pid = prog.plugin + prog.name;
+ });
+ this.progressList.update(progress);
+ this.render();
},
onEvent: function(event, args) {
diff --git a/module/web/static/js/views/linkGrabberModal.js b/module/web/static/js/views/linkGrabberModal.js
index 9f7a5882d..71f97f0bf 100644
--- a/module/web/static/js/views/linkGrabberModal.js
+++ b/module/web/static/js/views/linkGrabberModal.js
@@ -1,49 +1,53 @@
define(['jquery', 'underscore', 'app', 'views/abstract/modalView', 'text!tpl/default/linkgrabber.html'],
function($, _, App, modalView, template) {
- // Modal dialog for package adding - triggers package:added when package was added
- return modalView.extend({
-
- events: {
- 'click .btn-success': 'addPackage',
- 'keypress #inputPackageName': 'addOnEnter'
- },
-
- template: _.compile(template),
-
- initialize: function() {
- // Inherit parent events
- this.events = _.extend({}, modalView.prototype.events,this.events);
- },
-
- renderContent: function() {
- return $('<h1>Content!</h1>');
- },
-
- addOnEnter: function(e) {
- if (e.keyCode != 13) return;
- this.addPackage(e);
- },
-
- addPackage: function(e) {
- var self = this;
- var settings = {
- type: 'POST',
- data: {
- name: JSON.stringify($('#inputPackageName').val()),
- links: JSON.stringify(['http://download.pyload.org/random.bin', 'http://download.pyload.org/random100.bin',
- 'invalid link', 'invalid link 2', 'invalid link 3', 'inavlid link 4',
- 'http://download.pyload.org/random.bin', 'http://download.pyload.org/random.bin', 'http://download.pyload.org/random.bin',
- 'A really really long invalid url that should exceed length of most of the urls by far and split into two lines'])
- },
- success: function() {
- App.vent.trigger('package:added');
- self.hide();
- }
- };
-
- $.ajax('api/addPackage', settings);
- $('#inputPackageName').val('');
- }
-
- });
-}); \ No newline at end of file
+ // Modal dialog for package adding - triggers package:added when package was added
+ return modalView.extend({
+
+ events: {
+ 'click .btn-success': 'addPackage',
+ 'keypress #inputPackageName': 'addOnEnter'
+ },
+
+ template: _.compile(template),
+
+ initialize: function() {
+ // Inherit parent events
+ this.events = _.extend({}, modalView.prototype.events, this.events);
+ },
+
+ renderContent: function() {
+ return $('<h1>Content!</h1>');
+ },
+
+ addOnEnter: function(e) {
+ if (e.keyCode != 13) return;
+ this.addPackage(e);
+ },
+
+ addPackage: function(e) {
+ var self = this;
+ var settings = {
+ type: 'POST',
+ data: {
+ name: JSON.stringify($('#inputPackageName').val()),
+ links: JSON.stringify(['http://download.pyload.org/random.bin', 'http://download.pyload.org/random100.bin',
+ 'invalid link', 'invalid link 2', 'invalid link 3', 'inavlid link 4',
+ 'http://download.pyload.org/random.bin', 'http://download.pyload.org/random.bin', 'http://download.pyload.org/random.bin',
+ 'A really really long invalid url that should exceed length of most of the urls by far and split into two lines'])
+ },
+ success: function() {
+ App.vent.trigger('package:added');
+ self.hide();
+ }
+ };
+
+ $.ajax('api/addPackage', settings);
+ $('#inputPackageName').val('');
+ },
+
+ onShow: function() {
+ this.$('#inputPackageName').focus();
+ }
+
+ });
+ }); \ No newline at end of file
diff --git a/module/web/static/js/views/progressView.js b/module/web/static/js/views/progressView.js
new file mode 100644
index 000000000..40fbf0652
--- /dev/null
+++ b/module/web/static/js/views/progressView.js
@@ -0,0 +1,30 @@
+define(['jquery', 'backbone', 'underscore', 'app', 'utils/apitypes', 'views/abstract/itemView'],
+ function($, Backbone, _, App, Api, ItemView) {
+
+ // Renders single file item
+ return ItemView.extend({
+
+ idAttribute: 'pid',
+ tagName: 'li',
+ template: _.compile($("#template-header-progress").html()),
+ events: {
+ },
+
+ initialize: function() {
+ this.listenTo(this.model, 'change', this.render);
+ this.listenTo(this.model, 'remove', this.unrender);
+ },
+
+ onDestroy: function() {
+ },
+
+ render: function() {
+ // TODO: icon
+ // TODO: other states
+ // TODO: non download progress
+ this.$el.css('background-image', 'url(icons/sdf)');
+ this.$el.html(this.template(this.model.toJSON()));
+ return this;
+ }
+ });
+ }); \ No newline at end of file
diff --git a/module/web/templates/default/base.html b/module/web/templates/default/base.html
index 2046dd36d..f995f79b7 100644
--- a/module/web/templates/default/base.html
+++ b/module/web/templates/default/base.html
@@ -38,7 +38,18 @@
{% endblock %}
});
</script>
-
+ <script type="text/template" id="template-header">
+ <%= if downloads %>
+ <% downloads %> downloads running (<% formatSize speed %>/s)
+ <% else %>
+ No running tasks
+ <%/if%>
+ <i class="icon-white iconf-list pull-right"></i>
+
+ <div class="progress" id="globalprogress">
+ <div class="bar" style="width: 48%">48%</div>
+ </div>
+ </script>
<script type="text/template" id="template-header-status">
<span class="pull-right eta"><% formatTime eta %></span><br>
<span class="pull-right remeaning"><% formatSize sizequeue %></span><br>
@@ -47,18 +58,18 @@
</script>
<script type="text/template" id="template-header-progress">
- <li> {# background-image for logo #}
- Some Download
- <span class="pull-right">YouTube</span>
+ {# background-image for logo #}
+ <% name %>
+ <span class="pull-right"><% plugin %></span>
- <div class="progress">
- <div class="bar" style="width: 25%"></div>
- </div>
- 20 Kb of 23 MB (500 kb/s)
- <span class="pull-right">
- 50%
- </span>
- </li>
+ <div class="progress">
+ <div class="bar" style="width: <% percent %>%"></div>
+ </div>
+ <% formatSize done %> of <% formatSize total %> (<% formatSize download.speed %>/s)
+ <span class="pull-right">
+ <% percent %>%
+ <% formatTime eta %>
+ </span>
</script>
{% block head %}
@@ -109,17 +120,8 @@
</div>
<div id="progress-area" style="margin-top: 16px">
- No running tasks
- <i class="icon-white iconf-list pull-right"></i>
-
- <div class="progress" id="globalprogress">
- <div class="bar" style="width: 48%">48%</div>
- </div>
-
- {# <div>#}
- {# <span class="pull-left">3,65 MB of 5,30 MB</span>#}
- {# <span class="pull-right">420,7 kB / sec</span>#}
- {# </div>#}
+ <span id="progress-info">
+ </span>
<div class="popover bottom">
<div class="arrow"></div>
<div class="popover-inner">
@@ -128,32 +130,7 @@
<button type="button" class="close" aria-hidden="true">&times;</button>
</h3>
<div class="popover-content">
- <ul class="progress-list">
- <li style="background-image: url('icons/sdf')">
- Some Download
- <span class="pull-right">YouTube</span>
-
- <div class="progress">
- <div class="bar" style="width: 25%"></div>
- </div>
- 20 Kb of 23 MB (500 kb/s)
- <span class="pull-right">
- 50%
- </span>
- </li>
- <li style="background-image: url('icons/sdf')">
- Some Download
- <span class="pull-right">YouTube</span>
-
- <div class="progress">
- <div class="bar" style="width: 45%"></div>
- </div>
- 20 Kb of 23 MB (500 kb/s)
- <span class="pull-right">
- 50%
- </span>
- </li>
- </ul>
+ <ul class="progress-list"></ul>
</div>
</div>
</div>
@@ -197,7 +174,7 @@
<div class="block">
<h2 class="block-title">Powered by</h2>
Bootstrap <br>
- dsfdsf <br>
+ Backbone <br>
sdf dsg <br>
</div>