From c781ed1f80188ffb274eeada974172f4aa07c0b5 Mon Sep 17 00:00:00 2001 From: fisher60 Date: Fri, 23 Jul 2021 20:20:10 -0500 Subject: change resources to prepare for smart resource search --- pydis_site/apps/resources/views/resources.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'pydis_site/apps/resources/views/resources.py') diff --git a/pydis_site/apps/resources/views/resources.py b/pydis_site/apps/resources/views/resources.py index 25ce3e50..dfd21682 100644 --- a/pydis_site/apps/resources/views/resources.py +++ b/pydis_site/apps/resources/views/resources.py @@ -1,7 +1,11 @@ from django.views.generic import TemplateView +from django.shortcuts import render +# class ResourcesView(TemplateView): +# """View for resources index page.""" +# +# template_name = "resources/resources.html" -class ResourcesView(TemplateView): - """View for resources index page.""" - template_name = "resources/resources.html" +def resource_view(request): + return render(request, template_name="resources/resources.html") -- cgit v1.2.3 From 156951f12c05146650a84d4ac9d45e7a8a085023 Mon Sep 17 00:00:00 2001 From: fisher60 Date: Sat, 24 Jul 2021 18:22:59 -0500 Subject: add constant for resource tags. Add Functional front end This change adds a fully functional front end menu for testing. This is a very rough outline and will need a bit of UI and UX love to get working fully. Should act as an example of functionality --- pydis_site/apps/resources/views/resources.py | 25 +++++++-- pydis_site/templates/resources/resources.html | 81 +++++++++++++++++---------- 2 files changed, 71 insertions(+), 35 deletions(-) (limited to 'pydis_site/apps/resources/views/resources.py') diff --git a/pydis_site/apps/resources/views/resources.py b/pydis_site/apps/resources/views/resources.py index dfd21682..f88a23fb 100644 --- a/pydis_site/apps/resources/views/resources.py +++ b/pydis_site/apps/resources/views/resources.py @@ -1,11 +1,24 @@ -from django.views.generic import TemplateView from django.shortcuts import render -# class ResourcesView(TemplateView): -# """View for resources index page.""" -# -# template_name = "resources/resources.html" +from pydis_site.apps.resources.utils import get_resources_meta + +RESOURCE_META_TAGS = get_resources_meta() + + +def format_checkbox_options(options: str) -> list: + """Split up the comma separated parameters into a list.""" + if options: + return options.split(",")[:-1] + return list() def resource_view(request): - return render(request, template_name="resources/resources.html") + """View for resources index page.""" + context = { + "checkboxOptions": format_checkbox_options(request.GET.get("checkboxOptions")), + "topics": RESOURCE_META_TAGS.get("topics"), + "tag_types": RESOURCE_META_TAGS.get("type"), + "payment_tiers": RESOURCE_META_TAGS.get("payment_tiers"), + "complexities": RESOURCE_META_TAGS.get("complexity") + } + return render(request, template_name="resources/resources.html", context=context) diff --git a/pydis_site/templates/resources/resources.html b/pydis_site/templates/resources/resources.html index 7eb21432..fca3d0da 100644 --- a/pydis_site/templates/resources/resources.html +++ b/pydis_site/templates/resources/resources.html @@ -23,55 +23,66 @@
Topic -
- -
- -
-
+ {% endfor %}
Type + + {% for tag_type in tag_types %}
-
+
+ {% endfor %}
Payment + + {% for payment_tier in payment_tiers %}
-
+
+ {% endfor %}
Level + + {% for complexity in complexities %}
-
+
+ {% endfor %} -
- +
+ + + + + + + + +
@@ -79,9 +90,18 @@ {% endblock %} -- cgit v1.2.3 From 0d55308776a029517899f8f26d454b0bb920a9ee Mon Sep 17 00:00:00 2001 From: swfarnsworth Date: Sat, 24 Jul 2021 20:33:11 -0400 Subject: Added type annotations; refactored. --- pydis_site/apps/resources/views/resources.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'pydis_site/apps/resources/views/resources.py') diff --git a/pydis_site/apps/resources/views/resources.py b/pydis_site/apps/resources/views/resources.py index f88a23fb..2414e48b 100644 --- a/pydis_site/apps/resources/views/resources.py +++ b/pydis_site/apps/resources/views/resources.py @@ -1,3 +1,4 @@ +from django.http import HttpRequest, HttpResponse from django.shortcuts import render from pydis_site.apps.resources.utils import get_resources_meta @@ -5,20 +6,21 @@ from pydis_site.apps.resources.utils import get_resources_meta RESOURCE_META_TAGS = get_resources_meta() -def format_checkbox_options(options: str) -> list: +def format_checkbox_options(options: str) -> list[str]: """Split up the comma separated parameters into a list.""" - if options: - return options.split(",")[:-1] - return list() + return options.split(",")[:-1] if options else [] -def resource_view(request): +def resource_view(request: HttpRequest) -> HttpResponse: """View for resources index page.""" - context = { - "checkboxOptions": format_checkbox_options(request.GET.get("checkboxOptions")), - "topics": RESOURCE_META_TAGS.get("topics"), - "tag_types": RESOURCE_META_TAGS.get("type"), - "payment_tiers": RESOURCE_META_TAGS.get("payment_tiers"), - "complexities": RESOURCE_META_TAGS.get("complexity") - } - return render(request, template_name="resources/resources.html", context=context) + return render( + request, + template_name="resources/resources.html", + context={ + "checkboxOptions": format_checkbox_options(request.GET.get("checkboxOptions")), + "topics": RESOURCE_META_TAGS.get("topics"), + "tag_types": RESOURCE_META_TAGS.get("type"), + "payment_tiers": RESOURCE_META_TAGS.get("payment_tiers"), + "complexities": RESOURCE_META_TAGS.get("complexity") + } + ) -- cgit v1.2.3 From 95e7b11df812e09baffe9ef16807e7d02a5e6f1d Mon Sep 17 00:00:00 2001 From: fisher60 Date: Sun, 25 Jul 2021 19:49:01 -0500 Subject: working demo of smart resources search I have incorporated a search that allows users to check boxes to filter resources. This is a working version, but the algo for searching likely needs to be modified. The frontend also needs some style updates. All necessary functionality should be present now though. --- pydis_site/apps/resources/utils.py | 25 ++++++++++++-- pydis_site/apps/resources/views/resources.py | 10 +++--- pydis_site/apps/resources/views/resources_list.py | 4 +-- pydis_site/templates/resources/resources.html | 41 +++++++++++++++++++++-- 4 files changed, 69 insertions(+), 11 deletions(-) (limited to 'pydis_site/apps/resources/views/resources.py') diff --git a/pydis_site/apps/resources/utils.py b/pydis_site/apps/resources/utils.py index bb812ec0..7f238431 100644 --- a/pydis_site/apps/resources/utils.py +++ b/pydis_site/apps/resources/utils.py @@ -15,7 +15,28 @@ default_categories = [ ] -def get_resources() -> list[dict[str, t.Union[list[str], str]]]: +def yaml_file_matches_search(yaml_data: dict[str, t.Union[list[str], str]], search_terms: list[str]) -> bool: + match_count = 0 + search_len = len(search_terms) + for search in search_terms: + for _, values in yaml_data["tags"].items(): + if search.lower() in values: + match_count += 1 + if match_count >= search_len: + return True + return False + + +def get_resources_from_search(search_categories: list[str]) -> list[dict[str, t.Union[list[str], str]]]: + out = [] + for item in RESOURCES_PATH.rglob("*.yaml"): + this_dict = yaml.safe_load(item.read_text()) + if yaml_file_matches_search(this_dict, search_categories): + out.append(this_dict) + return out + + +def get_all_resources() -> list[dict[str, t.Union[list[str], str]]]: """Loads resource YAMLs from provided path.""" return [yaml.safe_load(item.read_text()) for item in RESOURCES_PATH.rglob("*.yaml")] @@ -24,7 +45,7 @@ def get_resources_meta() -> dict[str, list[str]]: """Combines the tags from each resource into one dictionary of unique tags.""" resource_meta_tags = {x: set() for x in default_categories} - for resource in get_resources(): + for resource in get_all_resources(): for tag_key, tag_values in resource.get("tags").items(): for tag_item in tag_values: resource_meta_tags[tag_key].add(tag_item.title().replace('And', 'and', -1)) diff --git a/pydis_site/apps/resources/views/resources.py b/pydis_site/apps/resources/views/resources.py index 2414e48b..ffb4f4a8 100644 --- a/pydis_site/apps/resources/views/resources.py +++ b/pydis_site/apps/resources/views/resources.py @@ -1,26 +1,28 @@ from django.http import HttpRequest, HttpResponse from django.shortcuts import render -from pydis_site.apps.resources.utils import get_resources_meta +from pydis_site.apps.resources.utils import get_all_resources, get_resources_from_search, get_resources_meta RESOURCE_META_TAGS = get_resources_meta() def format_checkbox_options(options: str) -> list[str]: - """Split up the comma separated parameters into a list.""" + """Split up the comma separated query parameters for checkbox options into a list.""" return options.split(",")[:-1] if options else [] def resource_view(request: HttpRequest) -> HttpResponse: """View for resources index page.""" + checkbox_options = format_checkbox_options(request.GET.get("checkboxOptions")) return render( request, template_name="resources/resources.html", context={ - "checkboxOptions": format_checkbox_options(request.GET.get("checkboxOptions")), + "checkboxOptions": checkbox_options, "topics": RESOURCE_META_TAGS.get("topics"), "tag_types": RESOURCE_META_TAGS.get("type"), "payment_tiers": RESOURCE_META_TAGS.get("payment_tiers"), - "complexities": RESOURCE_META_TAGS.get("complexity") + "complexities": RESOURCE_META_TAGS.get("complexity"), + "resources": get_resources_from_search(checkbox_options) } ) diff --git a/pydis_site/apps/resources/views/resources_list.py b/pydis_site/apps/resources/views/resources_list.py index 0ec74d78..bd43be33 100644 --- a/pydis_site/apps/resources/views/resources_list.py +++ b/pydis_site/apps/resources/views/resources_list.py @@ -2,7 +2,7 @@ from typing import Any, Dict from django.views.generic import TemplateView -from pydis_site.apps.resources.utils import get_resources +from pydis_site.apps.resources.utils import get_all_resources class ResourcesListView(TemplateView): @@ -13,6 +13,6 @@ class ResourcesListView(TemplateView): def get_context_data(self, **kwargs) -> Dict[str, Any]: """Add resources and subcategories data into context.""" context = super().get_context_data(**kwargs) - context["resources"] = get_resources() + context["resources"] = get_all_resources() return context diff --git a/pydis_site/templates/resources/resources.html b/pydis_site/templates/resources/resources.html index fca3d0da..e2275e89 100644 --- a/pydis_site/templates/resources/resources.html +++ b/pydis_site/templates/resources/resources.html @@ -1,9 +1,11 @@ {% extends 'base/base.html' %} +{% load as_icon %} {% load static %} {% block title %}Resources{% endblock %} {% block head %} - + + {% endblock %} {% block content %} @@ -89,16 +91,49 @@ + + {% if resources|length > 0 %} +
+
+
+
+ {% for resource in resources %} + {% include "resources/resource_box.html" %} + {% endfor %} + + {% for subcategory in subcategories %} +

