diff --git a/ext/js/results.js b/ext/js/results.js index 4cd81a1..3fe8cca 100644 --- a/ext/js/results.js +++ b/ext/js/results.js @@ -19,6 +19,25 @@ let url = document.location.href; const contestID = getContestID(url); + /** + * Get submit extension if possible + * @returns {string|null} extension without dot or null + */ + function getExt() { + const downloadUrl = $('a[href^="/download/Submit/"]').attr('href'); + const dotPos = downloadUrl.lastIndexOf('.'); + if (dotPos === -1) { + return null; + } + const ext = downloadUrl.substring(dotPos + 1).trim(); + if (ext === '') { + return null; + } + return ext; + } + + const ext = getExt(); + /** * Parse given HTML and return problem status code if it's found. * @@ -68,10 +87,8 @@ } function initializeSyntaxHighlighter() { - const downloadUrl = $('a[href^="/download/Submit/"]').attr('href'); - const dotPos = downloadUrl.lastIndexOf('.'); - if (dotPos !== -1) { - let lang = downloadUrl.substr(dotPos + 1); + if (ext !== null) { + let lang = ext; if (lang === 'asm') { lang = 'x86asm'; } @@ -97,9 +114,13 @@ 'href', `${SATORI_URL_HTTPS}contest/${contestID}/results?results_filter_problem=${submitID}`, ); + let resubmitUrl = new URL(submitUrl, window.location); + if (ext !== null) { + resubmitUrl.searchParams.set('filename', `program.${ext}`); + } const submitButton = $('Submit another').attr( 'href', - submitUrl, + resubmitUrl, ); $('
') .append(resultsButton) diff --git a/ext/js/submit.js b/ext/js/submit.js index 300bf0d..11b2bee 100644 --- a/ext/js/submit.js +++ b/ext/js/submit.js @@ -5,28 +5,80 @@ $('#content table tr:nth-child(1) th').text('Problem:'); $('#content table tr:nth-child(2) th').text('File:'); - $('#content table').append( - 'Code:', - ); + $('#content table') + .append( + 'Code:', + ) + .append( + 'Filename:' + + '
' + + ' ' + + ' ' + + '
' + + '', + ); const problemSelect = $('#id_problem'); const filePicker = $('#id_codefile'); const codeTextarea = $('#code-textarea'); + const codeFilenameRow = $('#code-filename-row'); + const codeFilename = $('#code-filename'); + const codeFilenameAuto = $('#code-filename-auto'); const form = $('#content form'); const submitButton = $('#content form input[type=submit]'); - submitButton.attr('tabindex', '4'); + codeFilename.val( + new URLSearchParams(window.location.search).get('filename') || + 'program.cpp', + ); + + ['c', 'cpp', 'py', 'asm', 'sql'].forEach((ext) => { + $('').insertAfter( + filePicker, + ); + submitButton.attr('tabindex', '6'); let loading = false; const updatePickers = () => { const fileSelected = filePicker.val() !== ''; const textEntered = codeTextarea.val() !== ''; - codeTextarea.attr('disabled', fileSelected); - filePicker.attr('disabled', textEntered); + const filenameEntered = codeFilename.val().trim() !== ''; + + // disable one type if the other one is filled, + // but don't disable in case somehow both are filled + codeTextarea.attr('disabled', fileSelected && !textEntered); + filePicker.attr('disabled', textEntered && !fileSelected); + + const showAutoFilename = fileSelected && !textEntered; + codeFilename.toggleClass('hidden', showAutoFilename); + setExtButtons.attr('disabled', showAutoFilename); + codeFilenameAuto.toggleClass('hidden', !showAutoFilename); + codeFilenameAuto.val(filePicker[0]?.files[0]?.name ?? ''); + + clearButton.toggleClass('hidden', !fileSelected); + submitButton.attr( 'disabled', - loading || !problemSelect.val() || !(textEntered || fileSelected), + loading || + !problemSelect.val() || + // NXOR - disable submit if somehow both file and text are set: + textEntered === fileSelected || + (textEntered && !filenameEntered), ); }; @@ -74,10 +126,14 @@ if (filePicker.val() !== '') { formData.set('codefile', filePicker[0].files[0]); } else if (codeTextarea.val() !== '') { + const filename = codeFilename.val().trim(); + if (filename === '') { + return; + } const blob = new Blob([codeTextarea.val()], { type: 'text/plain', }); - formData.set('codefile', blob, 'code.cpp'); + formData.set('codefile', blob, filename); } else { return; } @@ -112,4 +168,10 @@ loading = false; updatePickers(); }); + + clearButton.on('click', (event) => { + event.preventDefault(); + filePicker.val(''); + updatePickers(); + }); })(); diff --git a/ext/scss/submit.scss b/ext/scss/submit.scss index d50a567..c6bdc83 100644 --- a/ext/scss/submit.scss +++ b/ext/scss/submit.scss @@ -11,14 +11,14 @@ } td { - select, - input, - textarea { + & > select, + & > input, + & > textarea { width: 100%; box-sizing: border-box; } - textarea { + & > textarea { resize: vertical; min-height: 100px; height: 200px; @@ -26,6 +26,21 @@ } } + .input-row { + display: flex; + flex-direction: row; + align-items: center; + gap: 4px; + + input { + flex-grow: 1; + } + + &.hidden { + display: none; + } + } + input[type='submit'] { display: block; margin-left: auto;