MediaWiki:Common.js: Difference between revisions
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); | |||
}); | }); | ||
}); | }); | ||