forked from xziino/ff14-mitigator
Merge pull request 'akus_schabernack2' (#2) from akurosia/ff14-mitigator:akus_schabernack2 into master
Reviewed-on: xziino/ff14-mitigator#2
This commit is contained in:
commit
cc36aa27c4
@ -333,6 +333,7 @@ if (!empty($shieldStatusIds)) {
|
|||||||
// Group events by abilityId, then cluster by time proximity (≤ 1000ms from
|
// Group events by abilityId, then cluster by time proximity (≤ 1000ms from
|
||||||
// the first event in the cluster) to avoid fixed-window boundary splits.
|
// the first event in the cluster) to avoid fixed-window boundary splits.
|
||||||
const CLUSTER_WINDOW_MS = 1000;
|
const CLUSTER_WINDOW_MS = 1000;
|
||||||
|
const HEAVY_TANKBUSTER_MIN_HP_RATIO = 0.33;
|
||||||
|
|
||||||
$byAbility = []; // abilityId → [{ts, tgtId, amount, hp, maxHp, buffs, name}]
|
$byAbility = []; // abilityId → [{ts, tgtId, amount, hp, maxHp, buffs, name}]
|
||||||
foreach ($allEvents as $ev) {
|
foreach ($allEvents as $ev) {
|
||||||
@ -404,7 +405,26 @@ foreach ($byAbility as $abId => $events) {
|
|||||||
|
|
||||||
$aoeEvents = [];
|
$aoeEvents = [];
|
||||||
foreach ($clusters as $group) {
|
foreach ($clusters as $group) {
|
||||||
if (count($group['targets']) < 3) continue;
|
$targetCount = count($group['targets']);
|
||||||
|
$isHeavyTankbuster = false;
|
||||||
|
if ($targetCount < 3) {
|
||||||
|
foreach ($group['targets'] as $tgtId => $tgt) {
|
||||||
|
$p = $players[$tgtId] ?? null;
|
||||||
|
if (($p['role'] ?? null) !== 'tank') continue;
|
||||||
|
|
||||||
|
$tankMaxHp = (int)($tgt['maxHp'] ?? 0);
|
||||||
|
$rawDamage = max(
|
||||||
|
(int)($tgt['unmitigatedAmount'] ?? 0),
|
||||||
|
(int)($tgt['amount'] ?? 0) + (int)($tgt['absorbed'] ?? 0) + (int)($tgt['mitigated'] ?? 0)
|
||||||
|
);
|
||||||
|
if ($tankMaxHp > 0 && $rawDamage >= $tankMaxHp * HEAVY_TANKBUSTER_MIN_HP_RATIO) {
|
||||||
|
$isHeavyTankbuster = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($targetCount < 3 && !$isHeavyTankbuster) continue;
|
||||||
|
|
||||||
$targets = [];
|
$targets = [];
|
||||||
foreach ($group['targets'] as $tgtId => $tgt) {
|
foreach ($group['targets'] as $tgtId => $tgt) {
|
||||||
@ -443,11 +463,12 @@ foreach ($clusters as $group) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
$aoeEvents[] = [
|
$aoeEvents[] = [
|
||||||
'timestamp' => $group['timestamp'],
|
'timestamp' => $group['timestamp'],
|
||||||
'abilityId' => $group['abilityId'],
|
'abilityId' => $group['abilityId'],
|
||||||
'abilityName' => $group['abilityName'],
|
'abilityName' => $group['abilityName'],
|
||||||
'targets' => $targets,
|
'targets' => $targets,
|
||||||
'totalDamage' => array_sum(array_column($targets, 'amount')),
|
'totalDamage' => array_sum(array_column($targets, 'amount')),
|
||||||
|
'isHeavyTankbuster' => $isHeavyTankbuster,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
usort($aoeEvents, fn($a, $b) => $a['timestamp'] <=> $b['timestamp']);
|
usort($aoeEvents, fn($a, $b) => $a['timestamp'] <=> $b['timestamp']);
|
||||||
|
|||||||
@ -2,10 +2,17 @@
|
|||||||
require_once __DIR__ . '/../config.php';
|
require_once __DIR__ . '/../config.php';
|
||||||
session_start_safe();
|
session_start_safe();
|
||||||
|
|
||||||
|
function redirect_with_error(string $returnPath, string $error): void {
|
||||||
|
$separator = str_contains($returnPath, '?') ? '&' : '?';
|
||||||
|
header('Location: ' . $returnPath . $separator . 'error=' . rawurlencode($error));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$returnPath = safe_return_path($_SESSION['oauth_return'] ?? null);
|
||||||
|
|
||||||
// user denied access
|
// user denied access
|
||||||
if (isset($_GET['error'])) {
|
if (isset($_GET['error'])) {
|
||||||
header('Location: ../index.php?error=' . urlencode($_GET['error']));
|
redirect_with_error($returnPath, $_GET['error']);
|
||||||
exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CSRF check
|
// CSRF check
|
||||||
@ -21,12 +28,11 @@ if (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (empty($_GET['code'])) {
|
if (empty($_GET['code'])) {
|
||||||
header('Location: ../index.php?error=missing_code');
|
redirect_with_error($returnPath, 'missing_code');
|
||||||
exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$verifier = $_SESSION['pkce_verifier'];
|
$verifier = $_SESSION['pkce_verifier'];
|
||||||
unset($_SESSION['pkce_verifier'], $_SESSION['oauth_state']);
|
unset($_SESSION['pkce_verifier'], $_SESSION['oauth_state'], $_SESSION['oauth_return']);
|
||||||
|
|
||||||
$post = http_build_query([
|
$post = http_build_query([
|
||||||
'grant_type' => 'authorization_code',
|
'grant_type' => 'authorization_code',
|
||||||
@ -56,12 +62,11 @@ if ($curlError || $status !== 200 || empty($data['access_token'])) {
|
|||||||
'http_status' => $status,
|
'http_status' => $status,
|
||||||
'response_body' => $body,
|
'response_body' => $body,
|
||||||
];
|
];
|
||||||
header('Location: ../index.php?error=token_failed');
|
redirect_with_error($returnPath, 'token_failed');
|
||||||
exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$_SESSION['access_token'] = $data['access_token'];
|
$_SESSION['access_token'] = $data['access_token'];
|
||||||
$_SESSION['token_expires'] = time() + ($data['expires_in'] ?? 3600);
|
$_SESSION['token_expires'] = time() + ($data['expires_in'] ?? 3600);
|
||||||
|
|
||||||
header('Location: ../index.php');
|
header('Location: ' . $returnPath);
|
||||||
exit;
|
exit;
|
||||||
|
|||||||
@ -8,6 +8,7 @@ $state = bin2hex(random_bytes(16));
|
|||||||
|
|
||||||
$_SESSION['pkce_verifier'] = $verifier;
|
$_SESSION['pkce_verifier'] = $verifier;
|
||||||
$_SESSION['oauth_state'] = $state;
|
$_SESSION['oauth_state'] = $state;
|
||||||
|
$_SESSION['oauth_return'] = safe_return_path($_GET['return'] ?? ($_SERVER['HTTP_REFERER'] ?? null));
|
||||||
|
|
||||||
$params = http_build_query([
|
$params = http_build_query([
|
||||||
'response_type' => 'code',
|
'response_type' => 'code',
|
||||||
|
|||||||
@ -77,6 +77,20 @@
|
|||||||
return `${min}:${sec}`;
|
return `${min}:${sec}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeFightName(name) {
|
||||||
|
return String(name ?? '').trim().toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
function currentFightName() {
|
||||||
|
const fight = (window.App?.fights ?? []).find(f => f.id === window.App?.fightId);
|
||||||
|
return normalizeFightName(fight?.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSameFightName(fight) {
|
||||||
|
const name = currentFightName();
|
||||||
|
return name !== '' && normalizeFightName(fight?.name) === name;
|
||||||
|
}
|
||||||
|
|
||||||
let hiddenPlayers = new Set();
|
let hiddenPlayers = new Set();
|
||||||
let hiddenPlayerNames = new Set();
|
let hiddenPlayerNames = new Set();
|
||||||
let lastEvents = [];
|
let lastEvents = [];
|
||||||
@ -265,7 +279,7 @@
|
|||||||
let allSameReportFights = [];
|
let allSameReportFights = [];
|
||||||
|
|
||||||
function populateRefFightSelect() {
|
function populateRefFightSelect() {
|
||||||
const visible = allSameReportFights.filter(f => f.id !== window.App.fightId);
|
const visible = allSameReportFights.filter(f => f.id !== window.App.fightId && isSameFightName(f));
|
||||||
refFightSelect.innerHTML = '<option value="">Kein Vergleich</option>';
|
refFightSelect.innerHTML = '<option value="">Kein Vergleich</option>';
|
||||||
visible.forEach(f => {
|
visible.forEach(f => {
|
||||||
const hp = f.kill ? 'Kill' : (f.fightPercentage != null ? f.fightPercentage.toFixed(2) + '%' : '?');
|
const hp = f.kill ? 'Kill' : (f.fightPercentage != null ? f.fightPercentage.toFixed(2) + '%' : '?');
|
||||||
@ -288,8 +302,22 @@
|
|||||||
const refExtPanel = document.getElementById('ref-ext-panel');
|
const refExtPanel = document.getElementById('ref-ext-panel');
|
||||||
const refReportInput = document.getElementById('ref-report-input');
|
const refReportInput = document.getElementById('ref-report-input');
|
||||||
const refReportLoad = document.getElementById('ref-report-load');
|
const refReportLoad = document.getElementById('ref-report-load');
|
||||||
|
const refFflogsLink = document.getElementById('ref-fflogs-report-link');
|
||||||
const refExtFightSelect = document.getElementById('ref-ext-fight-select');
|
const refExtFightSelect = document.getElementById('ref-ext-fight-select');
|
||||||
|
|
||||||
|
function updateRefFflogsLink(fightId = 0) {
|
||||||
|
if (!extReportCode) {
|
||||||
|
refFflogsLink.style.display = 'none';
|
||||||
|
refFflogsLink.href = '#';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
refFflogsLink.href = window.App?.fflogsReportUrl
|
||||||
|
? window.App.fflogsReportUrl(extReportCode, fightId)
|
||||||
|
: `https://www.fflogs.com/reports/${encodeURIComponent(extReportCode)}${fightId ? `#fight=${fightId}` : ''}`;
|
||||||
|
refFflogsLink.style.display = '';
|
||||||
|
}
|
||||||
|
|
||||||
refReportInput.addEventListener('input', () => {
|
refReportInput.addEventListener('input', () => {
|
||||||
const match = refReportInput.value.match(/fflogs\.com\/reports\/([A-Za-z0-9]+)/);
|
const match = refReportInput.value.match(/fflogs\.com\/reports\/([A-Za-z0-9]+)/);
|
||||||
if (match) refReportInput.value = match[1];
|
if (match) refReportInput.value = match[1];
|
||||||
@ -313,13 +341,14 @@
|
|||||||
body: new URLSearchParams({ report_code: code, language: window.App.language }),
|
body: new URLSearchParams({ report_code: code, language: window.App.language }),
|
||||||
});
|
});
|
||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
if (json.reauth) { window.location.href = 'auth/start.php'; return; }
|
if (json.reauth) { window.location.href = window.App?.authStartUrl?.() ?? 'auth/start.php'; return; }
|
||||||
|
|
||||||
const fights = json?.data?.reportData?.report?.fights ?? [];
|
const fights = json?.data?.reportData?.report?.fights ?? [];
|
||||||
extFights = fights;
|
extFights = fights;
|
||||||
extReportCode = code;
|
extReportCode = code;
|
||||||
|
updateRefFflogsLink();
|
||||||
|
|
||||||
const visibleExt = fights;
|
const visibleExt = fights.filter(isSameFightName);
|
||||||
refExtFightSelect.innerHTML = '<option value="">— Fight auswählen —</option>';
|
refExtFightSelect.innerHTML = '<option value="">— Fight auswählen —</option>';
|
||||||
visibleExt.forEach(f => {
|
visibleExt.forEach(f => {
|
||||||
const hp = f.kill ? 'Kill' : (f.fightPercentage != null ? f.fightPercentage.toFixed(2) + '%' : '?');
|
const hp = f.kill ? 'Kill' : (f.fightPercentage != null ? f.fightPercentage.toFixed(2) + '%' : '?');
|
||||||
@ -330,8 +359,9 @@
|
|||||||
});
|
});
|
||||||
refExtFightSelect.style.display = visibleExt.length ? '' : 'none';
|
refExtFightSelect.style.display = visibleExt.length ? '' : 'none';
|
||||||
refExtPanel.style.display = '';
|
refExtPanel.style.display = '';
|
||||||
if (preferredFightId) {
|
if (preferredFightId && visibleExt.some(f => f.id === preferredFightId)) {
|
||||||
refExtFightSelect.value = String(preferredFightId);
|
refExtFightSelect.value = String(preferredFightId);
|
||||||
|
updateRefFflogsLink(preferredFightId);
|
||||||
await loadExternalCompare(preferredFightId);
|
await loadExternalCompare(preferredFightId);
|
||||||
}
|
}
|
||||||
} catch { }
|
} catch { }
|
||||||
@ -392,7 +422,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
refExtFightSelect.addEventListener('change', async () => {
|
refExtFightSelect.addEventListener('change', async () => {
|
||||||
await loadExternalCompare(parseInt(refExtFightSelect.value, 10));
|
const refId = parseInt(refExtFightSelect.value, 10) || 0;
|
||||||
|
updateRefFflogsLink(refId);
|
||||||
|
await loadExternalCompare(refId);
|
||||||
});
|
});
|
||||||
|
|
||||||
// ── Timeline rendering ────────────────────────────────────────────────────
|
// ── Timeline rendering ────────────────────────────────────────────────────
|
||||||
@ -427,6 +459,7 @@
|
|||||||
!hiddenPlayers.has(t.id) &&
|
!hiddenPlayers.has(t.id) &&
|
||||||
(!playerFilter || t.name.toLowerCase().includes(playerFilter))
|
(!playerFilter || t.name.toLowerCase().includes(playerFilter))
|
||||||
);
|
);
|
||||||
|
if (ev.isHeavyTankbuster && !visibleTargets.some(t => t.role === 'tank')) return '';
|
||||||
if (!visibleTargets.length) return '';
|
if (!visibleTargets.length) return '';
|
||||||
|
|
||||||
// Collect boss debuffs (Reprisal/Feint/Addle) once at event level
|
// Collect boss debuffs (Reprisal/Feint/Addle) once at event level
|
||||||
@ -643,7 +676,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json.reauth) { window.location.href = 'auth/start.php'; return; }
|
if (json.reauth) { window.location.href = window.App?.authStartUrl?.() ?? 'auth/start.php'; return; }
|
||||||
if (json.error) { setEmpty('Fehler: ' + json.error); return; }
|
if (json.error) { setEmpty('Fehler: ' + json.error); return; }
|
||||||
|
|
||||||
lastFightId = fightId;
|
lastFightId = fightId;
|
||||||
@ -698,6 +731,8 @@
|
|||||||
refFightSelect.style.display = 'none';
|
refFightSelect.style.display = 'none';
|
||||||
refExtFightSelect.value = '';
|
refExtFightSelect.value = '';
|
||||||
refExtFightSelect.style.display = 'none';
|
refExtFightSelect.style.display = 'none';
|
||||||
|
refFflogsLink.style.display = 'none';
|
||||||
|
refFflogsLink.href = '#';
|
||||||
refExtPanel.style.display = 'none';
|
refExtPanel.style.display = 'none';
|
||||||
const exportBtn = document.getElementById('export-to-planner-btn');
|
const exportBtn = document.getElementById('export-to-planner-btn');
|
||||||
if (exportBtn) exportBtn.style.display = 'none';
|
if (exportBtn) exportBtn.style.display = 'none';
|
||||||
|
|||||||
39
js/app.js
39
js/app.js
@ -7,6 +7,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
const initialHint = document.getElementById('initial-hint');
|
const initialHint = document.getElementById('initial-hint');
|
||||||
const fightSelectCard = document.getElementById('fight-select-card');
|
const fightSelectCard = document.getElementById('fight-select-card');
|
||||||
const fightSelect = document.getElementById('fight-select');
|
const fightSelect = document.getElementById('fight-select');
|
||||||
|
const fflogsReportLink = document.getElementById('fflogs-report-link');
|
||||||
const languageSelect = document.getElementById('language-select');
|
const languageSelect = document.getElementById('language-select');
|
||||||
const explorerCard = document.getElementById('event-explorer-card');
|
const explorerCard = document.getElementById('event-explorer-card');
|
||||||
const exLoadBtn = document.getElementById('ex-load-btn');
|
const exLoadBtn = document.getElementById('ex-load-btn');
|
||||||
@ -59,6 +60,36 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
}
|
}
|
||||||
window.App.setUrlState = setUrlState;
|
window.App.setUrlState = setUrlState;
|
||||||
|
|
||||||
|
function authStartUrl() {
|
||||||
|
return 'auth/start.php?return=' + encodeURIComponent(window.location.pathname + window.location.search);
|
||||||
|
}
|
||||||
|
window.App.authStartUrl = authStartUrl;
|
||||||
|
|
||||||
|
function fflogsReportUrl(reportCode, fightId = 0) {
|
||||||
|
const code = String(reportCode || '').trim();
|
||||||
|
if (!code) return '#';
|
||||||
|
|
||||||
|
const host = {
|
||||||
|
de: 'de.fflogs.com',
|
||||||
|
fr: 'fr.fflogs.com',
|
||||||
|
jp: 'ja.fflogs.com',
|
||||||
|
}[window.App.language] ?? 'www.fflogs.com';
|
||||||
|
const fight = parseInt(fightId, 10) || 0;
|
||||||
|
return `https://${host}/reports/${encodeURIComponent(code)}${fight ? `#fight=${fight}` : ''}`;
|
||||||
|
}
|
||||||
|
window.App.fflogsReportUrl = fflogsReportUrl;
|
||||||
|
|
||||||
|
function updateFflogsReportLink() {
|
||||||
|
if (!window.App.reportCode) {
|
||||||
|
fflogsReportLink.style.display = 'none';
|
||||||
|
fflogsReportLink.href = '#';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fflogsReportLink.href = fflogsReportUrl(window.App.reportCode, window.App.fightId);
|
||||||
|
fflogsReportLink.style.display = '';
|
||||||
|
}
|
||||||
|
|
||||||
const initialUrlState = getUrlState();
|
const initialUrlState = getUrlState();
|
||||||
const storedLanguage = localStorage.getItem('ff14-mitigator-language');
|
const storedLanguage = localStorage.getItem('ff14-mitigator-language');
|
||||||
const legacyTranslateLanguage = initialUrlState.translate === '1' ? 'de' : 'en';
|
const legacyTranslateLanguage = initialUrlState.translate === '1' ? 'de' : 'en';
|
||||||
@ -114,6 +145,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
window.App.fightStart = fight.startTime;
|
window.App.fightStart = fight.startTime;
|
||||||
window.App.fightEnd = fight.endTime;
|
window.App.fightEnd = fight.endTime;
|
||||||
window.App.phases = buildPhases(fight);
|
window.App.phases = buildPhases(fight);
|
||||||
|
updateFflogsReportLink();
|
||||||
|
|
||||||
displayFight(fight);
|
displayFight(fight);
|
||||||
explorerCard.style.display = 'block';
|
explorerCard.style.display = 'block';
|
||||||
@ -210,7 +242,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
body: new URLSearchParams(params),
|
body: new URLSearchParams(params),
|
||||||
});
|
});
|
||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
if (json.reauth) { window.location.href = 'auth/start.php'; return; }
|
if (json.reauth) { window.location.href = authStartUrl(); return; }
|
||||||
output.textContent = JSON.stringify(json, null, 2);
|
output.textContent = JSON.stringify(json, null, 2);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
output.textContent = '// Fehler: ' + err.message;
|
output.textContent = '// Fehler: ' + err.message;
|
||||||
@ -224,6 +256,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
fightSelectCard.style.display = 'none';
|
fightSelectCard.style.display = 'none';
|
||||||
explorerCard.style.display = 'none';
|
explorerCard.style.display = 'none';
|
||||||
fightSelect.innerHTML = '<option value="">— Fight auswählen —</option>';
|
fightSelect.innerHTML = '<option value="">— Fight auswählen —</option>';
|
||||||
|
fflogsReportLink.style.display = 'none';
|
||||||
|
fflogsReportLink.href = '#';
|
||||||
allFights = [];
|
allFights = [];
|
||||||
|
|
||||||
window.App.reportCode = reportCode;
|
window.App.reportCode = reportCode;
|
||||||
@ -258,7 +292,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
|
|
||||||
if (json.reauth) {
|
if (json.reauth) {
|
||||||
output.textContent = '// session expired — redirecting...';
|
output.textContent = '// session expired — redirecting...';
|
||||||
setTimeout(() => { window.location.href = 'auth/start.php'; }, 1500);
|
setTimeout(() => { window.location.href = authStartUrl(); }, 1500);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,6 +325,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
|
|
||||||
window.App.fights = allFights;
|
window.App.fights = allFights;
|
||||||
fightSelectCard.style.display = 'block';
|
fightSelectCard.style.display = 'block';
|
||||||
|
updateFflogsReportLink();
|
||||||
window.analysisTab?.onFightsLoaded?.(allFights);
|
window.analysisTab?.onFightsLoaded?.(allFights);
|
||||||
|
|
||||||
if (preferredFightId && selectFight(preferredFightId, true)) return;
|
if (preferredFightId && selectFight(preferredFightId, true)) return;
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
<div class="card section-gap" id="fight-select-card" style="display:none">
|
<div class="card section-gap" id="fight-select-card" style="display:none">
|
||||||
<div class="card-title">Fight auswählen</div>
|
<div class="card-title-row">
|
||||||
|
<div class="card-title">Fight auswählen</div>
|
||||||
|
<a id="fflogs-report-link" class="btn btn-sm" href="#" target="_blank" rel="noopener" style="display:none;text-decoration:none;margin-left:auto">FFLogs öffnen</a>
|
||||||
|
</div>
|
||||||
<select id="fight-select">
|
<select id="fight-select">
|
||||||
<option value="">— Fight auswählen —</option>
|
<option value="">— Fight auswählen —</option>
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
@ -21,7 +21,7 @@
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<a href="auth/start.php" class="btn btn-gold btn-login">
|
<a href="<?= htmlspecialchars(auth_start_href(), ENT_QUOTES) ?>" class="btn btn-gold btn-login">
|
||||||
<?= $tokenExpired ? 'Reconnect to FFLogs' : 'Connect to FFLogs' ?>
|
<?= $tokenExpired ? 'Reconnect to FFLogs' : 'Connect to FFLogs' ?>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,7 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-gold" type="submit" style="align-self:flex-end">Fetch</button>
|
<button class="btn btn-gold" type="submit" style="align-self:flex-end">Fetch</button>
|
||||||
<a class="btn" href="auth/start.php" style="align-self:flex-end;text-decoration:none">Reconnect</a>
|
<a class="btn" href="<?= htmlspecialchars(auth_start_href(), ENT_QUOTES) ?>" style="align-self:flex-end;text-decoration:none">Reconnect</a>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
<div id="ref-ext-panel" style="display:none">
|
<div id="ref-ext-panel" style="display:none">
|
||||||
<input type="text" id="ref-report-input" class="ref-report-input" placeholder="Report-Code">
|
<input type="text" id="ref-report-input" class="ref-report-input" placeholder="Report-Code">
|
||||||
<button id="ref-report-load" class="btn btn-sm">Laden</button>
|
<button id="ref-report-load" class="btn btn-sm">Laden</button>
|
||||||
|
<a id="ref-fflogs-report-link" class="btn btn-sm" href="#" target="_blank" rel="noopener" style="display:none;text-decoration:none">FFLogs öffnen</a>
|
||||||
<select id="ref-ext-fight-select" class="filter-input" style="display:none">
|
<select id="ref-ext-fight-select" class="filter-input" style="display:none">
|
||||||
<option value="">— Fight auswählen —</option>
|
<option value="">— Fight auswählen —</option>
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user