From 64aeb1b47ed2a9308a6ac8b627d4b84a28737853 Mon Sep 17 00:00:00 2001 From: Mark Rapson Date: Thu, 15 Oct 2026 02:23:26 +0100 Subject: [PATCH] Remove playlist items with their group --- CHANGELOG.md | 1 + .../public/js/playlists/playlist-schedule.js | 17 +---------- test/playlists-duplicate.test.js | 28 +++++++++++++++++++ 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9931c3..2ee188c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file. ### Changed +- Removing a playlist group now removes all of its member slides. - Replaced the canvas-size duplicate action with reversible disable/enable controls. Disabled sizes remain assigned to existing templates and playlists but cannot be selected for new ones. ## 2.15.2 - 2026-10-15 diff --git a/src/web/public/js/playlists/playlist-schedule.js b/src/web/public/js/playlists/playlist-schedule.js index 9127982..4930cda 100644 --- a/src/web/public/js/playlists/playlist-schedule.js +++ b/src/web/public/js/playlists/playlist-schedule.js @@ -2895,22 +2895,7 @@ } var groupKey = String(header.getAttribute('data-group-key') || ''); getGroupRows(groupKey).forEach(function (row) { - var keyField = row.querySelector('[data-playlist-group-key]'); - var nameField = row.querySelector('[data-playlist-group-name-value]'); - var pickField = row.querySelector('[data-playlist-group-pick-count-value]'); - var rulesField = row.querySelector('[data-playlist-group-schedule-rules]'); - if (keyField) keyField.value = ''; - if (nameField) nameField.value = ''; - if (pickField) pickField.value = '1'; - var shuffleField = row.querySelector('[data-playlist-group-shuffle-value]'); - if (shuffleField) shuffleField.value = '0'; - var modeField = row.querySelector('[data-playlist-group-mode-value]'); - var repeatField = row.querySelector('[data-playlist-group-repeat-count-value]'); - if (modeField) modeField.value = 'select'; - if (repeatField) repeatField.value = '1'; - if (rulesField) rulesField.value = '[]'; - row.setAttribute('data-group-key', ''); - row.classList.remove('playlist-group-child'); + row.remove(); }); header.remove(); updateRowOrder(true); diff --git a/test/playlists-duplicate.test.js b/test/playlists-duplicate.test.js index 6d015a4..50146fb 100644 --- a/test/playlists-duplicate.test.js +++ b/test/playlists-duplicate.test.js @@ -105,6 +105,34 @@ test('playlist group colours differ, survive reorder, and clear on ungrouped sli assert.equal(firstMember.style['--playlist-group-bg'], undefined); }); +test('removing a playlist group removes all of its member rows', () => { + const source = fs.readFileSync(path.join(__dirname, '..', 'src', 'web', 'public', 'js', 'playlists', 'playlist-schedule.js'), 'utf8'); + const functionSource = source.match(/function removePlaylistGroup\(header\) \{[\s\S]*?\n \}/)[0]; + const removedRows = []; + let removedHeader = false; + let refreshedOrder = false; + const rows = [0, 1, 2].map((index) => ({ remove() { removedRows.push(index); } })); + const header = { + getAttribute(name) { return name === 'data-group-key' ? 'group-1' : null; }, + remove() { removedHeader = true; } + }; + const removeGroup = require('node:vm').runInNewContext('(' + functionSource + ')', { + getGroupRows(groupKey) { + assert.equal(groupKey, 'group-1'); + return rows; + }, + updateRowOrder(refresh) { + refreshedOrder = refresh; + } + }); + + removeGroup(header); + + assert.deepEqual(removedRows, [0, 1, 2]); + assert.equal(removedHeader, true); + assert.equal(refreshedOrder, true); +}); + test('empty playlist groups keep a drop area until a member is added', () => { const source = fs.readFileSync(path.join(__dirname, '..', 'src', 'web', 'public', 'js', 'playlists', 'playlist-schedule.js'), 'utf8'); const functionSource = source.match(/function updatePlaylistGroupEmptyRows\(\) \{[\s\S]*?\n \}/)[0];