Browse Source

Add markdown sidebar text for groups (no UI)

merge-requests/70/head
Deimos 6 years ago
parent
commit
415833853e
  1. 28
      tildes/alembic/versions/e9bbc2929d9c_group_add_sidebar_markdown_html.py
  2. 22
      tildes/tildes/models/group/group.py
  3. 15
      tildes/tildes/schemas/group.py
  4. 4
      tildes/tildes/templates/topic_listing.jinja2

28
tildes/alembic/versions/e9bbc2929d9c_group_add_sidebar_markdown_html.py

@ -0,0 +1,28 @@
"""Group: add sidebar markdown/html
Revision ID: e9bbc2929d9c
Revises: 9b88cb0a7b2c
Create Date: 2019-05-31 00:18:07.179045
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = "e9bbc2929d9c"
down_revision = "9b88cb0a7b2c"
branch_labels = None
depends_on = None
def upgrade():
op.add_column("groups", sa.Column("sidebar_markdown", sa.Text(), nullable=True))
op.add_column(
"groups", sa.Column("sidebar_rendered_html", sa.Text(), nullable=True)
)
def downgrade():
op.drop_column("groups", "sidebar_rendered_html")
op.drop_column("groups", "sidebar_markdown")

22
tildes/tildes/models/group/group.py

@ -9,10 +9,12 @@ from typing import Any, List, Optional, Sequence, Tuple
from pyramid.security import Allow, Authenticated, Deny, DENY_ALL, Everyone from pyramid.security import Allow, Authenticated, Deny, DENY_ALL, Everyone
from sqlalchemy import Boolean, CheckConstraint, Column, Index, Integer, Text, TIMESTAMP from sqlalchemy import Boolean, CheckConstraint, Column, Index, Integer, Text, TIMESTAMP
from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import deferred
from sqlalchemy.sql.expression import text from sqlalchemy.sql.expression import text
from sqlalchemy_utils import Ltree, LtreeType from sqlalchemy_utils import Ltree, LtreeType
from tildes.lib.database import ArrayOfLtree from tildes.lib.database import ArrayOfLtree
from tildes.lib.markdown import convert_markdown_to_safe_html
from tildes.models import DatabaseModel from tildes.models import DatabaseModel
from tildes.schemas.group import GroupSchema, SHORT_DESCRIPTION_MAX_LENGTH from tildes.schemas.group import GroupSchema, SHORT_DESCRIPTION_MAX_LENGTH
@ -45,6 +47,8 @@ class Group(DatabaseModel):
name="short_description_length", name="short_description_length",
), ),
) )
_sidebar_markdown: str = deferred(Column("sidebar_markdown", Text))
sidebar_rendered_html: str = deferred(Column(Text))
num_subscriptions: int = Column(Integer, nullable=False, server_default="0") num_subscriptions: int = Column(Integer, nullable=False, server_default="0")
is_admin_posting_only: bool = Column( is_admin_posting_only: bool = Column(
Boolean, nullable=False, server_default="false" Boolean, nullable=False, server_default="false"
@ -70,6 +74,24 @@ class Group(DatabaseModel):
def common_topic_tags(self, new_tags: List[str]) -> None: def common_topic_tags(self, new_tags: List[str]) -> None:
self._common_topic_tags = new_tags self._common_topic_tags = new_tags
@hybrid_property
def sidebar_markdown(self) -> str:
"""Return the sidebar's markdown."""
return self._sidebar_markdown
@sidebar_markdown.setter # type: ignore
def sidebar_markdown(self, new_markdown: str) -> None:
"""Set the sidebar's markdown and render its HTML."""
if new_markdown == self.sidebar_markdown:
return
self._sidebar_markdown = new_markdown
if self._sidebar_markdown is not None:
self.sidebar_rendered_html = convert_markdown_to_safe_html(new_markdown)
else:
self.sidebar_rendered_html = None
def __repr__(self) -> str: def __repr__(self) -> str:
"""Display the group's path and ID as its repr format.""" """Display the group's path and ID as its repr format."""
return f"<Group {self.path} ({self.group_id})>" return f"<Group {self.path} ({self.group_id})>"

15
tildes/tildes/schemas/group.py

@ -10,7 +10,7 @@ from marshmallow.exceptions import ValidationError
from marshmallow.fields import DateTime from marshmallow.fields import DateTime
import sqlalchemy_utils import sqlalchemy_utils
from tildes.schemas.fields import Ltree, SimpleString
from tildes.schemas.fields import Ltree, Markdown, SimpleString
# Validation regex for each individual "element" of a group path, encodes: # Validation regex for each individual "element" of a group path, encodes:
@ -37,6 +37,7 @@ class GroupSchema(Schema):
short_description = SimpleString( short_description = SimpleString(
max_length=SHORT_DESCRIPTION_MAX_LENGTH, allow_none=True max_length=SHORT_DESCRIPTION_MAX_LENGTH, allow_none=True
) )
sidebar_markdown = Markdown(allow_none=True)
@pre_load @pre_load
def prepare_path(self, data: dict) -> dict: def prepare_path(self, data: dict) -> dict:
@ -65,6 +66,18 @@ class GroupSchema(Schema):
if not GROUP_PATH_ELEMENT_VALID_REGEX.match(element): if not GROUP_PATH_ELEMENT_VALID_REGEX.match(element):
raise ValidationError("Path element %s is invalid" % element) raise ValidationError("Path element %s is invalid" % element)
@pre_load
def prepare_sidebar_markdown(self, data: dict) -> dict:
"""Prepare the sidebar_markdown value before it's validated."""
if "sidebar_markdown" not in data:
return data
# if the value is empty, convert it to None
if not data["sidebar_markdown"] or data["sidebar_markdown"].isspace():
data["sidebar_markdown"] = None
return data
class Meta: class Meta:
"""Always use strict checking so error handlers are invoked.""" """Always use strict checking so error handlers are invoked."""

4
tildes/tildes/templates/topic_listing.jinja2

@ -220,6 +220,10 @@
<a href="/~{{ group.path }}/new_topic" class="btn btn-primary">Post a new topic</a> <a href="/~{{ group.path }}/new_topic" class="btn btn-primary">Post a new topic</a>
{% endif %} {% endif %}
{% if group.sidebar_rendered_html %}
{{ group.sidebar_rendered_html|safe }}
{% endif %}
{% if wiki_pages %} {% if wiki_pages %}
<ul class="nav"> <ul class="nav">
<li>Group wiki pages</li> <li>Group wiki pages</li>

Loading…
Cancel
Save