Collections - Featured sounds finish#2075
Conversation
…lection publicity is changed, featured sounds implementation has started
ffont
left a comment
There was a problem hiding this comment.
Hi!
I'm generally fine with it, but there's something that I dislike a lot and that we should try to improve. We discussed this but I understood something wrong. The problem basically has to do with that sound card rendering thing, because you need to replicate a lot of server-side code for displaying a sound, and this can be very problematic if we make changes in the "original" display sound in the future and don't update the "old" one. I would consider an alternative solution, which involves the server but in a different way as before. I was wondering if there could be an endpoint to which you pass a list of sound IDs, and it returns the rendered sound cards (well, the HTML bits of course!) so that you can then place them where needed. I mention that the endpoint can support passing a list of IDs because you'll typically want to display "a page" of sounds. You'd be calling this endpoint every time that you need to display a group of sounds that you have not displayed yet.
The advantage of such a solution is that the sound rendering code is in sync with the rest of Freesound. Also, in your frontend code you will not need to save that much data per sound, only what's needed to implement filtering and sorting. This method would mean some more DB queries and server requests, but not that many probably. Nevertheless it is still very fundamentally different from the previous solution based on htmx as the communication with the server is simply to get rendered sound IDs, but does not include any database logic, etc.
I know what I'm asking is not minor a minor change, but I think it would make the code a bit cleaner and more maintainable.
That view for "rendering sound cards" btw should be generic, not necessarily tied to the collections app. It will be used in the future in other parts of the web most likely.
I hope the idea is clear, let me know if not!!
| ENABLE_COLLECTIONS = False | ||
| ENABLE_COLLECTIONS = True | ||
| MAX_SOUNDS_PER_COLLECTION = 250 | ||
| MAX_FEATURED_SOUNDS_PER_COLLECTION = 250 |
There was a problem hiding this comment.
Should we set a lower limit here? Say 10?
There was a problem hiding this comment.
I like the 6 because its 2 full rows on desktop and 3 on mobile but 12 is also good for this manner
| # ------------------------------------------------------------------------------- | ||
| # Collections | ||
| ENABLE_COLLECTIONS = False | ||
| ENABLE_COLLECTIONS = True |
There was a problem hiding this comment.
This should still be False, you can overwrite in your local_settings.py fie
| header_sounds = Sound.public.filter(id__in=collection.featured_sound_ids) | ||
| else: | ||
| header_sounds = Sound.public.filter(collections=collection)[:1] | ||
|
|
There was a problem hiding this comment.
Looks like the rendering of display_collection will make many db queries. We have methods to optimize this. I should give it a closer look, but one first optimization will definitely be something like his here:
if collection.featured_sound_ids:
header_sounds = Sound.objects.bulk_query_id(collection.featured_sound_ids)
else:
sound_ids = Sound.public.filter(collections=collection).values_list('id', flat=True)[:3]
header_sounds = Sound.objects.bulk_query_id(sound_ids)
You can check with the djang debug toolbar the number of queries that a page load triggers. There are many queries here that are "similar" (this is shown in the panel), which means that there are probably optimizations to be made when retrieving objets from DB using Django ORM.
|
Refactored the collection detail page and collection edit page to use HTMX. I optimized the approach based on what we discussed, so now the HTMX roundtrips are only for rendering a few cards instead of hitting full database queries, making it faster. What mainly changedAdded HTMX to the project
Collection detail page:
Collection edit page:
Featured sound limit:
Tests added:
|
1.
display_sound_with_actionstemplateNew template wrapping a sound card with featured-toggle and remove-toggle action buttons, driven entirely by JS.
Connected files:
objectSelector.js(binds buttons to store),soundCard.js(addEditActions()clones it),selectableObject.scss(action bar styles, active/hover states,.marked-for-removaldimming),object_selector.html(show_actionsbranch).2. Client-side collection grid
New modules:
soundStateStore.jsadded/remove/featuredflags,toggleAction(),idsWithFlag(), andonChangelisteners.soundGridEditor.js<template>via a pluggablerenderCardhook. Inits players/ratings/modals per page.soundCard.jspopulateSoundCard()fills a cloned template with player data, links, stats.addEditActions()wraps the card with toggle buttons for edit mode.formatters.jsescapeAttr,truncate,formatDate,formatNumber,soundPlayerUrls.Page entry points:
collection.js— Read-only grid with featured highlighting.collectionEdit.js— Edit grid withadded/remove/featuredflags. Wires add-sounds modal tostore.add(). On submit, populates hidden inputs from store state.Updated:
addSoundsModal.js— newprepareAddSoundsModalDynamic()that excludes present IDs and feeds selections into the store.Templates:
collection.html,edit_collection.html— replaced server-side loop with#sounds-gridcontainer +json_scriptdata blocks._sound_card_template.html— HTML<template>for client-side rendering.3. Backend: delta-based editing & featured sounds (
fscollections/)forms.py—CommaSeparatedIdField;CollectionEditFormusesadded_sounds/removed_sounds/featured_soundsdelta fields; atomicsave()withbulk_create(ignore_conflicts).views.py— Sounds serialized as JSON; edit view applies delta from form.models.py—featured_sound_idsJSON field onCollection.tests.py— Existing edit tests updated for delta fields. Four new tests: owner set/clear featured, maintainer changes ignored, featuring absent sound filtered, removing featured sound unfeatures it.Brief description of the workflow
The Django view serializes sounds as JSON into the page.
collectionEdit.jsparses them into aSoundStateStore(bitmask flags per sound).SoundGridEditorrenders paginated cards by cloning_sound_card_template.html, andaddEditActions()wraps each with thedisplay_sound_with_actionstoggle buttons.initializeObjectSelectorActions()binds those buttons tostore.toggleAction(), which flips the flag and firesonChange— re-rendering the grid. The add-sounds modal feeds new sounds viastore.add(). On submit, hidden inputs are populated fromstore.idsWithFlag()and the backend applies the delta atomically inCollectionEditForm.save().