From 5d9d6eec3159a9c87ca45dc5b294534daf8495fa Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Fri, 19 Apr 2019 15:29:27 +0200 Subject: Addressing all comments in volcyy's second review. The tests now mock the API calls so we don't have to actually call the API every time we run tests. --- pydis_site/apps/home/__init__.py | 0 pydis_site/apps/home/apps.py | 5 + pydis_site/apps/home/migrations/0001_initial.py | 26 +++++ pydis_site/apps/home/migrations/__init__.py | 0 pydis_site/apps/home/models/__init__.py | 3 + pydis_site/apps/home/models/repo_data.py | 33 +++++++ pydis_site/apps/home/templatetags/__init__.py | 3 + pydis_site/apps/home/templatetags/extra_filters.py | 8 ++ pydis_site/apps/home/tests/__init__.py | 0 .../apps/home/tests/mock_github_api_response.json | 44 +++++++++ .../apps/home/tests/test_repodata_helpers.py | 92 +++++++++++++++++ pydis_site/apps/home/tests/test_templatetags.py | 8 ++ pydis_site/apps/home/tests/test_views.py | 9 ++ pydis_site/apps/home/urls.py | 10 ++ pydis_site/apps/home/views/__init__.py | 3 + pydis_site/apps/home/views/home.py | 110 +++++++++++++++++++++ pydis_site/apps/main/__init__.py | 0 pydis_site/apps/main/apps.py | 5 - pydis_site/apps/main/migrations/0001_initial.py | 26 ----- pydis_site/apps/main/migrations/__init__.py | 0 pydis_site/apps/main/models/__init__.py | 3 - pydis_site/apps/main/models/repo_data.py | 33 ------- pydis_site/apps/main/templatetags/__init__.py | 3 - pydis_site/apps/main/templatetags/extra_filters.py | 8 -- pydis_site/apps/main/tests/__init__.py | 0 .../apps/main/tests/test_repodata_helpers.py | 66 ------------- pydis_site/apps/main/tests/test_templatetags.py | 8 -- pydis_site/apps/main/tests/test_views.py | 9 -- pydis_site/apps/main/urls.py | 11 --- pydis_site/apps/main/views/__init__.py | 3 - pydis_site/apps/main/views/home.py | 101 ------------------- pydis_site/hosts.py | 2 +- pydis_site/settings.py | 12 +-- pydis_site/static/css/base/base.css | 32 +++--- pydis_site/static/css/home/index.css | 12 ++- pydis_site/templates/base/navbar.html | 2 +- pydis_site/templates/home/index.html | 16 +-- pydis_site/urls.py | 2 +- 38 files changed, 390 insertions(+), 318 deletions(-) create mode 100644 pydis_site/apps/home/__init__.py create mode 100644 pydis_site/apps/home/apps.py create mode 100644 pydis_site/apps/home/migrations/0001_initial.py create mode 100644 pydis_site/apps/home/migrations/__init__.py create mode 100644 pydis_site/apps/home/models/__init__.py create mode 100644 pydis_site/apps/home/models/repo_data.py create mode 100644 pydis_site/apps/home/templatetags/__init__.py create mode 100644 pydis_site/apps/home/templatetags/extra_filters.py create mode 100644 pydis_site/apps/home/tests/__init__.py create mode 100644 pydis_site/apps/home/tests/mock_github_api_response.json create mode 100644 pydis_site/apps/home/tests/test_repodata_helpers.py create mode 100644 pydis_site/apps/home/tests/test_templatetags.py create mode 100644 pydis_site/apps/home/tests/test_views.py create mode 100644 pydis_site/apps/home/urls.py create mode 100644 pydis_site/apps/home/views/__init__.py create mode 100644 pydis_site/apps/home/views/home.py delete mode 100644 pydis_site/apps/main/__init__.py delete mode 100644 pydis_site/apps/main/apps.py delete mode 100644 pydis_site/apps/main/migrations/0001_initial.py delete mode 100644 pydis_site/apps/main/migrations/__init__.py delete mode 100644 pydis_site/apps/main/models/__init__.py delete mode 100644 pydis_site/apps/main/models/repo_data.py delete mode 100644 pydis_site/apps/main/templatetags/__init__.py delete mode 100644 pydis_site/apps/main/templatetags/extra_filters.py delete mode 100644 pydis_site/apps/main/tests/__init__.py delete mode 100644 pydis_site/apps/main/tests/test_repodata_helpers.py delete mode 100644 pydis_site/apps/main/tests/test_templatetags.py delete mode 100644 pydis_site/apps/main/tests/test_views.py delete mode 100644 pydis_site/apps/main/urls.py delete mode 100644 pydis_site/apps/main/views/__init__.py delete mode 100644 pydis_site/apps/main/views/home.py (limited to 'pydis_site') diff --git a/pydis_site/apps/home/__init__.py b/pydis_site/apps/home/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pydis_site/apps/home/apps.py b/pydis_site/apps/home/apps.py new file mode 100644 index 00000000..90dc7137 --- /dev/null +++ b/pydis_site/apps/home/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class HomeConfig(AppConfig): + name = 'home' diff --git a/pydis_site/apps/home/migrations/0001_initial.py b/pydis_site/apps/home/migrations/0001_initial.py new file mode 100644 index 00000000..a2bf9f3e --- /dev/null +++ b/pydis_site/apps/home/migrations/0001_initial.py @@ -0,0 +1,26 @@ +# Generated by Django 2.2 on 2019-04-16 15:27 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='RepositoryMetadata', + fields=[ + ('last_updated', models.DateTimeField(default=django.utils.timezone.now, help_text='The date and time this data was last fetched.')), + ('repo_name', models.CharField(help_text='The full name of the repo, e.g. python-discord/site', max_length=40, primary_key=True, serialize=False)), + ('description', models.CharField(help_text='The description of the repo.', max_length=400)), + ('forks', models.IntegerField(help_text='The number of forks of this repo')), + ('stargazers', models.IntegerField(help_text='The number of stargazers for this repo')), + ('language', models.CharField(help_text='The primary programming language used for this repo.', max_length=20)), + ], + ), + ] diff --git a/pydis_site/apps/home/migrations/__init__.py b/pydis_site/apps/home/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pydis_site/apps/home/models/__init__.py b/pydis_site/apps/home/models/__init__.py new file mode 100644 index 00000000..f327795a --- /dev/null +++ b/pydis_site/apps/home/models/__init__.py @@ -0,0 +1,3 @@ +from .repo_data import RepositoryMetadata + +__all__ = ["RepositoryMetadata"] diff --git a/pydis_site/apps/home/models/repo_data.py b/pydis_site/apps/home/models/repo_data.py new file mode 100644 index 00000000..c975c904 --- /dev/null +++ b/pydis_site/apps/home/models/repo_data.py @@ -0,0 +1,33 @@ +from django.db import models +from django.utils import timezone + + +class RepositoryMetadata(models.Model): + """Information about one of our repos fetched from the GitHub API.""" + + last_updated = models.DateTimeField( + default=timezone.now, + help_text="The date and time this data was last fetched." + ) + repo_name = models.CharField( + primary_key=True, + max_length=40, + help_text="The full name of the repo, e.g. python-discord/site" + ) + description = models.CharField( + max_length=400, + help_text="The description of the repo." + ) + forks = models.IntegerField( + help_text="The number of forks of this repo" + ) + stargazers = models.IntegerField( + help_text="The number of stargazers for this repo" + ) + language = models.CharField( + max_length=20, + help_text="The primary programming language used for this repo." + ) + + def __str__(self): + return self.repo_name diff --git a/pydis_site/apps/home/templatetags/__init__.py b/pydis_site/apps/home/templatetags/__init__.py new file mode 100644 index 00000000..70aca169 --- /dev/null +++ b/pydis_site/apps/home/templatetags/__init__.py @@ -0,0 +1,3 @@ +from .extra_filters import starts_with + +__all__ = ["starts_with"] diff --git a/pydis_site/apps/home/templatetags/extra_filters.py b/pydis_site/apps/home/templatetags/extra_filters.py new file mode 100644 index 00000000..edffe9ac --- /dev/null +++ b/pydis_site/apps/home/templatetags/extra_filters.py @@ -0,0 +1,8 @@ +from django import template + +register = template.Library() + + +@register.filter +def starts_with(value: str, arg: str): + return value.startswith(arg) diff --git a/pydis_site/apps/home/tests/__init__.py b/pydis_site/apps/home/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pydis_site/apps/home/tests/mock_github_api_response.json b/pydis_site/apps/home/tests/mock_github_api_response.json new file mode 100644 index 00000000..37dc672e --- /dev/null +++ b/pydis_site/apps/home/tests/mock_github_api_response.json @@ -0,0 +1,44 @@ +[ + { + "full_name": "python-discord/bot", + "description": "test", + "stargazers_count": 97, + "language": "Python", + "forks_count": 31 + }, + { + "full_name": "python-discord/site", + "description": "test", + "stargazers_count": 97, + "language": "Python", + "forks_count": 31 + }, + { + "full_name": "python-discord/snekbox", + "description": "test", + "stargazers_count": 97, + "language": "Python", + "forks_count": 31 + }, + { + "full_name": "python-discord/django-simple-bulma", + "description": "test", + "stargazers_count": 97, + "language": "Python", + "forks_count": 31 + }, + { + "full_name": "python-discord/django-crispy-bulma", + "description": "test", + "stargazers_count": 97, + "language": "Python", + "forks_count": 31 + }, + { + "full_name": "python-discord/seasonalbot", + "description": "test", + "stargazers_count": 97, + "language": "Python", + "forks_count": 31 + } +] diff --git a/pydis_site/apps/home/tests/test_repodata_helpers.py b/pydis_site/apps/home/tests/test_repodata_helpers.py new file mode 100644 index 00000000..8ab2a467 --- /dev/null +++ b/pydis_site/apps/home/tests/test_repodata_helpers.py @@ -0,0 +1,92 @@ +import json +from datetime import timedelta +from pathlib import Path +from unittest import mock + +from django.test import TestCase +from django.utils import timezone + +from pydis_site.apps.home.models import RepositoryMetadata +from pydis_site.apps.home.views import HomeView + + +def mocked_requests_get(*args, **kwargs): + """A mock version of requests.get, so we don't need to call the API every time we run a test""" + class MockResponse: + def __init__(self, json_data, status_code): + self.json_data = json_data + self.status_code = status_code + + def json(self): + return self.json_data + + if args[0] == HomeView.github_api: + json_path = Path(__file__).resolve().parent / "mock_github_api_response.json" + with open(json_path, 'r') as json_file: + mock_data = json.load(json_file) + + return MockResponse(mock_data, 200) + + return MockResponse(None, 404) + + +class TestRepositoryMetadataHelpers(TestCase): + + def setUp(self): + """Executed before each test method.""" + + self.home_view = HomeView() + + @mock.patch('requests.get', side_effect=mocked_requests_get) + def test_returns_metadata(self, _): + """Test if the _get_repo_data helper actually returns what it should.""" + + metadata = self.home_view._get_repo_data() + + self.assertIsInstance(metadata[0], RepositoryMetadata) + self.assertEquals(len(metadata), len(self.home_view.repos)) + + def test_returns_cached_metadata(self): + """Test if the _get_repo_data helper returns cached data when available.""" + + repo_data = RepositoryMetadata( + repo_name="python-discord/site", + description="testrepo", + forks=42, + stargazers=42, + language="English", + ) + repo_data.save() + metadata = self.home_view._get_repo_data() + + self.assertIsInstance(metadata[0], RepositoryMetadata) + self.assertIsInstance(str(metadata[0]), str) + + @mock.patch('requests.get', side_effect=mocked_requests_get) + def test_refresh_stale_metadata(self, _): + """Test if the _get_repo_data helper will refresh when the data is stale""" + + repo_data = RepositoryMetadata( + repo_name="python-discord/site", + description="testrepo", + forks=42, + stargazers=42, + language="English", + last_updated=timezone.now() - timedelta(seconds=121), # Make the data 2 minutes old. + ) + repo_data.save() + metadata = self.home_view._get_repo_data() + + self.assertIsInstance(metadata[0], RepositoryMetadata) + + @mock.patch('requests.get', side_effect=mocked_requests_get) + def test_returns_api_data(self, _): + """Tests if the _get_api_data helper returns what it should.""" + + api_data = self.home_view._get_api_data() + repo = self.home_view.repos[0] + + self.assertIsInstance(api_data, dict) + self.assertEquals(len(api_data), len(self.home_view.repos)) + self.assertIn(repo, api_data.keys()) + self.assertIn("stargazers_count", api_data[repo]) diff --git a/pydis_site/apps/home/tests/test_templatetags.py b/pydis_site/apps/home/tests/test_templatetags.py new file mode 100644 index 00000000..813588c8 --- /dev/null +++ b/pydis_site/apps/home/tests/test_templatetags.py @@ -0,0 +1,8 @@ +from django.test import TestCase + +from pydis_site.apps.home.templatetags import starts_with + + +class TestTemplateTags(TestCase): + def test_starts_with(self): + self.assertTrue(starts_with('foo', 'f')) diff --git a/pydis_site/apps/home/tests/test_views.py b/pydis_site/apps/home/tests/test_views.py new file mode 100644 index 00000000..73678b0a --- /dev/null +++ b/pydis_site/apps/home/tests/test_views.py @@ -0,0 +1,9 @@ +from django.test import TestCase +from django_hosts.resolvers import reverse + + +class TestIndexReturns200(TestCase): + def test_index_returns_200(self): + url = reverse('home') + resp = self.client.get(url) + self.assertEqual(resp.status_code, 200) diff --git a/pydis_site/apps/home/urls.py b/pydis_site/apps/home/urls.py new file mode 100644 index 00000000..d8dba2f6 --- /dev/null +++ b/pydis_site/apps/home/urls.py @@ -0,0 +1,10 @@ +from django.contrib import admin +from django.urls import path + +from .views import HomeView + +app_name = 'home' +urlpatterns = [ + path('', HomeView.as_view(), name='home'), + path('admin/', admin.site.urls) +] diff --git a/pydis_site/apps/home/views/__init__.py b/pydis_site/apps/home/views/__init__.py new file mode 100644 index 00000000..971d73a3 --- /dev/null +++ b/pydis_site/apps/home/views/__init__.py @@ -0,0 +1,3 @@ +from .home import HomeView + +__all__ = ["HomeView"] diff --git a/pydis_site/apps/home/views/home.py b/pydis_site/apps/home/views/home.py new file mode 100644 index 00000000..c91d13e2 --- /dev/null +++ b/pydis_site/apps/home/views/home.py @@ -0,0 +1,110 @@ +import requests +from django.shortcuts import render +from django.utils import timezone +from django.views import View + +from pydis_site.apps.home.models import RepositoryMetadata + + +class HomeView(View): + """The view""" + + github_api = "https://api.github.com/users/python-discord/repos" + + # Which of our GitHub repos should be displayed on the front page, and in which order? + repos = [ + "python-discord/site", + "python-discord/bot", + "python-discord/snekbox", + "python-discord/seasonalbot", + "python-discord/django-simple-bulma", + "python-discord/django-crispy-bulma", + ] + + def _get_api_data(self): + """Call the GitHub API and get information about our repos.""" + + repo_dict = {repo_name: {} for repo_name in self.repos} + + # Fetch the data from the GitHub API + api_data = requests.get(self.github_api) + api_data = api_data.json() + + # Process the API data into our dict + for repo in api_data: + full_name = repo["full_name"] + + if full_name in self.repos: + repo_dict[full_name] = { + "full_name": repo["full_name"], + "description": repo["description"], + "language": repo["language"], + "forks_count": repo["forks_count"], + "stargazers_count": repo["stargazers_count"], + } + return repo_dict + + def _get_repo_data(self): + """Build a list of RepositoryMetadata objects that we can use to populate the front page.""" + + # Try to get site data from the cache + try: + repo_data = RepositoryMetadata.objects.get(repo_name="python-discord/site") + + # If the data is older than 2 minutes, we should refresh it. + if (timezone.now() - repo_data.last_updated).seconds > 120: + + # Get new data from API + api_repositories = self._get_api_data() + database_repositories = [] + + # Update or create all RepoData objects in self.repos + for repo_name, api_data in api_repositories.items(): + try: + repo_data = RepositoryMetadata.objects.get(repo_name=repo_name) + repo_data.description = api_data["description"] + repo_data.language = api_data["language"] + repo_data.forks = api_data["forks_count"] + repo_data.stargazers = api_data["stargazers_count"] + except RepositoryMetadata.DoesNotExist: + repo_data = RepositoryMetadata( + repo_name=api_data["full_name"], + description=api_data["description"], + forks=api_data["forks_count"], + stargazers=api_data["stargazers_count"], + language=api_data["language"], + ) + repo_data.save() + database_repositories.append(repo_data) + return database_repositories + + # Otherwise, if the data is fresher than 2 minutes old, we should just return it. + else: + return RepositoryMetadata.objects.all() + + # If this is raised, the database has no repodata at all, we will create them all. + except RepositoryMetadata.DoesNotExist: + + # Get new data from API + api_repositories = self._get_api_data() + database_repositories = [] + + # Create all the repodata records in the database. + for api_data in api_repositories.values(): + repo_data = RepositoryMetadata( + repo_name=api_data["full_name"], + description=api_data["description"], + forks=api_data["forks_count"], + stargazers=api_data["stargazers_count"], + language=api_data["language"], + ) + repo_data.save() + database_repositories.append(repo_data) + + return database_repositories + + def get(self, request): + """Collect repo data and render the homepage view""" + + repo_data = self._get_repo_data() + return render(request, "home/index.html", {"repo_data": repo_data}) diff --git a/pydis_site/apps/main/__init__.py b/pydis_site/apps/main/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pydis_site/apps/main/apps.py b/pydis_site/apps/main/apps.py deleted file mode 100644 index 90dc7137..00000000 --- a/pydis_site/apps/main/apps.py +++ /dev/null @@ -1,5 +0,0 @@ -from django.apps import AppConfig - - -class HomeConfig(AppConfig): - name = 'home' diff --git a/pydis_site/apps/main/migrations/0001_initial.py b/pydis_site/apps/main/migrations/0001_initial.py deleted file mode 100644 index a2bf9f3e..00000000 --- a/pydis_site/apps/main/migrations/0001_initial.py +++ /dev/null @@ -1,26 +0,0 @@ -# Generated by Django 2.2 on 2019-04-16 15:27 - -from django.db import migrations, models -import django.utils.timezone - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ] - - operations = [ - migrations.CreateModel( - name='RepositoryMetadata', - fields=[ - ('last_updated', models.DateTimeField(default=django.utils.timezone.now, help_text='The date and time this data was last fetched.')), - ('repo_name', models.CharField(help_text='The full name of the repo, e.g. python-discord/site', max_length=40, primary_key=True, serialize=False)), - ('description', models.CharField(help_text='The description of the repo.', max_length=400)), - ('forks', models.IntegerField(help_text='The number of forks of this repo')), - ('stargazers', models.IntegerField(help_text='The number of stargazers for this repo')), - ('language', models.CharField(help_text='The primary programming language used for this repo.', max_length=20)), - ], - ), - ] diff --git a/pydis_site/apps/main/migrations/__init__.py b/pydis_site/apps/main/migrations/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pydis_site/apps/main/models/__init__.py b/pydis_site/apps/main/models/__init__.py deleted file mode 100644 index f327795a..00000000 --- a/pydis_site/apps/main/models/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .repo_data import RepositoryMetadata - -__all__ = ["RepositoryMetadata"] diff --git a/pydis_site/apps/main/models/repo_data.py b/pydis_site/apps/main/models/repo_data.py deleted file mode 100644 index c975c904..00000000 --- a/pydis_site/apps/main/models/repo_data.py +++ /dev/null @@ -1,33 +0,0 @@ -from django.db import models -from django.utils import timezone - - -class RepositoryMetadata(models.Model): - """Information about one of our repos fetched from the GitHub API.""" - - last_updated = models.DateTimeField( - default=timezone.now, - help_text="The date and time this data was last fetched." - ) - repo_name = models.CharField( - primary_key=True, - max_length=40, - help_text="The full name of the repo, e.g. python-discord/site" - ) - description = models.CharField( - max_length=400, - help_text="The description of the repo." - ) - forks = models.IntegerField( - help_text="The number of forks of this repo" - ) - stargazers = models.IntegerField( - help_text="The number of stargazers for this repo" - ) - language = models.CharField( - max_length=20, - help_text="The primary programming language used for this repo." - ) - - def __str__(self): - return self.repo_name diff --git a/pydis_site/apps/main/templatetags/__init__.py b/pydis_site/apps/main/templatetags/__init__.py deleted file mode 100644 index 70aca169..00000000 --- a/pydis_site/apps/main/templatetags/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .extra_filters import starts_with - -__all__ = ["starts_with"] diff --git a/pydis_site/apps/main/templatetags/extra_filters.py b/pydis_site/apps/main/templatetags/extra_filters.py deleted file mode 100644 index edffe9ac..00000000 --- a/pydis_site/apps/main/templatetags/extra_filters.py +++ /dev/null @@ -1,8 +0,0 @@ -from django import template - -register = template.Library() - - -@register.filter -def starts_with(value: str, arg: str): - return value.startswith(arg) diff --git a/pydis_site/apps/main/tests/__init__.py b/pydis_site/apps/main/tests/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pydis_site/apps/main/tests/test_repodata_helpers.py b/pydis_site/apps/main/tests/test_repodata_helpers.py deleted file mode 100644 index 040acb21..00000000 --- a/pydis_site/apps/main/tests/test_repodata_helpers.py +++ /dev/null @@ -1,66 +0,0 @@ -from datetime import timedelta - -from django.conf import settings -from django.test import TestCase -from django.utils import timezone - -from pydis_site.apps.main.models import RepositoryMetadata -from pydis_site.apps.main.views import HomeView - - -class TestRepositoryMetadataHelpers(TestCase): - - def test_returns_metadata(self): - """Test if the _get_repo_data helper actually returns what it should.""" - - home_view = HomeView() - metadata = home_view._get_repo_data() - - self.assertIsInstance(metadata[0], RepositoryMetadata) - self.assertEquals(len(metadata), len(settings.HOMEPAGE_REPOS)) - - def test_returns_cached_metadata(self): - """Test if the _get_repo_data helper returns cached data when available.""" - - home_view = HomeView() - repo_data = RepositoryMetadata( - repo_name="python-discord/site", - description="testrepo", - forks=42, - stargazers=42, - language="English", - ) - repo_data.save() - metadata = home_view._get_repo_data() - - self.assertIsInstance(metadata[0], RepositoryMetadata) - print(metadata[0]) # Tests the __str__ in the model - - def test_refresh_stale_metadata(self): - """Test if the _get_repo_data helper will refresh when the data is stale""" - - home_view = HomeView() - repo_data = RepositoryMetadata( - repo_name="python-discord/site", - description="testrepo", - forks=42, - stargazers=42, - language="English", - last_updated=timezone.now() - timedelta(seconds=121), # Make the data 2 minutes old. - ) - repo_data.save() - metadata = home_view._get_repo_data() - - self.assertIsInstance(metadata[0], RepositoryMetadata) - - def test_returns_api_data(self): - """Tests if the _get_api_data helper returns what it should.""" - - home_view = HomeView() - api_data = home_view._get_api_data() - repo = settings.HOMEPAGE_REPOS[0] - - self.assertIsInstance(api_data, dict) - self.assertEquals(len(api_data), len(settings.HOMEPAGE_REPOS)) - self.assertIn(repo, api_data.keys()) - self.assertIn("stargazers_count", api_data[repo]) diff --git a/pydis_site/apps/main/tests/test_templatetags.py b/pydis_site/apps/main/tests/test_templatetags.py deleted file mode 100644 index 44a5c491..00000000 --- a/pydis_site/apps/main/tests/test_templatetags.py +++ /dev/null @@ -1,8 +0,0 @@ -from django.test import TestCase - -from pydis_site.apps.main.templatetags import starts_with - - -class TestTemplateTags(TestCase): - def test_starts_with(self): - self.assertTrue(starts_with('foo', 'f')) diff --git a/pydis_site/apps/main/tests/test_views.py b/pydis_site/apps/main/tests/test_views.py deleted file mode 100644 index 73678b0a..00000000 --- a/pydis_site/apps/main/tests/test_views.py +++ /dev/null @@ -1,9 +0,0 @@ -from django.test import TestCase -from django_hosts.resolvers import reverse - - -class TestIndexReturns200(TestCase): - def test_index_returns_200(self): - url = reverse('home') - resp = self.client.get(url) - self.assertEqual(resp.status_code, 200) diff --git a/pydis_site/apps/main/urls.py b/pydis_site/apps/main/urls.py deleted file mode 100644 index edef9873..00000000 --- a/pydis_site/apps/main/urls.py +++ /dev/null @@ -1,11 +0,0 @@ -from django.contrib import admin -from django.urls import path - -from .views import HomeView - - -app_name = 'main' -urlpatterns = [ - path('', HomeView.as_view(), name='home'), - path('admin/', admin.site.urls) -] diff --git a/pydis_site/apps/main/views/__init__.py b/pydis_site/apps/main/views/__init__.py deleted file mode 100644 index 971d73a3..00000000 --- a/pydis_site/apps/main/views/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .home import HomeView - -__all__ = ["HomeView"] diff --git a/pydis_site/apps/main/views/home.py b/pydis_site/apps/main/views/home.py deleted file mode 100644 index d9255ed2..00000000 --- a/pydis_site/apps/main/views/home.py +++ /dev/null @@ -1,101 +0,0 @@ -import requests -from django.conf import settings -from django.shortcuts import render -from django.utils import timezone -from django.views import View - -from pydis_site.apps.main.models import RepositoryMetadata - -GITHUB_API = "https://api.github.com/users/python-discord/repos" - - -class HomeView(View): - - @staticmethod - def _get_api_data(): - """Call the GitHub API and get information about our repos.""" - - repo_dict = {repo_name: {} for repo_name in settings.HOMEPAGE_REPOS} - - # Fetch the data from the GitHub API - api_data = requests.get(GITHUB_API) - api_data = api_data.json() - - # Process the API data into our dict - for repo in api_data: - full_name = repo["full_name"] - - if full_name in settings.HOMEPAGE_REPOS: - repo_dict[full_name] = { - "full_name": repo["full_name"], - "description": repo["description"], - "language": repo["language"], - "forks_count": repo["forks_count"], - "stargazers_count": repo["stargazers_count"], - } - return repo_dict - - def _get_repo_data(self): - """Build a list of RepositoryMetadata objects that we can use to populate the front page.""" - - # Try to get site data from the cache - try: - repo_data = RepositoryMetadata.objects.get(repo_name="python-discord/site") - - # If the data is older than 2 minutes, we should refresh it. - if (timezone.now() - repo_data.last_updated).seconds > 120: - - # Get new data from API - api_data_container = self._get_api_data() - repo_data_container = [] - - # Update or create all RepoData objects in settings.HOMEPAGE_REPOS - for repo_name, api_data in api_data_container.items(): - try: - repo_data = RepositoryMetadata.objects.get(repo_name=repo_name) - repo_data.description = api_data["description"] - repo_data.language = api_data["language"] - repo_data.forks = api_data["forks_count"] - repo_data.stargazers = api_data["stargazers_count"] - except RepositoryMetadata.DoesNotExist: - repo_data = RepositoryMetadata( - repo_name=api_data["full_name"], - description=api_data["description"], - forks=api_data["forks_count"], - stargazers=api_data["stargazers_count"], - language=api_data["language"], - ) - repo_data.save() - repo_data_container.append(repo_data) - return repo_data_container - - # Otherwise, if the data is fresher than 2 minutes old, we should just return it. - else: - return RepositoryMetadata.objects.all() - - # If this is raised, the database has no repodata at all, we will create them all. - except RepositoryMetadata.DoesNotExist: - - # Get new data from API - api_data_container = self._get_api_data() - repo_data_container = [] - - # Create all the repodata records in the database. - for api_data in api_data_container.values(): - repo_data = RepositoryMetadata( - repo_name=api_data["full_name"], - description=api_data["description"], - forks=api_data["forks_count"], - stargazers=api_data["stargazers_count"], - language=api_data["language"], - ) - repo_data.save() - repo_data_container.append(repo_data) - - return repo_data_container - - def get(self, request): - """Collect repo data and render the homepage view""" - - repo_data = self._get_repo_data() - return render(request, "home/index.html", {"repo_data": repo_data}) diff --git a/pydis_site/hosts.py b/pydis_site/hosts.py index 9e58628c..0fa4793d 100644 --- a/pydis_site/hosts.py +++ b/pydis_site/hosts.py @@ -5,5 +5,5 @@ host_patterns = patterns( '', host(r'admin', 'pydis_site.apps.admin.urls', name="admin"), host(r'api', 'pydis_site.apps.api.urls', name='api'), - host(r'.*', 'pydis_site.apps.main.urls', name=settings.DEFAULT_HOST) + host(r'.*', 'pydis_site.apps.home.urls', name=settings.DEFAULT_HOST) ) diff --git a/pydis_site/settings.py b/pydis_site/settings.py index eb21de10..891084c9 100644 --- a/pydis_site/settings.py +++ b/pydis_site/settings.py @@ -63,7 +63,7 @@ else: INSTALLED_APPS = [ 'pydis_site.apps.api', - 'pydis_site.apps.main', + 'pydis_site.apps.home', 'django.contrib.admin', 'django.contrib.auth', @@ -258,13 +258,3 @@ BULMA_SETTINGS = { "footer-padding": "1rem 1.5rem 1rem", } } - -# Which of our GitHub repos should be displayed on the front page, and in which order? -HOMEPAGE_REPOS = [ - "python-discord/site", - "python-discord/bot", - "python-discord/snekbox", - "python-discord/seasonalbot", - "python-discord/django-simple-bulma", - "python-discord/django-crispy-bulma", -] diff --git a/pydis_site/static/css/base/base.css b/pydis_site/static/css/base/base.css index 969511f4..4f656189 100644 --- a/pydis_site/static/css/base/base.css +++ b/pydis_site/static/css/base/base.css @@ -1,15 +1,15 @@ html { - overflow:auto; + overflow: auto; } body.site { - display: flex; - min-height: 100vh; - flex-direction: column; + display: flex; + min-height: 100vh; + flex-direction: column; } main.site-content { - flex: 1; + flex: 1; } div.card.has-equal-height { @@ -19,20 +19,20 @@ div.card.has-equal-height { } #django-logo { - padding-bottom: 2px; - background: url(https://static.djangoproject.com/img/logos/django-logo-negative.png) no-repeat center; - filter: grayscale(1) invert(0.02); - background-size: 52px 25.5px; - background-position: -1px -2px; - color: #00000000; + padding-bottom: 2px; + background: url(https://static.djangoproject.com/img/logos/django-logo-negative.png) no-repeat center; + filter: grayscale(1) invert(0.02); + background-size: 52px 25.5px; + background-position: -1px -2px; + color: #00000000; } #bulma-logo { - padding-left: 18px; - height: 20px; - background: url(https://bulma.io/images/bulma-logo-white.png) no-repeat center; - background-size: 60px; - color: #00000000; + padding-left: 18px; + height: 20px; + background: url(https://bulma.io/images/bulma-logo-white.png) no-repeat center; + background-size: 60px; + color: #00000000; } #pydis-text { diff --git a/pydis_site/static/css/home/index.css b/pydis_site/static/css/home/index.css index 9aad02e5..0ad2e6b5 100644 --- a/pydis_site/static/css/home/index.css +++ b/pydis_site/static/css/home/index.css @@ -18,7 +18,7 @@ } .navbar-item.is-fullsize { - padding:0; + padding: 0; } .navbar-item.is-fullsize img { @@ -45,7 +45,7 @@ .video-container object, .video-container embed { width: 100%; - height: calc(92vw*0.5625); + height: calc(92vw * 0.5625); margin: 8px auto auto auto; } @@ -103,11 +103,13 @@ span.repo-language-dot.css { flex: none; width: 50%; } + .columns:not(.is-desktop) { display: flex; } + .video-container iframe { - height: calc(42vw*0.5625); + height: calc(42vw * 0.5625); max-height: 371px; max-width: 660px; } @@ -118,11 +120,13 @@ span.repo-language-dot.css { flex: none; width: 100%; } + .columns:not(.is-desktop) { display: block; } + .video-container iframe { - height: calc(92vw*0.5625); + height: calc(92vw * 0.5625); max-height: none; max-width: none; } diff --git a/pydis_site/templates/base/navbar.html b/pydis_site/templates/base/navbar.html index 6a7e683f..ed6ae118 100644 --- a/pydis_site/templates/base/navbar.html +++ b/pydis_site/templates/base/navbar.html @@ -8,7 +8,7 @@ Python Discord logo - + {# The navbar "burger" which appears when rendered on screens that can't fit the entire nav #}
diff --git a/pydis_site/urls.py b/pydis_site/urls.py index e4ef058b..c68375da 100644 --- a/pydis_site/urls.py +++ b/pydis_site/urls.py @@ -2,5 +2,5 @@ from django.urls import include, path urlpatterns = ( - path('', include('pydis_site.apps.main.urls', namespace='home')), + path('', include('pydis_site.apps.home.urls', namespace='home')), ) -- cgit v1.2.3