8000 Updated shared bug tracking scripts · xfq/csswg-drafts@a83a662 · GitHub
Skip to content

Commit a83a662

Browse files
committed
Updated shared bug tracking scripts
1 parent 60f722d commit a83a662

2 files changed

Lines changed: 223 additions & 167 deletions

File tree

shared/scripts/BugzillaTracker.js

Lines changed: 217 additions & 148 deletions
< 6C42 td data-grid-cell-id="diff-67cd1a7c556ec7a20afa751011cf90e8100413da4ed19542731e8807b64a3670-2-13-1" data-selected="false" role="gridcell" style="background-color:var(--diffBlob-additionNum-bgColor, var(--diffBlob-addition-bgColor-num));text-align:center" tabindex="-1" valign="top" class="focusable-grid-cell diff-line-number position-relative left-side">13
Original file line numberDiff line numberDiff line change
@@ -1,176 +1,245 @@
11
(function () {
2-
function getIssuesFromDocument () {
2+
3+
var util = {
4+
getOuterHTML: function(el){
5+
6+
if (el.outerHTML){
7+
return el.outerHTML
8+
}
9+
10+
var outerHTML,
11+
temp = document.createElement("div")
12+
+
temp.appendChild(el.cloneNode(true))
14+
outerHTML = temp.innerHTML
15+
16+
temp = null
17+
18+
return outerHTML
19+
}
20+
}
21+
22+
function IssueDashboard(){
23+
var _dashboard = document.createElement("div"),
24+
_offlineIssues = {},
25+
_onlineIssues = {},
26+
_issueTemplate = null,
27+
_header = document.createElement("a"),
28+
_message = document.createElement("em")
29+
30+
_header.href = "#"
31+
_header.className = "issue-dashboard-header"
32+
_header.textContent = "Bug Dashboard"
33+
_header.appendChild(_message)
34+
35+
_header.addEventListener("click", toggleDashboard, false)
36+
37+
_dashboard.id = "issue-dashboard"
38+
_dashboard.appendChild(_header)
39+
40+
document.body.appendChild(_dashboard)
41+
42+
function toggleDashboard(e){
43+
e.preventDefault()
44+
_dashboard.classList.toggle("open")
45+
}
46+
47+
function getNewIssues(){
48+
var id, issues = []
49+
50+
for (id in _onlineIssues){
51+
52+
if (!_offlineIssues[id]){
53+
// not found in the document.
54+
// it's a new issue if the bug_status is not RESOLVED
55+
if (_onlineIssues[id].bug_status !== "RESOLVED") {
56+
57+
_onlineIssues[id].issue_state = "new"
58+
issues.push(_onlineIssues[id])
59+
}
60+
}
61+
}
62+
63+
return issues
64+
}
65+
66+
function getChangedIssues(){
67+
var id, changed, issues = []
68+
69+
for (id in _onlineIssues){
70+
71+
// is the bug in the doument?
72+
if (_offlineIssues[id]){
73+
74+
changed = false
75+
76+
// bug description has changed
77+
if (_offlineIssues[id].short_desc !== _onlineIssues[id].short_desc){
78+
_onlineIssues[id].issue_state = "updated"
79+
changed = true
80+
}
81+
82+
// bug status has changed
83+
if (_offlineIssues[id].bug_status !== _onlineIssues[id].bug_status){
84+
85+
// changes from NEW -> ASSIGNED aren't noteworthy
86+
if ( !(_offlineIssues[id].bug_status == "NEW" && _onlineIssues[id].bug_status == "ASSIGNED") ){
87+
_onlineIssues[id].issue_state = "updated";
88+
changed = true
89+
}
90+
}
91+
92+
if (changed){
93+
// the issue has been changed, collect it
94+
issues.push(_onlineIssues[id])
95+
}
96+
}
97+
}
98+
99+
return issues
100+
}
101+
102+
103+
function renderIssues(issues){
104+
var issueItem,
105+
issueList = document.createElement("ul")
106+
107+
issueList.className = "issue-list"
108+
109+
issues.forEach(function(issue){
110+
issueItem = document.createElement("li")
111+
112+
var meta = document.createElement("span")
113+
meta.className = "meta"
114+
meta.innerHTML = issue["issue_state"]
115+
116+
if (issue["bug_status"] == "RESOLVED"){
117+
meta.innerHTML = issue["bug_status"]
118+
}
119+
var toggle = document.createElement("a")
120+
toggle.href = "#"
121+
toggle.className = "toggle"
122+
toggle.innerHTML = "toggle HTML"
123+
toggle.addEventListener("click", function(parent){
124+
125+
return function(e){
126+
e.preventDefault()
127+
parent.classList.toggle("showMarkup")
128+
}
129+
130+
}(issueItem))
131+
132+
// populate the issue template with data
133+
var issueDOM = _issueTemplate(issue)
134+
135+
// container for issue markup
136+
var markup = document.createElement("pre")
137+
markup.textContent = util.getOuterHTML(issueDOM)
138+
139+
issueItem.appendChild(meta)
140+
issueItem.appendChild(toggle)
141+
issueItem.appendChild(markup)
142+
issueItem.appendChild(issueDOM)
143+
144+
issueList.appendChild(issueItem)
145+
})
146+
147+
_dashboard.appendChild(issueList)
148+
}
149+
150+
return {
151+
setOnlineIssues: function(issues){
152+
_onlineIssues = issues || []
153+
},
154+
155+
setOfflineIssues: function(issues){
156+
_offlineIssues = issues || []
157+
},
158+
159+
setIssueTemplate: function(string){
160+
_issueTemplate = TemplateManager.compile(string)
161+
},
162+
163+
sync: function(){
164+
if (!_issueTemplate){
165+
throw new Error("IssueDashboard is missing 'issueTemplate'. Expected String, got "+ typeof _issueTemplate)
166+
}
167+
168+
if (!_onlineIssues){
169+
throw new TypeError("Missing 'serverIssues' from server. Expected Object, got "+ typeof _onlineIssues)
170+
}
171+
172+
if (!_offlineIssues){
173+
throw new TypeError("Missing 'documentIssues' from document. Expected Object, got "+ typeof _offlineIssues)
174+
}
175+
176+
var newIssues = getNewIssues(),
177+
changedIssues = getChangedIssues(),
178+
issues = newIssues.concat(changedIssues)
179+
180+
// there's work to be done
181+
if (issues.length){
182+
183+
_dashboard.className = "warning"
184+
renderIssues(issues)
185+
}
186+
else{
187+
_dashboard.className = "ok"
188+
_header.removeEventListener("click", toggleDashboard, false)
189+
}
190+
191+
_message.textContent = issues.length
192+
193+
}
194+
}
195+
}
196+
197+
function getIssuesFromDocument() {
3198
var list = {},
4199
issues = document.querySelectorAll(".issue-marker");
5200

6201
if (issues) {
7202
// make issue an array
8-
issues = Array.prototype.slice.call(issues);
203+
issues = Array.prototype.slice.call(issues);
9204

10205
// pluck out the bug data from the DOM object
11-
issues.forEach(function (issue) {
206+
issues.forEach(function (issue) {
12207

13208
var bugId = issue.dataset["bug_id"];
14209

15210
if (bugId){
16211
list[bugId] = {
17212
"bug_status": issue.dataset["bug_status"],
18-
"short_desc": issue.querySelector(".short-desc").innerText
213+
"short_desc": issue.querySelector(".short-desc").textContent.replace(/\n?\s+/g, " ")
19214
}
20-
}
21-
215+
}
216+
22217
})
23218
}
24219

25220
return list;
26-
}
27-
28-
// Decorate the issues received from the sever with their state related to the issues in the page (new, changed)
29-
function setIssueStates (serverIssues, documentIssues) {
30-
var serverIssue, documentIssue;
31-
32-
if (!serverIssues){
33-
throw new TypeError("Missing 'serverIssues' from server. Expected Object, got "+ typeof serverIssues)
34-
}
221+
}
35222

36-
if (!documentIssues){
37-
throw new TypeError("Missing 'documentIssues' from document. Expected Object, got "+ typeof documentIssues)
38-
}
223+
var dashboard = new IssueDashboard()
224+
dashboard.setIssueTemplate(document.querySelector("#issue-template").innerHTML)
39225

40-
for (var bugId in serverIssues){
41-
serverIssue = serverIssues[bugId];
42-
documentIssue = documentIssues[bugId];
43-
44-
// is the bug in the doument?
45-
if (documentIssues[bugId]){
46-
47-
// bug status has changed. it's an updated issue
48-
if ( (documentIssue.bug_status !== serverIssue.bug_status) ||
49-
(documentIssue.short_desc !== serverIssue.short_desc) ){
50-
51-
// changes from NEW->ASSIGNED aren't noteworthy
52-
if ( ! (documentIssue.bug_status == "NEW" &&
53-
serverIssue.bug_status == "ASSIGNED") )
54-
serverIssue.issue_state = "updated";
55-
}
56-
}
57-
else{
58-
// not found in the document. it's a new issue if the bug_status
59-
// is not RESOLVED
60-
if (serverIssue.bug_status === "RESOLVED") {
61-
//why do we want to show resolved issues that
62-
//have already been removed from the spec?
63-
64-
//serverIssue.issue_state = 'resolved';
65-
} else {
66-
serverIssue.issue_state = "new";
67-
}
68-
}
69-
}
226+
var docIssues = getIssuesFromDocument()
227+
dashboard.setOfflineIssues(docIssues)
70228

71-
return serverIssues;
72-
}
73-
74-
// "this" is bound to the "BugzillaTracker" instance
75-
function renderIssues (serverIssues) {
76-
77-
if (!serverIssues && !serverIssues.length){
78-
return;
79-
}
80-
81-
// get a list of bugs from the document
82-
var documentIssues = getIssuesFromDocument();
83-
84-
// get the bugs list with the updated state (not bug status) related to the bugs already in the page
85-
var issueList = setIssueStates(serverIssues, documentIssues);
86-
87-
var fragment = document.createDocumentFragment();
88-
89-
for (var issueId in issueList){
90-
91-
if (issueList[issueId]["issue_state"]){
92-
93-
// bind the bug data to the bug template
94-
var issueFragment = this.renderIssue(issueList[issueId]);
95-
96-
var wrapper = document.createElement("div");
97-
var trigger = document.createElement("a");
98-
trigger.className = "issue-markup-trigger";
99-
trigger.href = "#";
100-
trigger.innerHTML = "toggle markup"
101-
102-
wrapper.setAttribute("data-issue_state", issueList[issueId]["issue_state"]);
103-
104-
wrapper.appendChild(trigger);
105-
wrapper.appendChild(issueFragment);
106-
fragment.appendChild(wrapper);
107-
}
108-
}
109-
110-
var issueListContainer = document.querySelector("#issue-list");
111-
issueListContainer.appendChild(fragment);
112-
113-
// show/hide the markup for a bug entry
114-
issueListContainer.addEventListener("click", toggleMarkup);
115-
}
116-
117-
function toggleMarkup (e) {
118-
if (e.target.className && e.target.classList.contains("issue-markup-trigger")){
119-
e.preventDefault();
120-
121-
var parent = e.target.parentNode,
122-
issueEl = parent.querySelector(".issue-marker"),
123-
markup = issueEl.outerHTML;
124-
125-
126-
parent.classList.toggle("showMarkup");
127-
128-
// already generated the markup
129-
if (parent.querySelector("pre")){
130-
return
131-
}
132-
else{
133-
var pre = document.createElement("pre");
134-
pre.textContent = markup;
229+
window.checkSpecificationIssues = function (product, component) {
135230

136-
parent.appendChild(pre);
137-
}
138-
}
139-
}
140-
141-
function filterIssues (e) {
142-
if (e.target.name !== "issue-filter"){
143-
return
144-
}
145-
146-
var issueManager = document.querySelector("#issue-manager");
147-
148-
switch(e.target.value){
149-
case "all":
150-
issueManager.removeAttribute("data-view_state");
151-
break;
152-
153-
case "new":
154-
issueManager.setAttribute("data-view_state", "new");
155-
break;
156-
157-
case "updated":
158-
issueManager.setAttribute("data-view_state", "updated");
159-
break;
160-
}
161-
}
231+
document.addEventListener("DOMContentLoaded", function(){
162232

163-
164-
window.checkSpecificationIssues = function (product, component) {
165-
document.addEventListener("DOMContentLoaded", function(){
166-
BugzillaTracker.setIssueTemplate(document.querySelector("#issue-template").innerHTML);
167-
BugzillaTracker.sync({
233+
BugzillaTracker.search({
168234
product: product, // e.g., 'CSS'
169235
component: component // e.g., "Regions",
170-
},
171-
renderIssues);
172-
173-
document.querySelector("#issue-manager form").addEventListener("change", filterIssues)
174-
});
236+
},
237+
238+
function(issues){
239+
dashboard.setOnlineIssues(issues)
240+
dashboard.sync()
241+
});
242+
243+
});
175244
};
176245
})();

0 commit comments

Comments
 (0)