[Web UI] Changes in labels implementation

This commit is contained in:
ngosang 2015-07-16 01:04:53 +02:00
parent 4ae2f6c33b
commit a9e9a9c835
7 changed files with 161 additions and 166 deletions

View file

@ -669,19 +669,19 @@ void WebApplication::action_command_recheck()
void WebApplication::action_command_setLabel() void WebApplication::action_command_setLabel()
{ {
CHECK_URI(0); CHECK_URI(0);
CHECK_PARAMETERS("hash" << "label_obj"); CHECK_PARAMETERS("hashes" << "label");
QString hash = request().posts["hash"]; QStringList hashes = request().posts["hashes"].split("|");
QString label_obj = request().posts["label_obj"]; QString label = request().posts["label"].trimmed();
if (!Utils::Fs::isValidFileSystemName(label)) {
status(400, "Labels must not contain special characters");
return;
}
const QVariantMap m = json::fromJson(label_obj).toMap(); foreach (const QString &hash, hashes) {
if( m.contains("value") ) { BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
QString label = m["value"].toString(); if (torrent)
if (!hash.isEmpty()) { torrent->setLabel(label);
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
if (torrent)
torrent->setLabel(label);
}
} }
} }

View file

@ -106,9 +106,8 @@
<li><a href="#ForceStart"><img src="theme/media-seek-forward" alt="QBT_TR(Force Resume)QBT_TR"/> QBT_TR(Force Resume)QBT_TR</a></li> <li><a href="#ForceStart"><img src="theme/media-seek-forward" alt="QBT_TR(Force Resume)QBT_TR"/> QBT_TR(Force Resume)QBT_TR</a></li>
<li class="separator"><a href="#Delete"><img src="theme/list-remove" alt="QBT_TR(Delete)QBT_TR"/> QBT_TR(Delete)QBT_TR</a></li> <li class="separator"><a href="#Delete"><img src="theme/list-remove" alt="QBT_TR(Delete)QBT_TR"/> QBT_TR(Delete)QBT_TR</a></li>
<li class="separator"> <li class="separator">
<a href="#Label">QBT_TR(Label >)QBT_TR</a> <a href="#Label" class="arrow-right"><img src="theme/view-categories" alt="QBT_TR(Label)QBT_TR"/> QBT_TR(Label)QBT_TR</a>
<ul id="contextLabelList"> <ul id="contextLabelList"></ul>
</ul>
</li> </li>
<li id="queueingMenuItems" class="separator"> <li id="queueingMenuItems" class="separator">
<a href="#priority" class="arrow-right"><span style="display: inline-block; width:16px"></span> QBT_TR(Priority)QBT_TR</a> <a href="#priority" class="arrow-right"><span style="display: inline-block; width:16px"></span> QBT_TR(Priority)QBT_TR</a>

View file

