Skip to content

Commit

Permalink
Load user profile stats and packs section asynchronously
Browse files Browse the repository at this point in the history
  • Loading branch information
ffont committed Oct 31, 2023
1 parent 4d07c36 commit 2e67db4
Show file tree
Hide file tree
Showing 10 changed files with 122 additions and 56 deletions.
3 changes: 3 additions & 0 deletions accounts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@ def get_absolute_url(self):

def get_user_sounds_in_search_url(self):
return f'{reverse("sounds-search")}?f=username:"{ self.user.username }"&s=Date+added+(newest+first)&g=0'

def get_user_packs_in_search_url(self):
return f'{reverse("sounds-search")}?f=username:"{ self.user.username }"&s=Date+added+(newest+first)&g=1&only_p=1'

@staticmethod
def locations_static(user_id, has_avatar):
Expand Down
31 changes: 27 additions & 4 deletions accounts/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1416,9 +1416,6 @@ def charts(request):
def account(request, username):
user = request.parameter_user
latest_sounds = list(Sound.objects.bulk_sounds_for_user(user.id, settings.SOUNDS_PER_PAGE))
latest_pack_ids = Pack.objects.select_related().filter(user=user, num_sounds__gt=0).exclude(is_deleted=True) \
.order_by("-last_updated").values_list('id', flat=True)[0:10 if not using_beastwhoosh(request) else 15]
latest_packs = Pack.objects.ordered_ids(pack_ids=latest_pack_ids)
following = follow_utils.get_users_following_qs(user)
followers = follow_utils.get_users_followers_qs(user)
following_tags = follow_utils.get_tags_following_qs(user)
Expand Down Expand Up @@ -1452,7 +1449,6 @@ def account(request, username):
'home': request.user == user if using_beastwhoosh(request) else False,
'user': user,
'latest_sounds': latest_sounds,
'latest_packs': latest_packs,
'follow_user_url': follow_user_url,
'following': following,
'followers': followers,
Expand All @@ -1472,6 +1468,33 @@ def account(request, username):
return render(request, 'accounts/account.html', tvars)


@redirect_if_old_username_or_404
def account_stats_section(request, username):
if not request.GET.get('ajax'):
raise Http404 # Only accessible via ajax
user = request.parameter_user
tvars = {
'user': user,
'user_stats': user.profile.get_stats_for_profile_page(),
}
return render(request, 'accounts/account_stats_section.html', tvars)


@redirect_if_old_username_or_404
def account_latest_packs_section(request, username):
if not request.GET.get('ajax'):
raise Http404 # Only accessible via ajax
user = request.parameter_user
latest_pack_ids = Pack.objects.select_related().filter(user=user, num_sounds__gt=0).exclude(is_deleted=True) \
.order_by("-last_updated").values_list('id', flat=True)[0:15]
latest_packs = Pack.objects.ordered_ids(pack_ids=latest_pack_ids)
tvars = {
'user': user,
'latest_packs': latest_packs,
}
return render(request, 'accounts/account_latest_packs_section.html', tvars)


def handle_uploaded_file(user_id, f):
# Move or copy the uploaded file from the temporary folder created by Django to the /uploads path
dest_directory = os.path.join(settings.UPLOADS_PATH, str(user_id))
Expand Down
39 changes: 39 additions & 0 deletions freesound/static/bw-frontend/src/components/asyncSection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {showToast} from "./toast";
import {initPlayersInModal} from './modal';
import {bindSimilarSoundModals} from './similarSoundsModal';
import {bindBookmarkSoundButtons} from './bookmarkSound';
import {bindRemixGroupModals} from './remixGroupModal';

const asyncSectionPlaceholders = document.getElementsByClassName('async-section');

const initPlayersAndPlayerModalsInElement = (element) => {
initPlayersInModal(element);
bindSimilarSoundModals();
bindBookmarkSoundButtons();
bindRemixGroupModals();
}

