mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-08-19 21:03:30 -07:00
Allow WebUI Trackers table to be manipulated
This commit is contained in:
parent
94998b5da0
commit
5d114614bb
5 changed files with 72 additions and 108 deletions
|
@ -460,7 +460,7 @@ td.generalLabel {
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#trackersTable,
|
#torrentTrackersTableDiv,
|
||||||
#webseedsTable {
|
#webseedsTable {
|
||||||
line-height: 25px;
|
line-height: 25px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,24 +79,24 @@
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="prop_trackers" class="invisible">
|
<div id="prop_trackers" class="invisible unselectable">
|
||||||
<div id="trackers">
|
<div id="trackers">
|
||||||
<table class="dynamicTable" style="width: 100%">
|
<div id="torrentTrackersTableFixedHeaderDiv" class="dynamicTableFixedHeaderDiv">
|
||||||
|
<table class="dynamicTable" style="position:relative;">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr class="dynamicTableHeader"></tr>
|
||||||
<th style="width: 5%;">QBT_TR(#)QBT_TR[CONTEXT=TrackerListWidget]</th>
|
|
||||||
<th style="width: 30%;">QBT_TR(URL)QBT_TR[CONTEXT=TrackerListWidget]</th>
|
|
||||||
<th style="width: 10%;">QBT_TR(Status)QBT_TR[CONTEXT=TrackerListWidget]</th>
|
|
||||||
<th style="width: 5%;">QBT_TR(Peers)QBT_TR[CONTEXT=TrackerListWidget]</th>
|
|
||||||
<th style="width: 5%;">QBT_TR(Seeds)QBT_TR[CONTEXT=TrackerListWidget]</th>
|
|
||||||
<th style="width: 5%;">QBT_TR(Leeches)QBT_TR[CONTEXT=TrackerListWidget]</th>
|
|
||||||
<th style="width: 5%;">QBT_TR(Downloaded)QBT_TR[CONTEXT=TrackerListWidget]</th>
|
|
||||||
<th style="width: 35%;">QBT_TR(Message)QBT_TR[CONTEXT=TrackerListWidget]</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
</thead>
|
||||||
<tbody id="trackersTable"></tbody>
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="torrentTrackersTableDiv" class="dynamicTableDiv">
|
||||||
|
<table class="dynamicTable">
|
||||||
|
<thead>
|
||||||
|
<tr class="dynamicTableHeader"></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody></tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="prop_peers" class="invisible">
|
<div id="prop_peers" class="invisible">
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var torrentsTable = new TorrentsTable();
|
var torrentsTable = new TorrentsTable();
|
||||||
|
var torrentTrackersTable = new TorrentTrackersTable();
|
||||||
var torrentPeersTable = new TorrentPeersTable();
|
var torrentPeersTable = new TorrentPeersTable();
|
||||||
var searchResultsTable = new SearchResultsTable();
|
var searchResultsTable = new SearchResultsTable();
|
||||||
var searchPluginsTable = new SearchPluginsTable();
|
var searchPluginsTable = new SearchPluginsTable();
|
||||||
|
|
|
@ -1564,4 +1564,19 @@ var SearchPluginsTable = new Class({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var TorrentTrackersTable = new Class({
|
||||||
|
Extends: DynamicTable,
|
||||||
|
|
||||||
|
initColumns: function() {
|
||||||
|
this.newColumn('tier', '', 'QBT_TR(#)QBT_TR[CONTEXT=TrackerListWidget]', 35, true);
|
||||||
|
this.newColumn('url', '', 'QBT_TR(URL)QBT_TR[CONTEXT=TrackerListWidget]', 250, true);
|
||||||
|
this.newColumn('status', '', 'QBT_TR(Status)QBT_TR[CONTEXT=TrackerListWidget]', 125, true);
|
||||||
|
this.newColumn('peers', '', 'QBT_TR(Peers)QBT_TR[CONTEXT=TrackerListWidget]', 75, true);
|
||||||
|
this.newColumn('seeds', '', 'QBT_TR(Seeds)QBT_TR[CONTEXT=TrackerListWidget]', 75, true);
|
||||||
|
this.newColumn('leeches', '', 'QBT_TR(Leeches)QBT_TR[CONTEXT=TrackerListWidget]', 75, true);
|
||||||
|
this.newColumn('downloaded', '', 'QBT_TR(Downloaded)QBT_TR[CONTEXT=TrackerListWidget]', 100, true);
|
||||||
|
this.newColumn('message', '', 'QBT_TR(Message)QBT_TR[CONTEXT=TrackerListWidget]', 250, true);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
/*************************************************************/
|
/*************************************************************/
|
||||||
|
|
|
@ -1,61 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var trackersDynTable = new Class({
|
|
||||||
|
|
||||||
initialize: function() {},
|
|
||||||
|
|
||||||
setup: function(table, contextMenu) {
|
|
||||||
this.table = $(table);
|
|
||||||
this.rows = new Hash();
|
|
||||||
this.contextMenu = contextMenu;
|
|
||||||
},
|
|
||||||
|
|
||||||
removeRow: function(url) {
|
|
||||||
if (this.rows.has(url)) {
|
|
||||||
var tr = this.rows.get(url);
|
|
||||||
tr.dispose();
|
|
||||||
this.rows.erase(url);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
removeAllRows: function() {
|
|
||||||
this.rows.each(function(tr, url) {
|
|
||||||
this.removeRow(url);
|
|
||||||
}.bind(this));
|
|
||||||
},
|
|
||||||
|
|
||||||
updateRow: function(tr, row) {
|
|
||||||
var tds = tr.getElements('td');
|
|
||||||
for (var i = 0; i < row.length; ++i) {
|
|
||||||
tds[i].set('html', row[i]);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
insertRow: function(row) {
|
|
||||||
var url = row[1];
|
|
||||||
if (this.rows.has(url)) {
|
|
||||||
var tableRow = this.rows.get(url);
|
|
||||||
this.updateRow(tableRow, row);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//this.removeRow(id);
|
|
||||||
var tr = new Element('tr');
|
|
||||||
this.rows.set(url, tr);
|
|
||||||
for (var i = 0; i < row.length; ++i) {
|
|
||||||
var td = new Element('td');
|
|
||||||
td.set('html', row[i]);
|
|
||||||
td.injectInside(tr);
|
|
||||||
}
|
|
||||||
this.contextMenu.addTarget(tr);
|
|
||||||
tr.injectInside(this.table);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var current_hash = "";
|
var current_hash = "";
|
||||||
var selectedTracker = "";
|
|
||||||
|
|
||||||
var loadTrackersDataTimer;
|
var loadTrackersDataTimer;
|
||||||
var loadTrackersData = function() {
|
var loadTrackersData = function() {
|
||||||
|
@ -66,13 +11,13 @@ var loadTrackersData = function() {
|
||||||
}
|
}
|
||||||
var new_hash = torrentsTable.getCurrentTorrentHash();
|
var new_hash = torrentsTable.getCurrentTorrentHash();
|
||||||
if (new_hash === "") {
|
if (new_hash === "") {
|
||||||
torrentTrackersTable.removeAllRows();
|
torrentTrackersTable.clear();
|
||||||
clearTimeout(loadTrackersDataTimer);
|
clearTimeout(loadTrackersDataTimer);
|
||||||
loadTrackersDataTimer = loadTrackersData.delay(10000);
|
loadTrackersDataTimer = loadTrackersData.delay(10000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (new_hash != current_hash) {
|
if (new_hash != current_hash) {
|
||||||
torrentTrackersTable.removeAllRows();
|
torrentTrackersTable.clear();
|
||||||
current_hash = new_hash;
|
current_hash = new_hash;
|
||||||
}
|
}
|
||||||
var url = new URI('api/v2/torrents/trackers?hash=' + current_hash);
|
var url = new URI('api/v2/torrents/trackers?hash=' + current_hash);
|
||||||
|
@ -80,18 +25,17 @@ var loadTrackersData = function() {
|
||||||
url: url,
|
url: url,
|
||||||
noCache: true,
|
noCache: true,
|
||||||
method: 'get',
|
method: 'get',
|
||||||
onFailure: function() {
|
onComplete: function() {
|
||||||
$('error_div').set('html', 'QBT_TR(qBittorrent client is not reachable)QBT_TR[CONTEXT=HttpServer]');
|
|
||||||
clearTimeout(loadTrackersDataTimer);
|
clearTimeout(loadTrackersDataTimer);
|
||||||
loadTrackersDataTimer = loadTrackersData.delay(20000);
|
loadTrackersDataTimer = loadTrackersData.delay(10000);
|
||||||
},
|
},
|
||||||
onSuccess: function(trackers) {
|
onSuccess: function(trackers) {
|
||||||
$('error_div').set('html', '');
|
var selectedTrackers = torrentTrackersTable.selectedRowsIds();
|
||||||
torrentTrackersTable.removeAllRows();
|
torrentTrackersTable.clear();
|
||||||
|
|
||||||
if (trackers) {
|
if (trackers) {
|
||||||
// Update Trackers data
|
|
||||||
trackers.each(function(tracker) {
|
trackers.each(function(tracker) {
|
||||||
|
var url = escapeHtml(tracker.url);
|
||||||
var status;
|
var status;
|
||||||
switch (tracker.status) {
|
switch (tracker.status) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -111,22 +55,27 @@ var loadTrackersData = function() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var row = [
|
var row = {
|
||||||
tracker.tier,
|
rowId: url,
|
||||||
escapeHtml(tracker.url),
|
tier: tracker.tier,
|
||||||
status,
|
url: url,
|
||||||
tracker.num_peers,
|
status: status,
|
||||||
(tracker.num_seeds >= 0) ? tracker.num_seeds : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
|
peers: tracker.num_peers,
|
||||||
(tracker.num_leeches >= 0) ? tracker.num_leeches : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
|
seeds: (tracker.num_seeds >= 0) ? tracker.num_seeds : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
|
||||||
(tracker.num_downloaded >= 0) ? tracker.num_downloaded : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
|
leeches: (tracker.num_leeches >= 0) ? tracker.num_leeches : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
|
||||||
escapeHtml(tracker.msg)
|
downloaded: (tracker.num_downloaded >= 0) ? tracker.num_downloaded : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
|
||||||
];
|
message: escapeHtml(tracker.msg)
|
||||||
|
};
|
||||||
|
|
||||||
torrentTrackersTable.insertRow(row);
|
torrentTrackersTable.updateRowData(row);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
torrentTrackersTable.updateTable(false);
|
||||||
|
torrentTrackersTable.altRow();
|
||||||
|
|
||||||
|
if (selectedTrackers.length > 0)
|
||||||
|
torrentTrackersTable.reselectRows(selectedTrackers);
|
||||||
}
|
}
|
||||||
clearTimeout(loadTrackersDataTimer);
|
|
||||||
loadTrackersDataTimer = loadTrackersData.delay(10000);
|
|
||||||
}
|
}
|
||||||
}).send();
|
}).send();
|
||||||
};
|
};
|
||||||
|
@ -137,13 +86,15 @@ var updateTrackersData = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
var torrentTrackersContextMenu = new ContextMenu({
|
var torrentTrackersContextMenu = new ContextMenu({
|
||||||
targets: '.torrentTrackersMenuTarget',
|
targets: '#torrentTrackersTableDiv',
|
||||||
menu: 'torrentTrackersMenu',
|
menu: 'torrentTrackersMenu',
|
||||||
actions: {
|
actions: {
|
||||||
AddTracker: function(element, ref) {
|
AddTracker: function(element, ref) {
|
||||||
addTrackerFN();
|
addTrackerFN();
|
||||||
},
|
},
|
||||||
EditTracker: function(element, ref) {
|
EditTracker: function(element, ref) {
|
||||||
|
// only allow editing of one row
|
||||||
|
element.firstChild.click();
|
||||||
editTrackerFN(element);
|
editTrackerFN(element);
|
||||||
},
|
},
|
||||||
RemoveTracker: function(element, ref) {
|
RemoveTracker: function(element, ref) {
|
||||||
|
@ -155,9 +106,12 @@ var torrentTrackersContextMenu = new ContextMenu({
|
||||||
y: 2
|
y: 2
|
||||||
},
|
},
|
||||||
onShow: function() {
|
onShow: function() {
|
||||||
var element = this.options.element;
|
var selectedTrackers = torrentTrackersTable.selectedRowsIds();
|
||||||
selectedTracker = element;
|
var containsStaticTracker = selectedTrackers.some(function(tracker) {
|
||||||
if (element.childNodes[1].innerText.indexOf("** [") === 0) {
|
return (tracker.indexOf("** [") === 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (containsStaticTracker || (selectedTrackers.length === 0)) {
|
||||||
this.hideItem('EditTracker');
|
this.hideItem('EditTracker');
|
||||||
this.hideItem('RemoveTracker');
|
this.hideItem('RemoveTracker');
|
||||||
this.hideItem('CopyTrackerUrl');
|
this.hideItem('CopyTrackerUrl');
|
||||||
|
@ -167,7 +121,6 @@ var torrentTrackersContextMenu = new ContextMenu({
|
||||||
this.showItem('RemoveTracker');
|
this.showItem('RemoveTracker');
|
||||||
this.showItem('CopyTrackerUrl');
|
this.showItem('CopyTrackerUrl');
|
||||||
}
|
}
|
||||||
this.options.element.firstChild.click();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -218,13 +171,13 @@ var editTrackerFN = function(element) {
|
||||||
var removeTrackerFN = function(element) {
|
var removeTrackerFN = function(element) {
|
||||||
if (current_hash.length === 0) return;
|
if (current_hash.length === 0) return;
|
||||||
|
|
||||||
var trackerUrl = element.childNodes[1].innerText;
|
var selectedTrackers = torrentTrackersTable.selectedRowsIds();
|
||||||
new Request({
|
new Request({
|
||||||
url: 'api/v2/torrents/removeTrackers',
|
url: 'api/v2/torrents/removeTrackers',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: {
|
data: {
|
||||||
hash: current_hash,
|
hash: current_hash,
|
||||||
urls: trackerUrl
|
urls: selectedTrackers.join("|")
|
||||||
},
|
},
|
||||||
onSuccess: function() {
|
onSuccess: function() {
|
||||||
updateTrackersData();
|
updateTrackersData();
|
||||||
|
@ -232,15 +185,10 @@ var removeTrackerFN = function(element) {
|
||||||
}).send();
|
}).send();
|
||||||
};
|
};
|
||||||
|
|
||||||
var torrentTrackersTable = new trackersDynTable();
|
|
||||||
torrentTrackersTable.setup($('trackersTable'), torrentTrackersContextMenu);
|
|
||||||
|
|
||||||
new ClipboardJS('#CopyTrackerUrl', {
|
new ClipboardJS('#CopyTrackerUrl', {
|
||||||
text: function(trigger) {
|
text: function(trigger) {
|
||||||
if (selectedTracker) {
|
return torrentTrackersTable.selectedRowsIds().join("\n");
|
||||||
var url = selectedTracker.childNodes[1].innerText;
|
|
||||||
selectedTracker = "";
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
torrentTrackersTable.setup('torrentTrackersTableDiv', 'torrentTrackersTableFixedHeaderDiv', torrentTrackersContextMenu);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue