new uri modal in angular, with overall refactoring and fixes in the
codebase
This commit is contained in:
parent
5c02174117
commit
489f12ea1e
89
angular.html
89
angular.html
|
@ -16,16 +16,19 @@
|
|||
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
<link rel="stylesheet" href="css/download.css">
|
||||
<link rel="stylesheet" href="css/modals.css">
|
||||
|
||||
|
||||
<!-- external javascript dependencies -->
|
||||
<script src="js/libs/jquery-1.8.3.js"></script>
|
||||
<script src="js/libs/underscore.js"></script>
|
||||
|
||||
<script src="js/libs/bootstrap.js"></script>
|
||||
|
||||
<script src="js/libs/angular.js"></script>
|
||||
|
||||
<script src="js/libs/bootstrap.js"></script>
|
||||
<script src="js/libs/angularui-bootstrap.js"></script>
|
||||
|
||||
|
||||
<script src="js/libs/jquery.flot.js"></script>
|
||||
<!-- We do manual resize currently
|
||||
<script src="js/libs/jquery.flot.resize.js"></script>
|
||||
|
@ -66,8 +69,7 @@
|
|||
<div class="container">
|
||||
<!-- using a span for collapse rather than a to fix the angular majic on anchors -->
|
||||
<span class="btn btn-navbar"
|
||||
data-toggle="collapse"
|
||||
data-target=".nav-collapse">
|
||||
ng-click="collapsed = !collapsed">
|
||||
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
|
@ -76,27 +78,29 @@
|
|||
|
||||
<a class="brand">{{ name }}</a>
|
||||
|
||||
<div class="nav-collapse">
|
||||
<div class="nav-collapse" collapse="collapsed">
|
||||
<ul class="nav">
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<a class="dropdown-toggle" href="#">
|
||||
Add <b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a href="#"><i class="icon-download"></i> Add Download URL</a>
|
||||
<a href="#" data-toggle="modal" data-target=".modal-adduris">
|
||||
<i class="icon-download"></i> By URIs
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#"><i class="icon-file"></i> Add Metalink</a>
|
||||
<a href="#"><i class="icon-file"></i> By Metalinks</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#"><i class="icon-file"></i> Add Torrent</a>
|
||||
<a href="#"><i class="icon-file"></i> By Torrents</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown" id="stop_downloads">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<a class="dropdown-toggle" href="#">
|
||||
Manage <b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
@ -111,7 +115,7 @@
|
|||
|
||||
<ul class="nav">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||
<a href="#" class="dropdown-toggle" >
|
||||
Settings <b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
@ -126,7 +130,7 @@
|
|||
|
||||
<ul class="nav pull-right">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||
<a href="#" class="dropdown-toggle" >
|
||||
About <b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
@ -150,7 +154,7 @@
|
|||
<table ng-repeat="download in getDownloads()" class="download" data-gid="{{download.gid}}">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td data-toggle="collapse" data-target="[data-gid={{download.gid}}] .download-detail .collapse" class="download-overview">
|
||||
<td ng-click="download.collapsed = !download.collapsed" class="download-overview">
|
||||
<b class="download-name">{{getName(download)}}</b>
|
||||
</td>
|
||||
<td class="download-controls" rowspan="2">
|
||||
|
@ -164,7 +168,7 @@
|
|||
|
||||
<button class="btn download_settings hidden-phone"><i class="icon-cog"></i></button>
|
||||
|
||||
<button class="btn dropdown-toggle" data-toggle="dropdown">
|
||||
<button class="btn dropdown-toggle">
|
||||
<i class="caret"></i>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
|
@ -173,7 +177,7 @@
|
|||
|
||||
<li ng-show="download.bittorrent"><a href="#" class="torrent_info"><i class="icon-list-alt"></i> Peers</a></li>
|
||||
|
||||
<li><a href="#" data-toggle="collapse" data-target="[data-gid={{download.gid}}] .download-detail .collapse"><i class="icon-info-sign"></i> More Info</a></li>
|
||||
<li><a href="#" ng-click="download.collapsed = !download.collapsed"><i class="icon-info-sign"></i> More Info</a></li>
|
||||
|
||||
<li class="visible-phone"><a href="#" ng-click="remove(download)"><i class="icon-remove"></i> Remove</a></li>
|
||||
</ul>
|
||||
|
@ -181,7 +185,7 @@
|
|||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td data-toggle="collapse" data-target="[data-gid={{download.gid}}] .download-detail .collapse" class="download-overview">
|
||||
<td ng-click="download.collapsed = !download.collapsed" class="download-overview">
|
||||
<ul class="stats pull-left">
|
||||
|
||||
<li ng-show="hasStatus(download, 'active')" class="label label-success hidden-phone hidden-tablet">Status: <span class="download-status">{{download.status}}</span></li>
|
||||
|
@ -216,7 +220,7 @@
|
|||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="download-progress" colspan="2" data-toggle="collapse" data-target="[data-gid={{download.gid}}] .download-detail .collapse">
|
||||
<td class="download-progress" colspan="2" ng-click="download.collapsed = !download.collapsed">
|
||||
|
||||
<div ng-show="hasStatus(download, 'active')" class="progress progress-striped" style="width: 100%; margin: 0; padding: 0;">
|
||||
<div class="bar" style="width: {{getProgress(download)}}%;"></div>
|
||||
|
@ -240,10 +244,10 @@
|
|||
|
||||
</td>
|
||||
</tr>
|
||||
<tr data-toggle="collapse" data-target="[data-gid={{download.gid}}] .download-detail .collapse" class="download-detail">
|
||||
<tr ng-click="download.collapsed = !download.collapsed" class="download-detail">
|
||||
<td colspan="2">
|
||||
<div class="collapse more_info">
|
||||
<canvas bitfield="download.bitfield" pieces="download.numPieces" class="progress chunk-canvas" width="1400" style="width: 100%; margin: 5px;" chunkbar></canvas>
|
||||
<div class="more_info" collapse="download.collapsed">
|
||||
<canvas bitfield="download.bitfield" draw="!download.collapsed" pieces="download.numPieces" class="progress chunk-canvas" width="1400" style="width: 100%; margin: 5px;" chunkbar></canvas>
|
||||
<ul class="stats">
|
||||
<li class="label">Status: <span class="download-status">{{download.status}}</span></li>
|
||||
<li class="label">GID: <span class="download-gid">{{download.gid}}</span></li>
|
||||
|
@ -267,7 +271,7 @@
|
|||
</ul>
|
||||
|
||||
<div ng-show="hasStatus(download, 'active')">
|
||||
<div class="download-graph" dspeed="download.downloadSpeed" uspeed="download.uploadSpeed" dgraph></div>
|
||||
<div class="download-graph" dspeed="download.downloadSpeed" uspeed="download.uploadSpeed" dgraph draw="!download.collapsed"></div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
@ -281,6 +285,49 @@
|
|||
|
||||
<!-- {{{ modals -->
|
||||
<div ng-controller="ModalCtrl">
|
||||
|
||||
<!--{{{ add new Download template -->
|
||||
<div class="modal hide modal-adduris">
|
||||
<div class="modal-header">
|
||||
<button class="close" data-dismiss="modal">x</button>
|
||||
<h3>Add Downloads By URIs</h3>
|
||||
</div>
|
||||
<form class="modal-body">
|
||||
<fieldset>
|
||||
<legend>Download URIs</legend>
|
||||
<textarea rows="6" ng-model="uris"></textarea>
|
||||
<p class="help-block">
|
||||
{{ uris }} <br>
|
||||
You can add multiple downloads (files)
|
||||
at the same time by putting uris for each
|
||||
file on a separate line.
|
||||
<br>
|
||||
You can also add multiple uris (mirrors) for the
|
||||
*same* file. To do this separate the uris
|
||||
by a space.
|
||||
<br>
|
||||
Aria2 will use multiple uris (or mirrors) to boost
|
||||
the download speed for that file (download).
|
||||
<br>
|
||||
E.g. To add 2 files (downloads) f1.jpg
|
||||
and f2.mp4 with 2 uris (mirrors) each,
|
||||
add uris as following:
|
||||
<br>
|
||||
<!-- pre tags print tabs, so do not indent them! -->
|
||||
<pre>
|
||||
http://ex1.com/f1.jpg http://ex2.com/f1.jpg
|
||||
http://ex1.com/f2.mp4 http://ex2.com/f2.mp4
|
||||
</pre>
|
||||
A URI can be HTTP(S)/FTP/BitTorrent Magnet URI.
|
||||
</p>
|
||||
</fieldset>
|
||||
</form>
|
||||
<div class="modal-footer">
|
||||
<button class="btn" ng-click="addUris()">Add Downloads</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- add new Download template end }}}-->
|
||||
|
||||
</div>
|
||||
<!-- }}} -->
|
||||
|
||||
|
|
3
css/modals.css
Normal file
3
css/modals.css
Normal file
|
@ -0,0 +1,3 @@
|
|||
.modal-adduris textarea {
|
||||
width: 100%;
|
||||
}
|
|
@ -83,9 +83,14 @@ function(scope, rpc, utils) {
|
|||
'status', 'gid', 'bitfield', 'numPieces', 'connections',
|
||||
'bittorrent'
|
||||
], function(e) {
|
||||
if (ctx[e] != d[e])
|
||||
ctx[e] = d[e];
|
||||
});
|
||||
|
||||
// collapse the download details initially
|
||||
if (ctx.collapsed === undefined)
|
||||
ctx.collapsed = true;
|
||||
|
||||
return ctx;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,3 +1,27 @@
|
|||
app.controller('ModalCtrl', ['$scope', function(scope) {
|
||||
app.controller('ModalCtrl', ['$_', '$scope', '$rpc', function(_, scope, rpc) {
|
||||
scope.uris = '';
|
||||
scope.addUris = function() {
|
||||
console.log(scope.uris);
|
||||
var cnt = 0;
|
||||
var cb = function() {
|
||||
cnt--;
|
||||
if (!cnt) {
|
||||
// close modal
|
||||
console.log('closing modal');
|
||||
}
|
||||
};
|
||||
_.chain(scope.uris.trim().split(/\n\r?/g))
|
||||
.map(function(d) { return d.trim().split(/\s+/g) })
|
||||
.filter(function(d) { return d.length })
|
||||
.each(function(uris) {
|
||||
cnt++;
|
||||
// passing true to batch all the addUri calls
|
||||
rpc.once('addUri', [uris], cb, true);
|
||||
})
|
||||
|
||||
// now dispatch all addUri syscalls
|
||||
rpc.forceUpdate();
|
||||
|
||||
scope.uris = '';
|
||||
};
|
||||
}]);
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
|
||||
app.controller('NavCtrl', ['$scope', '$name', function(scope, name) {
|
||||
scope.name = name;
|
||||
|
||||
// initially collapsed in mobile resolution
|
||||
scope.collapsed = true;
|
||||
}]);
|
||||
|
|
|
@ -17,10 +17,14 @@ var draw = function(canvas, chunks, fillStyle) {
|
|||
x += dx;
|
||||
});
|
||||
};
|
||||
// put chunkbar and bitfield attributes in a canvas element
|
||||
// to use the directive, draw is optional and canvas is
|
||||
// only drawn when it is true if given
|
||||
app.directive('chunkbar', ['$utils', function(utils) {
|
||||
return function(scope, elem, attrs) {
|
||||
var bitfield = "", pieces = 0;
|
||||
var bitfield = "", pieces = 0, canDraw = true;
|
||||
var update = function() {
|
||||
if (canDraw)
|
||||
draw(elem[0], utils.getChunksFromHex(bitfield, pieces), attrs.fillStyle);
|
||||
};
|
||||
scope.$watch(attrs.bitfield, function(bf) {
|
||||
|
@ -32,6 +36,12 @@ app.directive('chunkbar', ['$utils', function(utils) {
|
|||
update();
|
||||
});
|
||||
|
||||
if (attrs.draw) {
|
||||
scope.$watch(attrs.draw, function(val) {
|
||||
canDraw = val;
|
||||
});
|
||||
}
|
||||
|
||||
update();
|
||||
};
|
||||
}]);
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
|
||||
app.directive('dgraph', ['$', '$filter', function($, filter) {
|
||||
// graph takes dspeed and uspeed, it queries them every second and draws
|
||||
// the last 20 secs, it also takes draw as an optional attribute and only
|
||||
// draws the graph when it is true, if not given then graph is always drawn
|
||||
app.directive('dgraph', ['$', '$filter', '$parse', function($, filter, parse) {
|
||||
|
||||
return function(scope, elem, attrs) {
|
||||
var canDraw = true;
|
||||
|
||||
var graphSize = 20
|
||||
, dspeed = 0, uspeed = 0
|
||||
|
@ -60,9 +63,9 @@ app.directive('dgraph', ['$', '$filter', function($, filter) {
|
|||
if (uconf.data.length > graphSize) uconf.data.shift();
|
||||
|
||||
// if any parents is collapsable, then confirm if it isnt
|
||||
var collapsable = elem.parents('.collapse');
|
||||
if (!collapsable.length || collapsable.hasClass('in'))
|
||||
if (canDraw)
|
||||
draw();
|
||||
|
||||
};
|
||||
|
||||
scope.$watch(attrs.dspeed, function(val) {
|
||||
|
@ -73,6 +76,12 @@ app.directive('dgraph', ['$', '$filter', function($, filter) {
|
|||
uspeed = val;
|
||||
});
|
||||
|
||||
if (attrs.draw) {
|
||||
scope.$watch(attrs.draw, function(val) {
|
||||
canDraw = val;
|
||||
});
|
||||
}
|
||||
|
||||
var interval = setInterval(update, 1000);
|
||||
|
||||
angular.element(window).bind('resize', draw);
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
var app = angular.module('app', []);
|
||||
|
||||
$(function() {
|
||||
angular.bootstrap(document, ['app'])
|
||||
angular.bootstrap(document, [
|
||||
// external deps
|
||||
'ui.bootstrap.collapse', 'ui.bootstrap.dropdownToggle',
|
||||
|
||||
'app'
|
||||
])
|
||||
});
|
||||
|
|
1210
js/libs/angularui-bootstrap.js
vendored
Executable file
1210
js/libs/angularui-bootstrap.js
vendored
Executable file
File diff suppressed because it is too large
Load Diff
|
@ -426,8 +426,11 @@ function getTemplateCtx(data) {
|
|||
function updateDownloadTemplates(elem, ctx) {
|
||||
elem = $(elem);
|
||||
|
||||
var oldctx = elem.data('ctx') || {};
|
||||
|
||||
// update spans
|
||||
for(var i in ctx) {
|
||||
if (oldctx[i] != ctx[i])
|
||||
elem.find('.download-' + i).text(ctx[i]);
|
||||
}
|
||||
|
||||
|
@ -439,6 +442,7 @@ function updateDownloadTemplates(elem, ctx) {
|
|||
elem.find('.download-files').html(html);
|
||||
|
||||
// update progress bar
|
||||
if (oldctx.percentage != ctx.percentage)
|
||||
elem.find('.progress .bar').css('width', ctx.percentage + '%');
|
||||
|
||||
// update the chunks bar
|
||||
|
@ -462,6 +466,7 @@ function updateDownloadTemplates(elem, ctx) {
|
|||
ctx.fillRect(x, 0, dx, height);
|
||||
x += dx;
|
||||
});
|
||||
elem.data('ctx', ctx);
|
||||
}
|
||||
function deleteDownloadTemplates($top_elem, data) {
|
||||
if(!data) {
|
||||
|
|
|
@ -66,8 +66,10 @@ app.factory('$rpc', ['$syscall', '$globalTimeout', function(syscall, time) {
|
|||
else
|
||||
configurations = [conf];
|
||||
},
|
||||
// syscall is done only once
|
||||
once: function(name, params, cb) {
|
||||
// syscall is done only once, delay is optional
|
||||
// and pass true to only dispatch it in the global timeout
|
||||
// which can be used to batch up once calls
|
||||
once: function(name, params, cb, delay) {
|
||||
cb = cb || angular.noop;
|
||||
params = params || [];
|
||||
|
||||
|
@ -78,12 +80,16 @@ app.factory('$rpc', ['$syscall', '$globalTimeout', function(syscall, time) {
|
|||
cb: cb
|
||||
});
|
||||
|
||||
if (!delay) {
|
||||
this.forceUpdate();
|
||||
}
|
||||
},
|
||||
|
||||
// callback is called each time with updated syscall data
|
||||
// after the global timeout
|
||||
subscribe: function(name, params, cb) {
|
||||
// after the global timeout, delay is optional and pass it
|
||||
// true to dispatch the first syscall also on global timeout
|
||||
// which can be used to batch the subscribe calls
|
||||
subscribe: function(name, params, cb, delay) {
|
||||
cb = cb || angular.noop;
|
||||
params = params || [];
|
||||
|
||||
|
@ -95,8 +101,7 @@ app.factory('$rpc', ['$syscall', '$globalTimeout', function(syscall, time) {
|
|||
};
|
||||
subscriptions.push(handle);
|
||||
|
||||
this.forceUpdate();
|
||||
|
||||
if (!delay) this.forceUpdate();
|
||||
return handle;
|
||||
},
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user