@govtechsg/oobee 0.10.70 → 0.10.72
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DETAILS.md +0 -1
- package/README.md +12 -0
- package/S3_UPLOAD_README.md +172 -0
- package/dev/runGenerateJustHtmlReport.ts +25 -0
- package/package.json +4 -2
- package/src/combine.ts +71 -14
- package/src/constants/common.ts +89 -91
- package/src/constants/constants.ts +534 -59
- package/src/crawlers/crawlDomain.ts +313 -305
- package/src/crawlers/crawlIntelligentSitemap.ts +24 -18
- package/src/crawlers/crawlLocalFile.ts +29 -27
- package/src/crawlers/crawlSitemap.ts +264 -253
- package/src/crawlers/custom/utils.ts +809 -119
- package/src/crawlers/runCustom.ts +29 -4
- package/src/generateHtmlReport.ts +224 -0
- package/src/mergeAxeResults.ts +94 -44
- package/src/runGenerateJustHtmlReport.ts +20 -0
- package/src/services/s3Uploader.ts +184 -0
- package/src/static/ejs/partials/components/allIssues/AllIssues.ejs +9 -0
- package/src/static/ejs/partials/components/allIssues/CategoryBadges.ejs +82 -0
- package/src/static/ejs/partials/components/allIssues/FilterBar.ejs +33 -0
- package/src/static/ejs/partials/components/allIssues/IssuesTable.ejs +41 -0
- package/src/static/ejs/partials/components/header/SiteInfo.ejs +119 -0
- package/src/static/ejs/partials/components/header/aboutScanModal/AboutScanModal.ejs +15 -0
- package/src/static/ejs/partials/components/header/aboutScanModal/ScanConfiguration.ejs +44 -0
- package/src/static/ejs/partials/components/header/aboutScanModal/ScanDetails.ejs +142 -0
- package/src/static/ejs/partials/components/prioritiseIssues/IssueDetailCard.ejs +36 -0
- package/src/static/ejs/partials/components/prioritiseIssues/PrioritiseIssues.ejs +47 -0
- package/src/static/ejs/partials/components/ruleModal/ruleOffcanvas.ejs +196 -0
- package/src/static/ejs/partials/components/scannedPagesSegmentedTabs.ejs +48 -0
- package/src/static/ejs/partials/components/shared/InfoAlert.ejs +3 -0
- package/src/static/ejs/partials/components/{topFive.ejs → topTen.ejs} +2 -2
- package/src/static/ejs/partials/components/wcagCompliance/FailedCriteria.ejs +47 -0
- package/src/static/ejs/partials/components/wcagCompliance/WcagCompliance.ejs +16 -0
- package/src/static/ejs/partials/components/wcagCompliance/WcagGaugeBar.ejs +16 -0
- package/src/static/ejs/partials/components/wcagCoverageDetails.ejs +18 -0
- package/src/static/ejs/partials/footer.ejs +1 -1
- package/src/static/ejs/partials/header.ejs +7 -223
- package/src/static/ejs/partials/main.ejs +12 -23
- package/src/static/ejs/partials/scripts/allIssues/AllIssues.ejs +376 -0
- package/src/static/ejs/partials/scripts/categorySummary.ejs +1 -1
- package/src/static/ejs/partials/scripts/header/SiteInfo.ejs +44 -0
- package/src/static/ejs/partials/scripts/header/aboutScanModal/AboutScanModal.ejs +51 -0
- package/src/static/ejs/partials/scripts/header/aboutScanModal/ScanConfiguration.ejs +127 -0
- package/src/static/ejs/partials/scripts/header/aboutScanModal/ScanDetails.ejs +60 -0
- package/src/static/ejs/partials/scripts/prioritiseIssues/IssueDetailCard.ejs +137 -0
- package/src/static/ejs/partials/scripts/prioritiseIssues/PrioritiseIssues.ejs +214 -0
- package/src/static/ejs/partials/scripts/prioritiseIssues/wcagSvgMap.ejs +861 -0
- package/src/static/ejs/partials/scripts/ruleModal/constants.ejs +949 -0
- package/src/static/ejs/partials/scripts/ruleModal/itemCardRenderer.ejs +352 -0
- package/src/static/ejs/partials/scripts/ruleModal/pageAccordionBuilder.ejs +468 -0
- package/src/static/ejs/partials/scripts/ruleModal/ruleOffcanvas.ejs +306 -0
- package/src/static/ejs/partials/scripts/ruleModal/utilities.ejs +483 -0
- package/src/static/ejs/partials/scripts/scannedPagesSegmentedTabs.ejs +35 -0
- package/src/static/ejs/partials/scripts/screenshotLightbox.ejs +61 -57
- package/src/static/ejs/partials/scripts/topTen.ejs +61 -0
- package/src/static/ejs/partials/scripts/utils.ejs +15 -0
- package/src/static/ejs/partials/scripts/wcagCompliance/FailedCriteria.ejs +103 -0
- package/src/static/ejs/partials/scripts/wcagCompliance/WcagGaugeBar.ejs +47 -0
- package/src/static/ejs/partials/scripts/wcagCompliance.ejs +15 -0
- package/src/static/ejs/partials/scripts/wcagCoverageDetails.ejs +75 -0
- package/src/static/ejs/partials/styles/allIssues/AllIssues.ejs +384 -0
- package/src/static/ejs/partials/styles/bootstrap.ejs +17 -1
- package/src/static/ejs/partials/styles/header/SiteInfo.ejs +121 -0
- package/src/static/ejs/partials/styles/header/aboutScanModal/AboutScanModal.ejs +82 -0
- package/src/static/ejs/partials/styles/header/aboutScanModal/ScanConfiguration.ejs +50 -0
- package/src/static/ejs/partials/styles/header/aboutScanModal/ScanDetails.ejs +149 -0
- package/src/static/ejs/partials/styles/header.ejs +7 -0
- package/src/static/ejs/partials/styles/prioritiseIssues/IssueDetailCard.ejs +141 -0
- package/src/static/ejs/partials/styles/prioritiseIssues/PrioritiseIssues.ejs +204 -0
- package/src/static/ejs/partials/styles/ruleModal/ruleOffcanvas.ejs +456 -0
- package/src/static/ejs/partials/styles/scannedPagesSegmentedTabs.ejs +46 -0
- package/src/static/ejs/partials/styles/shared/InfoAlert.ejs +12 -0
- package/src/static/ejs/partials/styles/styles.ejs +198 -470
- package/src/static/ejs/partials/styles/topTenCard.ejs +44 -0
- package/src/static/ejs/partials/styles/wcagCompliance/FailedCriteria.ejs +59 -0
- package/src/static/ejs/partials/styles/wcagCompliance/WcagGaugeBar.ejs +62 -0
- package/src/static/ejs/partials/styles/wcagCompliance.ejs +36 -0
- package/src/static/ejs/partials/styles/wcagCoverageDetails.ejs +33 -0
- package/src/static/ejs/report.ejs +42 -259
- package/src/static/ejs/summary.ejs +1 -1
- package/src/utils.ts +30 -0
- package/src/static/ejs/partials/components/categorySelector.ejs +0 -4
- package/src/static/ejs/partials/components/categorySelectorDropdown.ejs +0 -57
- package/src/static/ejs/partials/components/pagesScannedModal.ejs +0 -70
- package/src/static/ejs/partials/components/reportSearch.ejs +0 -47
- package/src/static/ejs/partials/components/ruleOffcanvas.ejs +0 -105
- package/src/static/ejs/partials/components/scanAbout.ejs +0 -328
- package/src/static/ejs/partials/components/wcagCompliance.ejs +0 -52
- package/src/static/ejs/partials/scripts/categorySelectorDropdownScript.ejs +0 -190
- package/src/static/ejs/partials/scripts/reportSearch.ejs +0 -287
- package/src/static/ejs/partials/scripts/ruleOffcanvas.ejs +0 -804
- package/src/static/ejs/partials/scripts/scanAboutScript.ejs +0 -38
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
(function initIssueDetailCard() {
|
|
3
|
+
window.populateIssueDetailCard = function (issue) {
|
|
4
|
+
const detailCard = document.getElementById('a11yIssueDetailCard');
|
|
5
|
+
if (!detailCard) return;
|
|
6
|
+
|
|
7
|
+
detailCard.style.display = 'block';
|
|
8
|
+
|
|
9
|
+
const titleElement = document.getElementById('issueDetailTitle');
|
|
10
|
+
if (titleElement) {
|
|
11
|
+
titleElement.textContent = issue.description || 'Issue';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const imageElement = document.getElementById('issueDetailImage');
|
|
15
|
+
const imageContainer = imageElement?.closest('.issue-detail-image-container');
|
|
16
|
+
|
|
17
|
+
if (imageElement && imageContainer) {
|
|
18
|
+
let imageSrc = null;
|
|
19
|
+
|
|
20
|
+
if (issue.conformance && issue.conformance.length > 0) {
|
|
21
|
+
const wcagConformance = issue.conformance.filter(c => c.startsWith('wcag'));
|
|
22
|
+
const wcagCriteriaLabels = scanData?.wcagCriteriaLabels || {};
|
|
23
|
+
|
|
24
|
+
for (const wcag of wcagConformance) {
|
|
25
|
+
const formattedWcag = formatWcagId(wcag);
|
|
26
|
+
|
|
27
|
+
if (wcagCriteriaLabels[formattedWcag]) {
|
|
28
|
+
const svg = window.getWcagSvg ? window.getWcagSvg(formattedWcag) : null;
|
|
29
|
+
if (svg) {
|
|
30
|
+
imageSrc = window.svgToDataUrl ? window.svgToDataUrl(svg) : svg;
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!imageSrc) {
|
|
38
|
+
imageContainer.style.display = 'none';
|
|
39
|
+
} else {
|
|
40
|
+
imageContainer.style.display = 'flex';
|
|
41
|
+
imageElement.src = imageSrc;
|
|
42
|
+
imageElement.alt = issue.description || 'Issue illustration';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Populate conformance badges
|
|
47
|
+
const conformanceContainer = document.getElementById('issueDetailConformance');
|
|
48
|
+
if (conformanceContainer && issue.conformance && issue.conformance.length > 0) {
|
|
49
|
+
const wcagConformance = issue.conformance.filter(c => c.startsWith('wcag'));
|
|
50
|
+
const wcagCriteriaLabels = scanData?.wcagCriteriaLabels || {};
|
|
51
|
+
|
|
52
|
+
const criteriaNumbers = [];
|
|
53
|
+
let level = null;
|
|
54
|
+
|
|
55
|
+
wcagConformance.forEach(wcag => {
|
|
56
|
+
const formattedWcag = formatWcagId(wcag);
|
|
57
|
+
|
|
58
|
+
if (wcagCriteriaLabels[formattedWcag]) {
|
|
59
|
+
criteriaNumbers.push(formattedWcag);
|
|
60
|
+
if (!level) {
|
|
61
|
+
level = wcagCriteriaLabels[formattedWcag];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const badges = criteriaNumbers.map(
|
|
67
|
+
criteria => `<span class="issue-detail-conformance-badge">${criteria}</span>`,
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
if (level) {
|
|
71
|
+
badges.push(`<span class="issue-detail-conformance-badge">Level ${level}</span>`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
conformanceContainer.innerHTML = badges.join('');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Populate long description
|
|
78
|
+
const longDescriptionElement = document.getElementById('issueDetailLongDescription');
|
|
79
|
+
const a11yRuleLongDescriptionMap = scanData?.a11yRuleLongDescriptionMap || {};
|
|
80
|
+
if (longDescriptionElement) {
|
|
81
|
+
const longDescription = a11yRuleLongDescriptionMap[issue.ruleId] || '';
|
|
82
|
+
longDescriptionElement.textContent = longDescription;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Populate disability impact
|
|
86
|
+
const disabilitySection = document.getElementById('issueDetailDisabilitySection');
|
|
87
|
+
const disabilityMessage = document.getElementById('issueDetailDisabilityMessage');
|
|
88
|
+
const disabilityBadgesMap = scanData?.disabilityBadgesMap || {};
|
|
89
|
+
const disabilities = disabilityBadgesMap[issue.ruleId] || [];
|
|
90
|
+
|
|
91
|
+
if (disabilityMessage && disabilities.length > 0) {
|
|
92
|
+
let disabilityText = '';
|
|
93
|
+
if (disabilities.length === 1) {
|
|
94
|
+
disabilityText = `${disabilities[0]} Disability `;
|
|
95
|
+
} else if (disabilities.length === 2) {
|
|
96
|
+
disabilityText = `${disabilities[0]} and ${disabilities[1]} Disability`;
|
|
97
|
+
} else {
|
|
98
|
+
const boldedDisabilities = disabilities.map(d => `${d}`);
|
|
99
|
+
const lastDisability = boldedDisabilities.pop();
|
|
100
|
+
disabilityText = `${boldedDisabilities.join(', ')} and ${lastDisability} Disability`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
disabilityMessage.innerHTML = `This issue prevents users with <span class="disability-text">${disabilityText}</span> from navigating your website.`;
|
|
104
|
+
disabilitySection.style.display = 'block';
|
|
105
|
+
} else {
|
|
106
|
+
disabilitySection.style.display = 'none';
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Handle "View issue details" button
|
|
110
|
+
const viewDetailsBtn = document.getElementById('viewIssueDetailsBtn');
|
|
111
|
+
if (viewDetailsBtn) {
|
|
112
|
+
const newBtn = viewDetailsBtn.cloneNode(true);
|
|
113
|
+
viewDetailsBtn.parentNode.replaceChild(newBtn, viewDetailsBtn);
|
|
114
|
+
|
|
115
|
+
newBtn.addEventListener('click', function () {
|
|
116
|
+
const category = issue.category || 'mustFix';
|
|
117
|
+
const ruleData = scanItems[category]?.rules?.find(r => r.rule === issue.ruleId);
|
|
118
|
+
|
|
119
|
+
if (ruleData && typeof expandRule === 'function') {
|
|
120
|
+
expandRule(category, ruleData);
|
|
121
|
+
|
|
122
|
+
const modalElement = document.getElementById('expandedRule');
|
|
123
|
+
if (modalElement) {
|
|
124
|
+
const modal = bootstrap.Modal.getOrCreateInstance(modalElement);
|
|
125
|
+
modal.show();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const detailCard = document.getElementById('a11yIssueDetailCard');
|
|
133
|
+
if (detailCard) {
|
|
134
|
+
detailCard.style.display = 'none';
|
|
135
|
+
}
|
|
136
|
+
})();
|
|
137
|
+
</script>
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
(function populatePrioritiseIssues() {
|
|
3
|
+
const a11yRuleShortDescriptionMap = scanData?.a11yRuleShortDescriptionMap || {};
|
|
4
|
+
const disabilityBadgesMap = scanData?.disabilityBadgesMap || {};
|
|
5
|
+
const wcagLinks = scanData?.wcagLinks || {};
|
|
6
|
+
const wcagViolations = scanData?.wcagViolations || [];
|
|
7
|
+
const wcagClauses = scanData?.wcagClauses || {};
|
|
8
|
+
const mustFixRules = scanItems?.mustFix?.rules || [];
|
|
9
|
+
|
|
10
|
+
const wcagCriteriaMap = new Map();
|
|
11
|
+
|
|
12
|
+
mustFixRules.forEach(rule => {
|
|
13
|
+
const ruleId = rule.rule;
|
|
14
|
+
const wcagCriteria = rule.conformance?.filter(c => c.startsWith('wcag')) || [];
|
|
15
|
+
|
|
16
|
+
wcagCriteria.forEach(wcag => {
|
|
17
|
+
const formattedWcag = formatWcagId(wcag);
|
|
18
|
+
|
|
19
|
+
if (!wcagCriteriaMap.has(formattedWcag)) {
|
|
20
|
+
const clauseKey = formattedWcag.replace('WCAG ', '');
|
|
21
|
+
wcagCriteriaMap.set(formattedWcag, {
|
|
22
|
+
id: formattedWcag,
|
|
23
|
+
name: wcagClauses[clauseKey] || formattedWcag,
|
|
24
|
+
issues: [],
|
|
25
|
+
totalIssueCount: 0,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const criteria = wcagCriteriaMap.get(formattedWcag);
|
|
30
|
+
const displayName = a11yRuleShortDescriptionMap[ruleId] || rule.description;
|
|
31
|
+
|
|
32
|
+
criteria.issues.push({
|
|
33
|
+
ruleId: ruleId,
|
|
34
|
+
description: displayName,
|
|
35
|
+
originalDescription: rule.description,
|
|
36
|
+
totalItems: rule.totalItems || 0,
|
|
37
|
+
helpUrl: rule.helpUrl || '',
|
|
38
|
+
axeImpact: rule.axeImpact || '',
|
|
39
|
+
conformance: rule.conformance || [],
|
|
40
|
+
pagesAffected: rule.pagesAffected || [],
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
criteria.totalIssueCount = criteria.issues.length || 0;
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const sortedCriteria = Array.from(wcagCriteriaMap.values()).sort((a, b) => {
|
|
48
|
+
if (a.totalIssueCount !== b.totalIssueCount) {
|
|
49
|
+
return a.totalIssueCount - b.totalIssueCount;
|
|
50
|
+
}
|
|
51
|
+
return a.id.localeCompare(b.id);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const failedCriteria = sortedCriteria.filter(criteria =>
|
|
55
|
+
wcagViolations.some(v => formatWcagId(v) === criteria.id),
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const cardElement = document.getElementById('prioritiseIssuesCard');
|
|
59
|
+
if (failedCriteria.length === 0) {
|
|
60
|
+
if (cardElement) {
|
|
61
|
+
cardElement.style.display = 'none';
|
|
62
|
+
}
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const accordionContainer = document.getElementById('prioritiseIssuesAccordion');
|
|
67
|
+
if (!accordionContainer) return;
|
|
68
|
+
|
|
69
|
+
const accordionHTML = failedCriteria
|
|
70
|
+
.map((criteria, index) => {
|
|
71
|
+
const wcagScore = criteria.id.replace('WCAG ', '');
|
|
72
|
+
const issueWord = criteria.issues.length === 1 ? 'issue' : 'issues';
|
|
73
|
+
|
|
74
|
+
const issuesListHTML = criteria.issues
|
|
75
|
+
.map(issue => {
|
|
76
|
+
const disabilities = disabilityBadgesMap[issue.ruleId] || [];
|
|
77
|
+
const disabilityBadges =
|
|
78
|
+
disabilities.length > 0
|
|
79
|
+
? `
|
|
80
|
+
<div class="priority-issue-badges">
|
|
81
|
+
${disabilities.map(disability => `<span class="disability-badge">${disability} Disability</span>`).join('')}
|
|
82
|
+
</div>
|
|
83
|
+
`
|
|
84
|
+
: '';
|
|
85
|
+
|
|
86
|
+
return `
|
|
87
|
+
<li class="priority-issue-item d-flex g-one" data-rule-id="${issue.ruleId}" role="button" tabindex="0">
|
|
88
|
+
<div class="d-flex justify-content-between align-items-center w-90">
|
|
89
|
+
<div class="priority-issue-title">${issue.description}</div>
|
|
90
|
+
${disabilityBadges}
|
|
91
|
+
</div>
|
|
92
|
+
</li>
|
|
93
|
+
`;
|
|
94
|
+
})
|
|
95
|
+
.join('');
|
|
96
|
+
|
|
97
|
+
return `
|
|
98
|
+
<div class="accordion-item">
|
|
99
|
+
<h3 class="accordion-header" id="heading${index}">
|
|
100
|
+
<button
|
|
101
|
+
class="accordion-button collapsed"
|
|
102
|
+
type="button"
|
|
103
|
+
data-bs-toggle="collapse"
|
|
104
|
+
data-bs-target="#collapse${index}"
|
|
105
|
+
aria-expanded="false"
|
|
106
|
+
aria-controls="collapse${index}"
|
|
107
|
+
>
|
|
108
|
+
<span class="h4 mb-0">WCAG ${wcagScore} - </span>
|
|
109
|
+
<span class="h4 fw-normal mb-0">${criteria.issues.length} ${issueWord}</span>
|
|
110
|
+
<span class="wcag-score-badge">-1 WCAG Score</span>
|
|
111
|
+
<svg class="accordion-icon-collapsed" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
112
|
+
<path d="M7.41 8.58984L12 13.1698L16.59 8.58984L18 9.99984L12 15.9998L6 9.99984L7.41 8.58984Z" fill="#5735DF"/>
|
|
113
|
+
</svg>
|
|
114
|
+
<svg class="accordion-icon-expanded" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
115
|
+
<path d="M7.41 15.4102L12 10.8302L16.59 15.4102L18 14.0002L12 8.00016L6 14.0002L7.41 15.4102Z" fill="#5735DF"/>
|
|
116
|
+
</svg>
|
|
117
|
+
</button>
|
|
118
|
+
</h3>
|
|
119
|
+
<div
|
|
120
|
+
id="collapse${index}"
|
|
121
|
+
class="accordion-collapse collapse"
|
|
122
|
+
data-bs-parent="#prioritiseIssuesAccordion"
|
|
123
|
+
>
|
|
124
|
+
<div class="accordion-body">
|
|
125
|
+
<ul class="priority-issues-list">
|
|
126
|
+
${issuesListHTML}
|
|
127
|
+
</ul>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
</div>
|
|
131
|
+
`;
|
|
132
|
+
})
|
|
133
|
+
.join('');
|
|
134
|
+
|
|
135
|
+
accordionContainer.innerHTML = accordionHTML;
|
|
136
|
+
|
|
137
|
+
document.querySelectorAll('.priority-issue-item').forEach(item => {
|
|
138
|
+
const selectIssue = function () {
|
|
139
|
+
const ruleId = item.getAttribute('data-rule-id');
|
|
140
|
+
|
|
141
|
+
document.querySelectorAll('.priority-issue-item').forEach(el => {
|
|
142
|
+
el.classList.remove('active');
|
|
143
|
+
el.setAttribute('aria-selected', 'false');
|
|
144
|
+
});
|
|
145
|
+
document.querySelectorAll('.priority-issue-title').forEach(el => {
|
|
146
|
+
el.classList.remove('active');
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
item.classList.add('active');
|
|
150
|
+
item.setAttribute('aria-selected', 'true');
|
|
151
|
+
const title = item.querySelector('.priority-issue-title');
|
|
152
|
+
if (title) {
|
|
153
|
+
title.classList.add('active');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
let selectedRule = null;
|
|
157
|
+
for (const criteria of failedCriteria) {
|
|
158
|
+
const issue = criteria.issues.find(i => i.ruleId === ruleId);
|
|
159
|
+
if (issue) {
|
|
160
|
+
selectedRule = issue;
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (selectedRule && typeof window.populateIssueDetailCard === 'function') {
|
|
166
|
+
window.populateIssueDetailCard(selectedRule);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
// Click handler
|
|
171
|
+
item.addEventListener('click', selectIssue);
|
|
172
|
+
|
|
173
|
+
// Keyboard handler
|
|
174
|
+
item.addEventListener('keydown', function (event) {
|
|
175
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
176
|
+
event.preventDefault();
|
|
177
|
+
selectIssue();
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// Automatically open first accordion and select first issue
|
|
183
|
+
if (failedCriteria.length > 0 && failedCriteria[0].issues.length > 0) {
|
|
184
|
+
const firstAccordionButton = document.querySelector(
|
|
185
|
+
'#prioritiseIssuesAccordion .accordion-button',
|
|
186
|
+
);
|
|
187
|
+
const firstAccordionCollapse = document.querySelector(
|
|
188
|
+
'#prioritiseIssuesAccordion .accordion-collapse',
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
if (firstAccordionButton && firstAccordionCollapse) {
|
|
192
|
+
firstAccordionButton.classList.remove('collapsed');
|
|
193
|
+
firstAccordionButton.setAttribute('aria-expanded', 'true');
|
|
194
|
+
firstAccordionCollapse.classList.add('show');
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const firstIssueItem = document.querySelector('.priority-issue-item');
|
|
198
|
+
if (firstIssueItem) {
|
|
199
|
+
firstIssueItem.classList.add('active');
|
|
200
|
+
firstIssueItem.setAttribute('aria-selected', 'true');
|
|
201
|
+
const firstIssueTitle = firstIssueItem.querySelector('.priority-issue-title');
|
|
202
|
+
if (firstIssueTitle) {
|
|
203
|
+
firstIssueTitle.classList.add('active');
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const firstIssue = failedCriteria[0].issues[0];
|
|
207
|
+
|
|
208
|
+
if (typeof window.populateIssueDetailCard === 'function') {
|
|
209
|
+
window.populateIssueDetailCard(firstIssue);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
})();
|
|
214
|
+
</script>
|