+ + {{ subcategory.category_info.name }} + +

+

{{ subcategory.category_info.description|safe }}

+ + {% for resource in subcategory.resources %} + {% with category_info=subcategory.category_info %} + {% include "resources/resource_box.html" %} + {% endwith %} + {% endfor %} + {% endfor %} +
+
+
+
+ {% else %} +

No resources matching search.

+ {% endif %} + + + + {% endblock %} {% block content %} {% include "base/navbar.html" %} - -
-
+ {% if resources|length > 0 %} +
+ {# Headline #}

Resources


-
-

Search Options

- -
-
-
-
Topic
-
-
- {% for topic in topics_1 %} -
- -
- {% endfor %} -
-
- {% for topic in topics_2 %} -
- -
- {% endfor %} -
-
- - - -
-
-
Type
+
+ {# Filtering toolbox #} +
+
+ +
+
- {% for payment_tier in payment_tiers %} -
- -
+ {# Actual resources #} +
+
+
+ {% for resource in resources.values %} + {% include "resources/resource_box.html" %} {% endfor %} - - - -
-
-
Level
+ {% for subcategory in subcategories %} +

+ + {{ subcategory.category_info.name }} + +

+

{{ subcategory.category_info.description|safe }}

- {% for complexity in complexities %} -
- -
- {% endfor %} - - - + {% for resource in subcategory.resources %} + {% with category_info=subcategory.category_info %} + {% include "resources/resource_box.html" %} + {% endwith %} + {% endfor %} + {% endfor %}
- -
- - - - - - - -
-
-
-
- - {% if resources|length > 0 %} -
-
-
-
- {% for resource in resources %} - {% include "resources/resource_box.html" %} - {% endfor %} - - {% for subcategory in subcategories %} -

- - {{ subcategory.category_info.name }} - -

-

{{ subcategory.category_info.description|safe }}

- - {% for resource in subcategory.resources %} - {% with category_info=subcategory.category_info %} - {% include "resources/resource_box.html" %} - {% endwith %} - {% endfor %} - {% endfor %}
-
-
+
{% else %} -

No resources matching search.

+

No resources matching search.

{% endif %} {% endblock %} -- cgit v1.2.3 From e54a3d18e208dd532533b5bbe146b1bff9875ba4 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Sat, 29 Jan 2022 13:42:38 +0100 Subject: Complexity -> Difficulty. --- pydis_site/apps/resources/resources/adafruit.yaml | 2 +- pydis_site/apps/resources/resources/atom.yaml | 2 +- .../apps/resources/resources/automate_the_boring_stuff_book.yaml | 2 +- .../resources/resources/automate_the_boring_stuff_course.yaml | 2 +- .../apps/resources/resources/awesome_programming_discord.yaml | 2 +- pydis_site/apps/resources/resources/byte_of_python.yaml | 2 +- pydis_site/apps/resources/resources/code_combat.yaml | 2 +- pydis_site/apps/resources/resources/corey_schafer.yaml | 2 +- .../apps/resources/resources/data_science_from_scratch.yaml | 2 +- pydis_site/apps/resources/resources/edublocks.yaml | 2 +- pydis_site/apps/resources/resources/effective_python.yaml | 2 +- pydis_site/apps/resources/resources/exercism.yaml | 2 +- pydis_site/apps/resources/resources/flask_web_development.yaml | 2 +- pydis_site/apps/resources/resources/fluent_python.yaml | 2 +- .../apps/resources/resources/getting_started_with_kivy.yaml | 2 +- .../getting_started_with_python_for_non_programmers.yaml | 2 +- .../resources/getting_started_with_python_for_programmers.yaml | 2 +- pydis_site/apps/resources/resources/google_collab.yaml | 2 +- .../apps/resources/resources/hitchhikers_guide_to_python.yaml | 2 +- pydis_site/apps/resources/resources/inferential_thinking.yaml | 2 +- pydis_site/apps/resources/resources/jetbrains_academy.yaml | 2 +- pydis_site/apps/resources/resources/jetbrains_videos.yaml | 2 +- pydis_site/apps/resources/resources/jim_shaped_coding.yaml | 2 +- pydis_site/apps/resources/resources/kaggle_pandas_tutorial.yaml | 2 +- pydis_site/apps/resources/resources/kivy.yaml | 2 +- pydis_site/apps/resources/resources/microsoft.yaml | 2 +- pydis_site/apps/resources/resources/microsoft_videos.yaml | 2 +- pydis_site/apps/resources/resources/mission_python.yaml | 2 +- .../mit_introduction_to_computer_science_and_programming.yaml | 2 +- pydis_site/apps/resources/resources/mu_editor.yaml | 2 +- pydis_site/apps/resources/resources/netbats_project_ideas.yaml | 2 +- .../resources/neural_networks_from_scratch_in_python.yaml | 2 +- pydis_site/apps/resources/resources/pallets.yaml | 2 +- pydis_site/apps/resources/resources/panda3d.yaml | 2 +- pydis_site/apps/resources/resources/people_postgres_data.yaml | 2 +- pydis_site/apps/resources/resources/podcast_dunder_init.yaml | 2 +- .../apps/resources/resources/practical_python_programming.yaml | 2 +- pydis_site/apps/resources/resources/pycharm.yaml | 2 +- pydis_site/apps/resources/resources/pyglet.yaml | 2 +- pydis_site/apps/resources/resources/python_bytes.yaml | 2 +- pydis_site/apps/resources/resources/python_cheat_sheet.yaml | 2 +- pydis_site/apps/resources/resources/python_cookbook.yaml | 2 +- pydis_site/apps/resources/resources/python_crash_course.yaml | 2 +- pydis_site/apps/resources/resources/python_developer_guide.yaml | 2 +- pydis_site/apps/resources/resources/python_discord_videos.yaml | 2 +- pydis_site/apps/resources/resources/python_morsels.yaml | 2 +- pydis_site/apps/resources/resources/python_subreddit.yaml | 2 +- pydis_site/apps/resources/resources/python_tricks.yaml | 2 +- pydis_site/apps/resources/resources/python_tutor.yaml | 2 +- pydis_site/apps/resources/resources/real_python.yaml | 2 +- pydis_site/apps/resources/resources/regex101.yaml | 2 +- pydis_site/apps/resources/resources/repl_it.yaml | 2 +- pydis_site/apps/resources/resources/screen_readers.yaml | 2 +- pydis_site/apps/resources/resources/sentdex.yaml | 2 +- pydis_site/apps/resources/resources/simple_guide_to_git.yaml | 2 +- pydis_site/apps/resources/resources/sololearn.yaml | 2 +- pydis_site/apps/resources/resources/spyder.yaml | 2 +- pydis_site/apps/resources/resources/sublime_text.yaml | 2 +- pydis_site/apps/resources/resources/talk_python_to_me.yaml | 2 +- pydis_site/apps/resources/resources/talon_voice.yaml | 2 +- pydis_site/apps/resources/resources/test_and_code.yaml | 2 +- pydis_site/apps/resources/resources/the_flask_mega_tutorial.yaml | 2 +- pydis_site/apps/resources/resources/the_real_python_podcast.yaml | 2 +- pydis_site/apps/resources/resources/think_python.yaml | 2 +- pydis_site/apps/resources/resources/thonny.yaml | 2 +- pydis_site/apps/resources/resources/two_scoops_of_django.yaml | 2 +- pydis_site/apps/resources/resources/university_of_michigan.yaml | 2 +- pydis_site/apps/resources/resources/university_of_toronto.yaml | 2 +- .../apps/resources/resources/vcokltfre_discord_bot_tutorial.yaml | 2 +- pydis_site/apps/resources/resources/visual_studio_code.yaml | 2 +- pydis_site/apps/resources/resources/wtf_python.yaml | 2 +- pydis_site/apps/resources/views/resources.py | 8 ++++---- pydis_site/static/js/resources.js | 6 +++--- pydis_site/templates/resources/resource_box.html | 4 ++-- pydis_site/templates/resources/resources.html | 2 +- 75 files changed, 81 insertions(+), 81 deletions(-) (limited to 'pydis_site/apps/resources/views/resources.py') diff --git a/pydis_site/apps/resources/resources/adafruit.yaml b/pydis_site/apps/resources/resources/adafruit.yaml index e8eeee37..f9466bd8 100644 --- a/pydis_site/apps/resources/resources/adafruit.yaml +++ b/pydis_site/apps/resources/resources/adafruit.yaml @@ -14,7 +14,7 @@ tags: - microcontrollers payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/atom.yaml b/pydis_site/apps/resources/resources/atom.yaml index 3a46a45f..26e125b1 100644 --- a/pydis_site/apps/resources/resources/atom.yaml +++ b/pydis_site/apps/resources/resources/atom.yaml @@ -7,7 +7,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/automate_the_boring_stuff_book.yaml b/pydis_site/apps/resources/resources/automate_the_boring_stuff_book.yaml index bc0e19ec..9bf9aba8 100644 --- a/pydis_site/apps/resources/resources/automate_the_boring_stuff_book.yaml +++ b/pydis_site/apps/resources/resources/automate_the_boring_stuff_book.yaml @@ -15,7 +15,7 @@ tags: payment_tiers: - free - paid - complexity: + difficulty: - beginner type: - book diff --git a/pydis_site/apps/resources/resources/automate_the_boring_stuff_course.yaml b/pydis_site/apps/resources/resources/automate_the_boring_stuff_course.yaml index b93ef868..133033f7 100644 --- a/pydis_site/apps/resources/resources/automate_the_boring_stuff_course.yaml +++ b/pydis_site/apps/resources/resources/automate_the_boring_stuff_course.yaml @@ -7,7 +7,7 @@ tags: - general payment_tiers: - paid - complexity: + difficulty: - beginner type: - course diff --git a/pydis_site/apps/resources/resources/awesome_programming_discord.yaml b/pydis_site/apps/resources/resources/awesome_programming_discord.yaml index 4233f26e..0ef7aefc 100644 --- a/pydis_site/apps/resources/resources/awesome_programming_discord.yaml +++ b/pydis_site/apps/resources/resources/awesome_programming_discord.yaml @@ -11,7 +11,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/byte_of_python.yaml b/pydis_site/apps/resources/resources/byte_of_python.yaml index d2b8fa35..c4b671c2 100644 --- a/pydis_site/apps/resources/resources/byte_of_python.yaml +++ b/pydis_site/apps/resources/resources/byte_of_python.yaml @@ -16,7 +16,7 @@ tags: payment_tiers: - free - paid - complexity: + difficulty: - beginner type: - book diff --git a/pydis_site/apps/resources/resources/code_combat.yaml b/pydis_site/apps/resources/resources/code_combat.yaml index ab4a4aed..84597c4d 100644 --- a/pydis_site/apps/resources/resources/code_combat.yaml +++ b/pydis_site/apps/resources/resources/code_combat.yaml @@ -13,7 +13,7 @@ tags: payment_tiers: - free - subscription - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/corey_schafer.yaml b/pydis_site/apps/resources/resources/corey_schafer.yaml index cb20bc24..b73f4b5d 100644 --- a/pydis_site/apps/resources/resources/corey_schafer.yaml +++ b/pydis_site/apps/resources/resources/corey_schafer.yaml @@ -22,7 +22,7 @@ tags: - tooling payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/data_science_from_scratch.yaml b/pydis_site/apps/resources/resources/data_science_from_scratch.yaml index 8ba95e9b..57e73a28 100644 --- a/pydis_site/apps/resources/resources/data_science_from_scratch.yaml +++ b/pydis_site/apps/resources/resources/data_science_from_scratch.yaml @@ -16,7 +16,7 @@ tags: - data science payment_tiers: - paid - complexity: + difficulty: - beginner type: - book diff --git a/pydis_site/apps/resources/resources/edublocks.yaml b/pydis_site/apps/resources/resources/edublocks.yaml index 9fd87945..3eaefc35 100644 --- a/pydis_site/apps/resources/resources/edublocks.yaml +++ b/pydis_site/apps/resources/resources/edublocks.yaml @@ -12,7 +12,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - beginner type: - interactive diff --git a/pydis_site/apps/resources/resources/effective_python.yaml b/pydis_site/apps/resources/resources/effective_python.yaml index 4e361bcb..96a3b21a 100644 --- a/pydis_site/apps/resources/resources/effective_python.yaml +++ b/pydis_site/apps/resources/resources/effective_python.yaml @@ -15,7 +15,7 @@ tags: - software design payment_tiers: - paid - complexity: + difficulty: - intermediate type: - book diff --git a/pydis_site/apps/resources/resources/exercism.yaml b/pydis_site/apps/resources/resources/exercism.yaml index ba8cd2df..b8f53d72 100644 --- a/pydis_site/apps/resources/resources/exercism.yaml +++ b/pydis_site/apps/resources/resources/exercism.yaml @@ -13,7 +13,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/flask_web_development.yaml b/pydis_site/apps/resources/resources/flask_web_development.yaml index 95b75a5b..0bd418e5 100644 --- a/pydis_site/apps/resources/resources/flask_web_development.yaml +++ b/pydis_site/apps/resources/resources/flask_web_development.yaml @@ -14,7 +14,7 @@ tags: - web development payment_tiers: - paid - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/fluent_python.yaml b/pydis_site/apps/resources/resources/fluent_python.yaml index e35c0134..1d525baa 100644 --- a/pydis_site/apps/resources/resources/fluent_python.yaml +++ b/pydis_site/apps/resources/resources/fluent_python.yaml @@ -15,7 +15,7 @@ tags: - software design payment_tiers: - paid - complexity: + difficulty: - intermediate type: - book diff --git a/pydis_site/apps/resources/resources/getting_started_with_kivy.yaml b/pydis_site/apps/resources/resources/getting_started_with_kivy.yaml index 5dbcd387..06eb2c14 100644 --- a/pydis_site/apps/resources/resources/getting_started_with_kivy.yaml +++ b/pydis_site/apps/resources/resources/getting_started_with_kivy.yaml @@ -8,7 +8,7 @@ tags: - game development payment_tiers: - free - complexity: + difficulty: - beginner type: - tutorial diff --git a/pydis_site/apps/resources/resources/getting_started_with_python_for_non_programmers.yaml b/pydis_site/apps/resources/resources/getting_started_with_python_for_non_programmers.yaml index 85c061bd..6fab0114 100644 --- a/pydis_site/apps/resources/resources/getting_started_with_python_for_non_programmers.yaml +++ b/pydis_site/apps/resources/resources/getting_started_with_python_for_non_programmers.yaml @@ -7,7 +7,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - beginner type: - tutorial diff --git a/pydis_site/apps/resources/resources/getting_started_with_python_for_programmers.yaml b/pydis_site/apps/resources/resources/getting_started_with_python_for_programmers.yaml index 2565eedd..74b6efb9 100644 --- a/pydis_site/apps/resources/resources/getting_started_with_python_for_programmers.yaml +++ b/pydis_site/apps/resources/resources/getting_started_with_python_for_programmers.yaml @@ -8,7 +8,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - intermediate type: - tutorial diff --git a/pydis_site/apps/resources/resources/google_collab.yaml b/pydis_site/apps/resources/resources/google_collab.yaml index 65876c0e..067a79c9 100644 --- a/pydis_site/apps/resources/resources/google_collab.yaml +++ b/pydis_site/apps/resources/resources/google_collab.yaml @@ -10,7 +10,7 @@ tags: - data science payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/hitchhikers_guide_to_python.yaml b/pydis_site/apps/resources/resources/hitchhikers_guide_to_python.yaml index bfac404a..c4b78af6 100644 --- a/pydis_site/apps/resources/resources/hitchhikers_guide_to_python.yaml +++ b/pydis_site/apps/resources/resources/hitchhikers_guide_to_python.yaml @@ -11,7 +11,7 @@ tags: - general payment_tiers: - paid - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/inferential_thinking.yaml b/pydis_site/apps/resources/resources/inferential_thinking.yaml index 20409f3a..a8cf2bc8 100644 --- a/pydis_site/apps/resources/resources/inferential_thinking.yaml +++ b/pydis_site/apps/resources/resources/inferential_thinking.yaml @@ -8,7 +8,7 @@ tags: - data science payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/jetbrains_academy.yaml b/pydis_site/apps/resources/resources/jetbrains_academy.yaml index 63c061ce..c3cb7657 100644 --- a/pydis_site/apps/resources/resources/jetbrains_academy.yaml +++ b/pydis_site/apps/resources/resources/jetbrains_academy.yaml @@ -12,7 +12,7 @@ tags: - data science payment_tiers: - subscription - complexity: + difficulty: - beginner type: - interactive diff --git a/pydis_site/apps/resources/resources/jetbrains_videos.yaml b/pydis_site/apps/resources/resources/jetbrains_videos.yaml index aba7c687..00d34e69 100644 --- a/pydis_site/apps/resources/resources/jetbrains_videos.yaml +++ b/pydis_site/apps/resources/resources/jetbrains_videos.yaml @@ -14,7 +14,7 @@ tags: - web development payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/jim_shaped_coding.yaml b/pydis_site/apps/resources/resources/jim_shaped_coding.yaml index 30992ef2..c9727888 100644 --- a/pydis_site/apps/resources/resources/jim_shaped_coding.yaml +++ b/pydis_site/apps/resources/resources/jim_shaped_coding.yaml @@ -15,7 +15,7 @@ tags: - web development payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/kaggle_pandas_tutorial.yaml b/pydis_site/apps/resources/resources/kaggle_pandas_tutorial.yaml index a1907e0f..c8e72c6e 100644 --- a/pydis_site/apps/resources/resources/kaggle_pandas_tutorial.yaml +++ b/pydis_site/apps/resources/resources/kaggle_pandas_tutorial.yaml @@ -7,7 +7,7 @@ tags: - data science payment_tiers: - free - complexity: + difficulty: - intermediate type: - tutorial diff --git a/pydis_site/apps/resources/resources/kivy.yaml b/pydis_site/apps/resources/resources/kivy.yaml index 5d7d3844..dad29e9a 100644 --- a/pydis_site/apps/resources/resources/kivy.yaml +++ b/pydis_site/apps/resources/resources/kivy.yaml @@ -21,7 +21,7 @@ tags: - game development payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/microsoft.yaml b/pydis_site/apps/resources/resources/microsoft.yaml index cc5ca93f..e1d62955 100644 --- a/pydis_site/apps/resources/resources/microsoft.yaml +++ b/pydis_site/apps/resources/resources/microsoft.yaml @@ -12,7 +12,7 @@ tags: - tooling payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/microsoft_videos.yaml b/pydis_site/apps/resources/resources/microsoft_videos.yaml index 39187650..f45aef63 100644 --- a/pydis_site/apps/resources/resources/microsoft_videos.yaml +++ b/pydis_site/apps/resources/resources/microsoft_videos.yaml @@ -19,7 +19,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - beginner type: - video diff --git a/pydis_site/apps/resources/resources/mission_python.yaml b/pydis_site/apps/resources/resources/mission_python.yaml index 4e7b30b0..e8e0a6b8 100644 --- a/pydis_site/apps/resources/resources/mission_python.yaml +++ b/pydis_site/apps/resources/resources/mission_python.yaml @@ -14,7 +14,7 @@ tags: - game development payment_tiers: - paid - complexity: + difficulty: - beginner type: - book diff --git a/pydis_site/apps/resources/resources/mit_introduction_to_computer_science_and_programming.yaml b/pydis_site/apps/resources/resources/mit_introduction_to_computer_science_and_programming.yaml index 4aa028ea..4e74936d 100644 --- a/pydis_site/apps/resources/resources/mit_introduction_to_computer_science_and_programming.yaml +++ b/pydis_site/apps/resources/resources/mit_introduction_to_computer_science_and_programming.yaml @@ -10,7 +10,7 @@ tags: payment_tiers: - free - paid - complexity: + difficulty: - beginner type: - course diff --git a/pydis_site/apps/resources/resources/mu_editor.yaml b/pydis_site/apps/resources/resources/mu_editor.yaml index 68c9b7db..b6318d0e 100644 --- a/pydis_site/apps/resources/resources/mu_editor.yaml +++ b/pydis_site/apps/resources/resources/mu_editor.yaml @@ -9,7 +9,7 @@ tags: - microcontrollers payment_tiers: - free - complexity: + difficulty: - beginner type: - tool diff --git a/pydis_site/apps/resources/resources/netbats_project_ideas.yaml b/pydis_site/apps/resources/resources/netbats_project_ideas.yaml index faa029f9..80ba771c 100644 --- a/pydis_site/apps/resources/resources/netbats_project_ideas.yaml +++ b/pydis_site/apps/resources/resources/netbats_project_ideas.yaml @@ -7,7 +7,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/neural_networks_from_scratch_in_python.yaml b/pydis_site/apps/resources/resources/neural_networks_from_scratch_in_python.yaml index 5d3060a4..6313cabe 100644 --- a/pydis_site/apps/resources/resources/neural_networks_from_scratch_in_python.yaml +++ b/pydis_site/apps/resources/resources/neural_networks_from_scratch_in_python.yaml @@ -13,7 +13,7 @@ tags: - data science payment_tiers: - paid - complexity: + difficulty: - intermediate type: - book diff --git a/pydis_site/apps/resources/resources/pallets.yaml b/pydis_site/apps/resources/resources/pallets.yaml index de3f7fad..0da2a625 100644 --- a/pydis_site/apps/resources/resources/pallets.yaml +++ b/pydis_site/apps/resources/resources/pallets.yaml @@ -12,7 +12,7 @@ tags: - web development payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/panda3d.yaml b/pydis_site/apps/resources/resources/panda3d.yaml index 0d488565..61ecba4b 100644 --- a/pydis_site/apps/resources/resources/panda3d.yaml +++ b/pydis_site/apps/resources/resources/panda3d.yaml @@ -16,7 +16,7 @@ tags: - game development payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/people_postgres_data.yaml b/pydis_site/apps/resources/resources/people_postgres_data.yaml index 70088af2..c2d63252 100644 --- a/pydis_site/apps/resources/resources/people_postgres_data.yaml +++ b/pydis_site/apps/resources/resources/people_postgres_data.yaml @@ -20,7 +20,7 @@ tags: - databases payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/podcast_dunder_init.yaml b/pydis_site/apps/resources/resources/podcast_dunder_init.yaml index ee3028a3..2751481a 100644 --- a/pydis_site/apps/resources/resources/podcast_dunder_init.yaml +++ b/pydis_site/apps/resources/resources/podcast_dunder_init.yaml @@ -7,7 +7,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/practical_python_programming.yaml b/pydis_site/apps/resources/resources/practical_python_programming.yaml index 85b3967a..12873b7c 100644 --- a/pydis_site/apps/resources/resources/practical_python_programming.yaml +++ b/pydis_site/apps/resources/resources/practical_python_programming.yaml @@ -12,7 +12,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - beginner type: - course diff --git a/pydis_site/apps/resources/resources/pycharm.yaml b/pydis_site/apps/resources/resources/pycharm.yaml index 1fda3bff..574158bc 100644 --- a/pydis_site/apps/resources/resources/pycharm.yaml +++ b/pydis_site/apps/resources/resources/pycharm.yaml @@ -8,7 +8,7 @@ tags: payment_tiers: - free - paid - complexity: + difficulty: - intermediate type: - tool diff --git a/pydis_site/apps/resources/resources/pyglet.yaml b/pydis_site/apps/resources/resources/pyglet.yaml index d4a37fa8..a47c7e62 100644 --- a/pydis_site/apps/resources/resources/pyglet.yaml +++ b/pydis_site/apps/resources/resources/pyglet.yaml @@ -15,7 +15,7 @@ tags: - game development payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/python_bytes.yaml b/pydis_site/apps/resources/resources/python_bytes.yaml index 578fff2e..9beba4f4 100644 --- a/pydis_site/apps/resources/resources/python_bytes.yaml +++ b/pydis_site/apps/resources/resources/python_bytes.yaml @@ -8,7 +8,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/python_cheat_sheet.yaml b/pydis_site/apps/resources/resources/python_cheat_sheet.yaml index da9b980f..56f61165 100644 --- a/pydis_site/apps/resources/resources/python_cheat_sheet.yaml +++ b/pydis_site/apps/resources/resources/python_cheat_sheet.yaml @@ -7,7 +7,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - beginner type: - tutorial diff --git a/pydis_site/apps/resources/resources/python_cookbook.yaml b/pydis_site/apps/resources/resources/python_cookbook.yaml index 855adb2f..fbb1bdc8 100644 --- a/pydis_site/apps/resources/resources/python_cookbook.yaml +++ b/pydis_site/apps/resources/resources/python_cookbook.yaml @@ -15,7 +15,7 @@ tags: - software design payment_tiers: - paid - complexity: + difficulty: - intermediate type: - book diff --git a/pydis_site/apps/resources/resources/python_crash_course.yaml b/pydis_site/apps/resources/resources/python_crash_course.yaml index 379cf954..9de1a53c 100644 --- a/pydis_site/apps/resources/resources/python_crash_course.yaml +++ b/pydis_site/apps/resources/resources/python_crash_course.yaml @@ -21,7 +21,7 @@ tags: - game development payment_tiers: - paid - complexity: + difficulty: - beginner type: - book diff --git a/pydis_site/apps/resources/resources/python_developer_guide.yaml b/pydis_site/apps/resources/resources/python_developer_guide.yaml index f17c88ce..2806d75d 100644 --- a/pydis_site/apps/resources/resources/python_developer_guide.yaml +++ b/pydis_site/apps/resources/resources/python_developer_guide.yaml @@ -7,7 +7,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - intermediate type: - tutorial diff --git a/pydis_site/apps/resources/resources/python_discord_videos.yaml b/pydis_site/apps/resources/resources/python_discord_videos.yaml index bf44083f..15a04097 100644 --- a/pydis_site/apps/resources/resources/python_discord_videos.yaml +++ b/pydis_site/apps/resources/resources/python_discord_videos.yaml @@ -8,7 +8,7 @@ tags: - software design payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/python_morsels.yaml b/pydis_site/apps/resources/resources/python_morsels.yaml index de02be7f..bbc8133b 100644 --- a/pydis_site/apps/resources/resources/python_morsels.yaml +++ b/pydis_site/apps/resources/resources/python_morsels.yaml @@ -13,7 +13,7 @@ tags: - software design payment_tiers: - subscription - complexity: + difficulty: - intermediate type: - interactive diff --git a/pydis_site/apps/resources/resources/python_subreddit.yaml b/pydis_site/apps/resources/resources/python_subreddit.yaml index ef9f23d9..e94f84fc 100644 --- a/pydis_site/apps/resources/resources/python_subreddit.yaml +++ b/pydis_site/apps/resources/resources/python_subreddit.yaml @@ -9,7 +9,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/python_tricks.yaml b/pydis_site/apps/resources/resources/python_tricks.yaml index 17f40732..a38fa74b 100644 --- a/pydis_site/apps/resources/resources/python_tricks.yaml +++ b/pydis_site/apps/resources/resources/python_tricks.yaml @@ -13,7 +13,7 @@ tags: - software design payment_tiers: - paid - complexity: + difficulty: - intermediate type: - book diff --git a/pydis_site/apps/resources/resources/python_tutor.yaml b/pydis_site/apps/resources/resources/python_tutor.yaml index 4f6d5130..6bee0d69 100644 --- a/pydis_site/apps/resources/resources/python_tutor.yaml +++ b/pydis_site/apps/resources/resources/python_tutor.yaml @@ -6,7 +6,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/real_python.yaml b/pydis_site/apps/resources/resources/real_python.yaml index 1669638e..0d0b2ad3 100644 --- a/pydis_site/apps/resources/resources/real_python.yaml +++ b/pydis_site/apps/resources/resources/real_python.yaml @@ -15,7 +15,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/regex101.yaml b/pydis_site/apps/resources/resources/regex101.yaml index db3df957..45d00f1b 100644 --- a/pydis_site/apps/resources/resources/regex101.yaml +++ b/pydis_site/apps/resources/resources/regex101.yaml @@ -8,7 +8,7 @@ tags: - other payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/repl_it.yaml b/pydis_site/apps/resources/resources/repl_it.yaml index e1ba1d19..e0f6cbb3 100644 --- a/pydis_site/apps/resources/resources/repl_it.yaml +++ b/pydis_site/apps/resources/resources/repl_it.yaml @@ -7,7 +7,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/screen_readers.yaml b/pydis_site/apps/resources/resources/screen_readers.yaml index 9673a132..b086b301 100644 --- a/pydis_site/apps/resources/resources/screen_readers.yaml +++ b/pydis_site/apps/resources/resources/screen_readers.yaml @@ -10,7 +10,7 @@ tags: payment_tiers: - free - paid - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/sentdex.yaml b/pydis_site/apps/resources/resources/sentdex.yaml index 47a8852d..d9131039 100644 --- a/pydis_site/apps/resources/resources/sentdex.yaml +++ b/pydis_site/apps/resources/resources/sentdex.yaml @@ -24,7 +24,7 @@ tags: - data science payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/simple_guide_to_git.yaml b/pydis_site/apps/resources/resources/simple_guide_to_git.yaml index 6dacdf5c..3bb46e6d 100644 --- a/pydis_site/apps/resources/resources/simple_guide_to_git.yaml +++ b/pydis_site/apps/resources/resources/simple_guide_to_git.yaml @@ -8,7 +8,7 @@ tags: - tooling payment_tiers: - free - complexity: + difficulty: - beginner type: - tutorial diff --git a/pydis_site/apps/resources/resources/sololearn.yaml b/pydis_site/apps/resources/resources/sololearn.yaml index b9b59bca..998f5368 100644 --- a/pydis_site/apps/resources/resources/sololearn.yaml +++ b/pydis_site/apps/resources/resources/sololearn.yaml @@ -10,7 +10,7 @@ tags: payment_tiers: - free - subscription - complexity: + difficulty: - beginner type: - interactive diff --git a/pydis_site/apps/resources/resources/spyder.yaml b/pydis_site/apps/resources/resources/spyder.yaml index 8dc05542..668e9306 100644 --- a/pydis_site/apps/resources/resources/spyder.yaml +++ b/pydis_site/apps/resources/resources/spyder.yaml @@ -7,7 +7,7 @@ tags: - data science payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/sublime_text.yaml b/pydis_site/apps/resources/resources/sublime_text.yaml index 76aeac45..05596477 100644 --- a/pydis_site/apps/resources/resources/sublime_text.yaml +++ b/pydis_site/apps/resources/resources/sublime_text.yaml @@ -7,7 +7,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/talk_python_to_me.yaml b/pydis_site/apps/resources/resources/talk_python_to_me.yaml index 00726203..509922c3 100644 --- a/pydis_site/apps/resources/resources/talk_python_to_me.yaml +++ b/pydis_site/apps/resources/resources/talk_python_to_me.yaml @@ -7,7 +7,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/talon_voice.yaml b/pydis_site/apps/resources/resources/talon_voice.yaml index 0f28a328..3be5fe20 100644 --- a/pydis_site/apps/resources/resources/talon_voice.yaml +++ b/pydis_site/apps/resources/resources/talon_voice.yaml @@ -8,7 +8,7 @@ tags: - other payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/test_and_code.yaml b/pydis_site/apps/resources/resources/test_and_code.yaml index efe0c218..f0d1c3b3 100644 --- a/pydis_site/apps/resources/resources/test_and_code.yaml +++ b/pydis_site/apps/resources/resources/test_and_code.yaml @@ -8,7 +8,7 @@ tags: - tooling payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/the_flask_mega_tutorial.yaml b/pydis_site/apps/resources/resources/the_flask_mega_tutorial.yaml index 514da947..151768a5 100644 --- a/pydis_site/apps/resources/resources/the_flask_mega_tutorial.yaml +++ b/pydis_site/apps/resources/resources/the_flask_mega_tutorial.yaml @@ -6,7 +6,7 @@ tags: - web development payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/the_real_python_podcast.yaml b/pydis_site/apps/resources/resources/the_real_python_podcast.yaml index 62ba32ce..647779d5 100644 --- a/pydis_site/apps/resources/resources/the_real_python_podcast.yaml +++ b/pydis_site/apps/resources/resources/the_real_python_podcast.yaml @@ -9,7 +9,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/think_python.yaml b/pydis_site/apps/resources/resources/think_python.yaml index aceaf951..f9211308 100644 --- a/pydis_site/apps/resources/resources/think_python.yaml +++ b/pydis_site/apps/resources/resources/think_python.yaml @@ -18,7 +18,7 @@ tags: - software design payment_tiers: - paid - complexity: + difficulty: - beginner type: - book diff --git a/pydis_site/apps/resources/resources/thonny.yaml b/pydis_site/apps/resources/resources/thonny.yaml index a60e4d1b..29ba9e07 100644 --- a/pydis_site/apps/resources/resources/thonny.yaml +++ b/pydis_site/apps/resources/resources/thonny.yaml @@ -8,7 +8,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - beginner type: - tool diff --git a/pydis_site/apps/resources/resources/two_scoops_of_django.yaml b/pydis_site/apps/resources/resources/two_scoops_of_django.yaml index 4eadc28d..63730ac9 100644 --- a/pydis_site/apps/resources/resources/two_scoops_of_django.yaml +++ b/pydis_site/apps/resources/resources/two_scoops_of_django.yaml @@ -14,7 +14,7 @@ tags: - web development payment_tiers: - paid - complexity: + difficulty: - intermediate type: - book diff --git a/pydis_site/apps/resources/resources/university_of_michigan.yaml b/pydis_site/apps/resources/resources/university_of_michigan.yaml index 843b64ed..7aaaf2ae 100644 --- a/pydis_site/apps/resources/resources/university_of_michigan.yaml +++ b/pydis_site/apps/resources/resources/university_of_michigan.yaml @@ -7,7 +7,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - beginner type: - course diff --git a/pydis_site/apps/resources/resources/university_of_toronto.yaml b/pydis_site/apps/resources/resources/university_of_toronto.yaml index d057eb39..94df96f2 100644 --- a/pydis_site/apps/resources/resources/university_of_toronto.yaml +++ b/pydis_site/apps/resources/resources/university_of_toronto.yaml @@ -13,7 +13,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/vcokltfre_discord_bot_tutorial.yaml b/pydis_site/apps/resources/resources/vcokltfre_discord_bot_tutorial.yaml index 02f9fe5a..1a3dd457 100644 --- a/pydis_site/apps/resources/resources/vcokltfre_discord_bot_tutorial.yaml +++ b/pydis_site/apps/resources/resources/vcokltfre_discord_bot_tutorial.yaml @@ -8,7 +8,7 @@ tags: - discord bots payment_tiers: - free - complexity: + difficulty: - intermediate type: - tutorial diff --git a/pydis_site/apps/resources/resources/visual_studio_code.yaml b/pydis_site/apps/resources/resources/visual_studio_code.yaml index f09efcf8..3cf858f8 100644 --- a/pydis_site/apps/resources/resources/visual_studio_code.yaml +++ b/pydis_site/apps/resources/resources/visual_studio_code.yaml @@ -6,7 +6,7 @@ tags: - general payment_tiers: - free - complexity: + difficulty: - beginner - intermediate type: diff --git a/pydis_site/apps/resources/resources/wtf_python.yaml b/pydis_site/apps/resources/resources/wtf_python.yaml index 7f67ccf9..6d90ba39 100644 --- a/pydis_site/apps/resources/resources/wtf_python.yaml +++ b/pydis_site/apps/resources/resources/wtf_python.yaml @@ -12,7 +12,7 @@ tags: - other payment_tiers: - free - complexity: + difficulty: - intermediate type: - tutorial diff --git a/pydis_site/apps/resources/views/resources.py b/pydis_site/apps/resources/views/resources.py index 57cb4f71..14b3d0bf 100644 --- a/pydis_site/apps/resources/views/resources.py +++ b/pydis_site/apps/resources/views/resources.py @@ -28,7 +28,7 @@ class ResourceView(View): resource_tags = { "topics": set(), "payment_tiers": set(), - "complexity": set(), + "difficulty": set(), "type": set(), } for resource_name, resource in self.resources.items(): @@ -53,8 +53,8 @@ class ResourceView(View): # Set up all the filter checkbox metadata self.filters = { - "Complexity": { - "filters": sorted(resource_tags.get("complexity")), + "Difficulty": { + "filters": sorted(resource_tags.get("difficulty")), "icon": "fas fa-brain", "hidden": False, }, @@ -84,7 +84,7 @@ class ResourceView(View): ('topics', 'topics'), ('type', 'type'), ('payment_tiers', 'payment'), - ('complexity', 'complexity'), + ('difficulty', 'difficulty'), ) } diff --git a/pydis_site/static/js/resources.js b/pydis_site/static/js/resources.js index 89b8ae06..eaca3978 100644 --- a/pydis_site/static/js/resources.js +++ b/pydis_site/static/js/resources.js @@ -5,7 +5,7 @@ var activeFilters = { topics: [], type: [], "payment-tiers": [], - complexity: [] + difficulty: [] }; function addFilter(filterName, filterItem) { @@ -45,7 +45,7 @@ function noFilters() { activeFilters.topics.length === 0 && activeFilters.type.length === 0 && activeFilters["payment-tiers"].length === 0 && - activeFilters.complexity.length === 0 + activeFilters.difficulty.length === 0 ); } @@ -120,7 +120,7 @@ function updateUI() { topics: false, type: false, 'payment-tiers': false, - complexity: false + difficulty: false }; let resourceBox = $(this); diff --git a/pydis_site/templates/resources/resource_box.html b/pydis_site/templates/resources/resource_box.html index 476a4841..8a1017b5 100644 --- a/pydis_site/templates/resources/resource_box.html +++ b/pydis_site/templates/resources/resource_box.html @@ -64,10 +64,10 @@ {{ tag|title }} {% endfor %} - {% for tag in resource.tags.complexity %} + {% for tag in resource.tags.difficulty %} diff --git a/pydis_site/templates/resources/resources.html b/pydis_site/templates/resources/resources.html index 166863c3..9ebebe1f 100644 --- a/pydis_site/templates/resources/resources.html +++ b/pydis_site/templates/resources/resources.html @@ -29,7 +29,7 @@
{% for filter_name, filter_data in filters.items %} {% for filter_item in filter_data.filters %} - {% if filter_name == "Complexity" %} + {% if filter_name == "Difficulty" %} Date: Sat, 29 Jan 2022 14:55:01 +0100 Subject: Sort all the resources alphabetically. --- pydis_site/apps/resources/tests/test_views.py | 1 - pydis_site/apps/resources/views/resources.py | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'pydis_site/apps/resources/views/resources.py') diff --git a/pydis_site/apps/resources/tests/test_views.py b/pydis_site/apps/resources/tests/test_views.py index f96a04b0..dab3599d 100644 --- a/pydis_site/apps/resources/tests/test_views.py +++ b/pydis_site/apps/resources/tests/test_views.py @@ -1,5 +1,4 @@ from pathlib import Path -from unittest.mock import patch from django.conf import settings from django.test import TestCase diff --git a/pydis_site/apps/resources/views/resources.py b/pydis_site/apps/resources/views/resources.py index 14b3d0bf..d0b8bae7 100644 --- a/pydis_site/apps/resources/views/resources.py +++ b/pydis_site/apps/resources/views/resources.py @@ -2,7 +2,7 @@ from pathlib import Path import yaml from django.core.handlers.wsgi import WSGIRequest -from django.http import HttpRequest, HttpResponse +from django.http import HttpResponse from django.shortcuts import render from django.views import View @@ -24,6 +24,9 @@ class ResourceView(View): for path in RESOURCES_PATH.rglob("*.yaml") } + # Sort the resources alphabetically + self.resources = dict(sorted(self.resources.items())) + # Parse out all current tags resource_tags = { "topics": set(), -- cgit v1.2.3 From e53a3a15d0213b3854a3c9619390f0a0e35c4bf6 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Sun, 30 Jan 2022 11:41:44 +0100 Subject: Redirects from old endpoints now filter correctly. For example, navigating to pydis.com/resources/communities will now correctly redirect to pydis.com/resources/?type=community. --- pydis_site/apps/redirect/redirects.yaml | 10 ++++++---- pydis_site/apps/resources/urls.py | 1 + pydis_site/apps/resources/views/resources.py | 25 ++++++++----------------- pydis_site/static/js/resources.js | 8 ++++++++ pydis_site/templates/resources/resources.html | 1 + 5 files changed, 24 insertions(+), 21 deletions(-) (limited to 'pydis_site/apps/resources/views/resources.py') diff --git a/pydis_site/apps/redirect/redirects.yaml b/pydis_site/apps/redirect/redirects.yaml index bee65103..533b9e25 100644 --- a/pydis_site/apps/redirect/redirects.yaml +++ b/pydis_site/apps/redirect/redirects.yaml @@ -90,30 +90,32 @@ resources_index_redirect: resources_reading_redirect: original_path: resources/reading/ redirect_route: "resources:index" + redirect_arguments: ["book"] resources_videos_redirect: original_path: resources/videos/ redirect_route: "resources:index" - -resources_interactive_redirect: - original_path: resources/interactive/ - redirect_route: "resources:index" + redirect_arguments: ["video"] resources_courses_redirect: original_path: resources/courses/ redirect_route: "resources:index" + redirect_arguments: ["course"] resources_communities_redirect: original_path: resources/communities/ redirect_route: "resources:index" + redirect_arguments: ["community"] resources_podcasts_redirect: original_path: resources/podcasts/ redirect_route: "resources:index" + redirect_arguments: ["podcast"] resources_tools_redirect: original_path: resources/tools/ redirect_route: "resources:index" + redirect_arguments: ["tool"] # Events events_index_redirect: diff --git a/pydis_site/apps/resources/urls.py b/pydis_site/apps/resources/urls.py index 5d5ae7fb..ed24dc99 100644 --- a/pydis_site/apps/resources/urls.py +++ b/pydis_site/apps/resources/urls.py @@ -5,4 +5,5 @@ from pydis_site.apps.resources import views app_name = "resources" urlpatterns = [ distill_path("", views.resources.ResourceView.as_view(), name="index"), + distill_path("/", views.resources.ResourceView.as_view(), name="index"), ] diff --git a/pydis_site/apps/resources/views/resources.py b/pydis_site/apps/resources/views/resources.py index d0b8bae7..b828d89a 100644 --- a/pydis_site/apps/resources/views/resources.py +++ b/pydis_site/apps/resources/views/resources.py @@ -1,8 +1,9 @@ from pathlib import Path +import typing as t import yaml from django.core.handlers.wsgi import WSGIRequest -from django.http import HttpResponse +from django.http import HttpResponse, HttpResponseNotFound from django.shortcuts import render from django.views import View @@ -78,22 +79,12 @@ class ResourceView(View): } } - @staticmethod - def _get_filter_options(request: WSGIRequest) -> dict[str, set]: - """Get the requested filter options out of the request object.""" - return { - option: set(request.GET.get(url_param, "").split(",")[:-1]) - for option, url_param in ( - ('topics', 'topics'), - ('type', 'type'), - ('payment_tiers', 'payment'), - ('difficulty', 'difficulty'), - ) - } - - def get(self, request: WSGIRequest) -> HttpResponse: + def get(self, request: WSGIRequest, resource_type: t.Optional[str] = None) -> HttpResponse: """List out all the resources, and any filtering options from the URL.""" - filter_options = self._get_filter_options(request) + + # Add type filtering if the request is made to somewhere like /resources/video + if resource_type and resource_type.title() not in self.filters['Type']['filters']: + return HttpResponseNotFound() return render( request, @@ -101,6 +92,6 @@ class ResourceView(View): context={ "resources": self.resources, "filters": self.filters, - "filter_options": filter_options, + "resource_type": resource_type, } ) diff --git a/pydis_site/static/js/resources.js b/pydis_site/static/js/resources.js index eaca3978..bf570097 100644 --- a/pydis_site/static/js/resources.js +++ b/pydis_site/static/js/resources.js @@ -160,6 +160,14 @@ function updateUI() { // Executed when the page has finished loading. document.addEventListener("DOMContentLoaded", function () { + /* Check if the user has navigated to one of the old resource pages, + like pydis.com/resources/communities. In this case, we'll rewrite + the URL before we do anything else. */ + let resourceTypeInput = $("#resource-type-input").val(); + if (resourceTypeInput.length !== 0) { + window.history.replaceState(null, document.title, `../?type=${resourceTypeInput}`); + } + // Update the filters on page load to reflect URL parameters. $('.filter-box-tag').hide(); deserializeURLParams(); diff --git a/pydis_site/templates/resources/resources.html b/pydis_site/templates/resources/resources.html index 9ebebe1f..7a284fd6 100644 --- a/pydis_site/templates/resources/resources.html +++ b/pydis_site/templates/resources/resources.html @@ -16,6 +16,7 @@ {% block content %} {% include "base/navbar.html" %} +
{# Filtering toolbox #} -- cgit v1.2.3 From d8c5571a266438d5e2e0c9fd4a35adf469688730 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Sun, 30 Jan 2022 12:34:29 +0100 Subject: Support dashful redirects. Previously, trying to go to `resources/project%20ideas` would crash the filtering JS. This has now been sorted out, so that these types of redirects have their spaces replaced by dashes, which makes them valid again. --- pydis_site/apps/resources/views/resources.py | 7 +++++-- pydis_site/static/js/resources.js | 11 +++++------ pydis_site/templates/resources/resources.html | 1 - 3 files changed, 10 insertions(+), 9 deletions(-) (limited to 'pydis_site/apps/resources/views/resources.py') diff --git a/pydis_site/apps/resources/views/resources.py b/pydis_site/apps/resources/views/resources.py index b828d89a..709fad6c 100644 --- a/pydis_site/apps/resources/views/resources.py +++ b/pydis_site/apps/resources/views/resources.py @@ -82,9 +82,12 @@ class ResourceView(View): def get(self, request: WSGIRequest, resource_type: t.Optional[str] = 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 - if resource_type and resource_type.title() not in self.filters['Type']['filters']: + # 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. + dashless_resource_type = resource_type.replace("-", " ") + if resource_type and dashless_resource_type.title() not in self.filters['Type']['filters']: return HttpResponseNotFound() + resource_type = resource_type.replace(" ", "-") return render( request, diff --git a/pydis_site/static/js/resources.js b/pydis_site/static/js/resources.js index bfcd569d..34587c81 100644 --- a/pydis_site/static/js/resources.js +++ b/pydis_site/static/js/resources.js @@ -64,9 +64,9 @@ function deserializeURLParams() { // Update the corresponding filter UI, so it reflects the internal state. $(paramFilterArray).each(function(_, filter) { - let checkbox = $(`.filter-checkbox[data-filter-name=${filterType}][data-filter-item=${filter}]`); - let filterTag = $(`.filter-box-tag[data-filter-name=${filterType}][data-filter-item=${filter}]`); - let resourceTags = $(`.resource-tag[data-filter-name=${filterType}][data-filter-item=${filter}]`); + let checkbox = $(`.filter-checkbox[data-filter-name='${filterType}'][data-filter-item='${filter}']`); + let filterTag = $(`.filter-box-tag[data-filter-name='${filterType}'][data-filter-item='${filter}']`); + let resourceTags = $(`.resource-tag[data-filter-name='${filterType}'][data-filter-item='${filter}']`); checkbox.prop("checked", true); filterTag.show(); resourceTags.addClass("active"); @@ -149,7 +149,6 @@ function updateUI() { }).show(); // If there are no matches, show the no matches message - console.log(hasMatches); if (!hasMatches) { $(".no-resources-found").show(); } else { @@ -196,7 +195,7 @@ document.addEventListener("DOMContentLoaded", function () { $('.filter-box-tag').click(function() { let filterItem = this.dataset.filterItem; let filterName = this.dataset.filterName; - let checkbox = $(`.filter-checkbox[data-filter-name=${filterName}][data-filter-item=${filterItem}]`); + let checkbox = $(`.filter-checkbox[data-filter-name='${filterName}'][data-filter-item='${filterItem}']`); removeFilter(filterName, filterItem); checkbox.prop("checked", false); @@ -206,7 +205,7 @@ document.addEventListener("DOMContentLoaded", function () { $('.resource-tag').click(function() { let filterItem = this.dataset.filterItem; let filterName = this.dataset.filterName; - let checkbox = $(`.filter-checkbox[data-filter-name=${filterName}][data-filter-item=${filterItem}]`) + let checkbox = $(`.filter-checkbox[data-filter-name='${filterName}'][data-filter-item='${filterItem}']`); if (!$(this).hasClass("active")) { addFilter(filterName, filterItem); diff --git a/pydis_site/templates/resources/resources.html b/pydis_site/templates/resources/resources.html index 7a284fd6..4dd07270 100644 --- a/pydis_site/templates/resources/resources.html +++ b/pydis_site/templates/resources/resources.html @@ -7,7 +7,6 @@ {% block title %}Resources{% endblock %} {% block head %} - -- cgit v1.2.3 From bb401838ef8fa135a51d6a735dbbc3cc812d5e6c Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Sun, 30 Jan 2022 12:42:06 +0100 Subject: Ensure "Other" is always the bottom topic. --- pydis_site/apps/resources/views/resources.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'pydis_site/apps/resources/views/resources.py') diff --git a/pydis_site/apps/resources/views/resources.py b/pydis_site/apps/resources/views/resources.py index 709fad6c..a5c2cf7c 100644 --- a/pydis_site/apps/resources/views/resources.py +++ b/pydis_site/apps/resources/views/resources.py @@ -1,5 +1,5 @@ -from pathlib import Path import typing as t +from pathlib import Path import yaml from django.core.handlers.wsgi import WSGIRequest @@ -79,15 +79,21 @@ class ResourceView(View): } } + # The bottom topic should always be "Other". + self.filters["Topics"]["filters"].remove("Other") + self.filters["Topics"]["filters"].append("Other") + def get(self, request: WSGIRequest, resource_type: t.Optional[str] = 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. - dashless_resource_type = resource_type.replace("-", " ") - if resource_type and dashless_resource_type.title() not in self.filters['Type']['filters']: - return HttpResponseNotFound() - resource_type = resource_type.replace(" ", "-") + if resource_type: + dashless_resource_type = resource_type.replace("-", " ") + + if dashless_resource_type.title() not in self.filters['Type']['filters']: + return HttpResponseNotFound() + + resource_type = resource_type.replace(" ", "-") return render( request, -- cgit v1.2.3 From 91935d88476bade9701d354e82cafba912a33f69 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Mon, 31 Jan 2022 18:02:59 +0100 Subject: Get rid of invalid filters in the URL. --- pydis_site/apps/resources/views/resources.py | 11 +++++++++++ pydis_site/static/js/resources/resources.js | 24 +++++++++++++++++------- pydis_site/templates/resources/resources.html | 5 +++++ 3 files changed, 33 insertions(+), 7 deletions(-) (limited to 'pydis_site/apps/resources/views/resources.py') diff --git a/pydis_site/apps/resources/views/resources.py b/pydis_site/apps/resources/views/resources.py index a5c2cf7c..a38c3b59 100644 --- a/pydis_site/apps/resources/views/resources.py +++ b/pydis_site/apps/resources/views/resources.py @@ -1,3 +1,4 @@ +import json import typing as t from pathlib import Path @@ -8,6 +9,7 @@ from django.shortcuts import render from django.views import View from pydis_site import settings +from pydis_site.apps.resources.templatetags.as_css_class import as_css_class RESOURCES_PATH = Path(settings.BASE_DIR, "pydis_site", "apps", "resources", "resources") @@ -83,6 +85,14 @@ class ResourceView(View): self.filters["Topics"]["filters"].remove("Other") self.filters["Topics"]["filters"].append("Other") + # A complete list of valid filter names + self.valid_filters = { + "topics": [as_css_class(topic) for topic in self.filters["Topics"]["filters"]], + "payment_tiers": [as_css_class(tier) for tier in self.filters["Payment tiers"]["filters"]], + "type": [as_css_class(type_) for type_ in self.filters["Type"]["filters"]], + "difficulty": [as_css_class(tier) for tier in self.filters["Difficulty"]["filters"]], + } + def get(self, request: WSGIRequest, resource_type: t.Optional[str] = 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. @@ -101,6 +111,7 @@ class ResourceView(View): context={ "resources": self.resources, "filters": self.filters, + "valid_filters": json.dumps(self.valid_filters), "resource_type": resource_type, } ) diff --git a/pydis_site/static/js/resources/resources.js b/pydis_site/static/js/resources/resources.js index 44d4db5c..ad26afd4 100644 --- a/pydis_site/static/js/resources/resources.js +++ b/pydis_site/static/js/resources/resources.js @@ -67,17 +67,27 @@ function deserializeURLParams() { if (paramFilterContent !== null) { // We use split here because we always want an array, not a string. let paramFilterArray = paramFilterContent.split(","); - activeFilters[filterType] = paramFilterArray; // Update the corresponding filter UI, so it reflects the internal state. $(paramFilterArray).each(function(_, filter) { - let checkbox = $(`.filter-checkbox[data-filter-name='${filterType}'][data-filter-item='${filter}']`); - let filterTag = $(`.filter-box-tag[data-filter-name='${filterType}'][data-filter-item='${filter}']`); - let resourceTags = $(`.resource-tag[data-filter-name='${filterType}'][data-filter-item='${filter}']`); - checkbox.prop("checked", true); - filterTag.show(); - resourceTags.addClass("active"); + // Make sure the filter is valid before we do anything. + if (String(filter) === "rickroll" && filterType === "type") { + window.location.href = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"; + } else if (String(filter) === "sneakers" && filterType === "topics") { + window.location.href = "https://www.youtube.com/watch?v=NNZscmNE9QI"; + } else if (validFilters[filterType].includes(String(filter))) { + let checkbox = $(`.filter-checkbox[data-filter-name='${filterType}'][data-filter-item='${filter}']`); + let filterTag = $(`.filter-box-tag[data-filter-name='${filterType}'][data-filter-item='${filter}']`); + let resourceTags = $(`.resource-tag[data-filter-name='${filterType}'][data-filter-item='${filter}']`); + checkbox.prop("checked", true); + filterTag.show(); + resourceTags.addClass("active"); + activeFilters[filterType].push(filter); + } }); + + // Ditch all the params from the URL, and recalculate the URL params + updateURL(); } }); } diff --git a/pydis_site/templates/resources/resources.html b/pydis_site/templates/resources/resources.html index 13bba1f2..a37bf80a 100644 --- a/pydis_site/templates/resources/resources.html +++ b/pydis_site/templates/resources/resources.html @@ -6,6 +6,11 @@ {% block title %}Resources{% endblock %} {% block head %} + {# Inject a JSON object of all valid filter types from the view #} + + -- cgit v1.2.3 From 98c02d34aabb26babcc6def54c4f0872c7700be9 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Mon, 31 Jan 2022 19:57:06 +0100 Subject: Placate the flake8. --- pydis_site/apps/resources/views/resources.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'pydis_site/apps/resources/views/resources.py') diff --git a/pydis_site/apps/resources/views/resources.py b/pydis_site/apps/resources/views/resources.py index a38c3b59..55d104bd 100644 --- a/pydis_site/apps/resources/views/resources.py +++ b/pydis_site/apps/resources/views/resources.py @@ -88,7 +88,9 @@ class ResourceView(View): # A complete list of valid filter names self.valid_filters = { "topics": [as_css_class(topic) for topic in self.filters["Topics"]["filters"]], - "payment_tiers": [as_css_class(tier) for tier in self.filters["Payment tiers"]["filters"]], + "payment_tiers": [ + as_css_class(tier) for tier in self.filters["Payment tiers"]["filters"] + ], "type": [as_css_class(type_) for type_ in self.filters["Type"]["filters"]], "difficulty": [as_css_class(tier) for tier in self.filters["Difficulty"]["filters"]], } -- cgit v1.2.3 From 1f41d185414d5d3a7ce056828541d09a860037ce Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Tue, 1 Feb 2022 02:38:48 +0100 Subject: Sort resources alphabetically, disregarding 'the'. --- pydis_site/apps/resources/views/resources.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'pydis_site/apps/resources/views/resources.py') diff --git a/pydis_site/apps/resources/views/resources.py b/pydis_site/apps/resources/views/resources.py index 55d104bd..1895f12a 100644 --- a/pydis_site/apps/resources/views/resources.py +++ b/pydis_site/apps/resources/views/resources.py @@ -17,6 +17,15 @@ RESOURCES_PATH = Path(settings.BASE_DIR, "pydis_site", "apps", "resources", "res class ResourceView(View): """Our curated list of good learning resources.""" + @staticmethod + def _sort_key_disregard_the(tuple_): + """Sort a tuple by its key alphabetically, disregarding 'the' as a prefix.""" + name, resource = tuple_ + name = name.casefold() + if name.startswith("the ") or name.startswith("the_"): + return name[4:] + return name + def __init__(self, *args, **kwargs): """Set up all the resources.""" super().__init__(*args, **kwargs) @@ -28,7 +37,7 @@ class ResourceView(View): } # Sort the resources alphabetically - self.resources = dict(sorted(self.resources.items())) + self.resources = dict(sorted(self.resources.items(), key=self._sort_key_disregard_the)) # Parse out all current tags resource_tags = { -- cgit v1.2.3 From 3ad82bfd3f288dcd5eb270caa9f248cf7f97ffc5 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Tue, 1 Feb 2022 02:51:50 +0100 Subject: Add type annotations for sort key method. --- pydis_site/apps/resources/views/resources.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/resources/views/resources.py') diff --git a/pydis_site/apps/resources/views/resources.py b/pydis_site/apps/resources/views/resources.py index 1895f12a..0e448ece 100644 --- a/pydis_site/apps/resources/views/resources.py +++ b/pydis_site/apps/resources/views/resources.py @@ -18,7 +18,7 @@ class ResourceView(View): """Our curated list of good learning resources.""" @staticmethod - def _sort_key_disregard_the(tuple_): + 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() -- cgit v1.2.3 From 11cbc008ee5f5bafb9ca24fbd8564202310fa6f4 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Tue, 1 Feb 2022 20:21:10 +0100 Subject: Kaizen: Make jchrists wildest dreams come true Co-authored-by: Johannes Christ --- pydis_site/apps/resources/views/resources.py | 2 +- pydis_site/templates/resources/resource_box.html | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'pydis_site/apps/resources/views/resources.py') diff --git a/pydis_site/apps/resources/views/resources.py b/pydis_site/apps/resources/views/resources.py index 0e448ece..ac9e8355 100644 --- a/pydis_site/apps/resources/views/resources.py +++ b/pydis_site/apps/resources/views/resources.py @@ -111,7 +111,7 @@ class ResourceView(View): 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 self.filters["Type"]["filters"]: return HttpResponseNotFound() resource_type = resource_type.replace(" ", "-") diff --git a/pydis_site/templates/resources/resource_box.html b/pydis_site/templates/resources/resource_box.html index 0ba8b0ec..2ec233cb 100644 --- a/pydis_site/templates/resources/resource_box.html +++ b/pydis_site/templates/resources/resource_box.html @@ -14,8 +14,8 @@

{{ resource.description|safe }}

- {# Add primary link #} - {% if 'title_url' in resource %} + {# Add primary link #} + {% if "title_url" in resource %} -- cgit v1.2.3 From f3bccff688a7f5a9eb619dbed3f726ef2c07c402 Mon Sep 17 00:00:00 2001 From: Leon Sandøy Date: Tue, 1 Feb 2022 20:54:39 +0100 Subject: Refactor as_css_class to 'to_kebabcase'. We're making a few changes here - Changing the name to 'to_kebabcase' - Covering all edge cases - Adding a unit test for this utility --- .../apps/resources/templatetags/as_css_class.py | 18 ---------- .../apps/resources/templatetags/to_kebabcase.py | 39 ++++++++++++++++++++++ pydis_site/apps/resources/tests/test_resources.py | 9 ----- .../apps/resources/tests/test_to_kebabcase.py | 19 +++++++++++ .../testing/foobar/resource_test.yaml | 1 - .../testing_resources/testing/my_resource.yaml | 1 - pydis_site/apps/resources/views/resources.py | 14 ++++---- pydis_site/templates/resources/resource_box.html | 10 +++--- pydis_site/templates/resources/resources.html | 22 ++++++------ 9 files changed, 80 insertions(+), 53 deletions(-) delete mode 100644 pydis_site/apps/resources/templatetags/as_css_class.py create mode 100644 pydis_site/apps/resources/templatetags/to_kebabcase.py delete mode 100644 pydis_site/apps/resources/tests/test_resources.py create mode 100644 pydis_site/apps/resources/tests/test_to_kebabcase.py delete mode 100644 pydis_site/apps/resources/tests/testing_resources/testing/foobar/resource_test.yaml delete mode 100644 pydis_site/apps/resources/tests/testing_resources/testing/my_resource.yaml (limited to 'pydis_site/apps/resources/views/resources.py') diff --git a/pydis_site/apps/resources/templatetags/as_css_class.py b/pydis_site/apps/resources/templatetags/as_css_class.py deleted file mode 100644 index 8b628dc9..00000000 --- a/pydis_site/apps/resources/templatetags/as_css_class.py +++ /dev/null @@ -1,18 +0,0 @@ -from django import template - -register = template.Library() - - -@register.filter -def as_css_class(class_name: str) -> str: - """ - Convert any string to a css-class name. - - For example, convert - "Favorite FROOT_is_LEMON" to - "favorite-froot-is-lemon" - """ - class_name = class_name.lower() - class_name = class_name.replace(" ", "-") - class_name = class_name.replace("_", "-") - return class_name diff --git a/pydis_site/apps/resources/templatetags/to_kebabcase.py b/pydis_site/apps/resources/templatetags/to_kebabcase.py new file mode 100644 index 00000000..41e2ac85 --- /dev/null +++ b/pydis_site/apps/resources/templatetags/to_kebabcase.py @@ -0,0 +1,39 @@ +import re + +from django import template + +REGEX_CONSECUTIVE_NON_LETTERS = r"[^A-Za-z0-9]+" +register = template.Library() + + +def _to_kebabcase(class_name: str) -> str: + """ + Convert any string to kebab-case. + + For example, convert + "__Favorite FROOT¤#/$?is----LeMON???" to + "favorite-froot-is-lemon" + """ + # First, make it lowercase, and just remove any apostrophes. + # We remove the apostrophes because "wasnt" is better than "wasn-t" + class_name = class_name.casefold() + class_name = class_name.replace("'", '') + + # Now, replace any non-letter that remains with a dash. + # If there are multiple consecutive non-letters, just replace them with a single dash. + # my-favorite-class is better than my-favorite------class + class_name = re.sub( + REGEX_CONSECUTIVE_NON_LETTERS, + "-", + class_name, + ) + + # Now we use strip to get rid of any leading or trailing dashes. + class_name = class_name.strip("-") + return class_name + + +@register.filter +def to_kebabcase(class_name: str) -> str: + """Convert a string to kebab-case.""" + return _to_kebabcase(class_name) diff --git a/pydis_site/apps/resources/tests/test_resources.py b/pydis_site/apps/resources/tests/test_resources.py deleted file mode 100644 index 81638e2f..00000000 --- a/pydis_site/apps/resources/tests/test_resources.py +++ /dev/null @@ -1,9 +0,0 @@ -from django.test import TestCase - - -class TestResources(TestCase): - """Test our resource filtering systems.""" - - def test_utils_to_retrieve_tags(self): - """Test that the utils that retrieve the tags work as intended.""" - pass diff --git a/pydis_site/apps/resources/tests/test_to_kebabcase.py b/pydis_site/apps/resources/tests/test_to_kebabcase.py new file mode 100644 index 00000000..a141143d --- /dev/null +++ b/pydis_site/apps/resources/tests/test_to_kebabcase.py @@ -0,0 +1,19 @@ +from django.test import TestCase + +from pydis_site.apps.resources.templatetags.to_kebabcase import _to_kebabcase + + +class TestToKebabcase(TestCase): + """Tests for the `as_css_class` template tag.""" + + def test_to_kebabcase(self): + """Test the to_kebabcase utility and template tag.""" + weird_input = ( + "_-_--_A_LEm0n?in&¤'the##trEE£$@€@€@@£is-NOT----QUITE//" + "as#good! as one __IN-YOUR|||HaND" + ) + + self.assertEqual( + _to_kebabcase(weird_input), + "a-lem0n-in-the-tree-is-not-quite-as-good-as-one-in-your-hand", + ) diff --git a/pydis_site/apps/resources/tests/testing_resources/testing/foobar/resource_test.yaml b/pydis_site/apps/resources/tests/testing_resources/testing/foobar/resource_test.yaml deleted file mode 100644 index 22835090..00000000 --- a/pydis_site/apps/resources/tests/testing_resources/testing/foobar/resource_test.yaml +++ /dev/null @@ -1 +0,0 @@ -name: Resource Test diff --git a/pydis_site/apps/resources/tests/testing_resources/testing/my_resource.yaml b/pydis_site/apps/resources/tests/testing_resources/testing/my_resource.yaml deleted file mode 100644 index 61df6173..00000000 --- a/pydis_site/apps/resources/tests/testing_resources/testing/my_resource.yaml +++ /dev/null @@ -1 +0,0 @@ -name: My Resource diff --git a/pydis_site/apps/resources/views/resources.py b/pydis_site/apps/resources/views/resources.py index ac9e8355..2375f722 100644 --- a/pydis_site/apps/resources/views/resources.py +++ b/pydis_site/apps/resources/views/resources.py @@ -9,7 +9,7 @@ from django.shortcuts import render from django.views import View from pydis_site import settings -from pydis_site.apps.resources.templatetags.as_css_class import as_css_class +from pydis_site.apps.resources.templatetags.to_kebabcase import to_kebabcase RESOURCES_PATH = Path(settings.BASE_DIR, "pydis_site", "apps", "resources", "resources") @@ -58,9 +58,7 @@ class ResourceView(View): # Make a CSS class friendly representation too, while we're already iterating. for tag in tags: - css_tag = f"{tag_type}-{tag}" - css_tag = css_tag.replace("_", "-") - css_tag = css_tag.replace(" ", "-") + 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. @@ -96,12 +94,12 @@ class ResourceView(View): # A complete list of valid filter names self.valid_filters = { - "topics": [as_css_class(topic) for topic in self.filters["Topics"]["filters"]], + "topics": [to_kebabcase(topic) for topic in self.filters["Topics"]["filters"]], "payment_tiers": [ - as_css_class(tier) for tier in self.filters["Payment tiers"]["filters"] + to_kebabcase(tier) for tier in self.filters["Payment tiers"]["filters"] ], - "type": [as_css_class(type_) for type_ in self.filters["Type"]["filters"]], - "difficulty": [as_css_class(tier) for tier in self.filters["Difficulty"]["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: t.Optional[str] = None) -> HttpResponse: diff --git a/pydis_site/templates/resources/resource_box.html b/pydis_site/templates/resources/resource_box.html index 2ec233cb..e26203e9 100644 --- a/pydis_site/templates/resources/resource_box.html +++ b/pydis_site/templates/resources/resource_box.html @@ -1,5 +1,5 @@ {% load as_icon %} -{% load as_css_class %} +{% load to_kebabcase %} {% load get_category_icon %}
@@ -38,7 +38,7 @@ {{ tag|title }} @@ -48,7 +48,7 @@ {{ tag|title }} @@ -58,7 +58,7 @@ {{ tag|title }} @@ -68,7 +68,7 @@ {{ tag|title }} diff --git a/pydis_site/templates/resources/resources.html b/pydis_site/templates/resources/resources.html index c221c8a3..70fad097 100644 --- a/pydis_site/templates/resources/resources.html +++ b/pydis_site/templates/resources/resources.html @@ -1,6 +1,6 @@ {% extends 'base/base.html' %} {% load as_icon %} -{% load as_css_class %} +{% load to_kebabcase %} {% load get_category_icon %} {% load static %} @@ -44,8 +44,8 @@ {% if filter_name == "Difficulty" %} {{ filter_item|title }} @@ -55,8 +55,8 @@ {% if filter_name == "Type" %} {{ filter_item|title }} @@ -66,8 +66,8 @@ {% if filter_name == "Payment tiers" %} {{ filter_item|title }} @@ -77,8 +77,8 @@ {% if filter_name == "Topics" %} {{ filter_item|title }} @@ -127,8 +127,8 @@ {{ filter_item }} -- cgit v1.2.3