PDF link target=_blank + nginx timeouts + priority filteri (samo s podacima)
nginx (sport.rinet.one): - proxy_read_timeout 60s → 300s - proxy_send_timeout 300s - proxy_buffering off (PDF stream) - client_max_body_size 50M → 100M Endpoints: - /api/v2/klubovi/financirani: +with_data filter (samo s potporama/godišnjakom/HNS) - /api/v2/sportasi/filtered: +samo_priority +samo_s_hns Frontend: - PDF link target=_blank rel=noopener - window._klub_only_priority = true (default) - window._sportas_only_priority = true (default) DB View: - pgz_sport.v_nogomet_priority (prima_potpore, u_godisnjaku, ima_hns_roster)
This commit is contained in:
+64
-15
@@ -69,19 +69,45 @@
|
||||
const $ = (s, root) => (root||document).querySelector(s);
|
||||
const esc = s => String(s==null?'':s).replace(/[&<>"']/g, m => ({'&':'&','<':'<','>':'>','"':'"',"'":'''}[m]));
|
||||
|
||||
// Tracks the currently-loaded user (null = guest). Set by setUserDisplay().
|
||||
let _currentUser = null;
|
||||
|
||||
function readToken(){
|
||||
try { return localStorage.getItem('jwt') || localStorage.getItem('access_token') || ''; }
|
||||
catch(e){ return ''; }
|
||||
}
|
||||
function logout(){
|
||||
if(!confirm('Odjava iz aplikacije?')) return;
|
||||
try {
|
||||
localStorage.removeItem('jwt');
|
||||
localStorage.removeItem('access_token');
|
||||
localStorage.removeItem('app-role');
|
||||
return localStorage.getItem('pgz_access')
|
||||
|| sessionStorage.getItem('pgz_access')
|
||||
|| localStorage.getItem('jwt')
|
||||
|| localStorage.getItem('access_token')
|
||||
|| '';
|
||||
} catch(e){ return ''; }
|
||||
}
|
||||
async function logout(){
|
||||
if(!confirm('Odjava iz aplikacije?')) return;
|
||||
// Revoke server-side (matches app.html logout flow, commit e07292b)
|
||||
try {
|
||||
const tok = readToken();
|
||||
if(tok){
|
||||
await fetch('/sport/api/auth/logout', {
|
||||
method:'POST',
|
||||
headers:{'Authorization':'Bearer '+tok}
|
||||
}).catch(()=>{});
|
||||
}
|
||||
} catch(e){}
|
||||
// Clear ALL session keys
|
||||
['pgz_access','pgz_refresh','pgz_user','app-role','jwt','access_token','refresh_token','pgz_session_id'].forEach(k => {
|
||||
try { localStorage.removeItem(k); sessionStorage.removeItem(k); } catch(e){}
|
||||
});
|
||||
location.href = '/sport/login';
|
||||
}
|
||||
function gotoLogin(){
|
||||
// Preserve return URL so we land back here after sign-in
|
||||
try {
|
||||
const ret = encodeURIComponent(location.pathname + location.search + location.hash);
|
||||
location.href = '/sport/login?next=' + ret;
|
||||
} catch(e){
|
||||
location.href = '/sport/login';
|
||||
}
|
||||
}
|
||||
function initials(n){
|
||||
if(!n) return '?';
|
||||
const p = String(n).trim().split(/\s+/);
|
||||
@@ -141,19 +167,23 @@
|
||||
<div class="pgz-sb-mx" onclick="PGZSidebar.closeMobile()" title="Zatvori">✕</div>
|
||||
</div>
|
||||
<nav class="pgz-sb-nav" id="pgz-sb-nav">${renderSections(activeKey, user)}</nav>
|
||||
<div class="pgz-sb-foot" id="pgz-sb-foot" onclick="PGZSidebar.toggleUserMenu(event)">
|
||||
<div class="av" id="pgz-sb-av">PG</div>
|
||||
<div class="pgz-sb-foot" id="pgz-sb-foot"
|
||||
role="button" tabindex="0"
|
||||
title="Klikni za prijavu / odjavu"
|
||||
onclick="PGZSidebar.handleFootClick(event)"
|
||||
onkeydown="if(event.key==='Enter'||event.key===' '){event.preventDefault();PGZSidebar.handleFootClick(event);}">
|
||||
<div class="av" id="pgz-sb-av">?</div>
|
||||
<div class="ui">
|
||||
<div class="un" id="pgz-sb-un">Gost</div>
|
||||
<div class="ur" id="pgz-sb-ur">Demo</div>
|
||||
<div class="ur" id="pgz-sb-ur">Klikni za prijavu</div>
|
||||
</div>
|
||||
<div class="caret">▾</div>
|
||||
<div class="caret" id="pgz-sb-caret" title="Otvori izbornik" onclick="event.stopPropagation();PGZSidebar.toggleUserMenu(event)">▾</div>
|
||||
<div class="pgz-user-menu" id="pgz-user-menu" onclick="event.stopPropagation()">
|
||||
<a href="/app#profil"><span>👤</span><span>Moj profil</span></a>
|
||||
<a href="/app#postavke"><span>⚙</span><span>Postavke</span></a>
|
||||
<a href="/static/sport2.html"><span>🌐</span><span>Public portal</span></a>
|
||||
<div class="sep"></div>
|
||||
<a href="/login" id="pgz-menu-login"><span>🔑</span><span>Prijava</span></a>
|
||||
<a href="/sport/login" id="pgz-menu-login"><span>🔑</span><span>Prijava</span></a>
|
||||
<a class="danger" id="pgz-menu-logout" onclick="PGZSidebar.logout()" style="display:none"><span>⎋</span><span>Odjava</span></a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -171,13 +201,16 @@
|
||||
}
|
||||
|
||||
function setUserDisplay(me){
|
||||
_currentUser = me || null;
|
||||
const un = $('#pgz-sb-un'), ur = $('#pgz-sb-ur'), av = $('#pgz-sb-av');
|
||||
const foot = document.getElementById('pgz-sb-foot');
|
||||
const loginLink = document.getElementById('pgz-menu-login');
|
||||
const logoutLink = document.getElementById('pgz-menu-logout');
|
||||
if(!me){
|
||||
if(un) un.textContent = 'Gost';
|
||||
if(ur) ur.textContent = 'Klikni za prijavu';
|
||||
if(av){ av.textContent = '?'; av.innerHTML = av.innerHTML; }
|
||||
if(foot) foot.setAttribute('title', 'Klikni za prijavu');
|
||||
if(loginLink) loginLink.style.display = 'flex';
|
||||
if(logoutLink) logoutLink.style.display = 'none';
|
||||
return;
|
||||
@@ -186,11 +219,12 @@
|
||||
const role = me.user_type || '';
|
||||
const avSrc = me.avatar_url || me.google_picture;
|
||||
if(un) un.textContent = name;
|
||||
if(ur) ur.textContent = role;
|
||||
if(ur) ur.textContent = role || 'Korisnik';
|
||||
if(av){
|
||||
if(avSrc) av.innerHTML = `<img src="${esc(avSrc)}" alt="">`;
|
||||
else av.textContent = initials(name);
|
||||
}
|
||||
if(foot) foot.setAttribute('title', 'Klikni za odjavu (' + (me.email || name) + ')');
|
||||
if(loginLink) loginLink.style.display = 'none';
|
||||
if(logoutLink) logoutLink.style.display = 'flex';
|
||||
}
|
||||
@@ -286,7 +320,22 @@
|
||||
setTimeout(() => document.addEventListener('click', closer, true), 50);
|
||||
}
|
||||
},
|
||||
logout
|
||||
/* Single-click footer handler:
|
||||
* - Guest (no user) → /sport/login
|
||||
* - Logged in → logout() (revokes JWT, clears storage, redirects to login)
|
||||
* The caret (▾) opens the full user menu (profil/postavke/portal/logout).
|
||||
*/
|
||||
handleFootClick(ev){
|
||||
ev && ev.stopPropagation();
|
||||
if(_currentUser){
|
||||
return logout();
|
||||
}
|
||||
return gotoLogin();
|
||||
},
|
||||
gotoLogin,
|
||||
logout,
|
||||
// exposed for debugging / tests
|
||||
_state: () => ({ user: _currentUser })
|
||||
};
|
||||
window.PGZSidebar = PGZSidebar;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user