@ -1,15 +1,15 @@
QBT_TR(Torrents)QBT_TR QBT_TR(Torrents)QBT_TR
<ul class="filterList"> <ul class="filterList">
<li id="all_filter"><a href="#" onclick="setFilter('all');return false;"><img src="images/skin/filterall.png"/>QBT_TR(All)QBT_TR</a></li> <li id="all_filter"><a href="#" onclick="setFilter('all');return false;"><img src="images/skin/filterall.png"/>QBT_TR(All)QBT_TR</a></li>
<li id="downloading_filter"><a href="#" onclick="setFilter('downloading');return false;"><img src="images/skin/downloading.png"/>QBT_TR(Downloading)QBT_TR</a></li> <li id="downloading_filter"><a href="#" onclick="setFilter('downloading');return false;"><img src="images/skin/downloading.png"/>QBT_TR(Downloading)QBT_TR</a></li>
<li id="seeding_filter"><a href="#" onclick="setFilter('seeding');return false;"><img src="images/skin/uploading.png"/>QBT_TR(Seeding)QBT_TR</a></li> <li id="seeding_filter"><a href="#" onclick="setFilter('seeding');return false;"><img src="images/skin/uploading.png"/>QBT_TR(Seeding)QBT_TR</a></li>
<li id="completed_filter"><a href="#" onclick="setFilter('completed');return false;"><img src="images/skin/completed.png"/>QBT_TR(Completed)QBT_TR</a></li> <li id="completed_filter"><a href="#" onclick="setFilter('completed');return false;"><img src="images/skin/completed.png"/>QBT_TR(Completed)QBT_TR</a></li>
<li id="resumed_filter"><a href="#" onclick="setFilter('resumed');return false;"><img src="images/skin/resumed.png"/>QBT_TR(Resumed)QBT_TR</a></li> <li id="resumed_filter"><a href="#" onclick="setFilter('resumed');return false;"><img src="images/skin/resumed.png"/>QBT_TR(Resumed)QBT_TR</a></li>
<li id="paused_filter"><a href="#" onclick="setFilter('paused');return false;"><img src="images/skin/paused.png"/>QBT_TR(Paused)QBT_TR</a></li> <li id="paused_filter"><a href="#" onclick="setFilter('paused');return false;"><img src="images/skin/paused.png"/>QBT_TR(Paused)QBT_TR</a></li>
<li id="active_filter"><a href="#" onclick="setFilter('active');return false;"><img src="images/skin/filteractive.png"/>QBT_TR(Active)QBT_TR</a></li> <li id="active_filter"><a href="#" onclick="setFilter('active');return false;"><img src="images/skin/filteractive.png"/>QBT_TR(Active)QBT_TR</a></li>
<li id="inactive_filter"><a href="#" onclick="setFilter('inactive');return false;"><img src="images/skin/filterinactive.png"/>QBT_TR(Inactive)QBT_TR</a></li> <li id="inactive_filter"><a href="#" onclick="setFilter('inactive');return false;"><img src="images/skin/filterinactive.png"/>QBT_TR(Inactive)QBT_TR</a></li>
</ul> </ul>
<br/> <br/>
QBT_TR(Labels)QBT_TR QBT_TR(Labels)QBT_TR
<ul id="filterLabelList" style="padding-left: 0px;"> <ul id="filterLabelList" class="filterList">
</ul> </ul>

View file

