Skip to content

Commit

Permalink
Outline for the resource page #150 (#151)
Browse files Browse the repository at this point in the history
* first version of outline

* status

* bullet's style united

* border added

* different border added
  • Loading branch information
veselyvojtech authored Jul 31, 2020
1 parent a845f1d commit da46572
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 0 deletions.
32 changes: 32 additions & 0 deletions website/theses/migrations/0037_outlinethesissimple.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Generated by Django 2.2.1 on 2020-05-23 16:37

from django.db import migrations, models
import django.db.models.deletion
import theses.models
import wagtail.core.blocks
import wagtail.core.fields
import wagtail.embeds.blocks
import wagtail.images.blocks


class Migration(migrations.Migration):

dependencies = [
('wagtailcore', '0041_group_collection_permissions_verbose_name_plural'),
('theses', '0036_thesiscoachingpage_body2'),
]

operations = [
migrations.CreateModel(
name='OutlineThesisSimple',
fields=[
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
('outline_title', wagtail.core.fields.RichTextField()),
('body', wagtail.core.fields.StreamField([('heading', wagtail.core.blocks.CharBlock(classname='full title')), ('heading_linkable', theses.models.HeadingBlock(features=['h1', 'h2', 'h3', 'h4', 'h5', 'h6'], help_text='heading text')), ('paragraph', wagtail.core.blocks.RichTextBlock()), ('image', wagtail.images.blocks.ImageChooserBlock()), ('embed', wagtail.embeds.blocks.EmbedBlock()), ('rawHtml', wagtail.core.blocks.RawHTMLBlock())])),
],
options={
'abstract': False,
},
bases=('wagtailcore.page',),
),
]
145 changes: 145 additions & 0 deletions website/theses/models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from __future__ import annotations
import logging
import re
from textwrap import dedent
from typing import List, Tuple

from django.contrib import messages
from django.db import models
Expand All @@ -11,6 +14,7 @@
from wagtail.core import blocks
from wagtail.core.fields import RichTextField, StreamField
from wagtail.core.models import Page
from wagtail.core.rich_text import RichText
from wagtail.embeds.blocks import EmbedBlock
from wagtail.documents.edit_handlers import DocumentChooserPanel
from wagtail.images.blocks import ImageChooserBlock
Expand Down Expand Up @@ -432,6 +436,147 @@ def get_context(self, request):
return context


class HeadingBlock(blocks.RichTextBlock):
@staticmethod
def _get_title(m):
title = m.group("title")
to_drop = ("<br/>", r"<h\d>", r"</h\d>")
for text in to_drop:
title = re.sub(text, "", title)
return title.strip()

@staticmethod
def _get_link(title):
return title.lower().replace(" ", "-")

@classmethod
def _get_additional_context(cls, _value):

if isinstance(_value, RichText): # in case of using Preview
_value = _value.source
m = re.search("<h(?P<heading_size>\d)>(?P<title>.*)</h\d>", _value)
if not m:
return {}

title = cls._get_title(m)
return dict(
title=title,
link=cls._get_link(title),
heading_size=m.group("heading_size"),
)

def get_context(self, value, parent_context=None):
context = super().get_context(value=value, parent_context=parent_context)
context.update(self._get_additional_context(value.source))
return context

class Meta:
template = "blocks/heading.html"


class Heading:
title: str
link: str
size: int
nested_headings: List[Heading]

def __init__(self, title, link, heading_size):
self.title = title
self.link = link
self.size = int(heading_size)
self.nested_headings = []

def to_html(self):
nested_html = headings_to_html(self.nested_headings)
_html = f"<li><a href='#{self.link}'>{self.title}</a>{nested_html}</li>"
return _html


def headings_to_html(headings: List[Heading]):
_nested_htmls = "".join(_heading.to_html() for _heading in headings)
nested_html = f'<ul style="list-style-type:disc;">{_nested_htmls}</ul>' if _nested_htmls else ""
return nested_html


class OutlineThesisSimple(Page):
outline_title = RichTextField()
body = StreamField(
[
("heading", blocks.CharBlock(classname="full title")),
(
"heading_linkable",
HeadingBlock(
help_text="heading text",
features=["h1", "h2", "h3", "h4", "h5", "h6"],
),
),
("paragraph", blocks.RichTextBlock()),
("image", ImageChooserBlock()),
("embed", EmbedBlock()),
("rawHtml", blocks.RawHTMLBlock()),
]
)

content_panels = Page.content_panels + [
FieldPanel("outline_title"),
StreamFieldPanel("body"),
]

parent_page_types = ["theses.ThesisIndexPage"]

@staticmethod
def _get_heading(_data):
if isinstance(_data, tuple):
keys = ("type", "value", "id")
_data = dict(zip(keys, _data))

if _data["type"] == "heading_linkable":
source = _data["value"]
return HeadingBlock._get_additional_context(source)
return None

def _get_headings(self, stream_data):
headings = (self._get_heading(data) for data in stream_data)
return [Heading(**heading) for heading in headings if heading]

def _place_heading_into_structure(
self, heading: Heading, structure: List[Heading]
) -> List[Heading]:
if not structure:
return [heading]

if heading.size <= structure[-1].size:
structure.append(heading)
return structure

_structure = self._place_heading_into_structure(
heading, structure[-1].nested_headings
)
structure[-1].nested_headings = _structure
return structure

def _nest_headings(self, headings: list):
if not headings:
return []

structure = []
for heading in headings:
structure = self._place_heading_into_structure(heading, structure)

return structure

def _get_outline(self, stream_data) -> str:
headings = self._get_headings(stream_data)
headings_nested = self._nest_headings(headings)
return headings_to_html(headings_nested)

def get_context(self, request):
context = super(OutlineThesisSimple, self).get_context(request)
context["contactForm"] = SimpleContactForm
context["outline"] = self._get_outline(self.body.stream_data)
return context


class ThesisFinishedIndexPage(Page):
body = get_standard_streamfield()
footer = get_standard_streamfield()
Expand Down
5 changes: 5 additions & 0 deletions website/theses/templates/blocks/heading.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{% if link %}
<a id="{{ link }}"></a>
{% endif %}

{{ value }}
38 changes: 38 additions & 0 deletions website/theses/templates/theses/outline_thesis_simple.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{% extends "theses/theses_base.html" %}
{% load wagtailuserbar %}
{% load wagtailcore_tags %}
{% load static %}

{% block content %}

<style>
.table{
outline-style: solid;
outline-color: rgb(204, 204, 204);
outline-width: 2px;
}
</style>

<div class="container py-4">
<div class="row">
<div class="col-md-8 offset-md-2">
{% include_block page.outline_title %}
<table class="table table-responsive mt-3 mb-2" role="grid">

<tbody class=".table-hover .table-striped">

<tr class="row-2" role="row">
<td>
<div class="panel clearfix">
<h4 class="no_toc mt-1">Content</h4>
{% include_block outline %}
</div>
</td>
</tr>
</table>

{% include_block page.body %}
</div>
</div>
</div>
{% endblock %}

0 comments on commit da46572

Please sign in to comment.