|
| 1 | +// Shared detection-status predicates used by Encounter.jsx polling loop and |
| 2 | +// ImageCard.jsx "Detection in progress" indicator. Keeping them here avoids |
| 3 | +// the two files drifting out of sync. |
| 4 | + |
| 5 | +const POLL_INTERVAL_MS = 3000; |
| 6 | +const MAX_POLL_CYCLES = 100; // 100 cycles * 3s = ~5 minutes |
| 7 | + |
| 8 | +const isAnnotationTrivial = (a) => a?.isTrivial === true || a?.trivial === true; |
| 9 | + |
| 10 | +export const isTerminalDetectionStatus = (status) => |
| 11 | + !status || |
| 12 | + status === "complete" || |
| 13 | + status === "error" || |
| 14 | + status === "pending"; |
| 15 | + |
| 16 | +// True when an asset is from a bulk import and detection has been queued |
| 17 | +// to WBIA but the callback hasn't returned yet. In this state the API |
| 18 | +// returns detectionStatus=null and only a trivial placeholder annotation. |
| 19 | +// Scoped to encounters that have an importTaskId so we don't poll forever |
| 20 | +// on legacy/manual encounters that intentionally never run detection. |
| 21 | +export const isAwaitingBulkImportDetection = (asset, encounterData) => { |
| 22 | + if (!encounterData?.importTaskId) return false; |
| 23 | + if (asset?.detectionStatus !== null && asset?.detectionStatus !== undefined) |
| 24 | + return false; |
| 25 | + const anns = Array.isArray(asset?.annotations) ? asset.annotations : []; |
| 26 | + return anns.length > 0 && anns.every(isAnnotationTrivial); |
| 27 | +}; |
| 28 | + |
| 29 | +export const isAssetActivelyAwaitingDetection = (asset, encounterData) => |
| 30 | + !isTerminalDetectionStatus(asset?.detectionStatus) || |
| 31 | + isAwaitingBulkImportDetection(asset, encounterData); |
| 32 | + |
| 33 | +export const shouldContinuePollingEncounter = (encounterData) => { |
| 34 | + const mediaAssets = Array.isArray(encounterData?.mediaAssets) |
| 35 | + ? encounterData.mediaAssets |
| 36 | + : []; |
| 37 | + if (mediaAssets.length === 0) return false; |
| 38 | + return mediaAssets.some((asset) => |
| 39 | + isAssetActivelyAwaitingDetection(asset, encounterData), |
| 40 | + ); |
| 41 | +}; |
| 42 | + |
| 43 | +export { POLL_INTERVAL_MS, MAX_POLL_CYCLES }; |
0 commit comments