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

110 users can get more information on terms in the wiki #170

Merged
4 changes: 4 additions & 0 deletions frontend/components/RawHtml/RawHtml.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,7 @@
margin-top: 0.5rem;
margin-bottom: 0.5rem;
}
.Container a[data-introduction-text] {
cursor: pointer;
border-bottom: 1px dotted black;
}
104 changes: 99 additions & 5 deletions frontend/components/RawHtml/RawHtml.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,102 @@
import React from "react";
import React, { Fragment, useEffect, useState, useRef } from "react";
import { XMarkIcon } from "@heroicons/react/24/outline";
import s from "./RawHtml.module.css";
import HolonButton from "../VersionOne/Buttons/HolonButton";
import { Dialog, Transition } from "@headlessui/react";

const RawHtml = ({ html }: { html: string }) => (
<div className={s.Container} dangerouslySetInnerHTML={{ __html: html }} />
);
export default function RawHtml({ html }: { html: string }) {
const [modal, setModal] = useState<{
isOpen: boolean;
modalText: string;
modalLink: string;
modalTitle: string;
}>({
isOpen: false,
modalText: "",
modalLink: "",
modalTitle: "",
});

export default RawHtml;
const RawHtmlItem = useRef(null);

function closeModal() {
setModal({ isOpen: false, modalText: "", modalLink: "", modalTitle: "" });
}

function openModal(text: string, linkUrl: string, linkTitle: string) {
setModal({ isOpen: true, modalText: text, modalLink: linkUrl, modalTitle: linkTitle });
}

useEffect(() => {
const wikiLinks = RawHtmlItem.current.querySelectorAll(`a[data-introduction-text]`);

for (let i = 0; i < wikiLinks.length; i++) {
const link = wikiLinks[i] as HTMLElement | null;
if (link) {
link.addEventListener("click", function (e) {
e.preventDefault();

const linkText = link.getAttribute("data-introduction-text") || "";
const linkUrl = link.getAttribute("data-page-link") || "";
const linkTitle = link.getAttribute("data-title") || "";
openModal(linkText, linkUrl, linkTitle);
});
}
}
}, []);

return (
<Fragment>
<div ref={RawHtmlItem} className={s.Container} dangerouslySetInnerHTML={{ __html: html }} />
{modal.modalText && (
<Transition appear show={modal.isOpen} as={Fragment}>
<Dialog as="div" className="relative z-50" onClose={closeModal}>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0">
<div className="fixed inset-0 bg-black bg-opacity-25" />
</Transition.Child>

<div className="fixed inset-0 overflow-y-auto">
<div className="flex min-h-full items-center justify-center p-4 text-center">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95">
<Dialog.Panel className="w-full max-w-md transform overflow-hidden rounded bg-white p-6 text-left align-middle shadow-xl transition-all">
<Dialog.Title as="h3" className="text-lg font-medium leading-6 text-gray-900">
{modal.modalTitle}
</Dialog.Title>
<div className="mt-2">
<p className="text-sm text-gray-500">{modal.modalText}</p>
</div>
<div className="mt-4">
<HolonButton tag="a" href={modal.modalLink} variant="darkmode">
Lees meer
</HolonButton>
</div>
<button
onClick={closeModal}
pascalalferink marked this conversation as resolved.
Show resolved Hide resolved
aria-label="Sluiten"
className="w-6 h-6 absolute rounded-full right-6 top-6 ">
<XMarkIcon />
</button>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition>
)}
</Fragment>
);
}
2 changes: 1 addition & 1 deletion frontend/containers/LazyContainers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ export default {
PureHtmlPage: dynamic(() => import("./PureHtmlPage")),
WikiPage: dynamic(() => import("./WikiPage")),
StorylinePage: dynamic(() => import("./StorylinePage")),
StorylineOverviewPage: dynamic(() => import ("./StorylineOverviewPage"))
StorylineOverviewPage: dynamic(() => import("./StorylineOverviewPage")),
};
11 changes: 11 additions & 0 deletions src/main/contentstate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from draftjs_exporter.dom import DOM


def term_link_entity(props):
link_props = {}

link_props["linktype"] = "term"
link_props["introduction"] = props.get("introduction")
link_props["id"] = props.get("id")

return DOM.create_element("a", link_props, props["children"])
7 changes: 7 additions & 0 deletions src/main/factories/staticterm_page.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from .base_page import BasePageFactory
from ..pages import StaticTermPage


