Planificateur « Suggérer » : 4 stratégies (smart / meilleurs d'abord / équilibré / juste ce qu'il faut), compétences+niveaux par tech (édition inline), niveau requis par compétence + par job, carte des tournées (1 couleur/tech, domicile→arrêts, sélecteur de jour), fenêtre de dispatch auj.+demain (dates sélectionnées), règle week-end + placeholder « en attente du quart », clustering + lasso + filtre-date sur la carte, accès rapide « À assigner » (badge). Boîte : liste /conversations allégée (45 Mo → ~1 Mo, 17×) + messages chargés à l'ouverture. Rapports : cache SWR sur revenue-explorer (22×). Session : keep-alive + timeout fetch global + authFetch durci → fin des rechargements manuels. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
27 lines
1.4 KiB
JavaScript
27 lines
1.4 KiB
JavaScript
// Empêche TOUTE requête de l'app (same-origin : /api, /hub, /auth) de PENDRE indéfiniment.
|
|
// Cause du gel « même un clic de menu ne répond plus » : sur session Authentik morte/lente, un fetch
|
|
// sans timeout ne résout jamais → la page attendue ne s'affiche pas, la vue ne change pas au clic,
|
|
// et les 69 appels /hub (fetch nu) restent suspendus. On borne chaque requête app à 30 s.
|
|
// Externes (Mapbox api.mapbox.com, etc.) et appels fournissant déjà un signal : inchangés.
|
|
// EventSource (SSE) n'utilise pas window.fetch → non affecté.
|
|
import { boot } from 'quasar/wrappers'
|
|
|
|
const APP_TIMEOUT_MS = 30000
|
|
|
|
export default boot(() => {
|
|
if (typeof window === 'undefined' || window.__netTimeoutInstalled) return
|
|
window.__netTimeoutInstalled = true
|
|
const orig = window.fetch.bind(window)
|
|
const origin = window.location.origin
|
|
window.fetch = function (input, init) {
|
|
init = init || {}
|
|
let url = ''
|
|
try { url = typeof input === 'string' ? input : (input && input.url) || '' } catch { /* Request exotique */ }
|
|
const sameApp = url.startsWith('/') || url.startsWith(origin) // requêtes app ; exclut absolu cross-origin
|
|
if (!sameApp || init.signal) return orig(input, init) // externe ou signal déjà fourni → ne pas toucher
|
|
const ctrl = new AbortController()
|
|
const id = setTimeout(() => ctrl.abort(), APP_TIMEOUT_MS)
|
|
return orig(input, { ...init, signal: ctrl.signal }).finally(() => clearTimeout(id))
|
|
}
|
|
})
|