feat: v4.2.0 - series blocks (add to all days, delete one/all in series); 37 tests
Some checks failed
Build & Push Docker / build (push) Has been cancelled

This commit is contained in:
2026-02-20 17:58:56 +01:00
parent b91f336c12
commit b494d29790
7 changed files with 165 additions and 12 deletions

View File

@@ -178,7 +178,18 @@ const App = {
this._populateDaySelect(block.date);
this._updateDuration();
document.getElementById('modalDeleteBtn').style.display = 'inline-block';
// Show delete buttons; series delete only if block belongs to a series
document.getElementById('modalDeleteBtn').classList.remove('hidden');
document.getElementById('seriesRow').classList.add('hidden');
const seriesBtn = document.getElementById('modalDeleteSeriesBtn');
if (block.series_id) {
const seriesCount = this.state.blocks.filter(b => b.series_id === block.series_id).length;
seriesBtn.textContent = `Smazat sérii (${seriesCount} bloků)`;
seriesBtn.classList.remove('hidden');
} else {
seriesBtn.classList.add('hidden');
}
document.getElementById('blockModal').classList.remove('hidden');
},
@@ -196,7 +207,12 @@ const App = {
this._populateDaySelect(date);
this._updateDuration();
document.getElementById('modalDeleteBtn').style.display = 'none';
// Hide delete buttons, show series row
document.getElementById('modalDeleteBtn').classList.add('hidden');
document.getElementById('modalDeleteSeriesBtn').classList.add('hidden');
document.getElementById('seriesRow').classList.remove('hidden');
document.getElementById('modalAddToAllDays').checked = false;
document.getElementById('blockModal').classList.remove('hidden');
},
@@ -281,14 +297,32 @@ const App = {
if (!start || !end) { this.toast('Zadejte čas začátku a konce', 'error'); return; }
if (blockId) {
// Edit existing
// Edit existing block (no series expansion on edit — user edits only this one)
const idx = this.state.blocks.findIndex(b => b.id === blockId);
if (idx !== -1) {
Object.assign(this.state.blocks[idx], { date, title, type_id, start, end, responsible, notes });
const existing = this.state.blocks[idx];
Object.assign(this.state.blocks[idx], {
date, title, type_id, start, end, responsible, notes,
series_id: existing.series_id || null
});
}
} else {
// New block
this.state.blocks.push({ id: this.uid(), date, title, type_id, start, end, responsible, notes });
const addToAll = document.getElementById('modalAddToAllDays').checked;
if (addToAll) {
// Add a copy to every day in the event range, all sharing a series_id
const series_id = this.uid();
const dates = this.getDates();
for (const d of dates) {
this.state.blocks.push({ id: this.uid(), date: d, title, type_id, start, end, responsible, notes, series_id });
}
document.getElementById('blockModal').classList.add('hidden');
this.renderCanvas();
this.toast(`Blok přidán do ${dates.length} dnů`, 'success');
return;
} else {
this.state.blocks.push({ id: this.uid(), date, title, type_id, start, end, responsible, notes, series_id: null });
}
}
document.getElementById('blockModal').classList.add('hidden');
@@ -305,6 +339,23 @@ const App = {
this.toast('Blok smazán', 'success');
},
_deleteBlockSeries() {
const blockId = document.getElementById('modalBlockId').value;
if (!blockId) return;
const block = this.state.blocks.find(b => b.id === blockId);
if (!block || !block.series_id) {
// Fallback: delete just this one
this._deleteBlock();
return;
}
const seriesId = block.series_id;
const count = this.state.blocks.filter(b => b.series_id === seriesId).length;
this.state.blocks = this.state.blocks.filter(b => b.series_id !== seriesId);
document.getElementById('blockModal').classList.add('hidden');
this.renderCanvas();
this.toast(`Série smazána (${count} bloků)`, 'success');
},
// ─── Toast ────────────────────────────────────────────────────────
toast(message, type = 'success') {
@@ -376,6 +427,7 @@ const App = {
});
document.getElementById('modalSaveBtn').addEventListener('click', () => this._saveModal());
document.getElementById('modalDeleteBtn').addEventListener('click', () => this._deleteBlock());
document.getElementById('modalDeleteSeriesBtn').addEventListener('click', () => this._deleteBlockSeries());
// Duration ↔ end sync (hours + minutes fields)
const durUpdater = () => {