diff --git a/tildes/alembic/versions/e9bbc2929d9c_group_add_sidebar_markdown_html.py b/tildes/alembic/versions/e9bbc2929d9c_group_add_sidebar_markdown_html.py new file mode 100644 index 0000000..f22a57b --- /dev/null +++ b/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") diff --git a/tildes/tildes/models/group/group.py b/tildes/tildes/models/group/group.py index b915a08..ea60100 100644 --- a/tildes/tildes/models/group/group.py +++ b/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 sqlalchemy import Boolean, CheckConstraint, Column, Index, Integer, Text, TIMESTAMP from sqlalchemy.ext.hybrid import hybrid_property +from sqlalchemy.orm import deferred from sqlalchemy.sql.expression import text from sqlalchemy_utils import Ltree, LtreeType from tildes.lib.database import ArrayOfLtree +from tildes.lib.markdown import convert_markdown_to_safe_html from tildes.models import DatabaseModel from tildes.schemas.group import GroupSchema, SHORT_DESCRIPTION_MAX_LENGTH @@ -45,6 +47,8 @@ class Group(DatabaseModel): 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") is_admin_posting_only: bool = Column( Boolean, nullable=False, server_default="false" @@ -70,6 +74,24 @@ class Group(DatabaseModel): def common_topic_tags(self, new_tags: List[str]) -> None: 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: """Display the group's path and ID as its repr format.""" return f"" diff --git a/tildes/tildes/schemas/group.py b/tildes/tildes/schemas/group.py index ed00850..0c127e9 100644 --- a/tildes/tildes/schemas/group.py +++ b/tildes/tildes/schemas/group.py @@ -10,7 +10,7 @@ from marshmallow.exceptions import ValidationError from marshmallow.fields import DateTime 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: @@ -37,6 +37,7 @@ class GroupSchema(Schema): short_description = SimpleString( max_length=SHORT_DESCRIPTION_MAX_LENGTH, allow_none=True ) + sidebar_markdown = Markdown(allow_none=True) @pre_load def prepare_path(self, data: dict) -> dict: @@ -65,6 +66,18 @@ class GroupSchema(Schema): if not GROUP_PATH_ELEMENT_VALID_REGEX.match(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: """Always use strict checking so error handlers are invoked.""" diff --git a/tildes/tildes/templates/topic_listing.jinja2 b/tildes/tildes/templates/topic_listing.jinja2 index 1fdac49..f3703ac 100644 --- a/tildes/tildes/templates/topic_listing.jinja2 +++ b/tildes/tildes/templates/topic_listing.jinja2 @@ -220,6 +220,10 @@ Post a new topic {% endif %} + {% if group.sidebar_rendered_html %} + {{ group.sidebar_rendered_html|safe }} + {% endif %} + {% if wiki_pages %}