-
Notifications
You must be signed in to change notification settings - Fork 15
Add governance and licensing pages #695
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b02d171
be844dc
f0c6822
63341d0
0191199
30247bb
5e182ce
c6441af
68c9282
296ec0b
c40574b
4abedc3
d93cd23
32dbee7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| {% extends "main/base.page.html" %} | ||
| {% load static %} | ||
| {% block title %} | ||
| Digital Research Competencies Framework | ||
| {% endblock title %} | ||
| {% block breadcrumb_items %} | ||
| <li class="breadcrumb-item">Policies</li> | ||
| <li class="breadcrumb-item active" aria-current="page">Governance</li> | ||
| {% endblock breadcrumb_items %} | ||
| {% block content %} | ||
| <section id="licensing" class="container"> | ||
| <h1 class="display-4 text-center pb-2 pb-lg-3">{{ page_heading }}</h1> | ||
| <div class="row justify-content-center pt-xxl-2"> | ||
| <div class="col-lg-9 col-xl-8">{{ markdown_content }}</div> | ||
| </div> | ||
| </section> | ||
| {% endblock content %} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| {% extends "main/base.page.html" %} | ||
| {% load static %} | ||
| {% block title %} | ||
| Digital Research Competencies Framework | ||
| {% endblock title %} | ||
| {% block breadcrumb_items %} | ||
| <li class="breadcrumb-item">Policies</li> | ||
| <li class="breadcrumb-item active" aria-current="page">Licensing</li> | ||
| {% endblock breadcrumb_items %} | ||
| {% block content %} | ||
| <section id="licensing" class="container"> | ||
| <h1 class="display-4 text-center pb-2 pb-lg-3">{{ page_heading }}</h1> | ||
| <div class="row justify-content-center pt-xxl-2"> | ||
| <div class="col-lg-9 col-xl-8">{{ markdown_content }}</div> | ||
| </div> | ||
| </section> | ||
| {% endblock content %} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,10 +6,16 @@ | |
| from collections.abc import Mapping | ||
| from json import dumps | ||
| from pathlib import Path | ||
| from typing import Any | ||
| from typing import Any, ClassVar | ||
|
|
||
| import markdown | ||
| import nh3 | ||
| import requests | ||
| from django.shortcuts import get_object_or_404 | ||
| from django.templatetags.static import static | ||
| from django.utils.decorators import method_decorator | ||
| from django.utils.safestring import mark_safe | ||
| from django.views.decorators.cache import cache_page | ||
| from django.views.generic.base import TemplateView | ||
| from django_tables2 import SingleTableView | ||
|
|
||
|
|
@@ -65,7 +71,7 @@ def get_context_data(self, **kwargs: Mapping[str, Any]) -> dict[str, Any]: | |
| class PrivacyPageView(TemplateView): | ||
| """View that renders the privacy page.""" | ||
|
|
||
| template_name = "main/pages/privacy.html" | ||
| template_name = "main/pages/policies/privacy.html" | ||
|
|
||
|
|
||
| class AboutPageView(TemplateView): | ||
|
|
@@ -77,7 +83,7 @@ class AboutPageView(TemplateView): | |
| class TermsPageView(TemplateView): | ||
| """View that renders the terms and conditions page.""" | ||
|
|
||
| template_name = "main/pages/terms.html" | ||
| template_name = "main/pages/policies/terms.html" | ||
|
|
||
|
|
||
| class SkillLevelsPageView(TemplateView): | ||
|
|
@@ -222,3 +228,85 @@ class FrameworkOverviewPageView(TemplateView): | |
| """View that renders an overview page for the framework.""" | ||
|
|
||
| template_name = "main/pages/framework-overview.html" | ||
|
|
||
|
|
||
| class GitHubMarkdownPageView(TemplateView): | ||
| """Base view for pages that render markdown content fetched from GitHub.""" | ||
|
|
||
| github_raw_url = "" | ||
| page_heading = "" | ||
| unavailable_message = "Document is temporarily unavailable." | ||
| markdown_extensions: ClassVar[list[str]] = ["fenced_code", "tables", "toc"] | ||
|
|
||
| def _strip_duplicate_heading(self, markdown_text: str) -> str: | ||
| """Remove leading H1 if it duplicates the configured page heading.""" | ||
| lines = markdown_text.splitlines() | ||
| if not lines: | ||
| return markdown_text | ||
|
|
||
| first_line = lines[0].strip() | ||
| if self.page_heading not in first_line: | ||
| return markdown_text | ||
|
|
||
| # Remove the duplicate title line and one following blank line if present. | ||
| del lines[0] | ||
| if lines and lines[0].strip() == "": | ||
| del lines[0] | ||
|
|
||
| return "\n".join(lines) | ||
|
|
||
| def get_markdown_content(self) -> str: | ||
| """Fetch and convert remote markdown content to HTML.""" | ||
| if not self.github_raw_url: | ||
| raise ValueError("github_raw_url must be set on GitHubMarkdownPageView") | ||
|
|
||
| response = requests.get(self.github_raw_url, timeout=5) | ||
| response.raise_for_status() | ||
| markdown_text = self._strip_duplicate_heading(response.text) | ||
| return markdown.markdown( | ||
| markdown_text, | ||
| extensions=self.markdown_extensions, | ||
| ) | ||
|
|
||
| def get_context_data(self, **kwargs: Mapping[str, Any]) -> dict[str, Any]: | ||
| """Add rendered markdown content and page metadata to the context.""" | ||
| context = super().get_context_data(**kwargs) | ||
| context["page_heading"] = self.page_heading | ||
|
davehorsfall marked this conversation as resolved.
|
||
|
|
||
| try: | ||
| context["markdown_content"] = mark_safe( | ||
| nh3.clean(self.get_markdown_content()) | ||
| ) | ||
| except requests.RequestException: | ||
| logger.exception("Failed to load markdown from %s", self.github_raw_url) | ||
| context["markdown_content"] = mark_safe( | ||
| f"<p>{self.unavailable_message}</p>" | ||
| ) | ||
|
|
||
| return context | ||
|
|
||
|
|
||
| @method_decorator(cache_page(60 * 60), name="dispatch") # cache 1 hour | ||
| class GovernancePageView(GitHubMarkdownPageView): | ||
| """View that renders the governance page from GitHub Markdown.""" | ||
|
|
||
| template_name = "main/pages/policies/governance.html" | ||
| page_heading = "DIRECT Governance" | ||
| unavailable_message = "Governance document is temporarily unavailable." | ||
|
|
||
| github_raw_url = ( | ||
| "https://raw.githubusercontent.com/direct-framework/.github/main/GOVERNANCE.md" | ||
| ) | ||
|
|
||
|
|
||
| @method_decorator(cache_page(60 * 60), name="dispatch") # cache 1 hour | ||
| class LicensingPageView(GitHubMarkdownPageView): | ||
| """View that renders the licensing page from GitHub Markdown.""" | ||
|
|
||
| template_name = "main/pages/policies/licensing.html" | ||
| page_heading = "DIRECT Licensing" | ||
| unavailable_message = "Licensing document is temporarily unavailable." | ||
|
|
||
| github_raw_url = ( | ||
| "https://raw.githubusercontent.com/direct-framework/.github/main/LICENSING.md" | ||
| ) | ||
|
Comment on lines
+290
to
+312
|
||
Uh oh!
There was an error while loading. Please reload this page.