Skip to content

Commit

Permalink
Merge 459d113 into f48b05d
Browse files Browse the repository at this point in the history
  • Loading branch information
RohanJnr committed Feb 11, 2024
2 parents f48b05d + 459d113 commit 2595757
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 95 deletions.
92 changes: 92 additions & 0 deletions pydis_site/apps/resources/apps.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,99 @@
from pathlib import Path

import yaml
from django.apps import AppConfig

from pydis_site import settings
from pydis_site.apps.resources.templatetags.to_kebabcase import to_kebabcase

RESOURCES_PATH = Path(settings.BASE_DIR, "pydis_site", "apps", "resources", "resources")


class ResourcesConfig(AppConfig):
"""AppConfig instance for Resources app."""

name = 'pydis_site.apps.resources'

@staticmethod
def _sort_key_disregard_the(tuple_: tuple) -> str:
"""Sort a tuple by its key alphabetically, disregarding 'the' as a prefix."""
name, resource = tuple_
name = name.casefold()
if name.startswith(("the ", "the_")):
return name[4:]
return name


def ready(self) -> None:
"""Set up all the resources."""
# Load the resources from the yaml files in /resources/
self.resources = {
path.stem: yaml.safe_load(path.read_text())
for path in RESOURCES_PATH.rglob("*.yaml")
}

# Sort the resources alphabetically
self.resources = dict(sorted(self.resources.items(), key=self._sort_key_disregard_the))

# Parse out all current tags
resource_tags = {
"topics": set(),
"payment_tiers": set(),
"difficulty": set(),
"type": set(),
}
for resource_name, resource in self.resources.items():
css_classes = []
for tag_type in resource_tags:
# Store the tags into `resource_tags`
tags = resource.get("tags", {}).get(tag_type, [])
for tag in tags:
tag = tag.title()
tag = tag.replace("And", "and")
resource_tags[tag_type].add(tag)

# Make a CSS class friendly representation too, while we're already iterating.
for tag in tags:
css_tag = to_kebabcase(f"{tag_type}-{tag}")
css_classes.append(css_tag)

# Now add the css classes back to the resource, so we can use them in the template.
self.resources[resource_name]["css_classes"] = " ".join(css_classes)

# Set up all the filter checkbox metadata
self.filters = {
"Difficulty": {
"filters": sorted(resource_tags.get("difficulty")),
"icon": "fas fa-brain",
"hidden": False,
},
"Type": {
"filters": sorted(resource_tags.get("type")),
"icon": "fas fa-photo-video",
"hidden": False,
},
"Payment tiers": {
"filters": sorted(resource_tags.get("payment_tiers")),
"icon": "fas fa-dollar-sign",
"hidden": True,
},
"Topics": {
"filters": sorted(resource_tags.get("topics")),
"icon": "fas fa-lightbulb",
"hidden": True,
}
}

# The bottom topic should always be "Other".
self.filters["Topics"]["filters"].remove("Other")
self.filters["Topics"]["filters"].append("Other")

# A complete list of valid filter names
self.valid_filters = {
"topics": [to_kebabcase(topic) for topic in self.filters["Topics"]["filters"]],
"payment_tiers": [
to_kebabcase(tier) for tier in self.filters["Payment tiers"]["filters"]
],
"type": [to_kebabcase(type_) for type_ in self.filters["Type"]["filters"]],
"difficulty": [to_kebabcase(tier) for tier in self.filters["Difficulty"]["filters"]],
}
2 changes: 1 addition & 1 deletion pydis_site/apps/resources/tests/test_resource_data.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import yaml
from django.test import TestCase

from pydis_site.apps.resources.views import RESOURCES_PATH
from pydis_site.apps.resources.apps import RESOURCES_PATH


class TestResourceData(TestCase):
Expand Down
103 changes: 9 additions & 94 deletions pydis_site/apps/resources/views.py
Original file line number Diff line number Diff line change
@@ -1,114 +1,29 @@
import json
from pathlib import Path

import yaml
from django.apps import apps
from django.core.handlers.wsgi import WSGIRequest
from django.http import HttpResponse, HttpResponseNotFound
from django.shortcuts import render
from django.views import View