asyncSectionPlaceholders.forEach(element => {
const contentUrl = element.dataset.asyncSectionContentUrl;

const req = new XMLHttpRequest();
req.open('GET', contentUrl);
req.onload = () => {
if (req.status >= 200 && req.status < 300) {
element.innerHTML = req.responseText;

// Make sure we initialize sound/pack players inside the async section
initPlayersAndPlayerModalsInElement(element);
} else {
// Unexpected errors happened while processing request: show toast
showToast('Unexpected errors occurred while loading some of the content of this page. Please try again later...')
}
};
req.onerror = () => {
// Unexpected errors happened while processing request: show toast
showToast('Unexpected errors occurred while loading some of the content of this page. Please try again later...')
};

// Send the form
req.send();
});
1 change: 1 addition & 0 deletions freesound/static/bw-frontend/src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import './bookmarkSound';
import './checkbox';
import './commentsModal';
import './cookieConsent';
import './asyncSection';
import './djangoMessages';
import './downloadersModals';
import './moderationModals';
Expand Down
10 changes: 2 additions & 8 deletions freesound/static/bw-frontend/src/components/mapsMapbox.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import {initPlayersInModal} from './modal';
import {bindSimilarSoundModals} from './similarSoundsModal';
import {bindBookmarkSoundButtons} from './bookmarkSound';
import {bindRemixGroupModals} from './remixGroupModal';
import {initPlayersAndPlayerModalsInElement} from './asyncSection';
import {stopAllPlayers} from '../components/player/utils'


Expand Down Expand Up @@ -262,10 +259,7 @@ function makeSoundsMap(geotags_url, map_element_id, on_built_callback, on_bounds
zoomLinkElement.onclick = () => {setMaxZoomCenter(zoomLinkElement.dataset.lat, zoomLinkElement.dataset.lon, zoomLinkElement.dataset.zoom)};

// Init sound player inside popup
initPlayersInModal(document.getElementById('infoWindowPlayerWrapper-' + sound_id));
bindSimilarSoundModals();
bindBookmarkSoundButtons();
bindRemixGroupModals();
initPlayersAndPlayerModalsInElement(document.getElementById('infoWindowPlayerWrapper-' + sound_id));
});
});

Expand Down
2 changes: 2 additions & 0 deletions freesound/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@

path('people/', accounts.views.accounts, name="accounts"),
path('people/<username>/', accounts.views.account, name="account"),
path('people/<username>/section/stats/', accounts.views.account_stats_section, name="account-stats-section"),
path('people/<username>/section/latest_packs/', accounts.views.account_latest_packs_section, name="account-latest-packs-section"),
path('people/<username>/sounds/', sounds.views.for_user, name="sounds-for-user"),
path('people/<username>/flag/', accounts.views.flag_user, name="flag-user"),
path('people/<username>/clear_flags/', accounts.views.clear_flags_user, name="clear-flags-user"),
Expand Down
28 changes: 8 additions & 20 deletions templates_bw/accounts/account.html
Original file line number Diff line number Diff line change
Expand Up @@ -156,33 +156,21 @@ <h5>No sounds... &#128543</h5>
{% endif %}
</div>
<div class="bw-profile__tap_container" id="packs">
{% if latest_packs %}
<div class="row">
{% for pack in latest_packs %}
<div class="col-6 col-lg-4">
{% display_pack pack %}
</div>
{% endfor %}
</div>
<div class="v-spacing-top-4 text-center">
<a class="no-hover" href="{% url "sounds-search" %}?f=username:%22{{ user.username }}%22&s=Date+added+(newest+first)&g=1&only_p=1"><button class="btn-primary">See all packs by {{ user.username }}</button></a>
</div>
{% else %}
<div class="text-center">
<h5>No packs... &#128543</h5>
<div class="text-grey v-spacing-top-1">Looks like {{ user.username }} has not uploaded any packs yet</div>
</div>
{% endif %}
<div class="async-section"
data-async-section-content-url="{% url 'account-latest-packs-section' user.username %}?ajax=1">
<img width="12px" height="12px" src="{% static 'bw-frontend/public/bw_indicator.gif' %}">
</div>
</div>
<div class="bw-profile__tap_container" id="tapDownloaded">
downloaded
</div>
</div>
<aside class="col-md-4 col-extra-left-padding-middle-md bw-profile__sections">
<div class="divider-light v-spacing-top-6 v-spacing-5 d-md-none"></div>
{% with user.profile.get_stats_for_profile_page as user_stats %}
{% include 'accounts/account_stats.html' %}
{% endwith %}
<section class="bw-profile__section_stats v-spacing-top-4 async-section"
data-async-section-content-url="{% url 'account-stats-section' user.username %}?ajax=1">
<img width="12px" height="12px" src="{% static 'bw-frontend/public/bw_indicator.gif' %}">
</section>
{% if last_geotags_serialized %}
<div class="divider-light"></div>
<section id="latest_geotags" class="v-spacing-top-4 v-spacing-4" data-map-loaded="false">
Expand Down
18 changes: 18 additions & 0 deletions templates_bw/accounts/account_latest_packs_section.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{% load display_pack %}
{% if latest_packs %}
<div class="row">
{% for pack in latest_packs %}
<div class="col-6 col-lg-4">
{% display_pack pack %}
</div>
{% endfor %}
</div>
<div class="v-spacing-top-4 text-center">
<a class="no-hover" href="{{ user.profile.get_user_packs_in_search_url }}"><button class="btn-primary">See all packs by {{ user.username }}</button></a>
</div>
{% else %}
<div class="text-center">
<h5>No packs... &#128543</h5>
<div class="text-grey v-spacing-top-1">Looks like {{ user.username }} has not uploaded any packs yet</div>
</div>
{% endif %}
24 changes: 0 additions & 24 deletions templates_bw/accounts/account_stats.html

