Merge pull request #819 from ArthurHoaro/feature/multi-delete

Bulk deletion
This commit is contained in:
ArthurHoaro 2017-05-25 15:03:32 +02:00 committed by GitHub
commit 8b27824338
5 changed files with 93 additions and 17 deletions

View File

@ -1311,18 +1311,21 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history)
// -------- User clicked the "Delete" button when editing a link: Delete link from database.
if ($targetPage == Router::$PAGE_DELETELINK)
{
// We do not need to ask for confirmation:
// - confirmation is handled by JavaScript
// - we are protected from XSRF by the token.
if (! tokenOk($_GET['token'])) {
die('Wrong token.');
}
$id = intval(escape($_GET['lf_linkdate']));
$link = $LINKSDB[$id];
$pluginManager->executeHooks('delete_link', $link);
unset($LINKSDB[$id]);
if (strpos($_GET['lf_linkdate'], ' ') !== false) {
$ids = array_values(array_filter(preg_split('/\s+/', escape($_GET['lf_linkdate']))));
} else {
$ids = [$_GET['lf_linkdate']];
}
foreach ($ids as $id) {
$id = (int) escape($id);
$link = $LINKSDB[$id];
$pluginManager->executeHooks('delete_link', $link);
unset($LINKSDB[$id]);
}
$LINKSDB->save($conf->get('resource.page_cache')); // save to disk
$history->deleteLink($link);

View File

@ -279,6 +279,19 @@ body, .pure-g [class*="pure-u"] {
}
}
.subheader-form a.button {
color: #f5f5f5;
font-weight: bold;
text-decoration: none;
border: 2px solid #f5f5f5;
border-radius: 5px;
padding: 3px 10px;
}
.linklist-item-editbuttons .delete-checkbox {
display: none;
}
#header-login-form input[type="text"], #header-login-form input[type="password"] {
width: 200px;
}

View File

@ -216,14 +216,14 @@ window.onload = function () {
/**
* Autofocus text fields
*/
// ES6 syntax
let autofocusElements = document.querySelectorAll('.autofocus');
for (let autofocusElement of autofocusElements) {
if (autofocusElement.value == '') {
var autofocusElements = document.querySelectorAll('.autofocus');
var breakLoop = false;
[].forEach.call(autofocusElements, function(autofocusElement) {
if (autofocusElement.value == '' && ! breakLoop) {
autofocusElement.focus();
break;
breakLoop = true;
}
}
});
/**
* Handle sub menus/forms
@ -357,11 +357,61 @@ window.onload = function () {
var continent = document.getElementById('continent');
var city = document.getElementById('city');
if (continent != null && city != null) {
continent.addEventListener('change', function(event) {
continent.addEventListener('change', function (event) {
hideTimezoneCities(city, continent.options[continent.selectedIndex].value, true);
});
hideTimezoneCities(city, continent.options[continent.selectedIndex].value, false);
}
/**
* Bulk actions
*/
var linkCheckboxes = document.querySelectorAll('.delete-checkbox');
var bar = document.getElementById('actions');
[].forEach.call(linkCheckboxes, function(checkbox) {
checkbox.style.display = 'block';
checkbox.addEventListener('click', function(event) {
var count = 0;
var linkCheckedCheckboxes = document.querySelectorAll('.delete-checkbox:checked');
[].forEach.call(linkCheckedCheckboxes, function(checkbox) {
count++;
});
if (count == 0 && bar.classList.contains('open')) {
bar.classList.toggle('open');
} else if (count > 0 && ! bar.classList.contains('open')) {
bar.classList.toggle('open');
}
});
});
var deleteButton = document.getElementById('actions-delete');
var token = document.querySelector('input[type="hidden"][name="token"]');
if (deleteButton != null && token != null) {
deleteButton.addEventListener('click', function(event) {
event.preventDefault();
var links = [];
var linkCheckedCheckboxes = document.querySelectorAll('.delete-checkbox:checked');
[].forEach.call(linkCheckedCheckboxes, function(checkbox) {
links.push({
'id': checkbox.value,
'title': document.querySelector('.linklist-item[data-id="'+ checkbox.value +'"] .linklist-link').innerHTML
});
});
var message = 'Are you sure you want to delete '+ links.length +' links?\n';
message += 'This action is IRREVERSIBLE!\n\nTitles:\n';
var ids = '';
links.forEach(function(item) {
message += ' - '+ item['title'] +'\n';
ids += item['id'] +'+';
});
if (window.confirm(message)) {
window.location = '?delete_link&lf_linkdate='+ ids +'&token='+ token.value;
}
});
}
};
function activateFirefoxSocial(node) {
@ -397,7 +447,7 @@ function activateFirefoxSocial(node) {
*/
function hideTimezoneCities(cities, currentContinent, reset = false) {
var first = true;
[].forEach.call(cities, function(option) {
[].forEach.call(cities, function (option) {
if (option.getAttribute('data-continent') != currentContinent) {
option.className = 'hidden';
} else {

View File

@ -15,6 +15,8 @@
{/if}
</div>
<input type="hidden" name="token" value="{$token}">
<div id="search-linklist">
<div class="pure-g">
@ -121,7 +123,7 @@
<div class="pure-u-lg-20-24 pure-u-22-24">
{loop="links"}
<div class="anchor" id="{$value.shorturl}"></div>
<div class="linklist-item{if="$value.class"} {$value.class}{/if}">
<div class="linklist-item linklist-item{if="$value.class"} {$value.class}{/if}" data-id="{$value.id}">
<div class="linklist-item-title">
{if="isLoggedIn()"}
@ -129,6 +131,7 @@
{if="$value.private"}
<span class="label label-private">{'Private'|t}</span>
{/if}
<input type="checkbox" class="delete-checkbox" value="{$value.id}">
<!-- FIXME! JS translation -->
<a href="?edit_link={$value.id}" title="{'Edit'|t}"><i class="fa fa-pencil-square-o edit-link"></i></a>
<a href="#" title="{'Fold'|t}" class="fold-button"><i class="fa fa-chevron-up"></i></a>

View File

@ -122,6 +122,13 @@
</div>
</div>
</div>
<div id="actions" class="subheader-form">
<div class="pure-g">
<div class="pure-u-1">
<a href="" id="actions-delete" class="button">Delete</a>
</div>
</div>
</div>
{if="!isLoggedIn()"}
<form method="post" name="loginform">
<div class="subheader-form" id="header-login-form">