Training materials: admin-only Delete file; purge after library edits
Fix library Remove/Delete buttons for Media: /images/ links
Line 3,509: Line 3,509:
}
}


function filenameFromHref(href) {
function filenameFromHref(href, titleAttr) {
if (titleAttr && /\.[a-z0-9]{2,5}$/i.test(titleAttr)) {
return String(titleAttr).replace(/ /g, '_');
}
if (!href) {
if (!href) {
return '';
return '';
Line 3,517: Line 3,520:
} catch (e) { /* ignore */ }
} catch (e) { /* ignore */ }
var m = href.match(/\/wiki\/(?:File|Media):([^?#]+)/i) ||
var m = href.match(/\/wiki\/(?:File|Media):([^?#]+)/i) ||
href.match(/[?&]title=(?:File|Media):([^&#]+)/i);
href.match(/[?&]title=(?:File|Media):([^&#]+)/i) ||
href.match(/\/images\/(?:thumb\/)?[^/]+\/[^/]+\/([^/?#]+)$/i);
if (!m) {
if (!m) {
return '';
return '';
Line 3,525: Line 3,529:


function enhanceLibraryManage() {
function enhanceLibraryManage() {
var canEdit = !!mw.config.get('wgIsProbablyEditable') || !!mw.config.get('wgUserName');
if (!mw.config.get('wgUserName')) {
if (!canEdit) {
return;
return;
}
}
var $heading = $('.mw-parser-output .mw-heading, .mw-parser-output h2').filter(function () {
var $heading = $('.mw-parser-output .mw-heading, .mw-parser-output h2').filter(function () {
return $(this).text().replace(/\s*\[edit\].*$/i, '').trim() === 'Library';
return /^Library\b/i.test($(this).text().replace(/\s*\[.*$/, '').trim());
}).first();
}).first();
if (!$heading.length) {
if (!$heading.length) {
Line 3,544: Line 3,547:
$list.data('rbCampManualManage', 1);
$list.data('rbCampManualManage', 1);


var groups = mw.config.get('wgUserGroups') || [];
var canDeleteFile = groups.indexOf('sysop') !== -1;
var api = new mw.Api();
var api = new mw.Api();
var canDeleteFile = false;
 
api.get({
$list.children('li').each(function () {
action: 'query',
var $li = $(this);
meta: 'userinfo',
if ($li.find('.camp-manual-lib-actions').length) {
uiprop: 'groups',
return;
formatversion: 2
}
}).then(function (data) {
var $a = $li.find('a.internal, a[href*="/images/"], a[href*="File:"], a[href*="Media:"]').first();
var groups = (data.query && data.query.userinfo && data.query.userinfo.groups) || [];
if (!$a.length) {
/* Delete file is administrators (sysop) only. */
$a = $li.find('a[href]').first();
canDeleteFile = groups.indexOf('sysop') !== -1;
}
}).always(function () {
var filename = filenameFromHref($a.attr('href'), $a.attr('title'));
$list.children('li').each(function () {
if (!filename) {
var $li = $(this);
return;
if ($li.find('.camp-manual-lib-actions').length) {
}
var $actions = $('<span>', { 'class': 'camp-manual-lib-actions' });
var $remove = $('<button>', {
type: 'button',
'class': 'camp-manual-lib-remove',
text: 'Remove'
}).attr('title', 'Remove from this list (file stays on the wiki)');
$actions.append($remove);
if (canDeleteFile) {
$actions.append($('<button>', {
type: 'button',
'class': 'camp-manual-lib-delete',
text: 'Delete file'
}).attr('title', 'Delete the file from the wiki (administrators only)'));
}
$li.append($actions);
 
$remove.on('click', function () {
if (!window.confirm('Remove “' + filename.replace(/_/g, ' ') + '” from the Library list?\n(The file will remain on the wiki.)')) {
return;
return;
}
}
var $a = $li.find('a[href*="File:"], a[href*="Media:"]').first();
$actions.find('button').prop('disabled', true);
var filename = filenameFromHref($a.attr('href'));
removeFromLibrary(api, filename).done(function () {
if (!filename && $a.length) {
window.location.reload();
filename = String($a.text() || '').replace(/ /g, '_');
}).fail(function (code, data) {
if (!/\.[a-z0-9]+$/i.test(filename)) {
window.alert(failMessage(code, data));
filename = '';
$actions.find('button').prop('disabled', false);
}
});
}
});
if (!filename) {
 
$actions.on('click', '.camp-manual-lib-delete', function () {
if (!window.confirm('Permanently delete file “' + filename.replace(/_/g, ' ') + '” from the wiki?')) {
return;
return;
}
}
var $actions = $('<span>', { 'class': 'camp-manual-lib-actions' });
$actions.find('button').prop('disabled', true);
var $remove = $('<button>', {
deleteLibraryFile(api, filename).done(function () {
type: 'button',
window.location.reload();
'class': 'camp-manual-lib-remove',
}).fail(function (code, data) {
text: 'Remove'
window.alert(failMessage(code, data));
}).attr('title', 'Remove from this list (file stays on the wiki)');
$actions.find('button').prop('disabled', false);
$actions.append($remove);
if (canDeleteFile) {
$actions.append($('<button>', {
type: 'button',
'class': 'camp-manual-lib-delete',
text: 'Delete file'
}).attr('title', 'Delete the file from the wiki'));
}
$li.append($actions);
 
$remove.on('click', function () {
if (!window.confirm('Remove “' + filename.replace(/_/g, ' ') + '” from the Library list?\n(The file will remain on the wiki.)')) {
return;
}
$actions.find('button').prop('disabled', true);
removeFromLibrary(api, filename).done(function () {
window.location.reload();
}).fail(function (code, data) {
window.alert(failMessage(code, data));
$actions.find('button').prop('disabled', false);
});
});
 
$actions.on('click', '.camp-manual-lib-delete', function () {
if (!window.confirm('Permanently delete file “' + filename.replace(/_/g, ' ') + '” from the wiki?')) {
return;
}
$actions.find('button').prop('disabled', true);
deleteLibraryFile(api, filename).done(function () {
window.location.reload();
}).fail(function (code, data) {
window.alert(failMessage(code, data));
$actions.find('button').prop('disabled', false);
});
});
});
});
});