Improve ref pull comparison UX and fight filtering
- Replace ghost icons (missing buffs in current pull) with green-bordered icons on the REF row, indicating buffs unique to the reference pull - Add shield tooltip to REF row absorbed values showing which shields were active and which are missing in the current pull - Filter same-report and external ref fight dropdowns to only show fights matching the current fight name; current fight excluded from same-report list - Extract FFLogs report code from pasted URLs in the ext-report input field Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
182f24ee93
commit
e5b70c5589
@ -252,6 +252,12 @@
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.aoe-buff-ref-unique {
|
||||
border: 2px solid #3dff6e;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 0 4px #3dff6e;
|
||||
}
|
||||
|
||||
/* ── Target buffs ────────────────────────────────────────────────────────── */
|
||||
.aoe-target-buffs {
|
||||
display: flex;
|
||||
|
||||
@ -201,16 +201,27 @@
|
||||
renderTimeline(lastEvents, lastFightStart);
|
||||
});
|
||||
|
||||
function onFightsLoaded(fights) {
|
||||
let allSameReportFights = [];
|
||||
|
||||
function populateRefFightSelect() {
|
||||
const currentName = (window.App.fights ?? []).find(f => f.id === window.App.fightId)?.name;
|
||||
const visible = allSameReportFights.filter(f =>
|
||||
f.id !== window.App.fightId && (!currentName || f.name === currentName)
|
||||
);
|
||||
refFightSelect.innerHTML = '<option value="">Kein Vergleich</option>';
|
||||
fights.forEach(f => {
|
||||
visible.forEach(f => {
|
||||
const hp = f.kill ? 'Kill' : (f.fightPercentage != null ? f.fightPercentage.toFixed(2) + '%' : '?');
|
||||
const opt = document.createElement('option');
|
||||
opt.value = f.id;
|
||||
opt.textContent = `${f.name} — ${fmtDur(f.endTime - f.startTime)} — ${hp}`;
|
||||
refFightSelect.appendChild(opt);
|
||||
});
|
||||
refFightSelect.style.display = '';
|
||||
refFightSelect.style.display = visible.length ? '' : 'none';
|
||||
}
|
||||
|
||||
function onFightsLoaded(fights) {
|
||||
allSameReportFights = fights;
|
||||
populateRefFightSelect();
|
||||
}
|
||||
|
||||
// ── External report comparison ────────────────────────────────────────────
|
||||
@ -221,6 +232,11 @@
|
||||
const refReportLoad = document.getElementById('ref-report-load');
|
||||
const refExtFightSelect = document.getElementById('ref-ext-fight-select');
|
||||
|
||||
refReportInput.addEventListener('input', () => {
|
||||
const match = refReportInput.value.match(/fflogs\.com\/reports\/([A-Za-z0-9]+)/);
|
||||
if (match) refReportInput.value = match[1];
|
||||
});
|
||||
|
||||
refExtToggle.addEventListener('click', () => {
|
||||
const hidden = refExtPanel.style.display === 'none';
|
||||
refExtPanel.style.display = hidden ? '' : 'none';
|
||||
@ -246,15 +262,17 @@
|
||||
extFights = fights;
|
||||
extReportCode = code;
|
||||
|
||||
const currentName = (window.App.fights ?? []).find(f => f.id === window.App.fightId)?.name;
|
||||
const visibleExt = currentName ? fights.filter(f => f.name === currentName) : fights;
|
||||
refExtFightSelect.innerHTML = '<option value="">— Fight auswählen —</option>';
|
||||
fights.forEach(f => {
|
||||
visibleExt.forEach(f => {
|
||||
const hp = f.kill ? 'Kill' : (f.fightPercentage != null ? f.fightPercentage.toFixed(2) + '%' : '?');
|
||||
const opt = document.createElement('option');
|
||||
opt.value = f.id;
|
||||
opt.textContent = `${f.name} — ${fmtDur(f.endTime - f.startTime)} — ${hp}`;
|
||||
refExtFightSelect.appendChild(opt);
|
||||
});
|
||||
refExtFightSelect.style.display = fights.length ? '' : 'none';
|
||||
refExtFightSelect.style.display = visibleExt.length ? '' : 'none';
|
||||
} catch { }
|
||||
|
||||
refReportLoad.disabled = false;
|
||||
@ -389,12 +407,6 @@
|
||||
return `<img class="aoe-target-buff-icon" src="${iconSrc}" alt="${m.name}" title="${m.name}${dr}">`;
|
||||
}).join('');
|
||||
|
||||
const missingIcons = missingMitigs.map(m => {
|
||||
const iconSrc = MITIG_ICONS[m.name];
|
||||
if (!iconSrc) return '';
|
||||
return `<img class="aoe-target-buff-icon aoe-buff-missing" src="${iconSrc}" alt="${m.name}" title="${m.name} fehlt (war im Referenz-Pull aktiv)">`;
|
||||
}).join('');
|
||||
|
||||
// Shield tooltip on absorbed value
|
||||
const activeShields = (t.mitigations ?? []).filter(m => m.buffType === 'shield');
|
||||
const missingShields = refTarget
|
||||
@ -423,7 +435,7 @@
|
||||
${hpBar}
|
||||
</div>
|
||||
</div>
|
||||
${(mitigIcons || missingIcons) ? `<div class="aoe-target-buffs">${mitigIcons}${missingIcons}</div>` : ''}
|
||||
${mitigIcons ? `<div class="aoe-target-buffs">${mitigIcons}</div>` : ''}
|
||||
</div>`;
|
||||
}).join('');
|
||||
|
||||
@ -457,13 +469,23 @@
|
||||
? `<span class="${diff > 0 ? 'aoe-delta-worse' : 'aoe-delta-better'}">${diff > 0 ? '+' : '-'}${fmtDmg(Math.abs(diff))}</span>`
|
||||
: '';
|
||||
|
||||
const currMitigNames = new Set((curr?.mitigations ?? []).map(m => m.name));
|
||||
|
||||
const refMitigIcons = (t.mitigations ?? []).filter(m => m.buffType === 'buff').map(m => {
|
||||
const iconSrc = MITIG_ICONS[m.name];
|
||||
if (!iconSrc) return '';
|
||||
const dr = m.dr > 0 ? ` −${m.dr}%` : '';
|
||||
return `<img class="aoe-target-buff-icon" src="${iconSrc}" alt="${m.name}" title="${m.name}${dr}">`;
|
||||
const dr = m.dr > 0 ? ` −${m.dr}%` : '';
|
||||
const missing = !currMitigNames.has(m.name);
|
||||
const cls = missing ? ' aoe-buff-ref-unique' : '';
|
||||
const titleSufx = missing ? ' (fehlt im aktuellen Pull)' : '';
|
||||
return `<img class="aoe-target-buff-icon${cls}" src="${iconSrc}" alt="${m.name}" title="${m.name}${dr}${titleSufx}">`;
|
||||
}).join('');
|
||||
|
||||
const refShields = (t.mitigations ?? []).filter(m => m.buffType === 'shield');
|
||||
const refShieldTitle = refShields.length
|
||||
? refShields.map(s => currMitigNames.has(s.name) ? s.name : `${s.name} [fehlt im aktuellen Pull]`).join('\n')
|
||||
: null;
|
||||
|
||||
return `
|
||||
<div class="aoe-target-wrap">
|
||||
<div class="aoe-ref-target${dead ? ' aoe-target--dead' : ''}">
|
||||
@ -472,7 +494,7 @@
|
||||
${deltaHtml}
|
||||
</div>
|
||||
<span class="aoe-target-name">${t.name}</span>
|
||||
<span class="aoe-target-dmg">${fmtDmg(t.amount)}${t.absorbed > 0 ? ` <span class="aoe-target-absorbed">+${fmtDmg(t.absorbed)}</span>` : ''}</span>
|
||||
<span class="aoe-target-dmg">${fmtDmg(t.amount)}${t.absorbed > 0 ? ` <span class="aoe-target-absorbed" title="${refShieldTitle ?? 'Keine erkannten Schilde'}">+${fmtDmg(t.absorbed)}</span>` : ''}</span>
|
||||
</div>
|
||||
${refMitigIcons ? `<div class="aoe-target-buffs">${refMitigIcons}</div>` : ''}
|
||||
</div>`;
|
||||
@ -545,6 +567,7 @@
|
||||
if (json.error) { setEmpty('Fehler: ' + json.error); return; }
|
||||
|
||||
lastFightId = fightId;
|
||||
populateRefFightSelect();
|
||||
setupPhases(window.App?.phases ?? []);
|
||||
renderPlayers(json.players ?? []);
|
||||
renderTimeline(json.aoe_events ?? [], json.fight_start ?? fightStart);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user