-
-
Notifications
You must be signed in to change notification settings - Fork 225
feat(bulkProcessing): near limit alert DEV-1399 #7232
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 10 commits
95e8d7b
9b9d314
c4e958c
d0ed10c
b5600da
74c5b76
5ad031d
adeca59
70c735c
5579acc
df5ab5e
dfb1c87
3541a3b
f27a5da
21fa9e3
1bed4f2
0175204
d954166
4f40087
a4f10c3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| import { Anchor, Group, Stack, Text } from '@mantine/core' | ||
| import { useQueryClient } from '@tanstack/react-query' | ||
| import { useState } from 'react' | ||
| import { useMemo, useState } from 'react' | ||
| import { useNavigate } from 'react-router-dom' | ||
| import { ACCOUNT_ROUTES } from '#/account/routes.constants' | ||
| import type { ServerError } from '#/api/ServerError' | ||
|
|
@@ -18,6 +18,7 @@ import { | |
| import Alert from '#/components/common/alert' | ||
| import RegionSelector from '#/components/languages/RegionSelector' | ||
| import { getSuggestedLanguages } from '#/components/processing/common/utils' | ||
| import { getSupplementalPathParts } from '#/components/processing/processingUtils' | ||
| import type { SubmissionResponse } from '#/dataInterface' | ||
| import envStore from '#/envStore' | ||
| import { useCalculateAudioDuration } from '#/hooks/useCalculateAudioDuration.hook' | ||
|
|
@@ -32,6 +33,18 @@ import { useBulkProcessingAlerts } from '../alerts/useBulkProcessingAlerts' | |
|
|
||
| const GOOGLE_TRANSCRIPTION_LANGUAGE_SUPPORT_URL = 'transcription-translation.html#language-list' | ||
|
|
||
| function getAlreadyTranscribedMessage(count: number, duration: string): string { | ||
| return t('##count## audio files totaling ##duration## already transcribed and will be ignored') | ||
| .replace('##count##', String(count)) | ||
| .replace('##duration##', duration) | ||
| } | ||
|
|
||
| function isAlreadyTranscribedSubmission(submission: SubmissionResponse, sourceRowPath: string): boolean { | ||
| const transcript = submission._supplementalDetails?.[sourceRowPath]?.transcript | ||
|
|
||
| return Boolean(transcript?.value || transcript?.pendingReview) | ||
| } | ||
|
|
||
| export interface BulkTranscriptionModalProps { | ||
| fieldXpath: string | ||
| assetUid: string | ||
|
|
@@ -102,18 +115,55 @@ export function BulkTranscriptionModal(props: BulkTranscriptionModalProps) { | |
| const advancedFeatures = advancedFeaturesData?.status === 200 ? advancedFeaturesData.data : [] | ||
| const suggestedLanguages = getSuggestedLanguages(advancedFeatures) | ||
|
|
||
| const { sourceRowPath } = getSupplementalPathParts(props.fieldXpath) | ||
|
|
||
| // Keep the quota estimate aligned with the rows that will actually be sent. | ||
| // The alert hook filters already-transcribed submissions later, so we mirror | ||
| // that exclusion here instead of counting every selected row up front. | ||
| const transcribableSubmissions = useMemo( | ||
| () => props.selectedSubmissions.filter((submission) => !isAlreadyTranscribedSubmission(submission, sourceRowPath)), | ||
| [props.selectedSubmissions, sourceRowPath], | ||
| ) | ||
|
|
||
| const { | ||
| duration: totalSelectedAudioDuration, | ||
| isLoading: isTotalSelectedAudioDurationLoading, | ||
| isError: isTotalSelectedAudioDurationError, | ||
| } = useCalculateAudioDuration({ | ||
| selectedSubmissions: transcribableSubmissions, | ||
| fieldId: sourceRowPath, | ||
| assetUid: props.assetUid, | ||
| }) | ||
|
|
||
| const nearLimitRequiredSeconds = | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From what I understand in the preview steps, we want this number to be big to simulate not having enough ASR minutes left(?) I tried setting this to very large numbers (1,000,000,000,000) and
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Weird, if I change this line: to this then it works for me |
||
| isTotalSelectedAudioDurationLoading || isTotalSelectedAudioDurationError ? undefined : totalSelectedAudioDuration | ||
|
magicznyleszek marked this conversation as resolved.
|
||
|
|
||
| const { activeAlerts, hasErrors, hasBlockingError, eligibleSubmissions } = useBulkProcessingAlerts({ | ||
| actionType: 'transcript', | ||
| selectedSubmissions: props.selectedSubmissions, | ||
| selectedLanguage: selectedLanguage || undefined, | ||
| selectedRegion: selectedRegion || undefined, | ||
| fieldXpath: props.fieldXpath, | ||
| nearLimitRequiredAmount: nearLimitRequiredSeconds, | ||
| serviceUsageData: serviceUsageData || undefined, | ||
| activeBulkActions: props.activeBulkActions, | ||
| }) | ||
|
|
||
| const eligibleSubmissionUuids = eligibleSubmissions.map((s) => s._uuid) | ||
|
|
||
| const alreadyTranscribedSubmissionUuids = useMemo( | ||
| () => activeAlerts.find((alert) => alert.id === 'already-transcribed')?.filteredSubmissionUuids ?? [], | ||
| [activeAlerts], | ||
| ) | ||
|
|
||
| const alreadyTranscribedSubmissions = useMemo(() => { | ||
| if (alreadyTranscribedSubmissionUuids.length === 0) { | ||
| return [] | ||
| } | ||
| const uuids = new Set(alreadyTranscribedSubmissionUuids) | ||
| return props.selectedSubmissions.filter((submission) => uuids.has(submission._uuid)) | ||
| }, [alreadyTranscribedSubmissionUuids, props.selectedSubmissions]) | ||
|
|
||
| const { | ||
| duration: audioDuration, | ||
| isLoading: isAudioDurationLoading, | ||
|
|
@@ -123,10 +173,50 @@ export function BulkTranscriptionModal(props: BulkTranscriptionModalProps) { | |
| errorMessage: audioDurationErrorMesssage, | ||
| } = useCalculateAudioDuration({ | ||
| selectedSubmissions: eligibleSubmissions, | ||
| fieldId: props.fieldXpath, | ||
| fieldId: sourceRowPath, | ||
| assetUid: props.assetUid, | ||
| }) | ||
|
|
||
| const { | ||
| duration: alreadyTranscribedDuration, | ||
| isLoading: isAlreadyTranscribedDurationLoading, | ||
| isError: isAlreadyTranscribedDurationError, | ||
| } = useCalculateAudioDuration({ | ||
| selectedSubmissions: alreadyTranscribedSubmissions, | ||
| fieldId: sourceRowPath, | ||
| assetUid: props.assetUid, | ||
| }) | ||
|
|
||
| // Keep useBulkProcessingAlerts generic, then enrich just the transcription-specific | ||
| // "already transcribed" warning with duration text calculated in this modal. | ||
| // All other alerts are rendered exactly as returned by the hook. | ||
| const activeAlertsWithResolvedMinutes = useMemo(() => { | ||
| const duration = | ||
| isAlreadyTranscribedDurationLoading || isAlreadyTranscribedDurationError | ||
| ? '…' | ||
| : formatTimeFromSeconds(alreadyTranscribedDuration) | ||
|
|
||
| return activeAlerts.map((alert) => { | ||
| if (alert.id !== 'already-transcribed') { | ||
| return alert | ||
| } | ||
|
|
||
| const computedValues = { | ||
| ...alert.computedValues, | ||
| duration, | ||
| } | ||
|
|
||
| return { | ||
| ...alert, | ||
| computedValues, | ||
| message: getAlreadyTranscribedMessage( | ||
| Number(alert.computedValues.count ?? 0), | ||
| String(computedValues.duration ?? 0), | ||
| ), | ||
| } | ||
| }) | ||
| }, [activeAlerts, alreadyTranscribedDuration, isAlreadyTranscribedDurationError, isAlreadyTranscribedDurationLoading]) | ||
|
|
||
| const handleLanguageChange = (language: LanguageCode | null) => { | ||
| setSelectedLanguage(language) | ||
| setSelectedRegion(null) | ||
|
|
@@ -143,7 +233,7 @@ export function BulkTranscriptionModal(props: BulkTranscriptionModalProps) { | |
| uidAsset: props.assetUid, | ||
| data: { | ||
| action_id: ActionIdEnum.automatic_google_transcription, | ||
| question_xpath: props.fieldXpath, | ||
| question_xpath: sourceRowPath, | ||
| submission_uuids: eligibleSubmissionUuids, | ||
| params: { | ||
| language: selectedLanguage!, | ||
|
|
@@ -212,10 +302,10 @@ export function BulkTranscriptionModal(props: BulkTranscriptionModalProps) { | |
| /> | ||
| </Group> | ||
|
|
||
| <BulkProcessingAlerts activeAlerts={activeAlerts} /> | ||
| <BulkProcessingAlerts activeAlerts={activeAlertsWithResolvedMinutes} /> | ||
|
|
||
| {/* Legacy alert - will be removed once evaluators are implemented */} | ||
| {hasExceededLimit && activeAlerts.length === 0 && ( | ||
| {hasExceededLimit && activeAlertsWithResolvedMinutes.length === 0 && ( | ||
| <Alert type='warning' iconName='information' mt={12} mb={12}> | ||
| {t("You've reached your automatic transcription limit. Please purchase an add‑on to continue.")} | ||
| </Alert> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here about the variable name, I think it reads better if we drop the "near limit" prefix
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed 👍