Use mw.util.getUrl for team links (short URLs)
Upload UI for Training materials library
Line 33: Line 33:
{ title: 'Category:Classes', label: 'Classes', icon: 'userGroup' },
{ title: 'Category:Classes', label: 'Classes', icon: 'userGroup' },
{ title: 'Photos', label: 'Photos', icon: 'imageGallery' },
{ title: 'Photos', label: 'Photos', icon: 'imageGallery' },
{ title: 'Training materials', label: 'Training materials', icon: 'articles' },
{ title: 'Contribute', label: 'Contribute', icon: 'edit' },
{ title: 'Contribute', label: 'Contribute', icon: 'edit' },
{ title: 'Contact Us', label: 'Contact Us', icon: 'speechBubbles' },
{ title: 'Contact Us', label: 'Contact Us', icon: 'speechBubbles' },
Line 3,201: Line 3,202:
$links.empty().append(wikiLink(cat, 'Browse team roster'));
$links.empty().append(wikiLink(cat, 'Browse team roster'));
});
});
});
});
}());
(function rbCampManualUpload() {
var $slot = $('.mw-parser-output .camp-manual-upload-slot').first();
if (!$slot.length || $slot.data('rbCampManualUpload')) {
return;
}
$slot.data('rbCampManualUpload', 1);
var PAGE = 'Training materials';
var BEGIN = '<!-- BEGIN camp-manuals -->';
var END = '<!-- END camp-manuals -->';
var PLACEHOLDER = "''No manuals listed yet. Upload a PDF above and it will appear here.''";
var DOC_EXT = /\.(pdf|docx?|txt|rtf|odt|tiff?|jpe?g|png|gif|webp)$/i;
var pageTitle = mw.config.get('wgPageName');
var loggedIn = !!mw.config.get('wgUserName');
var uploadUrl = mw.util.getUrl('Special:Upload');
$slot.empty();
var $box = $('<div>', { 'class': 'camp-manual-upload-box soldier-upload-body' });
$box.append($('<p>', { 'class': 'soldier-contrib-help' }).append(
document.createTextNode('Upload a manual or related Camp Ritchie document (PDF preferred). Also '),
$('<a>', { href: uploadUrl, text: 'Special:Upload' }),
document.createTextNode('.')
));
if (!loggedIn) {
$box.append($('<p>', { 'class': 'soldier-upload-login' }).html(
'<a href="' + mw.util.getUrl('Special:UserLogin', { returnto: pageTitle }) + '">Log in</a> to upload files.'
));
$slot.append($box);
return;
}
var $form = $('<form>', { 'class': 'soldier-upload-form camp-manual-upload-form' });
var $file = $('<input>', {
type: 'file',
name: 'campManualFile',
'class': 'soldier-upload-file',
accept: '.pdf,.doc,.docx,.txt,.rtf,.odt,.tif,.tiff,.jpg,.jpeg,.png'
});
var $label = $('<label>').append(
document.createTextNode('Display title (optional)'),
$('<input>', {
type: 'text',
name: 'campManualTitle',
'class': 'camp-manual-title',
placeholder: 'e.g. Interrogation manual, 1943',
maxlength: 200
})
);
var $note = $('<label>').append(
document.createTextNode('Short note / source (optional)'),
$('<input>', {
type: 'text',
name: 'campManualNote',
'class': 'camp-manual-note',
placeholder: 'e.g. NARA / museum scan',
maxlength: 300
})
);
var $status = $('<p>', { 'class': 'soldier-upload-status', text: '' });
var $submit = $('<button>', { type: 'submit', text: 'Upload to library' });
$form.append($file, $label, $note, $submit, $status);
$box.append($form);
$slot.append($box);
function setStatus(msg, isError) {
$status.text(msg).css('color', isError ? '#ba0000' : '#202122');
}
function escapePipe(s) {
return String(s || '').replace(/\|/g, '–').replace(/\[\[/g, '').replace(/\]\]/g, '');
}
function buildBullet(filename, displayTitle, note) {
var label = escapePipe(displayTitle || filename.replace(/_/g, ' '));
var line = '* [[Media:' + filename + '|' + label + ']]';
if (note) {
line += ' — ' + escapePipe(note);
}
return line;
}
function appendToLibrary(api, filename, displayTitle, note) {
return api.get({
action: 'query',
prop: 'revisions',
titles: PAGE,
rvprop: 'content',
rvslots: 'main',
formatversion: 2
}).then(function (data) {
var page = data.query && data.query.pages && data.query.pages[0];
var text = (page && page.revisions && page.revisions[0] &&
page.revisions[0].slots && page.revisions[0].slots.main &&
page.revisions[0].slots.main.content) || '';
var start = text.indexOf(BEGIN);
var end = text.indexOf(END);
if (start === -1 || end === -1 || end <= start) {
throw new Error('Library markers missing on Training materials page');
}
var inner = text.substring(start + BEGIN.length, end).replace(/^\s+|\s+$/g, '');
if (inner.indexOf(PLACEHOLDER) !== -1 || !inner) {
inner = buildBullet(filename, displayTitle, note);
} else {
inner = inner + '\n' + buildBullet(filename, displayTitle, note);
}
var next = text.substring(0, start + BEGIN.length) + '\n' + inner + '\n' + text.substring(end);
return api.postWithToken('csrf', {
action: 'edit',
title: PAGE,
text: next,
summary: 'Add training material: ' + filename,
format: 'json'
});
});
}
$form.on('submit', function (evt) {
evt.preventDefault();
var file = $file[0].files[0];
if (!file) {
setStatus('Choose a file first.', true);
return;
}
if (!DOC_EXT.test(file.name)) {
setStatus('File type not allowed (PDF, Office docs, images, TIFF).', true);
return;
}
var displayTitle = $.trim($form.find('.camp-manual-title').val() || '');
var note = $.trim($form.find('.camp-manual-note').val() || '');
$submit.prop('disabled', true);
setStatus('Uploading…');
var api = new mw.Api();
var fileText = 'Camp Ritchie / MITC training material.\n\n[[Category:Training materials]]';
api.postWithToken('csrf', {
action: 'upload',
filename: file.name,
file: file,
comment: 'Uploaded to Training materials library',
text: fileText,
format: 'json',
ignorewarnings: true
}, {
contentType: 'multipart/form-data'
}).then(function (data) {
var uploaded = data.upload && data.upload.filename;
if (!uploaded) {
throw new Error((data.error && data.error.info) || 'Upload failed');
}
setStatus('Adding to Library list…');
return appendToLibrary(api, uploaded, displayTitle, note);
}).done(function () {
setStatus('Done. Reloading…');
window.location.reload();
}).fail(function (code, data) {
var err = (data && data.error && data.error.info) || code || 'Upload failed';
setStatus(String(err), true);
$submit.prop('disabled', false);
});
});
});
});