From b85b8645aabee07ac2d049a8e160541c4885562c Mon Sep 17 00:00:00 2001 From: Bryon Lewis Date: Mon, 9 Dec 2024 09:51:59 -0500 Subject: [PATCH] adding file annotation to main recording view --- bats_ai/core/views/recording.py | 35 ++++-- bats_ai/core/views/recording_annotation.py | 2 +- client/src/api/api.ts | 1 + client/src/components/AnnotationList.vue | 57 ++++++--- .../components/RecordingAnnotationSummary.vue | 108 ++++++++++++++++++ client/src/views/Recordings.vue | 35 ++++-- 6 files changed, 203 insertions(+), 35 deletions(-) create mode 100644 client/src/components/RecordingAnnotationSummary.vue diff --git a/bats_ai/core/views/recording.py b/bats_ai/core/views/recording.py index d0701d9..c935880 100644 --- a/bats_ai/core/views/recording.py +++ b/bats_ai/core/views/recording.py @@ -253,9 +253,12 @@ def get_recordings(request: HttpRequest, public: bool | None = None): .count() ) recording['userAnnotations'] = unique_users_with_annotations - user_has_annotations = Annotations.objects.filter( - recording_id=recording['id'], owner=request.user - ).exists() + user_has_annotations = ( + Annotations.objects.filter(recording_id=recording['id'], owner=request.user).exists() + or RecordingAnnotation.objects.filter( + recording_id=recording['id'], owner=request.user + ).exists() + ) recording['userMadeAnnotations'] = user_has_annotations return list(recordings) @@ -275,16 +278,30 @@ def get_recording(request: HttpRequest, id: int): recording['hasSpectrogram'] = Recording.objects.get(id=recording['id']).has_spectrogram if recording['recording_location']: recording['recording_location'] = json.loads(recording['recording_location'].json) - unique_users_with_annotations = ( + annotation_owners = ( Annotations.objects.filter(recording_id=recording['id']) - .values('owner') + .values_list('owner', flat=True) + .distinct() + ) + recording_annotation_owners = ( + RecordingAnnotation.objects.filter(recording_id=recording['id']) + .values_list('owner', flat=True) .distinct() - .count() + ) + + # Combine the sets of owners and count unique entries + unique_users_with_annotations = len( + set(annotation_owners).union(set(recording_annotation_owners)) ) recording['userAnnotations'] = unique_users_with_annotations - user_has_annotations = Annotations.objects.filter( - recording_id=recording['id'], owner=request.user - ).exists() + user_has_annotations = ( + Annotations.objects.filter( + recording_id=recording['id'], owner=request.user + ).exists() + or RecordingAnnotation.objects.filter( + recording_id=recording['id'], owner=request.user + ).exists() + ) recording['userMadeAnnotations'] = user_has_annotations fileAnnotations = RecordingAnnotation.objects.filter(recording=id).order_by( 'confidence' diff --git a/bats_ai/core/views/recording_annotation.py b/bats_ai/core/views/recording_annotation.py index 4f258c1..20fc06f 100644 --- a/bats_ai/core/views/recording_annotation.py +++ b/bats_ai/core/views/recording_annotation.py @@ -100,7 +100,7 @@ def update_recording_annotation( annotation = RecordingAnnotation.objects.get(pk=id) # Check permission - if annotation.recording.owner != request.user: + if annotation.recording.owner != request.user and not annotation.recording.public: raise HttpError(403, 'Permission denied.') # Update fields if provided diff --git a/client/src/api/api.ts b/client/src/api/api.ts index 858f54d..cbd5817 100644 --- a/client/src/api/api.ts +++ b/client/src/api/api.ts @@ -28,6 +28,7 @@ export interface Recording { userMadeAnnotations: boolean; userAnnotations: number; hasSpectrogram: boolean; + fileAnnotations: FileAnnotation[]; site_name?: string; software?: string; detector?: string; diff --git a/client/src/components/AnnotationList.vue b/client/src/components/AnnotationList.vue index 1f9b55f..d06034b 100644 --- a/client/src/components/AnnotationList.vue +++ b/client/src/components/AnnotationList.vue @@ -89,24 +89,51 @@ export default defineComponent({ class="ma-auto" @update:model-value="tabSwitch($event)" > - - Recording - - + + Recording + + + Recording/File Level Species Annotations + + - Pulse - - + + Sequence + + + Sequence Level annotations (Approach/Search/Terminal/Social) + + - Sequence - + + Pulse Level Annotations (for a single pulse) + diff --git a/client/src/components/RecordingAnnotationSummary.vue b/client/src/components/RecordingAnnotationSummary.vue new file mode 100644 index 0000000..47489f4 --- /dev/null +++ b/client/src/components/RecordingAnnotationSummary.vue @@ -0,0 +1,108 @@ + + + + + diff --git a/client/src/views/Recordings.vue b/client/src/views/Recordings.vue index 9275072..50fa104 100644 --- a/client/src/views/Recordings.vue +++ b/client/src/views/Recordings.vue @@ -6,12 +6,14 @@ import MapLocation from '../components/MapLocation.vue'; import useState from '../use/useState'; import BatchUploadRecording from '../components/BatchUploadRecording.vue'; import RecordingInfoDisplay from '../components/RecordingInfoDisplay.vue'; +import RecordingAnnotationSummary from '../components/RecordingAnnotationSummary.vue'; export default defineComponent({ components: { UploadRecording, MapLocation, BatchUploadRecording, - RecordingInfoDisplay + RecordingInfoDisplay, + RecordingAnnotationSummary, }, setup() { const itemsPerPage = ref(-1); @@ -26,11 +28,14 @@ export default defineComponent({ title:'Edit', key:'edit', }, - { title:'Name', key:'name', }, + { + title: 'Annotation', + key:'annotation' + }, { title:'Owner', key:'owner_username', @@ -39,10 +44,6 @@ export default defineComponent({ title:'Recorded Date', key:'recorded_date', }, - { - title:'Recorded Time', - key:'recorded_time', - }, { title:'Public', key:'public', @@ -71,6 +72,10 @@ export default defineComponent({ title:'Name', key:'name', }, + { + title: 'Annotation', + key:'annotation' + }, { title:'Owner', key:'owner_username', @@ -79,10 +84,6 @@ export default defineComponent({ title:'Recorded Date', key:'recorded_date', }, - { - title:'Recorded Time', - key:'recorded_time', - }, { title:'Public', key:'public', @@ -251,6 +252,14 @@ export default defineComponent({ + + + + + +