You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@community.apache.org by hu...@apache.org on 2019/08/02 13:13:36 UTC
svn commit: r1864224 - in /comdev/reporter.apache.org/trunk/site/wizard: ./
css/ js/ js/source/
Author: humbedooh
Date: Fri Aug 2 13:13:36 2019
New Revision: 1864224
URL: http://svn.apache.org/viewvc?rev=1864224&view=rev
Log:
Lotta updates:
- Scrap old wizard style, stick with unified for every needs.
- Class'ify the stepper and editor for easier maintenance.
- Scrap unneeded css and html.
Added:
comdev/reporter.apache.org/trunk/site/wizard/js/source/stepper.js
Modified:
comdev/reporter.apache.org/trunk/site/wizard/css/wizard.css
comdev/reporter.apache.org/trunk/site/wizard/index.html
comdev/reporter.apache.org/trunk/site/wizard/js/source/drafts.js
comdev/reporter.apache.org/trunk/site/wizard/js/source/generators.js
comdev/reporter.apache.org/trunk/site/wizard/js/source/init.js
comdev/reporter.apache.org/trunk/site/wizard/js/source/primer.js
comdev/reporter.apache.org/trunk/site/wizard/js/source/unified.js
comdev/reporter.apache.org/trunk/site/wizard/js/wizard.js
comdev/reporter.apache.org/trunk/site/wizard/steps.json
comdev/reporter.apache.org/trunk/site/wizard/unified.html
Modified: comdev/reporter.apache.org/trunk/site/wizard/css/wizard.css
URL: http://svn.apache.org/viewvc/comdev/reporter.apache.org/trunk/site/wizard/css/wizard.css?rev=1864224&r1=1864223&r2=1864224&view=diff
==============================================================================
--- comdev/reporter.apache.org/trunk/site/wizard/css/wizard.css (original)
+++ comdev/reporter.apache.org/trunk/site/wizard/css/wizard.css Fri Aug 2 13:13:36 2019
@@ -113,18 +113,8 @@
}
-#steps {
- width: 720px;
- border: 1.5px solid #3339;
- background: #EEE;
- border-radius: 10px;
- margin: 10px auto;
- padding: 10px;
- height: 110px;
- text-align: center;
-}
-.unified #steps {
+#unified-steps {
width: 120px;
border: 1.5px solid #3339;
background: #EEE;
@@ -257,10 +247,6 @@
}
#unified-helper {
- display: none;
-}
-
-.unified #unified-helper {
display: inline-block;
width: 400px;
height: 600px;
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=1864224&r1=1864223&r2=1864224&view=diff
==============================================================================
--- comdev/reporter.apache.org/trunk/site/wizard/index.html (original)
+++ comdev/reporter.apache.org/trunk/site/wizard/index.html Fri Aug 2 13:13:36 2019
@@ -12,12 +12,12 @@
<meta property='og:image' content='https://reporter.apache.org/guide/logo.png'>
<script type="text/javascript">
-let editor_type = 'default';
+let editor_type = 'unified';
</script>
<title>ASF Board Report Wizard</title>
-<link rel="stylesheet" href="css/wizard.css"/>
-<link rel="stylesheet" href="highlighter/highlighter.css"/>
+<link rel="stylesheet" href="css/wizard.css?newstuff"/>
+<link rel="stylesheet" href="highlighter/highlighter.css?newstuff"/>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
@@ -26,37 +26,18 @@ let editor_type = 'default';
<div class="loader"></div>
</div>
- <div id="wrapper" style="display: none;">
+ <div id="wrapper" style="display: none;" class="unified">
<h2 id="pname" style="text-align: center;">Board Report Wizard</h2>
- <div id="steps">
+ <div id="unified-steps">
+
-
</div>
<div id="unified-editor">
- <textarea id="unified-report" onmouseup="find_section();" onkeyup="find_section();"></textarea>
+ <textarea id="unified-report"></textarea>
</div>
<div id="unified-helper"></div>
- <div id="wizard-content">
- <div id="help_wrapper">
- <h3 id="step_title">Project Activity:</h3>
- <p id="step_help">
-
- </p>
- </div>
- <p style="text-align: center; width: 100%; height: 100%;">
- <textarea id="step_text" style="width: 90%; height: 60%; margin: 0 auto;"
-placeholder="Example activity:
-- This quarter, we attended FooCon - it was a sounding success!
-- Apache Foo 1.2.3 was released on August 4th, 2019."></textarea><br/>
-<button id="step_prev" onclick="build_steps(current_step-1);" class="btn btn-info" style="float: left;">‹‹ Previous step</button>
-<button id="step_next" onclick="build_steps(current_step+1);" class="btn btn-success" style="float: right;">›› Next step</button>
-</p>
- </div>
-
- <div id="tips" class="wizard-tip"></div>
- </div>
<!-- Modal for notices -->
<div class="modal fade" id="alert" role="dialog">
@@ -91,8 +72,8 @@ placeholder="Example activity:
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<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.js" type="text/javascript"></script>
+<script src="highlighter/highlighter.js?newstuff" type="text/javascript"></script>
+<script src="js/wizard.js?newstuff" type="text/javascript"></script>
</body>
</html>
Modified: comdev/reporter.apache.org/trunk/site/wizard/js/source/drafts.js
URL: http://svn.apache.org/viewvc/comdev/reporter.apache.org/trunk/site/wizard/js/source/drafts.js?rev=1864224&r1=1864223&r2=1864224&view=diff
==============================================================================
--- comdev/reporter.apache.org/trunk/site/wizard/js/source/drafts.js (original)
+++ comdev/reporter.apache.org/trunk/site/wizard/js/source/drafts.js Fri Aug 2 13:13:36 2019
@@ -1,14 +1,15 @@
// Draft saving/loading features
let saved_drafts = null;
+let draft_stepper = null;
function save_draft() {
js = {
'project': project,
'action': 'save',
- 'type': editor_type,
- 'report': JSON.stringify(report),
- 'report_compiled': compile_report(null, true, true)
+ 'type': 'unified',
+ 'report': JSON.stringify(draft_stepper.editor.report),
+ 'report_compiled': draft_stepper.editor.report
}
let formdata = $.param(js);
@@ -40,14 +41,9 @@ function load_draft(filename) {
function read_draft(state, json) {
if (json.report) {
-
- if (editor_type == 'unified') {
- document.getElementById('unified-report').value = json.report;
- window.setTimeout(() => { $('#unified-report').highlightWithinTextarea('update'); }, 250);
- } else {
- report = json.report;
- }
- build_steps(0, true, true);
+ draft_stepper.editor.object.value = json.report;
+ window.setTimeout(() => { draft_stepper.editor.highlight() }, 250);
+ draft_stepper.build(0, false, false);
modal("Draft was successfully loaded and is ready.");
} else {
modal("Could not load report draft :/");
@@ -55,20 +51,19 @@ function read_draft(state, json) {
}
-
-function list_drafts() {
+function list_drafts(pdata, editor) {
if (!saved_drafts) {
- GET('drafts.py?action=index&project=%s&type=%s'.format(project, editor_type), show_draft_list, {});
+ GET('drafts.py?action=index&project=%s&type=%s'.format(project, editor_type), show_draft_list, {stepper:editor.stepper});
return "";
}
else {
- return show_draft_list();
+ return show_draft_list({stepper: editor.stepper});
}
}
function show_draft_list(state, json) {
if (json && json) { saved_drafts = json.drafts || {}; }
-
+ draft_stepper = state.stepper; // hackish for now!
let txt = "";
let filenames = Object.keys(saved_drafts);
if (filenames.length > 0) {
@@ -87,17 +82,8 @@ function show_draft_list(state, json) {
txt += "</ul></small>"
}
if (json && current_step == 0) {
- let tip = document.getElementById('tips');
- if (txt.length > 0) {
- tip.style.display = 'block';
- tip.innerHTML = txt;
- } else {
- tip.style.display = 'none';
- }
- if (editor_type == 'unified') {
- let tip = document.getElementById('unified-helper');
- tip.innerHTML += txt;
- }
+ let tip = document.getElementById('unified-helper');
+ tip.innerHTML += txt;
} else {
return txt;
}
Modified: comdev/reporter.apache.org/trunk/site/wizard/js/source/generators.js
URL: http://svn.apache.org/viewvc/comdev/reporter.apache.org/trunk/site/wizard/js/source/generators.js?rev=1864224&r1=1864223&r2=1864224&view=diff
==============================================================================
--- comdev/reporter.apache.org/trunk/site/wizard/js/source/generators.js (original)
+++ comdev/reporter.apache.org/trunk/site/wizard/js/source/generators.js Fri Aug 2 13:13:36 2019
@@ -14,16 +14,15 @@ let gcd = (x,y) => {
}
-function generate_pmc_roster(data) {
-
+function generate_pmc_roster(pdata) {
// PMC age
- let founded = moment(data.pmcdates[project].pmc[2] * 1000.0);
+ let founded = moment(pdata.pmcdates[project].pmc[2] * 1000.0);
let age = founded.fromNow();
- let txt = "%s was founded %s (%s)\n".format(data.pmcsummary[project].name, founded.format('YYYY-MM-DD'), age);
+ let txt = "%s was founded %s (%s)\n".format(pdata.pmcsummary[project].name, founded.format('YYYY-MM-DD'), age);
// PMC and committer count
- let no_com = data.count[project][1];
- let no_pmc = data.count[project][0];
+ let no_com = pdata.count[project][1];
+ let no_pmc = pdata.count[project][0];
let y1 = no_com;
let y2 = no_pmc;
@@ -52,7 +51,7 @@ function generate_pmc_roster(data) {
// Last PMC addition
- let changes = data.changes[project].pmc;
+ let changes = pdata.changes[project].pmc;
let now = moment();
let three_months_ago = now.subtract(3, 'months');
let no_added = 0;
@@ -81,7 +80,7 @@ function generate_pmc_roster(data) {
// Last Committer addition
txt += "\n"
txt += "Committership changes, past quarter:\n"
- changes = data.changes[project].committer;
+ changes = pdata.changes[project].committer;
now = moment();
three_months_ago = now.subtract(3, 'months');
no_added = 0;
@@ -224,97 +223,6 @@ function health_tips(data) {
return txt;
}
-let compile_okay = false;
-
-function check_compile(data) {
-
- compile_okay = true;
- let text = "";
- if (editor_type == 'unified') {
- let required_sections = [];
- let sections = parse_unified();
-
- for (var i = 0; i < step_json.length; i++) {
- let step = step_json[i];
- if (!step.noinput) {
- let found = false;
- required_sections.push(step.rawname||step.description);
- for (var n = 0; n < sections.length; n++) {
- if (sections[n].title == (step.rawname||step.description)) {
- found = true;
- if (sections[n].text.indexOf(PLACEHOLDER) != -1) {
- console.log("Found placeholder text: " + PLACEHOLDER)
- text += "<li><span style='display: inline-block; width: 20px; font-size: 18px; color: red;'>÷</span> <kbd>%s</kbd> contains placeholder text!</li>".format(sections[n].title);
- compile_okay = false;
- } else if (sections[n].text.length < 20) {
- text += "<li><span style='display: inline-block; width: 20px; font-size: 18px; color: pink;'>‽</span> <kbd>%s</kbd> seems a tad short?</li>".format(sections[n].title);
- } else {
- text += "<li><span style='display: inline-block; width: 20px; font-size: 18px; color: green;'>✓</span> <kbd>%s</kbd> seems alright</li>".format(sections[n].title);
-
- }
- break;
- }
- }
- if (!found) {
- compile_okay = false;
- text += "<li><span style='display: inline-block; width: 20px; font-size: 18px; color: red;'>÷</span> <kbd>%s</kbd> is missing from the report!</li>".format(step.description);
- }
- }
-
- }
-
- // Remark on additional sections not required
- for (var n = 0; n < sections.length; n++) {
- if (!required_sections.has(sections[n].title)) {
- text += "<li><span style='display: inline-block; width: 20px; font-size: 18px; color: pink;'>‽</span> Found unknown section <kbd>%s</kbd></li>".format(sections[n].title);
- }
- }
-
-
- }
- else {
- for (var i = 1; i < 5; i++) {
- if (report[i] == null || report[i].length == 0) {
- text += "<li>You have not filled out the <kbd>%s</kbd> section yet.".format(step_json[i].description);
- compile_okay = false;
- }
- }
- }
-
- if (text.length > 0) {
- text = "<h5>Report review results:</h5>The following remarks were logged by the report compiler:<br/><ul>" + text + "</ul>";
- }
- if (!compile_okay) {
- text += "Your report could possibly use some more work, and that's okay! You can always save your current report as a draft and return later to work more on it. Drafts are saved for up to two months.";
- }
- else {
- 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 (compile_okay) text += " <button class='btn btn-success'>Publish via Whimsy</button>"
- return text;
-}
-
-
-function compile_report(data, okay, force) {
- if (!okay && !force) return -1
- if (editor_type == 'unified') {
- return document.getElementById('unified-report').value;
- }
- let rep = "## Board Report for %s ##\n".format(pdata.pdata[project].name);
- for (var i = 1; i < 5; i++) {
- let step = step_json[i];
- rep += "\n## %s:\n".format(step.description);
- if (report[i] !== null) {
- rep += report[i].replace(/(\r?\n)+$/, '');
- } else {
- rep += "Nothing entered yet...\n";
- }
- rep += "\n";
- }
- return rep;
-}
-
function activity_tips(data) {
let three_months_ago = moment().subtract(3, 'months');
let txt = "";
@@ -360,9 +268,13 @@ function reflow(txt, chars) {
return output;
}
-function get_charter(data) {
- let charter = data.pdata[project].charter;
+function get_charter(pdata) {
+ let charter = pdata.pdata[project].charter;
let txt = reflow(charter);
return txt;
+}
+
+function compile_check(pdata, editor) {
+ return editor.compile();
}
\ No newline at end of file
Modified: comdev/reporter.apache.org/trunk/site/wizard/js/source/init.js
URL: http://svn.apache.org/viewvc/comdev/reporter.apache.org/trunk/site/wizard/js/source/init.js?rev=1864224&r1=1864223&r2=1864224&view=diff
==============================================================================
--- comdev/reporter.apache.org/trunk/site/wizard/js/source/init.js (original)
+++ comdev/reporter.apache.org/trunk/site/wizard/js/source/init.js Fri Aug 2 13:13:36 2019
@@ -21,6 +21,9 @@ let project = location.search.substr(1);
let loaded_from_draft = false;
let PLACEHOLDER = '[Insert your own data here]';
+let editor = null;
+let stepper = null;
+
if (project.length < 2) {
GET("/reportingcycles.json", pre_splash, {});
} else {
Modified: comdev/reporter.apache.org/trunk/site/wizard/js/source/primer.js
URL: http://svn.apache.org/viewvc/comdev/reporter.apache.org/trunk/site/wizard/js/source/primer.js?rev=1864224&r1=1864223&r2=1864224&view=diff
==============================================================================
--- comdev/reporter.apache.org/trunk/site/wizard/js/source/primer.js (original)
+++ comdev/reporter.apache.org/trunk/site/wizard/js/source/primer.js Fri Aug 2 13:13:36 2019
@@ -1,8 +1,6 @@
+// some glopbal vars for now - we'll get them localized soon enough.
let pdata = {};
-let report = [null,null,null,null,null,null];
-let current_step = 0;
let cycles = {};
-let draft_mode = false;
let comments = {};
function modal(txt) {
@@ -39,151 +37,16 @@ function prime_cycles(state, json) {
}
-let step_json = {};
function prime_steps(state, json) {
+ // Cancel spinner
document.getElementById('wizard_spinner').style.display = 'none';
document.getElementById('wrapper').style.display = 'block';
- step_json = json.steps;
- build_steps(0, true);
-}
-
-let hilite_timer = null;
-
-function build_steps(s, start, noclick, e) {
- s = s || 0;
-
- let text = document.getElementById('step_text');
- if (!start && text && text.value.length > 0 && current_step < 5) {
- report[current_step] = text.value;
- }
-
- text.innerText = '';
- let step_changed = (s == current_step) ? false : true;
- current_step = s;
- let stepParent = document.getElementById('steps');
- stepParent.innerHTML = '';
- for (var i = 0; i < step_json.length; i++) {
- let element = step_json[i];
- let wrapper = new HTML('div', {class: 'wizard-step-wrapper', onclick: 'build_steps(%u);'.format(i)});
- let stepcircle = new HTML('div', {class: 'wizard-step'});
- let stepicon = new HTML('i', {class: 'fas fa-%s'.format(element.icon)});
- stepcircle.inject(stepicon);
- let steptext = new HTML('div', {class: 'wizard-step-text'}, element.description);
- wrapper.inject([stepcircle, steptext]);
- if (s == i) {
- stepcircle.setAttribute('class', 'wizard-step active');
- steptext.setAttribute('class', 'wizard-step-text active');
- }
- if (i < s) {
- stepcircle.setAttribute('class', 'wizard-step done');
- steptext.setAttribute('class', 'wizard-step-text done');
- }
- stepParent.inject(wrapper);
- if (i < step_json.length-1) {
- let line = new HTML('div', {class: 'wizard-line'});
- if (i < s) line.setAttribute('class', 'wizard-line done');
- stepParent.inject(line);
- }
- if (s == i) {
- let title = document.getElementById('step_title');
- title.innerText = element.description;
- let help = document.getElementById('step_help');
- help.innerHTML = element.help || "No helper information available for this step...";
- if (element.helpgenerator) {
- let data = eval("%s(pdata);".format(element.helpgenerator));
- help.innerHTML = data;
- }
- let text = document.getElementById('step_text');
- text.placeholder = element.placeholder || "";
- let hw = document.getElementById('help_wrapper');
- if (element.noinput) {
- text.style.display = 'none';
- }
- else text.style.display = 'inline';
- text.style.height = (395 - hw.scrollHeight) + "px";
- if (element.generator && !(report[s] && report[s].length > 0)) {
- let data = eval("%s(pdata, compile_okay);".format(element.generator));
- if (data === -1) text.style.display = 'none'; // hide if generator return -1
- else text.value = data;
- }
- else if (report[s]) {
- text.value = report[s];
- } else {
- text.value = '';
- }
-
- // tips??
- let tip = document.getElementById('tips');
- if (element.tipgenerator) {
- let data = eval("%s(pdata);".format(element.tipgenerator));
- if (data && data.length > 0) {
- tip.innerHTML = data;
- tip.style.display = 'block';
- } else {
- tip.style.display = 'none';
- }
- } else {
- tip.style.display = 'none';
- }
- }
- }
-
- let bp = document.getElementById('step_prev');
- if (s == 0) bp.style.display = 'none';
- else bp.style.display = 'block';
-
- let bn = document.getElementById('step_next');
- if (s == step_json.length -1) bn.style.display = 'none';
- else bn.style.display = 'block';
-
- if (editor_type == 'unified') {
- if (start) {
- let template = "";
- for (var i = 0; i < step_json.length; i++) {
- let step = step_json[i];
- if (!step.noinput || step.rawname) {
- template += "## %s:\n".format(step.rawname || step.description);
- if (step.generator) {
- let data = eval("%s(pdata);".format(step.generator));
- if (data && data.length > 0) template += data
- } else {
- template += PLACEHOLDER;
- }
- template += "\n\n";
- }
- }
- document.getElementById('unified-report').value = template;
- }
- if (report_changed) hilite_sections();
-
- let step = step_json[s];
- let helper = document.getElementById('unified-helper');
-
- helper.innerHTML = "<h5>%s:</h5>".format(step.description);
- // Add in help
- if (step.helpgenerator) {
- let data = eval("%s(pdata);".format(step.helpgenerator));
- helper.innerHTML += data;
- } else if (step.help) {
- helper.innerHTML += step.help;
- }
-
- // Add tips?
- if (step.tipgenerator) {
- let data = eval("%s(pdata);".format(step.tipgenerator));
- helper.innerHTML += data;
- }
- // If clicked to a section, move cursor
- if (!noclick) {
- set_position(step.description);
- }
- if (step_changed || !noclick) mark_section(step.rawname||step.description);
- else {
- window.clearTimeout(hilite_timer);
- if (event && event.keyCode == 13) mark_section(step.rawname||step.description);
- else hilite_timer = window.setTimeout(() => { mark_section(step.rawname||step.description)}, 200);
- }
- }
+ // Create editor and stepper class
+ let editor = new UnifiedEditor('unified-report', json.steps);
+ let stepper = new ReportStepper('unified-steps', editor, json.steps, 'unified-helper');
+ editor.stepper = stepper;
+ stepper.pdata = pdata;
+ stepper.build(0, true);
}
Added: comdev/reporter.apache.org/trunk/site/wizard/js/source/stepper.js
URL: http://svn.apache.org/viewvc/comdev/reporter.apache.org/trunk/site/wizard/js/source/stepper.js?rev=1864224&view=auto
==============================================================================
--- comdev/reporter.apache.org/trunk/site/wizard/js/source/stepper.js (added)
+++ comdev/reporter.apache.org/trunk/site/wizard/js/source/stepper.js Fri Aug 2 13:13:36 2019
@@ -0,0 +1,91 @@
+
+// Left-hand side stepper for reports
+function ReportStepper(div, editor, layout, helper) {
+
+ // bind to object
+ if (typeof div == "string") this.object = document.getElementById(div);
+ else this.object = div;
+
+ // bind to helper
+ if (typeof helper == "string") this.helper = document.getElementById(helper);
+ else this.helper = helper;
+
+ this.layout = layout;
+ this.editor = editor;
+ this.timer = null; // highlight timer
+ this.step = -1;
+ this.changed = false;
+ this.pdata = null;
+
+ this.build =function (s, start, noclick, e) {
+ s = s || 0;
+
+ this.changed = (s == this.step) ? false : true;
+ this.step = s;
+
+ if (start) {
+ this.editor.reset();
+ }
+
+
+ if (this.changed) this.editor.highlight();
+
+ // build the step div
+ this.object.innerHTML = '';
+ for (var i = 0; i < this.layout.length; i++) {
+ let element = this.layout[i];
+ let wrapper = new HTML('div', {class: 'wizard-step-wrapper'});
+ let x = i;
+ wrapper.addEventListener('click', () => { this.build(x);});
+ let stepcircle = new HTML('div', {class: 'wizard-step'});
+ let stepicon = new HTML('i', {class: 'fas fa-%s'.format(element.icon)});
+ stepcircle.inject(stepicon);
+ let steptext = new HTML('div', {class: 'wizard-step-text'}, element.description);
+ wrapper.inject([stepcircle, steptext]);
+ if (s == i) {
+ stepcircle.setAttribute('class', 'wizard-step active');
+ steptext.setAttribute('class', 'wizard-step-text active');
+ }
+ if (i < s) {
+ stepcircle.setAttribute('class', 'wizard-step done');
+ steptext.setAttribute('class', 'wizard-step-text done');
+ }
+ this.object.inject(wrapper);
+ if (i < step_json.length-1) {
+ let line = new HTML('div', {class: 'wizard-line'});
+ if (i < s) line.setAttribute('class', 'wizard-line done');
+ this.object.inject(line);
+ }
+ }
+
+ let step = this.layout[s];
+ // If helper exists, show useful data
+ if (this.helper) {
+ this.helper.innerHTML = "<h5>%s:</h5>".format(step.description);
+ // Add in help
+ if (step.helpgenerator) {
+ let f = Function('a', 'b', "return %s(a, b);".format(step.helpgenerator));
+ data = f(this.pdata, this.editor)
+ this.helper.innerHTML += data;
+ } else if (step.help) {
+ this.helper.innerHTML += step.help;
+ }
+ // Add tips?
+ if (step.tipgenerator) {
+ let f = Function('a', 'b', "return %s(a,b);".format(step.tipgenerator));
+ data = f(this.pdata, this.editor)
+ this.helper.innerHTML += data;
+ }
+ // If clicked to a section, move cursor
+ if (!noclick) {
+ this.editor.set_position(step.description);
+ }
+ if (this.changed || !noclick) this.editor.mark_section(step.rawname||step.description);
+ else {
+ window.clearTimeout(this.timer);
+ if (event && event.keyCode == 13) this.editor.mark_section(step.rawname||step.description);
+ else this.timer = window.setTimeout(() => { this.editor.mark_section(step.rawname||step.description)}, 200);
+ }
+ }
+ }
+}
\ No newline at end of file
Modified: comdev/reporter.apache.org/trunk/site/wizard/js/source/unified.js
URL: http://svn.apache.org/viewvc/comdev/reporter.apache.org/trunk/site/wizard/js/source/unified.js?rev=1864224&r1=1864223&r2=1864224&view=diff
==============================================================================
--- comdev/reporter.apache.org/trunk/site/wizard/js/source/unified.js (original)
+++ comdev/reporter.apache.org/trunk/site/wizard/js/source/unified.js Fri Aug 2 13:13:36 2019
@@ -1,130 +1,254 @@
-function hilite_sections(b) {
- if (highlighted && !b) return;
- highlighted = true;
- let hilites = [];
-
+// Function that highlights headers and optional sectin in a unified editor
+function UnifiedEditor_highlight_sections(additional_text) {
+ // Don't highlight unless we haven't before or new text is noted
+ if (this.have_highligted && !additional_text) return;
+ // Set which sections highlight
+ let hilites = [];
+ // Headers are blue
hilites.push({highlight: /^## [^\r\n]+:/mg, className: 'blue' });
+ // Placeholders are grey with red border
hilites.push({highlight: PLACEHOLDER, className: 'none' });
+ // Capture text cursor position(s) before we continue.
let x = $('#unified-report').selectionStart;
let y = $('#unified-report').selectionEnd;
-
- if (b) {
+
+ // If additional text is marked for highlighting, we'll have to
+ // first destroy any original highlighting, as it's params changed!
+ if (additional_text) {
$('#unified-report').highlightWithinTextarea('destroy');
+
+ // Sections are marked light green
hilites.push({
- highlight: b,
+ highlight: additional_text,
className: 'green'
});
}
-
- $('#unified-report').highlightWithinTextarea({
+ // Run the highlighter on ourselves
+ $(this.object).highlightWithinTextarea({
highlight: hilites
});
+
+ // If x == y (cursor is present and not marking characters),
+ // We'll force focus on ourselves as highlighting loses it.
if (x == y) {
- $('#unified-report').selectionStart = x;
- $('#unified-report').selectionEnd = y;
- $('#unified-report').focus();
+ $(this.object).selectionStart = x;
+ $(this.object).selectionEnd = y;
+ $(this.object).focus();
}
}
-let report_unified = "";
-let report_changed = true;
-let highlighted = false;
-function find_section(e) {
- let tmp = document.getElementById('unified-report').value;
- report_changed = (report_unified == tmp) ? false : true;
- report_unified = tmp;
- let spos = $('#unified-report').prop("selectionStart");
- let helper = document.getElementById('unified-helper');
+// Function for figuring out WHERE we are in our report, cursor-wise
+function UnifiedEditor_find_section(e) {
+ let tmp = this.object.value;
+ this.changed = (this.report == tmp) ? false : true;
+ this.report = tmp;
+ let spos = this.object.selectionStart;
// Hop to next newline, so marking the title will jump to the right section
- while (report_unified[spos] != "\n" && spos < report_unified.length) spos++;
+ while (this.report[spos] != "\n" && spos < this.report.length) spos++;
- let tprec = report_unified.substr(0, spos);
+ let tprec = this.report.substr(0, spos);
let at_step = -1;
- for (var i = 0; i < step_json.length; i++) {
- let step = step_json[i];
+ for (var i = 0; i < this.layout.length; i++) {
+ let step = this.layout[i];
let tline = "## %s:".format(step.rawname || step.description);
if (tprec.indexOf(tline) != -1) {
at_step = i;
}
}
- if (at_step != -1) {
- build_steps(at_step, false, true, e);
-
- } else {
- helper.innerText = "";
- }
+ if (at_step != -1 && this.stepper) {
+ this.stepper.build(at_step, false, true, e);
+ }
}
-function set_position(text) {
- let editor = document.getElementById('unified-report');
- let pos = editor.value.search(text);
- if (pos && pos > 0) {
- editor.selectionStart = (pos + text.length + 2);
- editor.selectionEnd = (pos + text.length + 2);
- editor.focus();
+
+// Quick shortcut to focusing somewhere in the report
+function UnifiedEditor_set_position(text) {
+ let pos = this.object.value.indexOf(text);
+ if (pos != -1) {
+ this.object.selectionStart = (pos + text.length + 2);
+ this.object.selectionEnd = (pos + text.length + 2);
+ this.object.focus();
}
}
// Parses a unified report into sections
-function parse_unified(quiet) {
- let sections = [];
- let sX = 0;
- let tmp = document.getElementById('unified-report').value;
+function UnifiedEditor_parse_report(quiet) {
+ this.sections = []; // Reset sections
+ let sX = 0; // sX is our moving cursor in the text as we parse.
+ let tmp = this.object.value; // get our textarea data
while (tmp.length > 0) {
+ // Look for the next "## Foo Bar:" line
let nextheader = tmp.match(/^## ([^\r\n]+)\r?\n/m);
if (nextheader) {
- if (!quiet) console.log("Found report header: %s".format(nextheader[0]))
+ if (!quiet) console.log("Found report header: %s".format(nextheader[0]));
let title = nextheader[1];
let spos = tmp.indexOf(nextheader[0]);
if (spos != -1) {
- sX += spos + nextheader[0].length;
+ sX += spos + nextheader[0].length; // move cursor
sY = sX;
+ // ourr buffer past this header, find another one further down
tmp = tmp.substr(spos + nextheader[0].length);
let epos = tmp.search(/^## [^\r\n]+/m);
+ // if no further headers, use end of buffer as end pos.
epos = (epos == -1) ? tmp.length : epos;
let section = tmp.substr(0, epos);
+ // We got something(?), push to sections array.
if (title.length > 2) {
- sections.push({
- title: title.replace(/:.*$/, ''),
+ this.sections.push({
+ title: title.replace(/:.*$/, ''), // crop away colon and any spaces following
text: section,
start: sX,
end: sX + epos
});
}
if (!quiet) console.log("Section contains:");
- if (!quiet) console.log(section)
+ if (!quiet) console.log(section);
tmp = tmp.substr(epos);
- } else { break }
+ } else { break; }
} else {
if (!quiet) console.log("No more report headers found.");
}
}
- return sections;
}
-// Mark a section using the highlighter
-function mark_section(title) {
- let sections = parse_unified(true);
+// Mark a section using the highlighter.
+function UnifiedEditor_mark_section(title) {
+ this.parse(true);
let foundit = false;
- for (var i = 0; i < sections.length; i++) {
- if (sections[i].title == title && sections[i].text.indexOf(PLACEHOLDER) == -1 && sections[i].text.length > 4) {
+ 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))
- hilite_sections(sections[i].text);
+ this.highlight(section.text);
foundit = true;
- break
+ break;
}
}
+ // If we don't know what to highlight, "reset" by highlighting a
+ // piece of text that doesn't exist. HACK HACK HACK.
if (!foundit) {
- hilite_sections("<-- EXTERMINATE -->");
+ this.highlight("<-- EXTERMINATE -->");
}
-}
\ No newline at end of file
+}
+
+
+// Function for resetting a report to follow layout
+function UnifiedEditor_reset() {
+ this.report = "";
+ this.changed = true;
+ for (var i = 0; i < this.layout.length; i++) {
+ let step = this.layout[i];
+ if (!step.noinput || step.rawname) {
+ this.report += "## %s:\n".format(step.rawname || step.description);
+ if (step.generator) {
+ let f = Function('a', "return %s(a);".format(step.generator));
+ data = f(this.stepper.pdata)
+ if (data && data.length > 0) this.report += data
+ } else {
+ this.report += PLACEHOLDER;
+ }
+ this.report += "\n\n";
+ }
+ }
+ this.object.value = this.report;
+ this.sections = [];
+}
+
+// Function for compiling (validating) a report
+function UnifiedEditor_compile() {
+ this.compiles = true;
+ let text = "";
+ let required_sections = [];
+ this.parse();
+ for (var i = 0; i < this.layout.length; i++) {
+ let step = this.layout[i];
+ if (!step.noinput) {
+ let found = false;
+ required_sections.push(step.rawname||step.description);
+ for (var n = 0; n < this.sections.length; n++) {
+ if (this.sections[n].title == (step.rawname||step.description)) {
+ found = true;
+ if (this.sections[n].text.indexOf(PLACEHOLDER) != -1) {
+ console.log("Found placeholder text: " + PLACEHOLDER)
+ text += "<li><span style='display: inline-block; width: 20px; font-size: 18px; color: red;'>÷</span> <kbd>%s</kbd> contains placeholder text!</li>".format(this.sections[n].title);
+ this.compiles = false;
+ } else if (this.sections[n].text.length < 20) {
+ text += "<li><span style='display: inline-block; width: 20px; font-size: 18px; color: pink;'>‽</span> <kbd>%s</kbd> seems a tad short?</li>".format(this.sections[n].title);
+ } else {
+ text += "<li><span style='display: inline-block; width: 20px; font-size: 18px; color: green;'>✓</span> <kbd>%s</kbd> seems alright</li>".format(this.sections[n].title);
+
+ }
+ break;
+ }
+ }
+ if (!found) {
+ this.compiles = false;
+ text += "<li><span style='display: inline-block; width: 20px; font-size: 18px; color: red;'>÷</span> <kbd>%s</kbd> is missing from the report!</li>".format(step.description);
+ }
+ }
+
+ }
+
+ // Remark on additional sections not required
+ for (var n = 0; n < this.sections.length; n++) {
+ if (!required_sections.has(this.sections[n].title)) {
+ text += "<li><span style='display: inline-block; width: 20px; font-size: 18px; color: pink;'>‽</span> Found unknown section <kbd>%s</kbd></li>".format(this.sections[n].title);
+ }
+ }
+
+
+ if (text.length > 0) {
+ text = "<h5>Report review results:</h5>The following remarks were logged by the report compiler:<br/><ul>" + text + "</ul>";
+ }
+ if (!this.compiles) {
+ text += "Your report could possibly use some more work, and that's okay! You can always save your current report as a draft and return later to work more on it. Drafts are saved for up to two months.";
+ }
+ else {
+ 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 class='btn btn-success'>Publish via Whimsy</button>"
+ return text;
+}
+
+
+// This is the Unfied Editor for reports.
+function UnifiedEditor(div, layout) {
+ // Bind to our textarea, direct or via ID.
+ console.log(typeof div)
+ if (typeof div == "string") this.object = document.getElementById(div);
+ else this.object = div;
+
+ this.layout = layout; // our JSON report layout (steps.json)
+ this.sections = []; // Sections we have or have found in the editor.
+ this.report = ""; // The combined report
+ this.stepper = null; // optional stepper class
+
+ this.have_highligted = false; // whether we have highlighted before?
+ this.changed = false; // whether report changed since last parse
+ this.compiles = false; // Whether compiles are okay
+
+ // Function references
+ this.highlight = UnifiedEditor_highlight_sections;
+ this.mark_section = UnifiedEditor_mark_section;
+ this.parse = UnifiedEditor_parse_report;
+ this.set_position = UnifiedEditor_set_position;
+ this.reset = UnifiedEditor_reset;
+ this.find_section = UnifiedEditor_find_section;
+ this.compile = UnifiedEditor_compile;
+
+ // set div events
+ this.object.addEventListener('keyup', () => { this.find_section(true); });
+ this.object.addEventListener('mouseup', () => { this.find_section(); });
+
+}
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=1864224&r1=1864223&r2=1864224&view=diff
==============================================================================
--- comdev/reporter.apache.org/trunk/site/wizard/js/wizard.js (original)
+++ comdev/reporter.apache.org/trunk/site/wizard/js/wizard.js Fri Aug 2 13:13:36 2019
@@ -1016,14 +1016,15 @@ function showCalendarPicker(parent, seed
// Draft saving/loading features
let saved_drafts = null;
+let draft_stepper = null;
function save_draft() {
js = {
'project': project,
'action': 'save',
- 'type': editor_type,
- 'report': JSON.stringify(report),
- 'report_compiled': compile_report(null, true, true)
+ 'type': 'unified',
+ 'report': JSON.stringify(draft_stepper.editor.report),
+ 'report_compiled': draft_stepper.editor.report
}
let formdata = $.param(js);
@@ -1055,14 +1056,9 @@ function load_draft(filename) {
function read_draft(state, json) {
if (json.report) {
-
- if (editor_type == 'unified') {
- document.getElementById('unified-report').value = json.report;
- window.setTimeout(() => { $('#unified-report').highlightWithinTextarea('update'); }, 250);
- } else {
- report = json.report;
- }
- build_steps(0, true, true);
+ draft_stepper.editor.object.value = json.report;
+ window.setTimeout(() => { draft_stepper.editor.highlight() }, 250);
+ draft_stepper.build(0, false, false);
modal("Draft was successfully loaded and is ready.");
} else {
modal("Could not load report draft :/");
@@ -1070,20 +1066,19 @@ function read_draft(state, json) {
}
-
-function list_drafts() {
+function list_drafts(pdata, editor) {
if (!saved_drafts) {
- GET('drafts.py?action=index&project=%s&type=%s'.format(project, editor_type), show_draft_list, {});
+ GET('drafts.py?action=index&project=%s&type=%s'.format(project, editor_type), show_draft_list, {stepper:editor.stepper});
return "";
}
else {
- return show_draft_list();
+ return show_draft_list({stepper: editor.stepper});
}
}
function show_draft_list(state, json) {
if (json && json) { saved_drafts = json.drafts || {}; }
-
+ draft_stepper = state.stepper; // hackish for now!
let txt = "";
let filenames = Object.keys(saved_drafts);
if (filenames.length > 0) {
@@ -1102,17 +1097,8 @@ function show_draft_list(state, json) {
txt += "</ul></small>"
}
if (json && current_step == 0) {
- let tip = document.getElementById('tips');
- if (txt.length > 0) {
- tip.style.display = 'block';
- tip.innerHTML = txt;
- } else {
- tip.style.display = 'none';
- }
- if (editor_type == 'unified') {
- let tip = document.getElementById('unified-helper');
- tip.innerHTML += txt;
- }
+ let tip = document.getElementById('unified-helper');
+ tip.innerHTML += txt;
} else {
return txt;
}
@@ -1163,16 +1149,15 @@ let gcd = (x,y) => {
}
-function generate_pmc_roster(data) {
-
+function generate_pmc_roster(pdata) {
// PMC age
- let founded = moment(data.pmcdates[project].pmc[2] * 1000.0);
+ let founded = moment(pdata.pmcdates[project].pmc[2] * 1000.0);
let age = founded.fromNow();
- let txt = "%s was founded %s (%s)\n".format(data.pmcsummary[project].name, founded.format('YYYY-MM-DD'), age);
+ let txt = "%s was founded %s (%s)\n".format(pdata.pmcsummary[project].name, founded.format('YYYY-MM-DD'), age);
// PMC and committer count
- let no_com = data.count[project][1];
- let no_pmc = data.count[project][0];
+ let no_com = pdata.count[project][1];
+ let no_pmc = pdata.count[project][0];
let y1 = no_com;
let y2 = no_pmc;
@@ -1201,7 +1186,7 @@ function generate_pmc_roster(data) {
// Last PMC addition
- let changes = data.changes[project].pmc;
+ let changes = pdata.changes[project].pmc;
let now = moment();
let three_months_ago = now.subtract(3, 'months');
let no_added = 0;
@@ -1230,7 +1215,7 @@ function generate_pmc_roster(data) {
// Last Committer addition
txt += "\n"
txt += "Committership changes, past quarter:\n"
- changes = data.changes[project].committer;
+ changes = pdata.changes[project].committer;
now = moment();
three_months_ago = now.subtract(3, 'months');
no_added = 0;
@@ -1373,97 +1358,6 @@ function health_tips(data) {
return txt;
}
-let compile_okay = false;
-
-function check_compile(data) {
-
- compile_okay = true;
- let text = "";
- if (editor_type == 'unified') {
- let required_sections = [];
- let sections = parse_unified();
-
- for (var i = 0; i < step_json.length; i++) {
- let step = step_json[i];
- if (!step.noinput) {
- let found = false;
- required_sections.push(step.rawname||step.description);
- for (var n = 0; n < sections.length; n++) {
- if (sections[n].title == (step.rawname||step.description)) {
- found = true;
- if (sections[n].text.indexOf(PLACEHOLDER) != -1) {
- console.log("Found placeholder text: " + PLACEHOLDER)
- text += "<li><span style='display: inline-block; width: 20px; font-size: 18px; color: red;'>÷</span> <kbd>%s</kbd> contains placeholder text!</li>".format(sections[n].title);
- compile_okay = false;
- } else if (sections[n].text.length < 20) {
- text += "<li><span style='display: inline-block; width: 20px; font-size: 18px; color: pink;'>‽</span> <kbd>%s</kbd> seems a tad short?</li>".format(sections[n].title);
- } else {
- text += "<li><span style='display: inline-block; width: 20px; font-size: 18px; color: green;'>✓</span> <kbd>%s</kbd> seems alright</li>".format(sections[n].title);
-
- }
- break;
- }
- }
- if (!found) {
- compile_okay = false;
- text += "<li><span style='display: inline-block; width: 20px; font-size: 18px; color: red;'>÷</span> <kbd>%s</kbd> is missing from the report!</li>".format(step.description);
- }
- }
-
- }
-
- // Remark on additional sections not required
- for (var n = 0; n < sections.length; n++) {
- if (!required_sections.has(sections[n].title)) {
- text += "<li><span style='display: inline-block; width: 20px; font-size: 18px; color: pink;'>‽</span> Found unknown section <kbd>%s</kbd></li>".format(sections[n].title);
- }
- }
-
-
- }
- else {
- for (var i = 1; i < 5; i++) {
- if (report[i] == null || report[i].length == 0) {
- text += "<li>You have not filled out the <kbd>%s</kbd> section yet.".format(step_json[i].description);
- compile_okay = false;
- }
- }
- }
-
- if (text.length > 0) {
- text = "<h5>Report review results:</h5>The following remarks were logged by the report compiler:<br/><ul>" + text + "</ul>";
- }
- if (!compile_okay) {
- text += "Your report could possibly use some more work, and that's okay! You can always save your current report as a draft and return later to work more on it. Drafts are saved for up to two months.";
- }
- else {
- 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 (compile_okay) text += " <button class='btn btn-success'>Publish via Whimsy</button>"
- return text;
-}
-
-
-function compile_report(data, okay, force) {
- if (!okay && !force) return -1
- if (editor_type == 'unified') {
- return document.getElementById('unified-report').value;
- }
- let rep = "## Board Report for %s ##\n".format(pdata.pdata[project].name);
- for (var i = 1; i < 5; i++) {
- let step = step_json[i];
- rep += "\n## %s:\n".format(step.description);
- if (report[i] !== null) {
- rep += report[i].replace(/(\r?\n)+$/, '');
- } else {
- rep += "Nothing entered yet...\n";
- }
- rep += "\n";
- }
- return rep;
-}
-
function activity_tips(data) {
let three_months_ago = moment().subtract(3, 'months');
let txt = "";
@@ -1509,13 +1403,17 @@ function reflow(txt, chars) {
return output;
}
-function get_charter(data) {
- let charter = data.pdata[project].charter;
+function get_charter(pdata) {
+ let charter = pdata.pdata[project].charter;
let txt = reflow(charter);
return txt;
}
+function compile_check(pdata, editor) {
+ return editor.compile();
+}
+
/******************************************
Fetched from source/init.js
******************************************/
@@ -1526,6 +1424,9 @@ let project = location.search.substr(1);
let loaded_from_draft = false;
let PLACEHOLDER = '[Insert your own data here]';
+let editor = null;
+let stepper = null;
+
if (project.length < 2) {
GET("/reportingcycles.json", pre_splash, {});
} else {
@@ -1549,11 +1450,9 @@ if (project.length < 2) {
Fetched from source/primer.js
******************************************/
+// some glopbal vars for now - we'll get them localized soon enough.
let pdata = {};
-let report = [null,null,null,null,null,null];
-let current_step = 0;
let cycles = {};
-let draft_mode = false;
let comments = {};
function modal(txt) {
@@ -1590,152 +1489,17 @@ function prime_cycles(state, json) {
}
-let step_json = {};
function prime_steps(state, json) {
+ // Cancel spinner
document.getElementById('wizard_spinner').style.display = 'none';
document.getElementById('wrapper').style.display = 'block';
- step_json = json.steps;
- build_steps(0, true);
-}
-
-let hilite_timer = null;
-
-function build_steps(s, start, noclick, e) {
- s = s || 0;
-
- let text = document.getElementById('step_text');
- if (!start && text && text.value.length > 0 && current_step < 5) {
- report[current_step] = text.value;
- }
-
- text.innerText = '';
- let step_changed = (s == current_step) ? false : true;
- current_step = s;
-
- let stepParent = document.getElementById('steps');
- stepParent.innerHTML = '';
- for (var i = 0; i < step_json.length; i++) {
- let element = step_json[i];
- let wrapper = new HTML('div', {class: 'wizard-step-wrapper', onclick: 'build_steps(%u);'.format(i)});
- let stepcircle = new HTML('div', {class: 'wizard-step'});
- let stepicon = new HTML('i', {class: 'fas fa-%s'.format(element.icon)});
- stepcircle.inject(stepicon);
- let steptext = new HTML('div', {class: 'wizard-step-text'}, element.description);
- wrapper.inject([stepcircle, steptext]);
- if (s == i) {
- stepcircle.setAttribute('class', 'wizard-step active');
- steptext.setAttribute('class', 'wizard-step-text active');
- }
- if (i < s) {
- stepcircle.setAttribute('class', 'wizard-step done');
- steptext.setAttribute('class', 'wizard-step-text done');
- }
- stepParent.inject(wrapper);
- if (i < step_json.length-1) {
- let line = new HTML('div', {class: 'wizard-line'});
- if (i < s) line.setAttribute('class', 'wizard-line done');
- stepParent.inject(line);
- }
- if (s == i) {
- let title = document.getElementById('step_title');
- title.innerText = element.description;
- let help = document.getElementById('step_help');
- help.innerHTML = element.help || "No helper information available for this step...";
- if (element.helpgenerator) {
- let data = eval("%s(pdata);".format(element.helpgenerator));
- help.innerHTML = data;
- }
- let text = document.getElementById('step_text');
- text.placeholder = element.placeholder || "";
- let hw = document.getElementById('help_wrapper');
- if (element.noinput) {
- text.style.display = 'none';
- }
- else text.style.display = 'inline';
- text.style.height = (395 - hw.scrollHeight) + "px";
- if (element.generator && !(report[s] && report[s].length > 0)) {
- let data = eval("%s(pdata, compile_okay);".format(element.generator));
- if (data === -1) text.style.display = 'none'; // hide if generator return -1
- else text.value = data;
- }
- else if (report[s]) {
- text.value = report[s];
- } else {
- text.value = '';
- }
-
- // tips??
- let tip = document.getElementById('tips');
- if (element.tipgenerator) {
- let data = eval("%s(pdata);".format(element.tipgenerator));
- if (data && data.length > 0) {
- tip.innerHTML = data;
- tip.style.display = 'block';
- } else {
- tip.style.display = 'none';
- }
- } else {
- tip.style.display = 'none';
- }
- }
- }
-
- let bp = document.getElementById('step_prev');
- if (s == 0) bp.style.display = 'none';
- else bp.style.display = 'block';
-
- let bn = document.getElementById('step_next');
- if (s == step_json.length -1) bn.style.display = 'none';
- else bn.style.display = 'block';
- if (editor_type == 'unified') {
- if (start) {
- let template = "";
- for (var i = 0; i < step_json.length; i++) {
- let step = step_json[i];
- if (!step.noinput || step.rawname) {
- template += "## %s:\n".format(step.rawname || step.description);
- if (step.generator) {
- let data = eval("%s(pdata);".format(step.generator));
- if (data && data.length > 0) template += data
- } else {
- template += PLACEHOLDER;
- }
- template += "\n\n";
- }
- }
- document.getElementById('unified-report').value = template;
- }
- if (report_changed) hilite_sections();
-
- let step = step_json[s];
- let helper = document.getElementById('unified-helper');
-
- helper.innerHTML = "<h5>%s:</h5>".format(step.description);
- // Add in help
- if (step.helpgenerator) {
- let data = eval("%s(pdata);".format(step.helpgenerator));
- helper.innerHTML += data;
- } else if (step.help) {
- helper.innerHTML += step.help;
- }
-
- // Add tips?
- if (step.tipgenerator) {
- let data = eval("%s(pdata);".format(step.tipgenerator));
- helper.innerHTML += data;
- }
- // If clicked to a section, move cursor
- if (!noclick) {
- set_position(step.description);
- }
- if (step_changed || !noclick) mark_section(step.rawname||step.description);
- else {
- window.clearTimeout(hilite_timer);
- if (event && event.keyCode == 13) mark_section(step.rawname||step.description);
- else hilite_timer = window.setTimeout(() => { mark_section(step.rawname||step.description)}, 200);
- }
- }
+ // Create editor and stepper class
+ let editor = new UnifiedEditor('unified-report', json.steps);
+ let stepper = new ReportStepper('unified-steps', editor, json.steps, 'unified-helper');
+ editor.stepper = stepper;
+ stepper.pdata = pdata;
+ stepper.build(0, true);
}
@@ -1985,136 +1749,356 @@ function toggleView(id) {
/******************************************
- Fetched from source/unified.js
+ Fetched from source/stepper.js
******************************************/
-function hilite_sections(b) {
- if (highlighted && !b) return;
- highlighted = true;
- let hilites = [];
+// Left-hand side stepper for reports
+function ReportStepper(div, editor, layout, helper) {
+ // bind to object
+ if (typeof div == "string") this.object = document.getElementById(div);
+ else this.object = div;
+
+ // bind to helper
+ if (typeof helper == "string") this.helper = document.getElementById(helper);
+ else this.helper = helper;
+
+ this.layout = layout;
+ this.editor = editor;
+ this.timer = null; // highlight timer
+ this.step = -1;
+ this.changed = false;
+ this.pdata = null;
+ this.build =function (s, start, noclick, e) {
+ s = s || 0;
+
+ this.changed = (s == this.step) ? false : true;
+ this.step = s;
+
+ if (start) {
+ this.editor.reset();
+ }
+
+
+ if (this.changed) this.editor.highlight();
+
+ // build the step div
+ this.object.innerHTML = '';
+ for (var i = 0; i < this.layout.length; i++) {
+ let element = this.layout[i];
+ let wrapper = new HTML('div', {class: 'wizard-step-wrapper'});
+ let x = i;
+ wrapper.addEventListener('click', () => { this.build(x);});
+ let stepcircle = new HTML('div', {class: 'wizard-step'});
+ let stepicon = new HTML('i', {class: 'fas fa-%s'.format(element.icon)});
+ stepcircle.inject(stepicon);
+ let steptext = new HTML('div', {class: 'wizard-step-text'}, element.description);
+ wrapper.inject([stepcircle, steptext]);
+ if (s == i) {
+ stepcircle.setAttribute('class', 'wizard-step active');
+ steptext.setAttribute('class', 'wizard-step-text active');
+ }
+ if (i < s) {
+ stepcircle.setAttribute('class', 'wizard-step done');
+ steptext.setAttribute('class', 'wizard-step-text done');
+ }
+ this.object.inject(wrapper);
+ if (i < step_json.length-1) {
+ let line = new HTML('div', {class: 'wizard-line'});
+ if (i < s) line.setAttribute('class', 'wizard-line done');
+ this.object.inject(line);
+ }
+ }
+
+ let step = this.layout[s];
+ // If helper exists, show useful data
+ if (this.helper) {
+ this.helper.innerHTML = "<h5>%s:</h5>".format(step.description);
+ // Add in help
+ if (step.helpgenerator) {
+ let f = Function('a', 'b', "return %s(a, b);".format(step.helpgenerator));
+ data = f(this.pdata, this.editor)
+ this.helper.innerHTML += data;
+ } else if (step.help) {
+ this.helper.innerHTML += step.help;
+ }
+ // Add tips?
+ if (step.tipgenerator) {
+ let f = Function('a', 'b', "return %s(a,b);".format(step.tipgenerator));
+ data = f(this.pdata, this.editor)
+ this.helper.innerHTML += data;
+ }
+ // If clicked to a section, move cursor
+ if (!noclick) {
+ this.editor.set_position(step.description);
+ }
+ if (this.changed || !noclick) this.editor.mark_section(step.rawname||step.description);
+ else {
+ window.clearTimeout(this.timer);
+ if (event && event.keyCode == 13) this.editor.mark_section(step.rawname||step.description);
+ else this.timer = window.setTimeout(() => { this.editor.mark_section(step.rawname||step.description)}, 200);
+ }
+ }
+ }
+}
+
+/******************************************
+ Fetched from source/unified.js
+******************************************/
+
+
+// Function that highlights headers and optional sectin in a unified editor
+function UnifiedEditor_highlight_sections(additional_text) {
+ // Don't highlight unless we haven't before or new text is noted
+ if (this.have_highligted && !additional_text) return;
+
+ // Set which sections highlight
+ let hilites = [];
+ // Headers are blue
hilites.push({highlight: /^## [^\r\n]+:/mg, className: 'blue' });
+ // Placeholders are grey with red border
hilites.push({highlight: PLACEHOLDER, className: 'none' });
+ // Capture text cursor position(s) before we continue.
let x = $('#unified-report').selectionStart;
let y = $('#unified-report').selectionEnd;
-
- if (b) {
+
+ // If additional text is marked for highlighting, we'll have to
+ // first destroy any original highlighting, as it's params changed!
+ if (additional_text) {
$('#unified-report').highlightWithinTextarea('destroy');
+
+ // Sections are marked light green
hilites.push({
- highlight: b,
+ highlight: additional_text,
className: 'green'
});
}
-
- $('#unified-report').highlightWithinTextarea({
+ // Run the highlighter on ourselves
+ $(this.object).highlightWithinTextarea({
highlight: hilites
});
+
+ // If x == y (cursor is present and not marking characters),
+ // We'll force focus on ourselves as highlighting loses it.
if (x == y) {
- $('#unified-report').selectionStart = x;
- $('#unified-report').selectionEnd = y;
- $('#unified-report').focus();
+ $(this.object).selectionStart = x;
+ $(this.object).selectionEnd = y;
+ $(this.object).focus();
}
}
-let report_unified = "";
-let report_changed = true;
-let highlighted = false;
-function find_section(e) {
- let tmp = document.getElementById('unified-report').value;
- report_changed = (report_unified == tmp) ? false : true;
- report_unified = tmp;
- let spos = $('#unified-report').prop("selectionStart");
- let helper = document.getElementById('unified-helper');
+// Function for figuring out WHERE we are in our report, cursor-wise
+function UnifiedEditor_find_section(e) {
+ let tmp = this.object.value;
+ this.changed = (this.report == tmp) ? false : true;
+ this.report = tmp;
+ let spos = this.object.selectionStart;
// Hop to next newline, so marking the title will jump to the right section
- while (report_unified[spos] != "\n" && spos < report_unified.length) spos++;
+ while (this.report[spos] != "\n" && spos < this.report.length) spos++;
- let tprec = report_unified.substr(0, spos);
+ let tprec = this.report.substr(0, spos);
let at_step = -1;
- for (var i = 0; i < step_json.length; i++) {
- let step = step_json[i];
+ for (var i = 0; i < this.layout.length; i++) {
+ let step = this.layout[i];
let tline = "## %s:".format(step.rawname || step.description);
if (tprec.indexOf(tline) != -1) {
at_step = i;
}
}
- if (at_step != -1) {
- build_steps(at_step, false, true, e);
-
- } else {
- helper.innerText = "";
- }
+ if (at_step != -1 && this.stepper) {
+ this.stepper.build(at_step, false, true, e);
+ }
}
-function set_position(text) {
- let editor = document.getElementById('unified-report');
- let pos = editor.value.search(text);
- if (pos && pos > 0) {
- editor.selectionStart = (pos + text.length + 2);
- editor.selectionEnd = (pos + text.length + 2);
- editor.focus();
+
+// Quick shortcut to focusing somewhere in the report
+function UnifiedEditor_set_position(text) {
+ let pos = this.object.value.indexOf(text);
+ if (pos != -1) {
+ this.object.selectionStart = (pos + text.length + 2);
+ this.object.selectionEnd = (pos + text.length + 2);
+ this.object.focus();
}
}
// Parses a unified report into sections
-function parse_unified(quiet) {
- let sections = [];
- let sX = 0;
- let tmp = document.getElementById('unified-report').value;
+function UnifiedEditor_parse_report(quiet) {
+ this.sections = []; // Reset sections
+ let sX = 0; // sX is our moving cursor in the text as we parse.
+ let tmp = this.object.value; // get our textarea data
while (tmp.length > 0) {
+ // Look for the next "## Foo Bar:" line
let nextheader = tmp.match(/^## ([^\r\n]+)\r?\n/m);
if (nextheader) {
- if (!quiet) console.log("Found report header: %s".format(nextheader[0]))
+ if (!quiet) console.log("Found report header: %s".format(nextheader[0]));
let title = nextheader[1];
let spos = tmp.indexOf(nextheader[0]);
if (spos != -1) {
- sX += spos + nextheader[0].length;
+ sX += spos + nextheader[0].length; // move cursor
sY = sX;
+ // ourr buffer past this header, find another one further down
tmp = tmp.substr(spos + nextheader[0].length);
let epos = tmp.search(/^## [^\r\n]+/m);
+ // if no further headers, use end of buffer as end pos.
epos = (epos == -1) ? tmp.length : epos;
let section = tmp.substr(0, epos);
+ // We got something(?), push to sections array.
if (title.length > 2) {
- sections.push({
- title: title.replace(/:.*$/, ''),
+ this.sections.push({
+ title: title.replace(/:.*$/, ''), // crop away colon and any spaces following
text: section,
start: sX,
end: sX + epos
});
}
if (!quiet) console.log("Section contains:");
- if (!quiet) console.log(section)
+ if (!quiet) console.log(section);
tmp = tmp.substr(epos);
- } else { break }
+ } else { break; }
} else {
if (!quiet) console.log("No more report headers found.");
}
}
- return sections;
}
-// Mark a section using the highlighter
-function mark_section(title) {
- let sections = parse_unified(true);
+// Mark a section using the highlighter.
+function UnifiedEditor_mark_section(title) {
+ this.parse(true);
let foundit = false;
- for (var i = 0; i < sections.length; i++) {
- if (sections[i].title == title && sections[i].text.indexOf(PLACEHOLDER) == -1 && sections[i].text.length > 4) {
+ 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))
- hilite_sections(sections[i].text);
+ this.highlight(section.text);
foundit = true;
- break
+ break;
}
}
+ // If we don't know what to highlight, "reset" by highlighting a
+ // piece of text that doesn't exist. HACK HACK HACK.
if (!foundit) {
- hilite_sections("<-- EXTERMINATE -->");
+ this.highlight("<-- EXTERMINATE -->");
+ }
+}
+
+
+// Function for resetting a report to follow layout
+function UnifiedEditor_reset() {
+ this.report = "";
+ this.changed = true;
+ for (var i = 0; i < this.layout.length; i++) {
+ let step = this.layout[i];
+ if (!step.noinput || step.rawname) {
+ this.report += "## %s:\n".format(step.rawname || step.description);
+ if (step.generator) {
+ let f = Function('a', "return %s(a);".format(step.generator));
+ data = f(this.stepper.pdata)
+ if (data && data.length > 0) this.report += data
+ } else {
+ this.report += PLACEHOLDER;
+ }
+ this.report += "\n\n";
+ }
}
-}
\ No newline at end of file
+ this.object.value = this.report;
+ this.sections = [];
+}
+
+// Function for compiling (validating) a report
+function UnifiedEditor_compile() {
+ this.compiles = true;
+ let text = "";
+ let required_sections = [];
+ this.parse();
+ for (var i = 0; i < this.layout.length; i++) {
+ let step = this.layout[i];
+ if (!step.noinput) {
+ let found = false;
+ required_sections.push(step.rawname||step.description);
+ for (var n = 0; n < this.sections.length; n++) {
+ if (this.sections[n].title == (step.rawname||step.description)) {
+ found = true;
+ if (this.sections[n].text.indexOf(PLACEHOLDER) != -1) {
+ console.log("Found placeholder text: " + PLACEHOLDER)
+ text += "<li><span style='display: inline-block; width: 20px; font-size: 18px; color: red;'>÷</span> <kbd>%s</kbd> contains placeholder text!</li>".format(this.sections[n].title);
+ this.compiles = false;
+ } else if (this.sections[n].text.length < 20) {
+ text += "<li><span style='display: inline-block; width: 20px; font-size: 18px; color: pink;'>‽</span> <kbd>%s</kbd> seems a tad short?</li>".format(this.sections[n].title);
+ } else {
+ text += "<li><span style='display: inline-block; width: 20px; font-size: 18px; color: green;'>✓</span> <kbd>%s</kbd> seems alright</li>".format(this.sections[n].title);
+
+ }
+ break;
+ }
+ }
+ if (!found) {
+ this.compiles = false;
+ text += "<li><span style='display: inline-block; width: 20px; font-size: 18px; color: red;'>÷</span> <kbd>%s</kbd> is missing from the report!</li>".format(step.description);
+ }
+ }
+
+ }
+
+ // Remark on additional sections not required
+ for (var n = 0; n < this.sections.length; n++) {
+ if (!required_sections.has(this.sections[n].title)) {
+ text += "<li><span style='display: inline-block; width: 20px; font-size: 18px; color: pink;'>‽</span> Found unknown section <kbd>%s</kbd></li>".format(this.sections[n].title);
+ }
+ }
+
+
+ if (text.length > 0) {
+ text = "<h5>Report review results:</h5>The following remarks were logged by the report compiler:<br/><ul>" + text + "</ul>";
+ }
+ if (!this.compiles) {
+ text += "Your report could possibly use some more work, and that's okay! You can always save your current report as a draft and return later to work more on it. Drafts are saved for up to two months.";
+ }
+ else {
+ 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 class='btn btn-success'>Publish via Whimsy</button>"
+ return text;
+}
+
+
+// This is the Unfied Editor for reports.
+function UnifiedEditor(div, layout) {
+ // Bind to our textarea, direct or via ID.
+ console.log(typeof div)
+ if (typeof div == "string") this.object = document.getElementById(div);
+ else this.object = div;
+
+ this.layout = layout; // our JSON report layout (steps.json)
+ this.sections = []; // Sections we have or have found in the editor.
+ this.report = ""; // The combined report
+ this.stepper = null; // optional stepper class
+
+ this.have_highligted = false; // whether we have highlighted before?
+ this.changed = false; // whether report changed since last parse
+ this.compiles = false; // Whether compiles are okay
+
+ // Function references
+ this.highlight = UnifiedEditor_highlight_sections;
+ this.mark_section = UnifiedEditor_mark_section;
+ this.parse = UnifiedEditor_parse_report;
+ this.set_position = UnifiedEditor_set_position;
+ this.reset = UnifiedEditor_reset;
+ this.find_section = UnifiedEditor_find_section;
+ this.compile = UnifiedEditor_compile;
+
+ // set div events
+ this.object.addEventListener('keyup', () => { this.find_section(true); });
+ this.object.addEventListener('mouseup', () => { this.find_section(); });
+
+}
Modified: comdev/reporter.apache.org/trunk/site/wizard/steps.json
URL: http://svn.apache.org/viewvc/comdev/reporter.apache.org/trunk/site/wizard/steps.json?rev=1864224&r1=1864223&r2=1864224&view=diff
==============================================================================
--- comdev/reporter.apache.org/trunk/site/wizard/steps.json (original)
+++ comdev/reporter.apache.org/trunk/site/wizard/steps.json Fri Aug 2 13:13:36 2019
@@ -46,7 +46,7 @@
"description": "Review Report",
"help": "That's it, we've compiled your report for you. Please review it. When it is time to file your report, you can submit it via the <a href='https://whimsy.apache.org/board/agenda/'>Whimsy Agenda Tool</a>.",
"generator": "compile_report",
- "helpgenerator": "check_compile",
+ "helpgenerator": "compile_check",
"noinput": true
}
]
Modified: comdev/reporter.apache.org/trunk/site/wizard/unified.html
URL: http://svn.apache.org/viewvc/comdev/reporter.apache.org/trunk/site/wizard/unified.html?rev=1864224&r1=1864223&r2=1864224&view=diff
==============================================================================
--- comdev/reporter.apache.org/trunk/site/wizard/unified.html (original)
+++ comdev/reporter.apache.org/trunk/site/wizard/unified.html Fri Aug 2 13:13:36 2019
@@ -16,8 +16,8 @@ let editor_type = 'unified';
</script>
<title>ASF Board Report Wizard</title>
-<link rel="stylesheet" href="css/wizard.css?foo2"/>
-<link rel="stylesheet" href="highlighter/highlighter.css"/>
+<link rel="stylesheet" href="css/wizard.css?newstuff"/>
+<link rel="stylesheet" href="highlighter/highlighter.css?newstuff"/>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
@@ -26,37 +26,18 @@ let editor_type = 'unified';
<div class="loader"></div>
</div>
- <div id="wrapper" style="display: none;">
+ <div id="wrapper" style="display: none;" class="unified">
<h2 id="pname" style="text-align: center;">Board Report Wizard</h2>
- <div id="steps">
+ <div id="unified-steps">
+
-
</div>
<div id="unified-editor">
- <textarea id="unified-report" onmouseup="find_section();" onkeyup="find_section(event);"></textarea>
+ <textarea id="unified-report"></textarea>
</div>
<div id="unified-helper"></div>
- <div id="wizard-content">
- <div id="help_wrapper">
- <h3 id="step_title">Project Activity:</h3>
- <p id="step_help">
-
- </p>
- </div>
- <p style="text-align: center; width: 100%; height: 100%;">
- <textarea id="step_text" style="width: 90%; height: 60%; margin: 0 auto;"
-placeholder="Example activity:
-- This quarter, we attended FooCon - it was a sounding success!
-- Apache Foo 1.2.3 was released on August 4th, 2019."></textarea><br/>
-<button id="step_prev" onclick="build_steps(current_step-1);" class="btn btn-info" style="float: left;">‹‹ Previous step</button>
-<button id="step_next" onclick="build_steps(current_step+1);" class="btn btn-success" style="float: right;">›› Next step</button>
-</p>
- </div>
-
- <div id="tips" class="wizard-tip"></div>
- </div>
<!-- Modal for notices -->
<div class="modal fade" id="alert" role="dialog">
@@ -79,7 +60,7 @@ placeholder="Example activity:
</div>
<footer style="text-align: center; font-size: 0.8rem; clear: both;">
- Powered by the <a href='?'>ASF Board Report Wizard</a>. Copyright© 2019 <a href='https://community.apache.org'>Apache Community Development</a>.<br/>
+ Powered by the <a href='./'>ASF Board Report Wizard</a>. Copyright© 2019 <a href='https://community.apache.org'>Apache Community Development</a>.<br/>
Queries or other feedback should go to our mailing list: dev@community.apache.org
</footer>
@@ -91,8 +72,8 @@ placeholder="Example activity:
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<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.js" type="text/javascript"></script>
+<script src="highlighter/highlighter.js?newstuff" type="text/javascript"></script>
+<script src="js/wizard.js?newstuff" type="text/javascript"></script>
</body>
</html>