@ -7,58 +7,41 @@
<script type="text/javascript" src="scripts/mootools-1.2-core-yc.js" charset="utf-8"></script> <script type="text/javascript" src="scripts/mootools-1.2-core-yc.js" charset="utf-8"></script>
<script type="text/javascript" src="scripts/mootools-1.2-more.js" charset="utf-8"></script> <script type="text/javascript" src="scripts/mootools-1.2-more.js" charset="utf-8"></script>
<script type="text/javascript"> <script type="text/javascript">
window.addEvent('domready', function(){ window.addEvent('domready', function() {
$('newLabel').focus(); $('newLabel').focus();
$('newLabelButton').addEvent('click', function(e){ $('newLabelButton').addEvent('click', function(e) {
// check field
var label_str = $('newLabel').value;
if( label_str == null || label_str == "" ) {
return false;
}
if( label_str.match("[\\\\/:?\"*<>|]") !== null ) {
$('alert_div').style.display = "block";
return false;
}
new Event(e).stop(); new Event(e).stop();
var hashes = new URI().getData('hashes'); // check field
var hashesList = hashes.split(','); var labelName = $('newLabel').value.trim();
var label_json = JSON.stringify( { value : label_str } ); if (labelName == null || labelName == "")
return false;
if (hashesList.length) { if (labelName.match("[\\\\/:?\"*<>|]") !== null) {
var counter = hashesList.length; alert("QBT_TR(Invalid label name:\nPlease do not use any special characters in the label name.)QBT_TR");
hashesList.each(function(hash, index) { return false;
new Request({
url: 'command/setLabel',
method: 'post',
data: {
hash: hash,
label_obj: label_json
},
onComplete: function() {
if( --counter === 0 ) {
window.parent.document.getElementById('newLabelPage').parentNode.removeChild(window.parent.document.getElementById('newLabelPage'));
}
}
}).send();
});
} }
var hashesList = new URI().getData('hashes');
new Request({
url: 'command/setLabel',
method: 'post',
data: {
hashes: hashesList,
label: labelName
},
onComplete: function() {
window.parent.closeWindows();
}
}).send();
}); });
}); });
</script> </script>
</head> </head>
<body> <body>
<center> <div style="padding: 10px 10px 0px 10px;">
<h1 class="vcenter">QBT_TR(Label)QBT_TR: <p style="font-weight: bold;">QBT_TR(Label)QBT_TR:</p>
<input type="text" name="label" id="newLabel" value="" maxlength="100" /> <input type="text" id="newLabel" value="" maxlength="100" style="width: 220px;"/>
</h1> <div style="text-align: center;">
<div id="alert_div" style="border: 1px #ff0000 solid; display: none; color: #ff0000; background-color: #ffdee8; width: 95%;"> <input type="button" value="QBT_TR(Add)QBT_TR" id="newLabelButton"/>
<b>QBT_TR(Invalid label name)QBT_TR</b>: </div>
<br/>
QBT_TR(Please don't use any special characters in the label name.)QBT_TR
<br/>
</div> </div>
<input type="button" value="QBT_TR(Add)QBT_TR" id="newLabelButton"/>
</center>
</body> </body>
</html> </html>

View file

@ -95,10 +95,10 @@ window.addEvent('load', function () {
resizeLimit : [100, 300] resizeLimit : [100, 300]
}); });
setLabelFilter = function( hash ) { setLabelFilter = function(hash) {
selected_label = hash; selected_label = hash;
localStorage.setItem('selected_label', selected_label); localStorage.setItem('selected_label', selected_label);
updateLabelList(); highlightSelectedLabel();
if (typeof myTable.table != 'undefined') if (typeof myTable.table != 'undefined')
updateMainData(); updateMainData();
}; };
@ -161,35 +161,33 @@ window.addEvent('load', function () {
var syncMainDataLastResponseId = 0; var syncMainDataLastResponseId = 0;
var serverState = {}; var serverState = {};
var removeTorrentFromLabelList = function( hash ) var removeTorrentFromLabelList = function(hash) {
{ if (hash == null || hash == "")
if( hash == null || hash == "" ) return false; return false;
var removed = false; var removed = false;
Object.each( label_list, function( label ) { Object.each(label_list, function(label) {
if( Object.contains( label.torrents, hash ) ) { if (Object.contains(label.torrents, hash)) {
removed = true; removed = true;
label.torrents.splice( label.torrents.indexOf( hash ), 1 ); label.torrents.splice(label.torrents.indexOf(hash), 1);
} }
}); });
return removed; return removed;
}; };
var addTorrentToLabelList = function( torrent ) { var addTorrentToLabelList = function(torrent) {
var label = torrent['label']; var label = torrent['label'];
if( label == null || label.length === 0 ) { if (label == null)
removeTorrentFromLabelList( torrent['hash'] );
return false; return false;
if (label.length === 0) { // Empty label
removeTorrentFromLabelList(torrent['hash']);
return true;
} }
var labelHash = genHash(label);
var labelHash = genHash( label ); if (label_list[labelHash] == null) // This should not happen
if( label_list[labelHash] == null ) { label_list[labelHash] = {name: label, torrents: []};
console.log( "addTorrentToLabelList: warning, label not found. label=", label, " label_list=", label_list ); if (!Object.contains(label_list[labelHash].torrents, torrent['hash'])) {
label_list[labelHash] = { name: label, torrents: [] }; removeTorrentFromLabelList(torrent['hash']);
} label_list[labelHash].torrents = label_list[labelHash].torrents.combine([torrent['hash']]);
if( !Object.contains(label_list[labelHash].torrents, torrent['hash'] ) ) {
removeTorrentFromLabelList( torrent['hash'] );
label_list[labelHash].torrents = label_list[labelHash].torrents.combine( [ torrent['hash'] ] );
return true; return true;
} }
return false; return false;
@ -198,15 +196,20 @@ window.addEvent('load', function () {
var updateContextMenu = function () { var updateContextMenu = function () {
var labelList = $('contextLabelList'); var labelList = $('contextLabelList');
labelList.empty(); labelList.empty();
labelList.appendChild(new Element('li', {html: '<a href="javascript:newLabelFN();">QBT_TR(New...)QBT_TR</a>'})); labelList.appendChild(new Element('li', {html: '<a href="javascript:newLabelFN();"><img src="theme/list-add" alt="QBT_TR(New...)QBT_TR"/> QBT_TR(New...)QBT_TR</a>'}));
labelList.appendChild(new Element('li', {html: '<a href="javascript:resetLabelFN();">QBT_TR(Reset)QBT_TR</a>'})); labelList.appendChild(new Element('li', {html: '<a href="javascript:updateLabelFN(0);"><img src="theme/edit-clear" alt="QBT_TR(Reset)QBT_TR"/> QBT_TR(Reset)QBT_TR</a>'}));
var sortedLabels = []
Object.each(label_list, function(label) {
sortedLabels.push(label.name);
});
sortedLabels.sort();
var first = true; var first = true;
Object.each(label_list, function (label) { Object.each(sortedLabels, function(labelName) {
var labelHash = genHash( label.name ); var labelHash = genHash(labelName);
var el = new Element('li', {html: '<a href="javascript:updateLabelFN(\'' + labelHash + '\');">' + label.name + '</a>'}); var el = new Element('li', {html: '<a href="javascript:updateLabelFN(\'' + labelHash + '\');"><img src="theme/inode-directory"/> ' + labelName + '</a>'});
if (first) { if (first) {
el.removeClass();
el.addClass('separator'); el.addClass('separator');
first = false; first = false;
} }
@ -215,42 +218,54 @@ window.addEvent('load', function () {
}; };
var updateLabelList = function() { var updateLabelList = function() {
var labelList = $( 'filterLabelList' ); var labelList = $('filterLabelList');
if( !labelList ) { if (!labelList)
return; return;
}
labelList.empty(); labelList.empty();
var create_link = function( hash, text, count ) var create_link = function(hash, text, count) {
{
var html = '<a href="#" onclick="setLabelFilter(' + hash + ');return false;">' + var html = '<a href="#" onclick="setLabelFilter(' + hash + ');return false;">' +
'<img src="images/oxygen/folder-documents.png"/>' + '<img src="theme/inode-directory"/>' +
text + '(' + count + ')' + '</a>'; text + ' (' + count + ')' + '</a>';
return new Element('li', {id: hash, html: html});
return new Element( 'li', { id: hash, html: html } );
}; };
var allLabels = 0; var all = myTable.getRowIds().length;
Object.each( label_list, function( label ) { var unlabelled = 0;
allLabels += label.torrents.length; Object.each(myTable.rows, function(row) {
if (row['full_data'].label.length === 0)
unlabelled += 1;
});
labelList.appendChild(create_link(LABELS_ALL, 'QBT_TR(All)QBT_TR', all));
labelList.appendChild(create_link(LABELS_UNLABELLED, 'QBT_TR(Unlabeled)QBT_TR', unlabelled));
var sortedLabels = []
Object.each(label_list, function(label) {
sortedLabels.push(label.name);
});
sortedLabels.sort();
Object.each(sortedLabels, function(labelName) {
var labelHash = genHash(labelName);
var labelCount = label_list[labelHash].torrents.length;
labelList.appendChild(create_link(labelHash, labelName, labelCount));
}); });
var unlabelled = myTable.getRowIds().length - allLabels; highlightSelectedLabel();
labelList.appendChild( create_link( LABELS_ALL, 'QBT_TR(All Labels)QBT_TR', allLabels ) ); };
labelList.appendChild( create_link( LABELS_UNLABELLED, 'QBT_TR(Unlabeled)QBT_TR', unlabelled ) );
Object.each( label_list, function( label ) {
var labelHash = genHash( label.name );
labelList.appendChild( create_link( labelHash, label.name, label.torrents.length ) );
} );
var highlightSelectedLabel = function() {
var labelList = $('filterLabelList');
if (!labelList)
return;
var childrens = labelList.childNodes; var childrens = labelList.childNodes;
for (var i in childrens) { for (var i in childrens) {
if( childrens[i].id == selected_label ) { if (childrens[i].id == selected_label)
childrens[i].className = "selectedFilter"; childrens[i].className = "selectedFilter";
} else
childrens[i].className = "";
} }
}; }
var syncMainDataTimer; var syncMainDataTimer;
var syncMainData = function () { var syncMainData = function () {
@ -268,30 +283,42 @@ window.addEvent('load', function () {
onSuccess : function (response) { onSuccess : function (response) {
$('error_div').set('html', ''); $('error_div').set('html', '');
if (response) { if (response) {
var update_labels = false;
var full_update = (response['full_update'] == true); var full_update = (response['full_update'] == true);
if (full_update) { if (full_update) {
myTable.rows.erase(); myTable.rows.erase();
label_list = {}; label_list = {};
Object.each( response['labels'], function( label ) {
var labelHash = genHash( label );
label_list[ labelHash ] = { name: label, torrents: [] };
} );
} }
if (response['rid']) { if (response['rid']) {
syncMainDataLastResponseId = response['rid']; syncMainDataLastResponseId = response['rid'];
} }
if (response['labels']) {
response['labels'].each(function(label) {
var labelHash = genHash(label);
label_list[labelHash] = {name: label, torrents: []};
});
update_labels = true;
}
if (response['labels_removed']) {
response['labels_removed'].each(function(label) {
var labelHash = genHash(label);
delete label_list[labelHash];
});
update_labels = true;
}
if (response['torrents']) { if (response['torrents']) {
for (var key in response['torrents']) { for (var key in response['torrents']) {
response['torrents'][key]['hash'] = key; response['torrents'][key]['hash'] = key;
myTable.updateRowData( response['torrents'][key] ); myTable.updateRowData(response['torrents'][key]);
addTorrentToLabelList( response['torrents'][key] ); if (addTorrentToLabelList(response['torrents'][key]))
update_labels = true;
} }
updateLabelList();
updateContextMenu();
} }
if (response['torrents_removed']) if (response['torrents_removed'])
response['torrents_removed'].each(function (hash) { response['torrents_removed'].each(function (hash) {
myTable.removeRow(hash); myTable.removeRow(hash);
removeTorrentFromLabelList(hash);
update_labels = true; // Allways to update All label
}); });
myTable.updateTable(full_update); myTable.updateTable(full_update);
myTable.altRow(); myTable.altRow();
@ -301,6 +328,10 @@ window.addEvent('load', function () {
serverState[key] = tmp[key]; serverState[key] = tmp[key];
processServerState(); processServerState();
} }
if (update_labels) {
updateLabelList();
updateContextMenu();
}
} }
clearTimeout(syncMainDataTimer); clearTimeout(syncMainDataTimer);
syncMainDataTimer = syncMainData.delay(syncMainDataTimerPeriod); syncMainDataTimer = syncMainData.delay(syncMainDataTimerPeriod);

View file

@ -280,7 +280,7 @@ var dynamicTable = new Class({
break; break;
} }
if (labelName == LABELS_ALL && row['full_data'].label.length > 0) if (labelName == LABELS_ALL)
return true; return true;
if (labelName == LABELS_UNLABELLED && row['full_data'].label.length === 0) if (labelName == LABELS_UNLABELLED && row['full_data'].label.length === 0)

View file

@ -314,52 +314,34 @@ initializeWindows = function() {
if (h.length) { if (h.length) {
new MochaUI.Window({ new MochaUI.Window({
id: 'newLabelPage', id: 'newLabelPage',
title: "QBT_TR(Torrent Label)QBT_TR", title: "QBT_TR(New Label)QBT_TR",
loadMethod: 'iframe', loadMethod: 'iframe',
contentURL: 'newlabel.html?hashes=' + h.join(','), contentURL: 'newlabel.html?hashes=' + h.join('|'),
scrollbars: false, scrollbars: false,
resizable: false, resizable: false,
maximizable: false, maximizable: false,
paddingVertical: 0, paddingVertical: 0,
paddingHorizontal: 0, paddingHorizontal: 0,
width: 424, width: 250,
height: 150 height: 100
}); });
} }
}; };
resetLabelFN = function () { updateLabelFN = function (labelHash) {
var h = myTable.selectedIds(); var labelName = '';
var label_json = JSON.stringify({value: ''}); if (labelHash != 0)
if (h.length) { var labelName = label_list[labelHash].name;
h.each(function (hash, index) {
new Request({
url: 'command/setLabel',
method: 'post',
data: {
hash: hash,
label_obj: label_json
}
}).send();
});
}
};
updateLabelFN = function (label_hash) {
var label = label_list[label_hash].name;
var label_json = JSON.stringify({value: label});
var h = myTable.selectedIds(); var h = myTable.selectedIds();
if (h.length) { if (h.length) {
h.each(function (hash, index) { new Request({
new Request({ url: 'command/setLabel',
url: 'command/setLabel', method: 'post',
method: 'post', data: {
data: { hashes: h.join("|"),
hash: hash, label: labelName
label_obj: label_json }
} }).send();
}).send();
});
} }
}; };