Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 84 additions & 1 deletion apps/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
from PIL import Image, ImageDraw

from django.conf import settings
from django.urls import reverse
from datetime import date, timedelta
from apps.views import get_top_downloaded_apps
from download.models import ReleaseDownloadsByDate
from django.core.files.uploadedfile import SimpleUploadedFile
from django.contrib.auth.models import User
from django.test import TestCase
Expand Down Expand Up @@ -676,4 +680,83 @@ def test_app_button_by_name_found_app(self):
active=True)
appobj.save()
res = app_buttons.app_button_by_name('myapp')
self.assertEqual('myapp', res['app'].name)
self.assertEqual('myapp', res['app'].name)


class TopDownloadedAppsTestCase(TestCase):

def setUp(self):
self.app1 = App.objects.create(name="app1", fullname="App One", active=True)
self.app2 = App.objects.create(name="app2", fullname="App Two", active=True)

uploaded = SimpleUploadedFile("file.jar", b"hello", content_type="text/plain")

self.rel1 = Release.objects.create(
app=self.app1,
version="1.0",
release_file=uploaded,
active=True
)

self.rel2 = Release.objects.create(
app=self.app2,
version="1.0",
release_file=uploaded,
active=True
)

today = date.today()

# within 24 months
ReleaseDownloadsByDate.objects.create(
release=self.rel1,
when=today - timedelta(days=100),
count=100
)

# older than 24 months (ignored)
ReleaseDownloadsByDate.objects.create(
release=self.rel2,
when=today - timedelta(days=900),
count=500
)

def test_top_downloads_returns_apps(self):
apps = list(get_top_downloaded_apps())

self.assertIn(self.app1, apps)
self.assertNotIn(self.app2, apps)

class TagNavigationTests(TestCase):

def setUp(self):
self.tag = Tag.objects.create(name="cluster", fullname="Cluster")

self.active_app = App.objects.create(
name="clusteractive",
fullname="Cluster Active",
active=True
)

self.inactive_app = App.objects.create(
name="clusterinactive",
fullname="Cluster Inactive",
active=False
)

self.active_app.tags.add(self.tag)
self.inactive_app.tags.add(self.tag)

def test_tag_page_shows_only_active_apps(self):
url = reverse("tag_page", args=["cluster"])
response = self.client.get(url)

self.assertEqual(response.status_code, 200)
self.assertContains(response, "Cluster Active")
self.assertNotContains(response, "Cluster Inactive")

def test_inactive_app_page_returns_404(self):
url = reverse("app_page", args=["clusterinactive"])
response = self.client.get(url)

self.assertEqual(response.status_code, 404)
53 changes: 45 additions & 8 deletions apps/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import re
import datetime
import html
from datetime import date, timedelta
from django.db.models import Case, When, IntegerField
from django.db.models import Sum
from download.models import ReleaseDownloadsByDate
from urllib.parse import unquote
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
Expand Down Expand Up @@ -29,15 +33,16 @@ class _NavPanelConfig:
tag_cloud_delta_font_size_em = tag_cloud_max_font_size_em - tag_cloud_min_font_size_em

def _all_tags_of_count(min_count):
return filter(lambda tag: tag.count >= min_count, Tag.objects.all())
return filter(lambda tag: tag.count >= min_count,
Tag.objects.filter(app__active=True).distinct())

_NavPanelContextCache = None

def _nav_panel_context(request):
global _NavPanelContextCache
if _NavPanelContextCache:
return _NavPanelContextCache
all_tags = _all_tags_of_count(_NavPanelConfig.min_tag_count)
all_tags = list(_all_tags_of_count(_NavPanelConfig.min_tag_count))
sorted_tags = sorted(all_tags, key=lambda tag: tag.count)
sorted_tags.reverse()

Expand Down Expand Up @@ -79,10 +84,41 @@ def _flush_tag_caches():
class _DefaultConfig:
num_of_top_apps = 6

def get_top_downloaded_apps(limit=None):
two_years_ago = date.today() - timedelta(days=730)

top_download_data = (
ReleaseDownloadsByDate.objects
.filter(
when__gte=two_years_ago,
release__app__active=True,
release__active=True
)
.values('release__app')
.annotate(total_downloads=Sum('count'))
.order_by('-total_downloads')
)

if limit is not None:
top_download_data = top_download_data[:limit]

app_ids = [item['release__app'] for item in top_download_data]

if not app_ids:
return App.objects.none()

preserved_order = Case(
*[When(id=pk, then=pos) for pos, pk in enumerate(app_ids)],
output_field=IntegerField()
)

return App.objects.filter(id__in=app_ids).order_by(preserved_order)


def apps_default(request):
latest_apps = App.objects.filter(active=True).order_by('-latest_release_date')[:_DefaultConfig.num_of_top_apps]
downloaded_apps = App.objects.filter(active=True).order_by('downloads').reverse()[:_DefaultConfig.num_of_top_apps]

# downloaded_apps = App.objects.filter(active=True).order_by('downloads').reverse()[:_DefaultConfig.num_of_top_apps]
downloaded_apps = get_top_downloaded_apps(_DefaultConfig.num_of_top_apps)
c = {
'latest_apps': latest_apps,
'downloaded_apps': downloaded_apps,
Expand Down Expand Up @@ -110,7 +146,8 @@ def all_apps_newest(request):


def all_apps_downloads(request):
apps = App.objects.filter(active=True).order_by('downloads').reverse()
# apps = App.objects.filter(active=True).order_by('downloads').reverse()
apps = get_top_downloaded_apps()
c = {
'apps': apps,
'navbar_selected_link': 'all',
Expand All @@ -120,10 +157,10 @@ def all_apps_downloads(request):

def wall_of_apps(request):
nav_panel_context = _nav_panel_context(request)
tags = [(tag.fullname, tag.app_set.all()) for tag in nav_panel_context['top_tags']]
tags = [(tag.fullname, tag.app_set.filter(active=True)) for tag in nav_panel_context['top_tags']]
apps_in_not_top_tags = set()
for not_top_tag in nav_panel_context['not_top_tags']:
apps_in_not_top_tags.update(not_top_tag.app_set.all())
apps_in_not_top_tags.update(not_top_tag.app_set.filter(active=True))
tags.append(('other', apps_in_not_top_tags))
c = {
'total_apps_count': App.objects.filter(active=True).count,
Expand Down Expand Up @@ -505,7 +542,7 @@ def app_page_edit(request, app_name):
if is_ajax(request):
return json_response(result)

all_tags = [tag.fullname for tag in Tag.objects.all()]
all_tags = [tag.fullname for tag in Tag.objects.filter(app__active=True).distinct()]
c = {
'app': app,
'all_tags': all_tags,
Expand Down