Skip to content
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

Use fullpage markdown widget for documentation pages #3762

Merged
merged 1 commit into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions app/grandchallenge/documentation/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
from crispy_forms.layout import Submit
from django import forms

from grandchallenge.core.widgets import MarkdownEditorInlineWidget
from grandchallenge.core.forms import SaveFormInitMixin
from grandchallenge.core.widgets import MarkdownEditorFullPageWidget
from grandchallenge.documentation.models import DocPage


Expand All @@ -14,13 +15,21 @@ def __init__(self, *args, **kwargs):

class Meta:
model = DocPage
fields = ("title", "content", "parent")
widgets = {"content": MarkdownEditorInlineWidget}
fields = ("title", "parent")


class DocPageUpdateForm(DocPageCreateForm):
"""Like the create form but you can also move the page."""
class DocPageMetadataUpdateForm(DocPageCreateForm):
"""Like the create form, but you can also move the page."""

position = forms.IntegerField()
position.label = "Move to index position"
position.required = False


class DocPageContentUpdateForm(SaveFormInitMixin, forms.ModelForm):
class Meta:
model = DocPage
fields = ("content",)
widgets = {
"content": MarkdownEditorFullPageWidget,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{% extends "documentation/docpage_form.html" %}
{% load crispy from crispy_forms_tags %}

{% block container %}container-fluid{% endblock %}

{% block outer_content %}

<h2>Update Page</h2>

{% crispy form %}
{% endblock %}
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,14 @@
<div class="row mt-3">
<div class="col-12 col-sm-6 col-md-7 d-inline-block text-left">
{% if 'documentation.change_docpage' in perms %}
<a class="btn btn-md btn-outline-dark d-inline-flex" href="{% url 'documentation:list' %}">Page overview</a>
<a class="btn btn-md btn-outline-dark d-inline-flex" href="{% url 'documentation:create' %}">Add</a>
<a class="btn btn-md btn-outline-dark" href="{% url 'documentation:update' slug=currentdocpage.slug %}">Edit</a>
<a class="btn btn-md btn-outline-dark" href="{% url 'documentation:list' %}">Page overview</a>
<a class="btn btn-md btn-outline-dark" href="{% url 'documentation:create' %}">Add</a>
<a class="btn btn-md btn-outline-dark" href="{% url 'documentation:content-update' slug=currentdocpage.slug %}" title="Edit page">
<i class="fas fa-edit"></i>
</a>
<a class="btn btn-md btn-outline-dark" href="{% url 'documentation:metadata-update' slug=currentdocpage.slug %}" title="Edit metadata">
<i class="fas fa-tools"></i>
</a>
{% endif %}
</div>
<div class="col-12 col-sm-6 col-md-5 justify-content-start justify-content-sm-end form-inline">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ <h2>Documentation Pages</h2>
</td>
{% if 'documentation.change_docpage' in perms %}
<td>
<a href="{% url 'documentation:update' slug=page.slug %}"><i class="fa fa-cog text-primary" aria-hidden="true"></i></a>
<a class="text-primary" title="Edit Page" href="{% url 'documentation:content-update' slug=page.slug %}"><i class="fa fa-edit"></i></a>
<a class="text-primary" title="Edit Metadata" href="{% url 'documentation:metadata-update' slug=page.slug %}"><i class="fa fa-tools"></i></a>
</td>
{% endif %}
</tr>
Expand Down
15 changes: 13 additions & 2 deletions app/grandchallenge/documentation/urls.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
from django.urls import path

from grandchallenge.documentation.views import (
DocPageContentUpdate,
DocPageCreate,
DocPageDetail,
DocPageList,
DocPageUpdate,
DocPageMetadataUpdate,
DocumentationHome,
)

app_name = "documentation"


urlpatterns = [
path("", DocumentationHome.as_view(), name="home"),
path("overview/", DocPageList.as_view(), name="list"),
path("create/", DocPageCreate.as_view(), name="create"),
path("<slug:slug>/", DocPageDetail.as_view(), name="detail"),
path("<slug:slug>/update/", DocPageUpdate.as_view(), name="update"),
path(
"<slug:slug>/content-update/",
DocPageContentUpdate.as_view(),
name="content-update",
),
path(
"<slug:slug>/metadata-update/",
DocPageMetadataUpdate.as_view(),
name="metadata-update",
),
]
31 changes: 27 additions & 4 deletions app/grandchallenge/documentation/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@
from guardian.mixins import LoginRequiredMixin

from grandchallenge.documentation.forms import (
DocPageContentUpdateForm,
DocPageCreateForm,
DocPageUpdateForm,
DocPageMetadataUpdateForm,
)
from grandchallenge.documentation.models import DocPage
from grandchallenge.subdomains.utils import reverse_lazy
from grandchallenge.subdomains.utils import reverse, reverse_lazy


class DocPageList(ListView):
Expand Down Expand Up @@ -72,9 +73,11 @@ def get_object(self, queryset=None):
return get_object_or_404(DocPage, order=1)


class DocPageUpdate(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
class DocPageMetadataUpdate(
LoginRequiredMixin, PermissionRequiredMixin, UpdateView
):
model = DocPage
form_class = DocPageUpdateForm
form_class = DocPageMetadataUpdateForm
permission_required = "documentation.change_docpage"
raise_exception = True
login_url = reverse_lazy("account_login")
Expand All @@ -85,9 +88,29 @@ def form_valid(self, form):
return response


class DocPageContentUpdate(
LoginRequiredMixin, PermissionRequiredMixin, UpdateView
):
model = DocPage
form_class = DocPageContentUpdateForm
template_name_suffix = "_content_update"
permission_required = "documentation.change_docpage"
raise_exception = True
login_url = reverse_lazy("account_login")


class DocPageCreate(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
model = DocPage
form_class = DocPageCreateForm
permission_required = "documentation.add_docpage"
raise_exception = True
login_url = reverse_lazy("account_login")

def get_success_url(self):
"""On successful creation, go to content update."""
return reverse(
"documentation:content-update",
kwargs={
"slug": self.object.slug,
},
)
54 changes: 44 additions & 10 deletions app/tests/documentation_tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,18 @@
"view, perm",
[
("documentation:create", "documentation.add_docpage"),
("documentation:update", "documentation.change_docpage"),
("documentation:content-update", "documentation.change_docpage"),
("documentation:metadata-update", "documentation.change_docpage"),
],
)
def test_permissions(client, view, perm):
u1 = UserFactory()
p1 = DocPageFactory()

if view == "documentation:update":
if view in (
"documentation:content-update",
"documentation:metadata-update",
):
reverse_kwargs = {"slug": p1.slug}
else:
reverse_kwargs = None
Expand All @@ -43,6 +47,7 @@ def test_permissions(client, view, perm):
def test_docpage_create(client):
u1 = UserFactory()
assign_perm("documentation.add_docpage", u1)
assign_perm("documentation.change_docpage", u1)

content = "<h1>Example content</h1>"
title = "Test title"
Expand All @@ -51,12 +56,21 @@ def test_docpage_create(client):
viewname="documentation:create",
client=client,
method=client.post,
data={"title": title, "content": content},
data={"title": title},
user=u1,
)

assert response.status_code == 302
assert DocPage.objects.count() == 1
assert response.url.endswith("test-title/content-update/")
response = get_view_for_user(
url=response.url,
client=client,
method=client.post,
data={"content": content},
user=u1,
)
assert response.status_code == 302

response = get_view_for_user(url=response.url, client=client)

Expand All @@ -65,30 +79,50 @@ def test_docpage_create(client):


@pytest.mark.django_db
def test_docpage_update(client):
def test_docpage_content_update(client):
u1 = UserFactory()
p = DocPageFactory()
assign_perm("documentation.change_docpage", u1)

new_content = "<h1>New content</h1>"

# change content of p
response = get_view_for_user(
viewname="documentation:content-update",
client=client,
method=client.post,
reverse_kwargs={"slug": p.slug},
data={"content": new_content},
user=u1,
)

assert response.status_code == 302
p.refresh_from_db()
assert p.content == new_content


@pytest.mark.django_db
def test_docpage_position_update(client):
u1 = UserFactory()
_ = DocPageFactory()
p2 = DocPageFactory()
assign_perm("documentation.change_docpage", u1)

assert p2.order == 2

new_content = "<h1>New content</h1>"

# change content and order of p2
# change order of p2
response = get_view_for_user(
viewname="documentation:update",
viewname="documentation:metadata-update",
client=client,
method=client.post,
reverse_kwargs={"slug": p2.slug},
data={"title": p2.title, "content": new_content, "position": 1},
data={"title": p2.title, "position": 1},
user=u1,
)

assert response.status_code == 302
p2.refresh_from_db()
assert p2.order == 1
assert p2.content == new_content


@pytest.mark.django_db
Expand Down
Loading