Skip to content

Recording pagination#328

Open
BryonLewis wants to merge 101 commits intomainfrom
recording-pagination
Open

Recording pagination#328
BryonLewis wants to merge 101 commits intomainfrom
recording-pagination

Conversation

@BryonLewis
Copy link
Collaborator

@BryonLewis BryonLewis commented Feb 3, 2026

resolves #325

  • Adds a copy_recordings management command that will take the existing recordings and create a new number of them efficiently by copying data instead of running the entire spectrogram generation. It also has the capability to add some random tags to test tagging and filtering.
    • Example manage.py copy_recordings --count 1000 --tags "foo,bar,test" should copy and create 1000 recordings with a mixure of tags being test foo and bar.
  • Modifies the basic /recording endpoint to support vuetify v-data-table-server pagination system
    • tried to make the creation of the output more efficient by structuring and using prefetch for certain fields
  • api.ts has been updated with the new request and return results for the /recording endpoint
  • Submission Logic moved from Client to Server Side
    • a lot of useState.ts submission logic and computed values have been removed in favor of the get /recordings endpoint returning filtered data. Moving the filtering to the server instead of the client
  • Added a new endpoint for getting the unsubmitted neighbors - /unsubmitted-neighbors. This will return the information for the previous and next buttons
  • The Recording List uses a default sort and only returns the next 20 recordings. I don't know if we want a full v-data-table-server system or not to be used with this.
  • When submitting a recording it re-retrieves the data so we don't need to mark it as complete locally using the emit system

@BryonLewis BryonLewis changed the title WIP: Recording pagination Recording pagination Feb 11, 2026
@BryonLewis BryonLewis requested a review from naglepuff February 11, 2026 15:15
Base automatically changed from batbot-metadata-drawing to main February 12, 2026 19:32
@BryonLewis BryonLewis marked this pull request as ready for review February 16, 2026 13:00
Copy link
Collaborator

@naglepuff naglepuff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if anything needs to change in particular, but I had some questions.

Comment on lines 25 to 26
if not details: # Ensure we return a consistent schema even if no details exist
return {'id': None, 'user_id': user_id, 'reference_materials': ''}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was there an issue that this is helping to solve? I thought that the front end knew what to do if this endpoint 404'd. I wasn't expecting to see any changes to vetting details stuff in this PR

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll revert it. This is a hard one because we are using vetting/user/{user.id} where there should only be a single value per user, unlike anotherexample comment/{id} where there it is the intention of it to exist or not based on the Id.

Like if you had /vetting/user and it used the request authentication to determine the user_id I wouldn't want it to 404 if no value is set, it would just be an empty value indicating it hasn't been set yet. I viewed it not as a possible collection of data and more as

Comment on lines 326 to 357
items.append(
{
'id': rec.id,
'name': rec.name,
'audio_file': str(rec.audio_file),
'owner_id': rec.owner_id,
'recorded_date': rec.recorded_date,
'recorded_time': rec.recorded_time,
'equipment': rec.equipment,
'comments': rec.comments,
'recording_location': location,
'grts_cell_id': rec.grts_cell_id,
'grts_cell': rec.grts_cell,
'public': rec.public,
'created': rec.created,
'modified': rec.modified,
'software': rec.software,
'detector': rec.detector,
'species_list': rec.species_list,
'site_name': rec.site_name,
'unusual_occurrences': rec.unusual_occurrences,
'tags_text': getattr(rec, 'tags_text', None),
'owner_username': rec.owner.username,
'audio_file_presigned_url': default_storage.url(rec.audio_file.name),
'hasSpectrogram': rec.has_spectrogram_attr,
'userAnnotations': annotation_counts.get(rec.id, 0),
'userMadeAnnotations': rec.id in user_has_annotations_ids,
'fileAnnotations': [
RecordingAnnotationSchema.from_orm(fa).dict()
for fa in rec.recordingannotation_set.all()
],
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a schema class we can use here instead of appending this dictionary?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created a Schema, while doing this I also updated a possible failure condition when using ArrayAgg for the tag text values.

Comment on lines +433 to +436
for tag in tag_list:
queryset = queryset.filter(tags__text=tag)
if tag_list:
queryset = queryset.distinct()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is tag_list ever None in this block?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q.tags above this line is guarded so it isn't None:

 if q.tags and q.tags.strip():
        tag_list = [t.strip() for t in q.tags.split(',') if t.strip()]
        for tag in tag_list:
            queryset = queryset.filter(tags__text=tag)
        if tag_list:
            queryset = queryset.distinct()

So the tags used for the for_list will always be at least a string. It can be an empty string but even that will create an empty array for tag_list.

Comment on lines +550 to +551
next_id = ids[idx + 1] if idx + 1 < len(ids) else None
previous_id = ids[idx - 1] if idx - 1 >= 0 else None
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this work if the user is looking at either the first or last recording? Should we "wrap" around in those cases, or is that too much of a lift? I can see both cases

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Vetting UI] Refactor data tables to use pagination

2 participants