from pydis_site import settings
from pydis_site.apps.resources.templatetags.to_kebabcase import to_kebabcase

RESOURCES_PATH = Path(settings.BASE_DIR, "pydis_site", "apps", "resources", "resources")
APP_NAME = "resources"


class ResourceView(View):
"""Our curated list of good learning resources."""

@staticmethod
def _sort_key_disregard_the(tuple_: tuple) -> str:
"""Sort a tuple by its key alphabetically, disregarding 'the' as a prefix."""
name, resource = tuple_
name = name.casefold()
if name.startswith(("the ", "the_")):
return name[4:]
return name

def __init__(self, *args, **kwargs):
"""Set up all the resources."""
super().__init__(*args, **kwargs)

# Load the resources from the yaml files in /resources/
self.resources = {
path.stem: yaml.safe_load(path.read_text())
for path in RESOURCES_PATH.rglob("*.yaml")
}

# Sort the resources alphabetically
self.resources = dict(sorted(self.resources.items(), key=self._sort_key_disregard_the))

# Parse out all current tags
resource_tags = {
"topics": set(),
"payment_tiers": set(),
"difficulty": set(),
"type": set(),
}
for resource_name, resource in self.resources.items():
css_classes = []
for tag_type in resource_tags:
# Store the tags into `resource_tags`
tags = resource.get("tags", {}).get(tag_type, [])
for tag in tags:
tag = tag.title()
tag = tag.replace("And", "and")
resource_tags[tag_type].add(tag)

# Make a CSS class friendly representation too, while we're already iterating.
for tag in tags:
css_tag = to_kebabcase(f"{tag_type}-{tag}")
css_classes.append(css_tag)

# Now add the css classes back to the resource, so we can use them in the template.
self.resources[resource_name]["css_classes"] = " ".join(css_classes)

# Set up all the filter checkbox metadata
self.filters = {
"Difficulty": {
"filters": sorted(resource_tags.get("difficulty")),
"icon": "fas fa-brain",
"hidden": False,
},
"Type": {
"filters": sorted(resource_tags.get("type")),
"icon": "fas fa-photo-video",
"hidden": False,
},
"Payment tiers": {
"filters": sorted(resource_tags.get("payment_tiers")),
"icon": "fas fa-dollar-sign",
"hidden": True,
},
"Topics": {
"filters": sorted(resource_tags.get("topics")),
"icon": "fas fa-lightbulb",
"hidden": True,
}
}

# The bottom topic should always be "Other".
self.filters["Topics"]["filters"].remove("Other")
self.filters["Topics"]["filters"].append("Other")

# A complete list of valid filter names
self.valid_filters = {
"topics": [to_kebabcase(topic) for topic in self.filters["Topics"]["filters"]],
"payment_tiers": [
to_kebabcase(tier) for tier in self.filters["Payment tiers"]["filters"]
],
"type": [to_kebabcase(type_) for type_ in self.filters["Type"]["filters"]],
"difficulty": [to_kebabcase(tier) for tier in self.filters["Difficulty"]["filters"]],
}

def get(self, request: WSGIRequest, resource_type: str | None = None) -> HttpResponse:
"""List out all the resources, and any filtering options from the URL."""
# Add type filtering if the request is made to somewhere like /resources/video.
# We also convert all spaces to dashes, so they'll correspond with the filters.

app = apps.get_app_config(APP_NAME)

if resource_type:
dashless_resource_type = resource_type.replace("-", " ")

if dashless_resource_type.title() not in self.filters["Type"]["filters"]:
if dashless_resource_type.title() not in app.filters["Type"]["filters"]:
return HttpResponseNotFound()

resource_type = resource_type.replace(" ", "-")
Expand All @@ -117,9 +32,9 @@ def get(self, request: WSGIRequest, resource_type: str | None = None) -> HttpRes
request,
template_name="resources/resources.html",
context={
"resources": self.resources,
"filters": self.filters,
"valid_filters": json.dumps(self.valid_filters),
"resources": app.resources,
"filters": app.filters,
"valid_filters": json.dumps(app.valid_filters),
"resource_type": resource_type,
}
)

0 comments on commit 2595757

Please sign in to comment.