diff options
author | 2018-03-04 16:33:01 +0000 | |
---|---|---|
committer | 2018-03-04 16:33:01 +0000 | |
commit | 5099ae7055b313d1a93d53069c2cfbb0ca0dcf5a (patch) | |
tree | e8d4b781a38b17502f24e1fd9f444926e88544d6 | |
parent | Fix navbar dropdown (diff) |
Info pages #13xan #13xak (#36)
* Info pages and templates
* Info pages and templates
* Info pages and templates
* Update navigation and fix up HTML
* Navigation HTML spacing for readability
* Fix error views not using `self.render()`
* `render()` method should accept Any for context values
* Change header linking CSS to a dedicated class
* Rules page
* Basic resources page setup
* Fix headers for new CSS class
* Resource categories and initial resource data
* Add link to JSON file on GH - won't work until the branch is merged
* Remove info overview page and redirect info root url to resources
* Flake8
* Add some tests
* Line lengths
-rw-r--r-- | app_test.py | 21 | ||||
-rw-r--r-- | pysite/base_route.py | 4 | ||||
-rw-r--r-- | pysite/views/error_handlers/http_4xx.py | 24 | ||||
-rw-r--r-- | pysite/views/error_handlers/http_5xx.py | 39 | ||||
-rw-r--r-- | pysite/views/main/info/index.py | 12 | ||||
-rw-r--r-- | pysite/views/main/info/resources.py | 21 | ||||
-rw-r--r-- | pysite/views/main/info/rules.py | 10 | ||||
-rw-r--r-- | static/resources.json | 45 | ||||
-rw-r--r-- | static/style.css | 8 | ||||
-rw-r--r-- | templates/main/info/help.html | 10 | ||||
-rw-r--r-- | templates/main/info/resources.html | 56 | ||||
-rw-r--r-- | templates/main/info/rules.html | 116 | ||||
-rw-r--r-- | templates/main/navigation.html | 42 |
13 files changed, 351 insertions, 57 deletions
diff --git a/app_test.py b/app_test.py index 2e8a53fb..39c61ff5 100644 --- a/app_test.py +++ b/app_test.py @@ -33,11 +33,32 @@ class BaseEndpoints(SiteTest): response = self.client.get('/', 'http://pytest.local') self.assertEqual(response.status_code, 200) + def test_info_index(self): + """ Check the info index path responds with a 301 """ + response = self.client.get('/info') + self.assertEqual(response.status_code, 301) + def test_info_help(self): """ Check the info help path responds with 200 OK """ response = self.client.get('/info/help') self.assertEqual(response.status_code, 200) + def test_info_resources(self): + """ Check the info resources path responds with 200 OK """ + response = self.client.get('/info/resources') + self.assertEqual(response.status_code, 200) + + def test_info_resources_json(self): + """ Check the resources JSON loads correctly """ + response = self.client.get('/static/resources.json') + self.assertEqual(response.status_code, 200) + self.assertIsInstance(json.loads(response.data), dict) + + def test_info_rules(self): + """ Check the info rules path responds with 200 OK """ + response = self.client.get('/info/help') + self.assertEqual(response.status_code, 200) + def test_not_found(self): """ Check paths without handlers returns 404 Not Found """ response = self.client.get('/nonexistentpath') diff --git a/pysite/base_route.py b/pysite/base_route.py index 400a4649..f389b56e 100644 --- a/pysite/base_route.py +++ b/pysite/base_route.py @@ -1,6 +1,6 @@ # coding=utf-8 from collections import Iterable -from typing import Any, Dict +from typing import Any from flask import Blueprint, Response, jsonify, render_template from flask.views import MethodView @@ -17,7 +17,7 @@ class BaseView(MethodView): name = None # type: str - def render(self, *template_names: str, **context: Dict[str, Any]) -> str: + def render(self, *template_names: str, **context: Any) -> str: """ Render some templates and get them back in a form that you can simply return from your view function. diff --git a/pysite/views/error_handlers/http_4xx.py b/pysite/views/error_handlers/http_4xx.py index 5717feae..74d43d6c 100644 --- a/pysite/views/error_handlers/http_4xx.py +++ b/pysite/views/error_handlers/http_4xx.py @@ -1,5 +1,5 @@ # coding=utf-8 -from flask import render_template, request +from flask import request from werkzeug.exceptions import HTTPException from pysite.base_route import ErrorView @@ -13,17 +13,19 @@ class Error400View(ErrorView): def get(self, error: HTTPException): error_desc = ERROR_DESCRIPTIONS.get(error.code, "We're not really sure what happened there, please try again.") - return render_template("errors/error.html", code=error.code, req=request, error_title=error_desc, - error_message=error_desc + - " If you believe we have made a mistake, please " - "<a href='https://github.com" - "/discord-python/site/issues'>open an issue on our GitHub</a>."), error.code + return self.render( + "errors/error.html", code=error.code, req=request, error_title=error_desc, + error_message=error_desc + + " If you believe we have made a mistake, please " + "<a href='https://github.com/discord-python/site/issues'>open an issue on our GitHub</a>." + ), error.code def post(self, error: HTTPException): error_desc = ERROR_DESCRIPTIONS.get(error.code, "We're not really sure what happened there, please try again.") - return render_template("errors/error.html", code=error.code, req=request, error_title=error_desc, - error_message=error_desc + - " If you believe we have made a mistake, please " - "<a href='https://github.com" - "/discord-python/site/issues'>open an issue on our GitHub</a>."), error.code + return self.render( + "errors/error.html", code=error.code, req=request, error_title=error_desc, + error_message=error_desc + + " If you believe we have made a mistake, please " + "<a href='https://github.com/discord-python/site/issues'>open an issue on our GitHub</a>." + ), error.code diff --git a/pysite/views/error_handlers/http_5xx.py b/pysite/views/error_handlers/http_5xx.py index 6bbc8275..60d3b1bb 100644 --- a/pysite/views/error_handlers/http_5xx.py +++ b/pysite/views/error_handlers/http_5xx.py @@ -1,5 +1,5 @@ # coding=utf-8 -from flask import render_template, request +from flask import request from werkzeug.exceptions import HTTPException from pysite.base_route import ErrorView @@ -13,28 +13,21 @@ class Error500View(ErrorView): def get(self, error: HTTPException): error_desc = ERROR_DESCRIPTIONS.get(error.code, "We're not really sure what happened there, please try again.") - return render_template("errors/error.html", code=error.code, req=request, error_title=error_desc, - error_message="An error occurred while " - "processing this " - "request, please try " - "again later. " - "If you believe we have made a mistake, " - "please " - "<a href='https://github.com" - "/discord-python/site/issues'>file an issue on our GitHub" - "</a>."), error.code + return self.render( + "errors/error.html", code=error.code, req=request, error_title=error_desc, + error_message="An error occurred while processing this request, please try " + "again later. If you believe we have made a mistake, please " + "<a href='https://github.com/discord-python/site/issues'>file an issue on our" + " GitHub</a>." + ), error.code def post(self, error: HTTPException): - error_desc = ERROR_DESCRIPTIONS.get(error.code, - "We're not really sure what happened there, please try again.") + error_desc = ERROR_DESCRIPTIONS.get(error.code, "We're not really sure what happened there, please try again.") - return render_template("errors/error.html", code=error.code, req=request, error_title=error_desc, - error_message="An error occurred while " - "processing this " - "request, please try " - "again later. " - "If you believe we have made a mistake, " - "please " - "<a href='https://github.com" - "/discord-python/site/issues'>file an issue on our GitHub" - "</a>."), error.code + return self.render( + "errors/error.html", code=error.code, req=request, error_title=error_desc, + error_message="An error occurred while processing this request, please try " + "again later. If you believe we have made a mistake, please " + "<a href='https://github.com/discord-python/site/issues'>file an issue on our" + " GitHub</a>." + ), error.code diff --git a/pysite/views/main/info/index.py b/pysite/views/main/info/index.py new file mode 100644 index 00000000..371a5353 --- /dev/null +++ b/pysite/views/main/info/index.py @@ -0,0 +1,12 @@ +# coding=utf-8 +from flask import redirect + +from pysite.base_route import RouteView + + +class IndexView(RouteView): + path = "/info/" + name = "info" + + def get(self): + return redirect("/info/resources") diff --git a/pysite/views/main/info/resources.py b/pysite/views/main/info/resources.py new file mode 100644 index 00000000..bce162f4 --- /dev/null +++ b/pysite/views/main/info/resources.py @@ -0,0 +1,21 @@ +# coding=utf-8 +import json +from logging import getLogger + +from pysite.base_route import RouteView + + +try: + with open("static/resources.json") as fh: + categories = json.load(fh) +except Exception: + getLogger("Resources").exception("Failed to load resources.json") + categories = None + + +class ResourcesView(RouteView): + path = "/info/resources" + name = "info/resources" + + def get(self): + return self.render("main/info/resources.html", categories=categories) diff --git a/pysite/views/main/info/rules.py b/pysite/views/main/info/rules.py new file mode 100644 index 00000000..75faded1 --- /dev/null +++ b/pysite/views/main/info/rules.py @@ -0,0 +1,10 @@ +# coding=utf-8 +from pysite.base_route import RouteView + + +class RulesView(RouteView): + path = "/info/rules" + name = "info/rules" + + def get(self): + return self.render("main/info/rules.html") diff --git a/static/resources.json b/static/resources.json new file mode 100644 index 00000000..1e6bc503 --- /dev/null +++ b/static/resources.json @@ -0,0 +1,45 @@ +{ + "Learning Resources": { + "description": "Tutorials and references for those that are just getting started with python", + "resources": { + "Automate the Boring Stuff with Python": { + "description": "One of the best books out there for Python beginners. You can buy a copy, but there's also a free online version.", + "url": "https://automatetheboringstuff.com/" + }, + "Getting Started for Non-Programmers": { + "description": "The list of resources for non-programmers from Python's official beginners' guide", + "url": "https://wiki.python.org/moin/BeginnersGuide/NonProgrammers" + }, + "Getting Started for Programmers": { + "description": "The list of resources for programmers from Python's official beginners' guide", + "url": "https://wiki.python.org/moin/BeginnersGuide/Programmers" + } + } + }, + "Editors": { + "description": "Lightweight code editors supporting Python", + "resources": { + "Visual Studio Code (Free)": { + "description": "A fully-featured editor based on Electron, extendable with plugins.", + "url": "https://code.visualstudio.com/" + }, + "Sublime Text (Paid, with shareware-style \"trial\")": { + "description": "A powerful Python-backed editor with great community support and a wealth of extensions.", + "url": "https://www.sublimetext.com/" + } + } + }, + "IDEs": { + "description": "Fully-integrated development environments for serious Python work", + "resources": { + "PyCharm (Community and Professional editions available)": { + "description": "The very best Python IDE, with a wealth of advanced features and convenience functions.", + "url": "https://www.jetbrains.com/pycharm/" + }, + "Spyder (Free)": { + "description": "The Scientific PYthon Development EnviRonment. Simpler and lighter than PyCharm, but still packs a punch.", + "url": "https://pythonhosted.org/spyder/" + } + } + } +} diff --git a/static/style.css b/static/style.css index fbbec5c1..2b14c8ce 100644 --- a/static/style.css +++ b/static/style.css @@ -25,7 +25,7 @@ top: 45px !important; } -.uk-article-title a { +.hover-title a { visibility: hidden; opacity: 0; @@ -34,7 +34,7 @@ -webkit-transition: opacity 200ms ease-in-out; } -.uk-article-title:hover a { +.hover-title:hover a { visibility: visible; opacity: 1; @@ -54,4 +54,8 @@ .uk-section { padding-top: 20px; padding-bottom: 30px; +} + +.uk-heading-divider .uk-article-meta { + margin-bottom: 0; }
\ No newline at end of file diff --git a/templates/main/info/help.html b/templates/main/info/help.html index d3084f8b..de041f66 100644 --- a/templates/main/info/help.html +++ b/templates/main/info/help.html @@ -4,7 +4,7 @@ <div class="uk-section"> <div class="uk-container uk-container-small"> <article class="uk-article"> - <h1 class="uk-article-title" id="top"> + <h1 class="uk-article-title hover-title" id="top"> Getting Help <a href="#top" class="uk-text-primary" title="Permanent link to this header"> @@ -26,7 +26,7 @@ behind that essay are in no way affiliated with us - please do not bother them with your Python problems. </p> - <h2 class="uk-article-title" id="before"> + <h2 class="uk-article-title hover-title" id="before"> Before You Ask <a href="#before" class="uk-text-primary" title="Permanent link to this header"> @@ -110,7 +110,7 @@ whether someone else has asked your question recently, or just feel free to pick one of the help channels and ask your question. </p> - <h2 class="uk-article-title" id="good-question"> + <h2 class="uk-article-title hover-title" id="good-question"> A Good Question <a href="#good-question" class="uk-text-primary" title="Permanent link to this header"> @@ -297,7 +297,7 @@ <div class="uk-section"> <div class="uk-container uk-container-small"> <article class="uk-article"> - <h2 class="uk-article-title" id="answers"> + <h2 class="uk-article-title hover-title" id="answers"> Interpreting Answers <a href="#answers" class="uk-text-primary" title="Permanent link to this header"> @@ -364,7 +364,7 @@ people applying actively them, visibly, in public. </p> - <h2 class="uk-article-title" id="what-not-to-ask"> + <h2 class="uk-article-title hover-title" id="what-not-to-ask"> What Not To Ask <a href="#what-not-to-ask" class="uk-text-primary" title="Permanent link to this header"> diff --git a/templates/main/info/resources.html b/templates/main/info/resources.html new file mode 100644 index 00000000..576d68ec --- /dev/null +++ b/templates/main/info/resources.html @@ -0,0 +1,56 @@ +{% extends "main/base.html" %} +{% block title %}Resources{% endblock %} +{% block content %} + <div class="uk-section"> + <div class="uk-container uk-container-small"> + <article class="uk-article"> + <h1 class="uk-article-title hover-title" id="top"> + Resources + + <a href="#top" class="uk-text-primary" title="Permanent link to this header"> + <i class="fas fa-paragraph" data-fa-transform="shrink-8"></i> + </a> + </h1> + <p class="uk-article-meta"> + Learn you a Haskell for great- wait, wrong book + </p> + <p> + This page is intended to be a listing of useful resources for beginner and experienced Python + programmers alike. This page is generated from a JSON file + <a href="https://github.com/discord-python/site/blob/master/static/resources.json">on GitHub</a> - + if there's a great resource that you love and you don't see it on this page, feel free to submit a + pull request! + </p> + + {% if categories is none %} + <div class="uk-alert-danger" uk-alert> + <p> + We were unable to load the <code>resources.json</code> file. If you see this, please + notify us! + </p> + </div> + {% else %} + {% for category_name, category_data in categories.items() %} + <h2 class="uk-heading-divider hover-title" id="{{ category_name.replace(" ", "-").lower() }}"> + {{ category_name }} + + <a href="#{{ category_name.replace(" ", "-").lower() }}" class="uk-text-primary" title="Permanent link to this header"> + <i class="fas fa-paragraph" data-fa-transform="shrink-8"></i> + </a> + <br/> + <p class="uk-article-meta"> + {{ category_data.description }} + </p> + </h2> + {% for item, data in category_data.resources.items() %} + <p> + <strong>{{ item }}</strong> <a href="{{ data.url }}"><i class="fas fa-link"></i></a><br /> + <span class="uk-text-meta">{{ data.description }}</span> + </p> + {% endfor %} + {% endfor %} + {% endif %} + </article> + </div> + </div> +{% endblock %}
\ No newline at end of file diff --git a/templates/main/info/rules.html b/templates/main/info/rules.html new file mode 100644 index 00000000..1853f090 --- /dev/null +++ b/templates/main/info/rules.html @@ -0,0 +1,116 @@ +{% extends "main/base.html" %} +{% block title %}Rules{% endblock %} +{% block content %} + <div class="uk-section"> + <div class="uk-container uk-container-small"> + <article class="uk-article"> + <h1 class="uk-article-title hover-title" id="top"> + Rules + + <a href="#top" class="uk-text-primary" title="Permanent link to this header"> + <i class="fas fa-paragraph" data-fa-transform="shrink-8"></i> + </a> + </h1> + <p class="uk-article-meta"> + Keeping our noses clean since 2017 + </p> + <p> + We have a small but strict set of rules on our server. Please read over them and take them on board - + if you don't understand anything or need some clarification, feel free to ask any staff member! + </p> + <ol> + <li> + Be polite, and do not spam + </li> + <li> + Follow the <a href="https://discordapp.com/guidelines">Discord community guidelines</a> + </li> + <li> + Be patient both with users asking questions, and the users answering them + </li> + <li> + Listen to and respect the staff members - we're here to help, but we're all human beings + </li> + <li> + All discussion should be kept within the relevant channels for the subject. + <ul> + <li> + General Python help and support requests go to one of the three help channels - pick + the one that is the quietest at the time. + </li> + <li> + The topical channels can be used for help and support requests, but general discussion + about the subjects covered by them should go there also. + </li> + <li> + If you're working with one of the bots, we ask you to specifically do that in + <code>#bot-commands</code>, to keep the other channels clear of bot output. + </li> + <li> + If you're working on a Python project or something directly related to our server, feel + free to post a link to it in <code>#show-your-projects</code>. We prefer links to source + code over websites, but we'll also accept screenshots and videos if you're not yet ready + to release the code. + <ul> + <li> + If you or someone else posts a project to <code>#show-your-projects</code>, you may + discuss it in <code>#show-your-projects-discussion</code>. <code>#show-your-projects</code> + is intended to be a listing channel, and any discussion there is removed regularly. + </li> + <li> + Please note, we <strong>do not</strong> allow postings for communities (such as + forums or other Discord servers) or commercial projects. + </li> + </ul> + </li> + </ul> + </li> + <li> + This is an English-speaking server. Please speak English to the best of your ability. Google + translate is fine if you're not sure. + </li> + <li> + Keep all discussions SFW - No <a href="https://www.wikiwand.com/en/Ecchi">ecchi</a> + or <a href="https://www.wikiwand.com/en/Not_safe_for_work">NSFW media</a>. If you wouldn't want + the entire world to know about your interest in it, it doesn't belong on this server. + </li> + <li> + We do not allow advertisements for communities or commercial projects - Contact us directly if + you want to discuss a partnership! + </li> + </ol> + + <h1 class="uk-article-title hover-title" id="infractions"> + Infractions + + <a href="#infractions" class="uk-text-primary" title="Permanent link to this header"> + <i class="fas fa-paragraph" data-fa-transform="shrink-8"></i> + </a> + </h1> + <p class="uk-article-meta"> + Why you gotta be so rude? + </p> + <p> + We have a generally no-nonsense policy when it comes to our rules. If you notice someone breaking + them, feel free to mention or DM a staff member and we'll try to deal with it as soon as possible. + </p> + <p> + The possible actions we take based on infractions can include the following: + </p> + <ul> + <li>A public verbal/textual warning</li> + <li>A short temporary mute</li> + <li>A long temporary mute</li> + <li>A kick from the server</li> + <li>A temporary ban from the server</li> + <li>A permanent ban from the server</li> + </ul> + <p> + While we do discuss more serious matters internally before handing out a punishment, simpler + infractions are dealt with directly by individual staffers and the punishment they hand out is left + to their own decision-making. + </p> + </article> + </div> + </div> +{% endblock %}
\ No newline at end of file diff --git a/templates/main/navigation.html b/templates/main/navigation.html index 5b518822..3178895e 100644 --- a/templates/main/navigation.html +++ b/templates/main/navigation.html @@ -11,40 +11,54 @@ </a> </div> - <div class="uk-navbar-right uk-visible@m"> - <ul class="uk-navbar-nav"> + <div class="uk-navbar-right"> + <ul class="uk-navbar-nav uk-visible@m"> {% if current_page == "index" %} <li class="uk-active"><a href="/"><i class="uk-icon fas fa-home"></i> Home</a></li> {% else %} <li><a href="/"><i class="uk-icon fas fa-home"></i> Home</a></li> {% endif %} <li><a href="/invite"><i class="uk-icon fab fa-discord"></i> Discord</a></li> + </ul> + <ul class="uk-navbar-nav"> <li> <a><i class="uk-icon fas fa-chevron-down"></i></a> <div class="uk-navbar-dropdown uk-background-secondary" uk-dropdown> <ul class="uk-nav uk-navbar-dropdown-nav"> + <li class="uk-nav-header uk-hidden@m">Navigation</li> + <li class="uk-nav-item uk-hidden@m"><a href="/"><i class="uk-icon fas fa-home"></i> Home</a></li> + <li class="uk-nav-item uk-hidden@m"><a href="/invite"><i class="uk-icon fab fa-discord"></i> Discord</a></li> + <li class="uk-nav-divider uk-hidden@m"></li> + + {% if current_page.startswith("info") %} + <li class="uk-nav-header uk-active">Information</li> + {% else %} + <li class="uk-nav-header">Information</li> + {% endif %} + {% if current_page == "info/help" %} <li class="uk-active"><a href="/info/help">Getting Help</a></li> {% else %} <li><a href="/info/help">Getting Help</a></li> {% endif %} + + {% if current_page == "info/rules" %} + <li class="uk-active"><a href="/info/rules">Server Rules</a></li> + {% else %} + <li><a href="/info/rules">Server Rules</a></li> + {% endif %} + + {% if current_page == "info/resources" %} + <li class="uk-active"><a href="/info/resources">Resources</a></li> + {% else %} + <li><a href="/info/resources">Resources</a></li> + {% endif %} + <li class="uk-nav-divider"></li> </ul> </div> </li> </ul> </div> - - <div class="uk-navbar-right uk-hidden@m"> - <button class="uk-button" style="font-size: 2em;"><i class="uk-icon fas fa-angle-down"></i></button> - <div uk-dropdown> - <ul class="uk-nav uk-dropdown-nav"> - <li class="uk-nav-item"><a href="/"><i class="uk-icon fas fa-home"></i> Home</a></li> - <li class="uk-nav-item"><a href="/invite"><i class="uk-icon fab fa-discord"></i> Discord</a></li> - <li class="uk-nav-item"><a href="/info/help"><i class="uk-icon fas fa-question"></i> Getting Help</a></li> - </ul> - </div> - </div> - </nav> </div> |