Merge branch 'toggle-display-of-children-nodes'

This commit is contained in:
Yisroel Baum 2026-04-20 09:43:30 +03:00
commit 70f0574330
Signed by: yisroelbaum
GPG key ID: 0FA60884F75520A9
4 changed files with 97 additions and 7 deletions

View file

@ -0,0 +1,67 @@
describe('Toggle display of child nodes', () => {
beforeEach(() => {
cy.exec('npm run db:seed')
cy.intercept('GET', '/api/texts/0').as('getText')
cy.intercept('GET', '/api/nodes/0').as('getNodes')
cy.visit('/admin/texts/0')
cy.wait('@getText')
cy.wait('@getNodes')
})
afterEach(() => {
cy.exec('npm run db:wipe')
})
it('shows a toggle button on nodes that have children', () => {
cy.get('#text-detail > ul > li')
.first()
.find('button.toggle-children')
.should('exist')
})
it('does not show a toggle button on leaf nodes', () => {
cy.get('#text-detail > ul > li > ul > li > ul > li')
.first()
.find('button.toggle-children')
.should('not.exist')
})
it('root node children are visible on initial load', () => {
cy.get('#text-detail > ul > li > ul > li')
.first()
.should('be.visible')
})
it('grandchildren are hidden on initial load', () => {
cy.get('#text-detail > ul > li > ul > li > ul')
.first()
.should('not.be.visible')
})
it('clicking toggle button on a node shows its children', () => {
cy.get('#text-detail > ul > li > ul > li')
.first()
.find('button.toggle-children')
.click()
cy.get('#text-detail > ul > li > ul > li > ul')
.first()
.should('be.visible')
})
it('clicking toggle button again hides children', () => {
cy.get('#text-detail > ul > li > ul > li')
.first()
.find('button.toggle-children')
.click()
cy.get('#text-detail > ul > li > ul > li > ul')
.first()
.should('be.visible')
cy.get('#text-detail > ul > li > ul > li')
.first()
.find('button.toggle-children')
.click()
cy.get('#text-detail > ul > li > ul > li > ul')
.first()
.should('not.be.visible')
})
})

View file

@ -3,23 +3,29 @@
$texts = [ $texts = [
[ [
'id' => 0, 'id' => 0,
'name' => 'test text', 'name' => 'Tanach',
], ],
]; ];
$nodes = [ $nodes = [
[ [
'id' => 0, 'id' => 0,
'title' => 'Chapter 1', 'title' => 'Tanach',
'textId' => 0, 'textId' => 0,
'parentNodeId' => null, 'parentNodeId' => null,
], ],
[ [
'id' => 1, 'id' => 1,
'title' => 'Section 1.1', 'title' => 'Torah',
'textId' => 0, 'textId' => 0,
'parentNodeId' => 0, 'parentNodeId' => 0,
], ],
[
'id' => 2,
'title' => 'Bereishis',
'textId' => 0,
'parentNodeId' => 1,
],
]; ];
$fileDataMap = [ $fileDataMap = [

View file

@ -6,7 +6,7 @@ $files = [
]; ];
foreach ($files as $file) { foreach ($files as $file) {
echo __DIR__ . "/$file"; echo __DIR__ . "/$file\n";
$path = __DIR__ . "/$file"; $path = __DIR__ . "/$file";
file_put_contents($path, json_encode([], JSON_PRETTY_PRINT)); file_put_contents($path, json_encode([], JSON_PRETTY_PRINT));
} }

View file

@ -43,7 +43,7 @@ function buildTree(nodes) {
return roots; return roots;
} }
function renderTree(nodes, textId) { function renderTree(nodes, textId, depth = 0) {
const ul = document.createElement('ul'); const ul = document.createElement('ul');
nodes.forEach(node => { nodes.forEach(node => {
const li = document.createElement('li'); const li = document.createElement('li');
@ -61,11 +61,28 @@ function renderTree(nodes, textId) {
const bulkBtn = document.createElement('button'); const bulkBtn = document.createElement('button');
bulkBtn.textContent = 'Bulk add children'; bulkBtn.textContent = 'Bulk add children';
bulkBtn.className = 'bulk-add-children'; bulkBtn.className = 'bulk-add-children';
bulkBtn.addEventListener('click', () => toggleBulkAddForm(li, node.id, textId)); bulkBtn.addEventListener(
'click',
() => toggleBulkAddForm(li, node.id, textId)
);
li.appendChild(bulkBtn); li.appendChild(bulkBtn);
if (node.children.length > 0) { if (node.children.length > 0) {
li.appendChild(renderTree(node.children, textId)); const childUl = renderTree(node.children, textId, depth + 1);
const childrenVisible = depth === 0;
childUl.style.display = childrenVisible ? '' : 'none';
const toggleBtn = document.createElement('button');
toggleBtn.className = 'toggle-children';
toggleBtn.textContent = childrenVisible ? '▼' : '▶';
toggleBtn.addEventListener('click', () => {
const isHidden = childUl.style.display === 'none';
childUl.style.display = isHidden ? '' : 'none';
toggleBtn.textContent = isHidden ? '▼' : '▶';
});
li.appendChild(toggleBtn);
li.appendChild(childUl);
} }
ul.appendChild(li); ul.appendChild(li);