133 lines
3.9 KiB
JavaScript
133 lines
3.9 KiB
JavaScript
import { loadIssuesForCheckedPaths } from './issues.js';
|
|
import { getCheckedFileRefs, initializeTree, renderProductTree, restoreTreeState } from './tree.js';
|
|
import { applyIssueSearchFilter, getIssueTypeFilters, initializeUI } from './ui.js';
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
initializeUI({ onSelectionChange: refreshIssuesForCurrentSelection });
|
|
initializeTree('product-tree', refreshIssuesForCurrentSelection);
|
|
loadProductTree();
|
|
});
|
|
|
|
let productsData = {};
|
|
|
|
function refreshIssuesForCurrentSelection() {
|
|
loadIssuesForCheckedPaths({
|
|
issueTypeFilters: getIssueTypeFilters(),
|
|
checkedFileRefs: getCheckedFileRefs(),
|
|
applyIssueSearchFilter
|
|
});
|
|
}
|
|
|
|
function loadProductTree() {
|
|
fetch('data/products.json')
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
productsData = expandFilePrefixLevel(data);
|
|
renderProductTree(productsData);
|
|
restoreTreeState();
|
|
refreshIssuesForCurrentSelection();
|
|
})
|
|
.catch(error => console.error('Error loading products:', error));
|
|
}
|
|
|
|
function expandFilePrefixLevel(root) {
|
|
if (!root || typeof root !== 'object') {
|
|
return root;
|
|
}
|
|
|
|
return transformNode(root);
|
|
}
|
|
|
|
function transformNode(node) {
|
|
if (!node || typeof node !== 'object' || Array.isArray(node)) {
|
|
return node;
|
|
}
|
|
|
|
const hasIssueArrays = Object.prototype.hasOwnProperty.call(node, 'addressed') ||
|
|
Object.prototype.hasOwnProperty.call(node, 'known');
|
|
|
|
if (hasIssueArrays) {
|
|
const addressed = Array.isArray(node.addressed) ? node.addressed : [];
|
|
const known = Array.isArray(node.known) ? node.known : [];
|
|
const allFiles = [...addressed, ...known];
|
|
|
|
if (allFiles.length === 0) {
|
|
return {
|
|
addressed: [],
|
|
known: []
|
|
};
|
|
}
|
|
|
|
const groupedByPrefix = {};
|
|
|
|
addressed.forEach(fileName => {
|
|
const prefix = getFilePrefix(fileName);
|
|
if (!groupedByPrefix[prefix]) {
|
|
groupedByPrefix[prefix] = { addressed: [], known: [] };
|
|
}
|
|
groupedByPrefix[prefix].addressed.push(fileName);
|
|
});
|
|
|
|
known.forEach(fileName => {
|
|
const prefix = getFilePrefix(fileName);
|
|
if (!groupedByPrefix[prefix]) {
|
|
groupedByPrefix[prefix] = { addressed: [], known: [] };
|
|
}
|
|
groupedByPrefix[prefix].known.push(fileName);
|
|
});
|
|
|
|
return groupHotfixPrefixes(groupedByPrefix);
|
|
}
|
|
|
|
const transformed = {};
|
|
Object.keys(node).forEach(key => {
|
|
transformed[key] = transformNode(node[key]);
|
|
});
|
|
return transformed;
|
|
}
|
|
|
|
function groupHotfixPrefixes(groupedByPrefix) {
|
|
const byFamily = {};
|
|
|
|
Object.keys(groupedByPrefix).forEach(prefix => {
|
|
const family = getReleaseFamily(prefix);
|
|
if (!byFamily[family]) {
|
|
byFamily[family] = [];
|
|
}
|
|
byFamily[family].push(prefix);
|
|
});
|
|
|
|
const result = {};
|
|
|
|
Object.keys(byFamily).forEach(family => {
|
|
const members = byFamily[family];
|
|
const hasHotfixes = members.length > 1 || members.some(member => member !== family);
|
|
|
|
if (!hasHotfixes && members[0] === family) {
|
|
result[family] = groupedByPrefix[family];
|
|
return;
|
|
}
|
|
|
|
const branch = {};
|
|
members.forEach(member => {
|
|
branch[member] = groupedByPrefix[member];
|
|
});
|
|
result[family] = branch;
|
|
});
|
|
|
|
return result;
|
|
}
|
|
|
|
function getReleaseFamily(prefix) {
|
|
return String(prefix || '').replace(/-h\d+$/i, '');
|
|
}
|
|
|
|
function getFilePrefix(fileName) {
|
|
const baseName = String(fileName || '');
|
|
const underscoreIndex = baseName.indexOf('_');
|
|
if (underscoreIndex <= 0) {
|
|
return baseName.replace(/\.json$/i, '') || 'unknown';
|
|
}
|
|
return baseName.slice(0, underscoreIndex);
|
|
}
|