Author: humbedooh Date: Mon Dec 16 10:35:31 2019 New Revision: 1871647 URL: http://svn.apache.org/viewvc?rev=1871647&view=rev Log: We're out of beta, really
Removed: comdev/reporter.apache.org/trunk/site/wizard/beta.html comdev/reporter.apache.org/trunk/site/wizard/js/wizard-beta.js Modified: comdev/reporter.apache.org/trunk/site/wizard/index.html comdev/reporter.apache.org/trunk/site/wizard/js/source/build.sh comdev/reporter.apache.org/trunk/site/wizard/js/wizard.js Modified: comdev/reporter.apache.org/trunk/site/wizard/index.html URL: http://svn.apache.org/viewvc/comdev/reporter.apache.org/trunk/site/wizard/index.html?rev=1871647&r1=1871646&r2=1871647&view=diff ============================================================================== --- comdev/reporter.apache.org/trunk/site/wizard/index.html (original) +++ comdev/reporter.apache.org/trunk/site/wizard/index.html Mon Dec 16 10:35:31 2019 @@ -64,6 +64,6 @@ <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script> <script src="highlighter/highlighter.js" type="text/javascript"></script> -<script src="js/wizard-beta.js?unified-1.3" type="text/javascript"></script> +<script src="js/wizard.js?unified-1.4" type="text/javascript"></script> </body> </html> Modified: comdev/reporter.apache.org/trunk/site/wizard/js/source/build.sh URL: http://svn.apache.org/viewvc/comdev/reporter.apache.org/trunk/site/wizard/js/source/build.sh?rev=1871647&r1=1871646&r2=1871647&view=diff ============================================================================== --- comdev/reporter.apache.org/trunk/site/wizard/js/source/build.sh (original) +++ comdev/reporter.apache.org/trunk/site/wizard/js/source/build.sh Mon Dec 16 10:35:31 2019 @@ -16,12 +16,12 @@ echo '/* limitations under the License. */ // THIS IS AN AUTOMATICALLY COMBINED FILE. PLEASE EDIT source/*.js!! -' > ../wizard-beta.js +' > ../wizard.js # Warning: ls/sort order depends on the locale; this can affect the order of '.' and '_' # i.e. statistics.js and statistics_generator.js # so force the use of 'C' for f in `LC_ALL=C ls *.js`; do - printf "\n\n/******************************************\n Fetched from source/${f}\n******************************************/\n\n" >> ../wizard-beta.js - perl -0pe 's/\/\*.*?\*\/[\r\n]*//sm' ${f} >> ../wizard-beta.js + printf "\n\n/******************************************\n Fetched from source/${f}\n******************************************/\n\n" >> ../wizard.js + perl -0pe 's/\/\*.*?\*\/[\r\n]*//sm' ${f} >> ../wizard.js done echo "Done!" Modified: comdev/reporter.apache.org/trunk/site/wizard/js/wizard.js URL: http://svn.apache.org/viewvc/comdev/reporter.apache.org/trunk/site/wizard/js/wizard.js?rev=1871647&r1=1871646&r2=1871647&view=diff ============================================================================== --- comdev/reporter.apache.org/trunk/site/wizard/js/wizard.js (original) +++ comdev/reporter.apache.org/trunk/site/wizard/js/wizard.js Mon Dec 16 10:35:31 2019 @@ -91,7 +91,7 @@ async function GET(url, callback, state, let meta = {method: method, credentials: 'include', referrerPolicy: 'unsafe-url', headers: {'x-original-referral': document.referrer}}; if (body) { meta.body = body; - meta.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'; + meta.headers['Content-Type'] = 'application/json; charset=UTF-8'; } console.log("putting %s in escrow...".format(url)); async_escrow[pkey] = new Date(); // Log start of request in escrow dict @@ -1024,11 +1024,10 @@ function save_draft() { 'project': project, 'action': 'save', 'type': 'unified', - 'report': JSON.stringify(draft_stepper.editor.report), - 'report_compiled': draft_stepper.editor.report + 'report': draft_stepper.editor.report } - let formdata = $.param(js); + let formdata = JSON.stringify(js); // Enable spinner, hide main wrapper document.getElementById('loader_text').innerText = "Saving draft..."; @@ -1036,7 +1035,7 @@ function save_draft() { document.getElementById('wrapper').style.display = 'none'; document.getElementById("pname").style.display = 'none'; - POST('drafts.py', draft_saved, {}, formdata); + POST('/api/drafts/save', draft_saved, {}, formdata); } function draft_saved(state, json) { @@ -1062,7 +1061,7 @@ function draft_saved(state, json) { function load_draft(filename) { - GET('drafts.py?action=fetch&project=%s&filename=%s&type=%s'.format(project, filename, editor_type), read_draft, {}); + GET('/api/drafts/fetch?%s'.format(filename), read_draft, {}); } function read_draft(state, json) { @@ -1081,7 +1080,7 @@ function read_draft(state, json) { function list_drafts(pdata, editor) { if (!saved_drafts) { - GET('drafts.py?action=index&project=%s&type=%s'.format(project, editor_type), show_draft_list, {stepper:editor.stepper}); + GET('/api/drafts/index?%s'.format(project), show_draft_list, {stepper:editor.stepper}); return ""; } else { @@ -1094,7 +1093,7 @@ function show_draft_list(state, json) { draft_stepper = state.stepper||draft_stepper; // hackish for now! if (!draft_stepper) return; let txt = ""; - let filenames = Object.keys(saved_drafts); + let filenames = Object.keys(saved_drafts||{}); if (filenames.length > 0) { txt += "<h6>Found the following saved drafts for %s:</h6>".format(project); txt += "<small style='font-size: 0.75rem;'><ul style='margin: 0px; padding: 10px;'>" @@ -1124,7 +1123,7 @@ function delete_draft(filename) { if (!window.confirm("Are you sure you wish to delete %s?".format(filename))) { return; } - GET('drafts.py?action=delete&project=%s&filename=%s'.format(project, filename), deleted_draft, {filename: filename}); + GET('/api/drafts/delete?%s'.format(filename), deleted_draft, {filename: filename}); } function deleted_draft(state, json) { @@ -1157,7 +1156,15 @@ function publish_report() { 'report': draft_stepper.editor.report }; - let formdata = $.param(js); + if (meta_data && meta_data.filed) { + if (!window.confirm("The report already exists in %s. Do you wish to force an update?".format(agendafile))) { + return; + } + js.digest = meta_data.report.digest; + js.attach = meta_data.report.attach; + } + + let formdata = JSON.stringify(js); // Enable spinner, hide main wrapper document.getElementById('loader_text').innerText = "Publishing report, hang on..."; @@ -1165,7 +1172,7 @@ function publish_report() { document.getElementById('wrapper').style.display = 'none'; document.getElementById("pname").style.display = 'none'; - POST('whimsy.py', report_published, {}, formdata); + POST('/api/whimsy/publish', report_published, {}, formdata); } function report_published(state, json) { @@ -1180,6 +1187,26 @@ function report_published(state, json) { } else { modal("Something went wrong, and we couldn't publish your report.<br/>Please check with the Whimsy tool to see if there is already a report posted!"); } + + // Force whimsy reload of report meta data + GET("/api/whimsy/agenda/refresh?%s".format(project), prime_meta, {noreset: true}); + +} + +function load_from_agenda() { + if (meta_data && meta_data.report && meta_data.filed) { + if (draft_stepper.editor.unsaved && !window.confirm("You have unsaved changes to your current draft. Do you wish to override these with the report in the agenda file??")) return; + draft_stepper.editor.object.value = meta_data.report.report; + draft_stepper.editor.report = meta_data.report.report; + window.setTimeout(() => { draft_stepper.editor.highlight() }, 250); + draft_stepper.build(0, false, false); + draft_stepper.editor.check_changes(true); + let reflower = document.getElementById('unified-reflow'); + if (reflower) { + reflower.innerHTML = "Notice: Loaded most recent version of report from current agenda into editor."; + reflower.style.visibility = 'visible'; + } + } } /****************************************** @@ -1310,13 +1337,24 @@ function generate_meta(data) { let txt = "<b>Founded: </b>%s (%s)<br/>".format(founded.format('YYYY-MM-DD'), age); txt += "<b>Chair: </b> %s<br/>".format(data.pdata[project].chair); txt += getReportDate(cycles, project); + txt += "<br/>" + if (meta_data.found) { + txt += "<b>Report expected this month:</b> YES<br/>"; + txt += "<b>Filed to agenda: </b>"; + if (meta_data.filed) { + txt += "<span style='color: #080;'>Yes</span> <a class='btn btn-primary btn-sm' href='javascript:void(load_from_agenda());'>Load from agenda</a>."; + } else { + txt += "<span style='color: #800;'>Not yet</span>"; + } + txt += "<br/>" + } // Previous comments of note? - let cdates = Object.keys(comments.comments); + let cdates = Object.keys(meta_data.comments||{}); cdates.sort(); - if (comments && cdates.length > 0) { + if (meta_data && cdates.length > 0) { let date = cdates[cdates.length-1]; - let comment = comments.comments[date]; + let comment = meta_data.comments[date]; // split and rejoin comments let ntxt = ""; @@ -1337,13 +1375,12 @@ function generate_meta(data) { function pre_splash(state, json) { cycles = json; - GET("/quickjson", splash, {}); + GET("/api/overview", splash, {}); } function splash(state, json, all) { pdata = json; - let html = document.body; - html.style.margin = '16px'; + let html = document.getElementById('outer_wrapper'); let link = all ? 'All projects (<a href="javascript:splash({}, pdata, false);">show only your projects</a>):' : 'Your projects (<a href="javascript:splash({}, pdata, true);">show all projects</a>):' html.innerHTML = '<h3>%s</h3>'.format(link); let tbl = new HTML('table', {cellpadding: '8px', style: {margin: '20px'}}); @@ -1351,7 +1388,7 @@ function splash(state, json, all) { hdr.inject([ new HTML('td', {}, "Project:"), new HTML('td', {}, "Chair:"), - new HTML('td', {}, "Next report date:"), + new HTML('td', {}, "Next report due:"), new HTML('td', {}, "Editor:"), new HTML('td', {}, "Full statistics:"), ]) @@ -1370,7 +1407,7 @@ function splash(state, json, all) { ccolor = '#195'; } let tr = new HTML('tr'); - let rd = new HTML('td', {}, getReportDate(cycles, key, true)); + let rd = new HTML('td', {}, getReportDate(cycles, key, "due")); let elink = new HTML('td', {}, new HTML('a', {href: '?%s'.format(key)}, "Board report editor")); let slink = new HTML('td', {}, new HTML('a', {href: 'statistics?%s'.format(key)}, "Full statistics for %s".format(tlpname))); let title = new HTML('td', {}, new HTML('b', {}, tlpname)); @@ -1693,6 +1730,7 @@ function activity_tips(data) { // Quick check for reflow needs function should_reflow(txt, chars) { + if (typeof txt != 'string') return false; chars = chars || 80; let lines = txt.split(/[\r\n]+/g); for (var i = 0; i < lines.length; i++) { @@ -1702,6 +1740,7 @@ function should_reflow(txt, chars) { } function reflow(txt, chars) { + if (typeof txt != 'string') return ""; chars = chars || 80; let words = txt.match(/([\S+?]+\s*)/mg); if (!words) return txt; @@ -1743,6 +1782,7 @@ function show_examples(examples, title) modal(out, title); } + /****************************************** Fetched from source/init.js ******************************************/ @@ -1776,7 +1816,7 @@ function init_wizard(so) { console.log("Initializing escrow checks"); window.setInterval(escrow_check, 250); - GET("/quickjson?%s".format(project), prime_wizard, {}); + GET("/api/overview?%s".format(project), prime_wizard, {}); } } document.body.addEventListener('keydown', () => { if (event.keyCode == 27) $("#alert").modal('hide'); }); @@ -1789,7 +1829,7 @@ document.body.addEventListener('keydown' // some glopbal vars for now - we'll get them localized soon enough. let pdata = {}; let cycles = {}; -let comments = {}; +let meta_data = {}; function modal(txt, title = 'Notification') { document.getElementById('alert_text').innerHTML = txt; @@ -1815,12 +1855,13 @@ function prime_wizard(state, json) { if (statsonly) { GET("/reportingcycles.json", prime_cycles, {}); } else { - GET("comments.py?project=%s".format(project), prime_comments, {}) + GET("/api/whimsy/agenda?%s".format(project), prime_meta, {}) } } -function prime_comments(state, json) { - comments = json; +function prime_meta(state, json) { + meta_data = json; + if (state && state.noreset) return; GET("/reportingcycles.json", prime_cycles, {}) } @@ -1840,6 +1881,7 @@ function prime_steps(state, json) { let editor = new UnifiedEditor('unified-report', json.steps); let stepper = new ReportStepper('unified-steps', editor, json.steps, 'unified-helper'); editor.stepper = stepper; + draft_stepper = stepper; stepper.pdata = pdata; stepper.build(0, true); } @@ -1948,7 +1990,21 @@ function getReportDate(json, pmc, dateOn nextdate = dates.shift(); } if (agenda) return "board_agenda_%s.txt".format(moment(nextdate).format('YYYY_MM_DD')); - if (dateOnly) return nextdate ? (nextdate.toDateString() + " (" + moment(nextdate).fromNow() + ")"): "Unknown(?)"; + if (dateOnly) { + // agenda date or due date? + if (dateOnly == "due") { + nextdate.setDate(nextdate.getDate() - 2); // Due 48 hours prior to board meeting. + let rightnow = new Date(); + if (nextdate && Math.abs(rightnow - nextdate) < (86400*2*1000)) { + let fromnow = moment(nextdate).fromNow(); + if (nextdate && Math.abs(rightnow - nextdate) < (86400*1000)) fromnow = "TODAY"; + return new HTML('span', {style: { color: '#711'}}, nextdate.toDateString() + " (" + fromnow + ")"); + } + return nextdate ? (nextdate.toDateString() + " (" + moment(nextdate).fromNow() + ")"): "Unknown(?)"; + } else { + return nextdate ? (nextdate.toDateString() + " (" + moment(nextdate).fromNow() + ")"): "Unknown(?)"; + } + } let txt = ""; txt += "<b>Reporting schedule:</b> " + (json[pmc] ? formatRm(json[pmc]) : "Unknown(?)") + "<br>" txt += "<b>Next report date: " + (nextdate ? nextdate.toDateString() : "Unknown(?)") + "</b>" @@ -2097,6 +2153,45 @@ function toggleView(id) { /****************************************** + Fetched from source/statistics.js +******************************************/ + + +function StatisticsPage(layout, pdata) { + let wrapper = document.getElementById('wrapper'); + wrapper.style.padding = '8px'; + wrapper.style.height = 'auto'; + wrapper.innerHTML = ""; + for (var i = 0; i < layout.length; i++) { + let step = layout[i]; + if (step.statsgenerator||step.tipgenerator) { + let thtml = new HTML('p'); + let f = Function('a', 'b', "return %s(a,b);".format(step.statsgenerator||step.tipgenerator)); + data = f(pdata, {}); + if (typeof data == 'string') thtml.innerHTML += data; + else if (typeof data == 'object') thtml.inject(data); + thtml.inject(new HTML('hr')); + wrapper.inject(thtml); + } + } + + headers = $(wrapper).find("h4"); + let toc = "<ul style='background: #3333;'>"; + for (var i = 0; i < headers.length; i++) { + let t = headers[i].innerText.replace(/:.*$/, ''); + let id = t.replace(/\s+/g, '').toLowerCase(); + headers[i].setAttribute('id', id); + toc += "<li style='display: inline-block; margin-left: 24px;'><a href='#%s'>%s</a></li>".format(id, t); + } + toc += "</ul>"; + let twrap = new HTML('div'); + twrap.innerHTML = toc; + wrapper.insertBefore(twrap, wrapper.childNodes[0]); + +} + + +/****************************************** Fetched from source/statistics_generator.js ******************************************/ @@ -2487,8 +2582,8 @@ function statistics_health(data) { } } cols[0].push(date); - cols[1].push(c); - cols[2].push(o); + cols[1].push(o); + cols[2].push(c); } let cutoff = moment.utc().subtract(13, 'weeks').startOf('week').weekday(4); let chartdiv = new HTML('div', { @@ -2723,8 +2818,8 @@ function statistics_health(data) { } } cols[0].push(date); - cols[1].push(c); - cols[2].push(o); + cols[1].push(o); + cols[2].push(c); } let cutoff = moment.utc().subtract(13, 'weeks').startOf('week').weekday(4); let chartdiv = new HTML('div', { @@ -2851,8 +2946,8 @@ function statistics_health(data) { } } cols[0].push(date); - cols[1].push(c); - cols[2].push(o); + cols[1].push(o); + cols[2].push(c); } let cutoff = moment.utc().subtract(13, 'weeks').startOf('week').weekday(4); let chartdiv = new HTML('div', { @@ -3071,45 +3166,6 @@ function statistics_releases(data) { } /****************************************** - Fetched from source/statistics.js -******************************************/ - - -function StatisticsPage(layout, pdata) { - let wrapper = document.getElementById('wrapper'); - wrapper.style.padding = '8px'; - wrapper.style.height = 'auto'; - wrapper.innerHTML = ""; - for (var i = 0; i < layout.length; i++) { - let step = layout[i]; - if (step.statsgenerator||step.tipgenerator) { - let thtml = new HTML('p'); - let f = Function('a', 'b', "return %s(a,b);".format(step.statsgenerator||step.tipgenerator)); - data = f(pdata, {}); - if (typeof data == 'string') thtml.innerHTML += data; - else if (typeof data == 'object') thtml.inject(data); - thtml.inject(new HTML('hr')); - wrapper.inject(thtml); - } - } - - headers = $(wrapper).find("h4"); - let toc = "<ul style='background: #3333;'>"; - for (var i = 0; i < headers.length; i++) { - let t = headers[i].innerText.replace(/:.*$/, ''); - let id = t.replace(/\s+/g, '').toLowerCase(); - headers[i].setAttribute('id', id); - toc += "<li style='display: inline-block; margin-left: 24px;'><a href='#%s'>%s</a></li>".format(id, t); - } - toc += "</ul>"; - let twrap = new HTML('div'); - twrap.innerHTML = toc; - wrapper.insertBefore(twrap, wrapper.childNodes[0]); - -} - - -/****************************************** Fetched from source/stepper.js ******************************************/ @@ -3150,7 +3206,7 @@ function ReportStepper(div, editor, layo if (this.changed) this.editor.highlight(); // skip building if nothing changed - if (!this.changed && !start && this.editor.report == this.editor.last_cursor_report) return; + if (!this.changed && !start && this.editor.report == this.editor.last_cursor_report && s != -1) return; this.editor.last_cursor_report = this.editor.report; // build the step div @@ -3258,10 +3314,12 @@ function UnifiedEditor_highlight_section // Set which sections highlight let hilites = []; // Headers are blue - hilites.push({highlight: /^## [^\r\n]+:/mg, className: 'blue' }); + hilites.push({highlight: /^## [^\r\n]+:?/mg, className: 'blue' }); // Placeholders are grey with red border hilites.push({highlight: PLACEHOLDER, className: 'none' }); - + // <private> sections + hilites.push({highlight: /<private>[\s\S]+?<\/private>/i, className: 'classified' }); + // Capture text cursor position(s) before we continue. let x = $('#unified-report').prop('selectionStart'); let y = $('#unified-report').prop('selectionEnd'); @@ -3346,7 +3404,7 @@ function UnifiedEditor_find_section(e) { } else { for (var i = 0; i < this.layout.length; i++) { let step = this.layout[i]; - let tline = "## %s:".format(step.rawname || step.description); + let tline = "## %s".format(step.rawname || step.description); if (tprec.indexOf(tline) != -1) { at_step = i; } @@ -3421,7 +3479,7 @@ function UnifiedEditor_mark_section(titl for (var i = 0; i < this.sections.length; i++) { let section = this.sections[i]; if (section.title == title && section.text.indexOf(PLACEHOLDER) == -1 && section.text.length > 4) { - //console.log("Marking entire %s section from %u to %u".format(title, sections[i].start, sections[i].end)) + //console.log("Marking entire %s section from %u to %u".format(title, this.sections[i].start, this.sections[i].end)) this.highlight(section.text); foundit = true; break; @@ -3437,6 +3495,11 @@ function UnifiedEditor_mark_section(titl // Function for resetting a report to follow layout function UnifiedEditor_reset() { + // Check whether we have a report in agenda, if so reset to that. + if (meta_data && meta_data.report && meta_data.filed) { + load_from_agenda(); + return + } this.report = ""; this.changed = true; for (var i = 0; i < this.layout.length; i++) { @@ -3517,7 +3580,11 @@ function UnifiedEditor_compile() { text += "That's it, your board report compiled a-okay and is potentially ready for submission! If you'd like more time to work on it, you can save it as a draft, and return later to make some final edits. Or you can publish it to the agenda via Whimsy."; } text += "<br/><button class='btn btn-warning' onclick='save_draft();'>Save as draft</button>" - if (this.compiles) text += " <button onclick='publish_report();' class='btn btn-success'>Publish via Whimsy</button>" + if (!meta_data.found) { + text += " <button class='btn btn-secondary' disabled title='Your project is not listed in the current agenda!'>Publish via Whimsy</button>"; + text += "<br/><span style='color: maroon;'>Your project is not expected to report this month. You may save drafts but you cannot publish yet.</span>"; + } + else if (this.compiles) text += " <button onclick='publish_report();' class='btn btn-success'>Publish via Whimsy</button>" else text += " <button class='btn btn-secondary' disabled title='Please fix the above issues before you can publish'>Publish via Whimsy</button>" return text; } @@ -3532,6 +3599,7 @@ function UnifiedEditor_check_changes(for this.stepper.helper.inject(saver); } if (this.report != this.report_saved) { + this.unsaved = true; if (saver) { saver.innerText = "Current changes not saved yet - "; let btn = new HTML('button', { onclick: 'save_draft();', class: 'btn btn-warning btn-sm'}, 'Save draft'); @@ -3543,6 +3611,7 @@ function UnifiedEditor_check_changes(for } } else if (saver) { + this.unsaved = false; saver.style.display = 'none'; window.onbeforeunload = null; }