class StaticTermPageFactory(BasePageFactory):
class Meta:
model = StaticTermPage
71 changes: 71 additions & 0 deletions src/main/handlers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from wagtail.rich_text import LinkHandler
from django.utils.html import escape
from wagtail.admin.rich_text.converters.html_to_contentstate import LinkElementHandler

from main.pages.wiki import WikiPage


class TermLinkHTMLHandler(LinkHandler):
# Determines how a term is rendered in the api
identifier = "term"

@staticmethod
def get_model():
return WikiPage

@classmethod
def get_instance(cls, attrs):
return super().get_instance(attrs).specific

@classmethod
def expand_db_attributes(cls, attrs):
try:
page = cls.get_instance(attrs)
return '<a data-page-link="%s" data-introduction-text="%s" data-title="%s">' % (
escape(page.localized.specific.url),
page.introduction,
page.title,
)

except WikiPage.DoesNotExist:
return "<a>"


class TermLinkEditorHandler:
# Determines how the HTML of a term is rendered in the richtext editor
@staticmethod
def get_db_attributes(tag):
return {"id": tag["data-id"]}

@staticmethod
def expand_db_attributes(attrs):
try:
page = WikiPage.objects.get(id=attrs["id"])

attrs = 'data-linktype="term" data-id="%d" ' % page.id
parent_page = page.get_parent()
if parent_page:
attrs += 'data-parent-id="%d" ' % parent_page.id

return '<a %shref="%s">' % (attrs, escape(page.localized.specific.url))
except WikiPage.DoesNotExist:
return "<a>"


class TermLinkElementHandler(LinkElementHandler):
# Determines how the page is extracted from the database
def get_attribute_data(self, attrs):
try:
page = WikiPage.objects.get(id=attrs["id"]).specific
except WikiPage.DoesNotExist:
# retain ID so that it's still identified as a page link (albeit a broken one)
return {"id": int(attrs["id"]), "url": None, "parentId": None}

parent_page = page.get_parent()

return {
"id": page.id,
"url": page.url,
"introduction": page.introduction,
"parentId": parent_page.id if parent_page else None,
}
41 changes: 41 additions & 0 deletions src/main/migrations/0014_statictermpage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Generated by Django 4.1.3 on 2022-11-11 14:58

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
("main", "0013_alter_homepage_content_alter_staticpage_content_and_more"),
]

operations = [
migrations.CreateModel(
name="StaticTermPage",
fields=[
(
"staticpage_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="main.staticpage",
),
),
(
"introduction",
models.CharField(
help_text="Text used in the highlight on other pages",
max_length=500,
),
),
],
options={
"verbose_name": "StaticTermPage",
},
bases=("main.staticpage",),
),
]
13 changes: 13 additions & 0 deletions src/main/migrations/0017_merge_20221117_1320.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Generated by Django 4.1.3 on 2022-11-17 12:20

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("main", "0014_statictermpage"),
("main", "0016_remove_storylineoverviewpage_body_and_more"),
]

operations = []
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Generated by Django 4.1.3 on 2022-11-18 10:26

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("main", "0017_merge_20221117_1320"),
]

operations = [
migrations.AddField(
model_name="wikipage",
name="introduction",
field=models.CharField(
default="",
help_text="Text used in the highlight on other pages",
max_length=500,
),
preserve_default=False,
),
migrations.DeleteModel(
name="StaticTermPage",
),
]
7 changes: 6 additions & 1 deletion src/main/pages/wiki.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
from django.utils.translation import gettext_lazy as _
from wagtail_headless_preview.models import HeadlessPreviewMixin
from django.db import models
from wagtail.fields import RichTextField
from wagtail.admin.panels import FieldPanel

from .base import BasePage


class WikiPage(HeadlessPreviewMixin, BasePage):
introduction = models.CharField(
max_length=500, help_text=_("Text used in the highlight on other pages")
)

rich_text = RichTextField(blank=True, null=True, verbose_name=_("Rich text"))

content_panels = BasePage.content_panels + [FieldPanel("rich_text")]
content_panels = BasePage.content_panels + [FieldPanel("introduction"), FieldPanel("rich_text")]

extra_panels = BasePage.extra_panels
serializer_class = "main.pages.WikiPageSerializer"
Expand Down
1 change: 1 addition & 0 deletions src/main/pages/wiki_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ class WikiPageSerializer(BasePageSerializer):
class Meta:
model = WikiPage
fields = [
"introduction",
"rich_text",
] + BasePageSerializer.Meta.fields