49 lines
2.2 KiB
JavaScript
49 lines
2.2 KiB
JavaScript
import { esc } from './esc.js';
|
||
import { fs } from './fs.js';
|
||
|
||
function renderNode(node, depth) {
|
||
const isGroup = node.kind !== 'file';
|
||
const padding = depth * 4;
|
||
const name = esc(node.name);
|
||
const action = isGroup
|
||
? `<button class="tree-name tree-group tree-${node.kind}" style="padding-left:${padding}ch" data-toggle="${node.id}" `
|
||
+ `aria-expanded="${node.expanded}"><span class="tree-chevron">${node.expanded ? '▼' : '▶'}</span>${name}</button>`
|
||
: `<span class="tree-name" style="padding-left:${padding}ch">${name}</span>`;
|
||
const indent = isGroup ? '' : ` style="padding-left:${padding}ch"`;
|
||
const remove = `<button class="remove-btn" type="button" data-remove="${node.id}" aria-label="Удалить ${name}">×</button>`;
|
||
const row = `<tr class="tree-row tree-${node.kind}"><td${indent}>${action}</td>`
|
||
+ `<td>${node.kind === 'file' ? fs(node.file.size) : ''}</td>`
|
||
+ `<td>${node.error ? esc(node.error) : node.kind === 'file' ? 'готов' : ''}</td><td>${remove}</td></tr>`;
|
||
if (!isGroup || !node.expanded) return row;
|
||
return row + node.children.map((child) => renderNode(child, depth + 1)).join('');
|
||
}
|
||
|
||
export function render(state, elements) {
|
||
elements.tableBodyEl.innerHTML = state.nodes.length
|
||
? state.nodes.map((node) => renderNode(node, 0)).join('')
|
||
: '<tr><td colspan="4">Нет выбранных файлов</td></tr>';
|
||
const files = [];
|
||
const visit = (node) => {
|
||
if (node.kind === 'file') files.push(node);
|
||
else node.children.forEach(visit);
|
||
};
|
||
state.nodes.forEach(visit);
|
||
elements.countEl.textContent = `${files.length} файлов · ${fs(files.reduce((sum, node) => sum + node.file.size, 0))}`;
|
||
}
|
||
|
||
export function findNode(nodes, id, parent = null) {
|
||
for (const node of nodes) {
|
||
if (node.id === id) return { node, parent, nodes };
|
||
const found = findNode(node.children || [], id, node);
|
||
if (found) return found;
|
||
}
|
||
return null;
|
||
}
|
||
|
||
export function flattenFiles(nodes, result = []) {
|
||
nodes.forEach((node) => {
|
||
if (node.kind === 'file') result.push({ path: node.path, name: node.name, size: node.file.size, file: node.file });
|
||
else flattenFiles(node.children, result);
|
||
});
|
||
return result;
|
||
} |