59 lines
2.4 KiB
JavaScript
59 lines
2.4 KiB
JavaScript
import { useState, useEffect, useRef } from 'react'
|
|
import { databases, DATABASE_ID, COLLECTIONS, Query } from '../lib/appwrite'
|
|
import { planTimeLoad, blockMinutes, mapLimit, TIME_PARALLEL, TIME_QUERY_LIMIT } from '../lib/ticketTimes'
|
|
|
|
// Spalte "Zeit" der Ticketliste: Arbeitszeit je woid, in Bloecken nachgeladen (nur Lesen).
|
|
// byWoid ist eine Map woid -> Minuten (null = nicht zu ermitteln). Sie wird an Ort und Stelle
|
|
// ergaenzt, `version` zaehlt hoch, wenn sich etwas geaendert hat (fuer useMemo-Abhaengigkeiten).
|
|
// Der Zwischenspeicher gilt nur fuer die Lebensdauer der Seite: wer von einer Ticketseite
|
|
// zurueckkehrt, sieht frische Zahlen.
|
|
export function useTicketMinutes(tickets) {
|
|
const cache = useRef(new Map())
|
|
const inFlight = useRef(new Set())
|
|
const mounted = useRef(true)
|
|
const [version, setVersion] = useState(0)
|
|
const [capped, setCapped] = useState(false)
|
|
|
|
useEffect(() => {
|
|
mounted.current = true
|
|
return () => { mounted.current = false }
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
const byWoid = cache.current
|
|
const running = inFlight.current
|
|
// Ein woid, dessen Abfrage noch laeuft, gilt als bekannt (kein Block doppelt anfragen)
|
|
const known = { has: (woid) => byWoid.has(woid) || running.has(woid) }
|
|
const plan = planTimeLoad(tickets, known)
|
|
setCapped(plan.capped)
|
|
if (plan.blocks.length === 0) return
|
|
|
|
for (const block of plan.blocks) {
|
|
for (const woid of block) running.add(woid)
|
|
}
|
|
|
|
// Auch wenn sich `tickets` inzwischen geaendert hat, wird das Ergebnis eingetragen:
|
|
// sonst bliebe das woid ungeladen und ohne Abfrage.
|
|
mapLimit(plan.blocks, TIME_PARALLEL, async (block) => {
|
|
const response = await databases.listDocuments(DATABASE_ID, COLLECTIONS.WORKSHEETS, [
|
|
Query.equal('woid', block),
|
|
Query.select(['woid', 'totalTime', 'supporters', 'isComment']),
|
|
Query.limit(TIME_QUERY_LIMIT),
|
|
])
|
|
return blockMinutes(block, response.documents, response.total)
|
|
}).then((results) => {
|
|
results.forEach((result, index) => {
|
|
const sums = result.ok ? result.value : null
|
|
if (!sums) console.warn('Zeitsummen nicht geladen:', result.ok ? 'Antwort abgeschnitten' : result.error)
|
|
for (const woid of plan.blocks[index]) {
|
|
byWoid.set(woid, sums ? sums[woid] ?? null : null)
|
|
running.delete(woid)
|
|
}
|
|
})
|
|
if (mounted.current) setVersion((v) => v + 1)
|
|
})
|
|
}, [tickets])
|
|
|
|
return { byWoid: cache.current, capped, version }
|
|
}
|