This file was deleted.

22 changes: 22 additions & 0 deletions templates_bw/accounts/account_stats_section.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{% load bw_templatetags %}
{% load util %}
<ol>
<li class="v-spacing-3">
{% bw_icon 'wave' 'text-light-grey' %} <a class="text-19 bw-link--black" title="{{ user.username }} has uploaded {{ user_stats.num_sounds|bw_intcomma }} sound{{ user_stats.num_sounds|pluralize }}" href="{{ user.profile.get_user_sounds_in_search_url }}">{{ user_stats.num_sounds|formatnumber }} sound{{ user_stats.num_sounds|pluralize }}</a>
</li>
<li class="v-spacing-3">
{% bw_icon 'stack' 'text-light-grey' %} <a class="text-19 bw-link--black" title="{{ user.username }} has created {{ user_stats.num_packs|bw_intcomma }} pack{{ user_stats.num_packs|pluralize }}" href="{{ user.profile.get_user_packs_in_search_url }}">{{ user_stats.num_packs|formatnumber }} pack{{ user_stats.num_packs|pluralize }}</a>
</li>
<li class="v-spacing-3">
{% bw_icon 'clock' 'text-light-grey' %} <span class="text-19" title="{{ user.username }}'s sounds together account for {{ user_stats.total_uploaded_sounds_length|duration_hours }} hours of audio">{{ user_stats.total_uploaded_sounds_length|duration_hours }} hours of audio</span>
</li>
<li class="v-spacing-3">
{% bw_icon 'star' 'text-light-grey' %} <span class="text-19" title="{{ user.username }}'s sounds have an average rating of {{ user_stats.avg_rating_0_5|floatformat:1 }}">{{ user_stats.avg_rating_0_5|floatformat:1 }} average rating</span>
</li>
<li class="v-spacing-3">
{% bw_icon 'download' 'text-light-grey' %} <span class="text-19" title="{{ user.username }}'s sounds and packs have been downloaded {{ user_stats.num_downloads }} times">{{ user_stats.num_downloads|formatnumber }} download{{ user_stats.num_downloads|pluralize }}</span>
</li>
<li class="v-spacing-3">
{% bw_icon 'comments' 'text-light-grey' %} <span class="text-19" title="{{ user.username }} has written {{ user_stats.num_posts }} forum posts">{{ user_stats.num_posts|formatnumber }} forum post{{ user_stats.num_posts|pluralize }}</span>
</li>
</ol>

0 comments on commit 2e67db4

Please sign in to comment.