'use strict'; module.exports = { getProgressPaths(rows) { const nodes = new Map(rows.map(row => [String(row.tree_id), row])); const paths = new Map(); for (const row of rows) { const path = []; const visited = new Set(); let node = row; while (node && !visited.has(String(node.tree_id))) { path.unshift(node); visited.add(String(node.tree_id)); node = nodes.get(String(node.tree_pid)); } paths.set(row.id, path); } return paths; }, sortProgressRows(rows, paths) { return rows.slice().sort((a, b) => { const pathA = paths.get(a.id); const pathB = paths.get(b.id); for (let i = 0; i < Math.min(pathA.length, pathB.length); i++) { if (pathA[i].id === pathB[i].id) continue; return pathA[i].tree_order - pathB[i].tree_order || String(pathA[i].id).localeCompare(String(pathB[i].id)); } return pathA.length - pathB.length; }); }, formatProgressPath(path, abbreviated = false) { const names = path.map(node => node.name); if (abbreviated && names.length > 2) return [names[0], '...', names[names.length - 1]].join(' / '); return names.join(' / '); }, };