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

Feature/34 text editor #35

Merged
merged 3 commits into from
Oct 17, 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
2 changes: 1 addition & 1 deletion requirements/base.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ django-treebeard

# API libraries
# django-extra-fields

django-tinymce

django-localflavor
3 changes: 3 additions & 0 deletions requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ django==4.2.13
# django-setup-configuration
# django-simple-certmanager
# django-solo
# django-tinymce
# django-treebeard
# django-two-factor-auth
# djangorestframework
Expand Down Expand Up @@ -156,6 +157,8 @@ django-solo==2.3.0
# mozilla-django-oidc-db
# notifications-api-common
# zgw-consumers
django-tinymce==4.1.0
# via -r requirements/base.in
django-treebeard==4.7.1
# via -r requirements/base.in
django-two-factor-auth[phonenumberslite,webauthn]==1.16.0
Expand Down
5 changes: 5 additions & 0 deletions requirements/ci.txt
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ django==4.2.13
# django-setup-configuration
# django-simple-certmanager
# django-solo
# django-tinymce
# django-treebeard
# django-two-factor-auth
# djangorestframework
Expand Down Expand Up @@ -286,6 +287,10 @@ django-solo==2.3.0
# mozilla-django-oidc-db
# notifications-api-common
# zgw-consumers
django-tinymce==4.1.0
# via
# -c requirements/base.txt
# -r requirements/base.txt
django-treebeard==4.7.1
# via
# -c requirements/base.txt
Expand Down
5 changes: 5 additions & 0 deletions requirements/dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ django==4.2.13
# django-setup-configuration
# django-simple-certmanager
# django-solo
# django-tinymce
# django-treebeard
# django-two-factor-auth
# djangorestframework
Expand Down Expand Up @@ -320,6 +321,10 @@ django-solo==2.3.0
# mozilla-django-oidc-db
# notifications-api-common
# zgw-consumers
django-tinymce==4.1.0
# via
# -c requirements/ci.txt
# -r requirements/ci.txt
django-treebeard==4.7.1
# via
# -c requirements/ci.txt
Expand Down
15 changes: 15 additions & 0 deletions src/open_producten/conf/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"rest_framework.authtoken",
"localflavor",
"treebeard",
"tinymce",
"open_producten.accounts",
"open_producten.utils",
"open_producten.producttypes",
Expand Down Expand Up @@ -90,3 +91,17 @@
"TOS": None,
"VERSION": API_VERSION,
}

TINYMCE_DEFAULT_CONFIG = { # TODO: light/dark mode based on browser settings
"height": 200,
"menubar": False,
"plugins": "advlist,autolink,lists,link,image,charmap,print,preview,anchor,"
"searchreplace,visualblocks,code,fullscreen,insertdatetime,media,table,paste,"
"code,wordcount",
"toolbar": "undo redo | formatselect | "
"bold italic backcolor | alignleft aligncenter "
"alignright alignjustify | bullist numlist outdent indent | "
"removeformat",
}

TINYMCE_EXTRA_MEDIA = {"js": ["initTinymce.js"]}
2 changes: 1 addition & 1 deletion src/open_producten/conf/dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
ELASTIC_APM["DEBUG"] = True

# Django debug toolbar
if not DEBUG:
if "test" not in sys.argv:
INSTALLED_APPS += ["debug_toolbar"]
MIDDLEWARE = ["debug_toolbar.middleware.DebugToolbarMiddleware"] + MIDDLEWARE
INTERNAL_IPS = ("127.0.0.1",)
Expand Down
3 changes: 3 additions & 0 deletions src/open_producten/producttypes/admin/price.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@ class PriceOptionInline(admin.TabularInline):
class PriceAdmin(admin.ModelAdmin):
model = Price
inlines = [PriceOptionInline]

def get_queryset(self, request):
return super().get_queryset(request).select_related("product_type")
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Generated by Django 4.2.13 on 2024-10-11 08:07

from django.db import migrations
import tinymce.models


class Migration(migrations.Migration):

dependencies = [
("producttypes", "0006_remove_uniformproductname_url_and_more"),
]

operations = [
migrations.AlterField(
model_name="category",
name="description",
field=tinymce.models.HTMLField(
blank=True,
default="",
help_text="Description of the category",
verbose_name="Description",
),
),
migrations.AlterField(
model_name="condition",
name="negative_text",
field=tinymce.models.HTMLField(
help_text="Description how not to meet the condition",
verbose_name="Negative text",
),
),
migrations.AlterField(
model_name="condition",
name="positive_text",
field=tinymce.models.HTMLField(
help_text="Description how to meet the condition",
verbose_name="Positive text",
),
),
migrations.AlterField(
model_name="condition",
name="question",
field=tinymce.models.HTMLField(
help_text="Question used in the question-answer game",
verbose_name="Question",
),
),
migrations.AlterField(
model_name="field",
name="description",
field=tinymce.models.HTMLField(
help_text="Short description of the field",
max_length=300,
verbose_name="Description",
),
),
migrations.AlterField(
model_name="producttype",
name="content",
field=tinymce.models.HTMLField(
help_text="Product type content with build-in WYSIWYG editor.",
verbose_name="Content",
),
),
migrations.AlterField(
model_name="producttype",
name="summary",
field=tinymce.models.HTMLField(
default="",
help_text="Short description of the product type, limited to 300 characters.",
max_length=300,
verbose_name="Summary",
),
),
migrations.AlterField(
model_name="question",
name="answer",
field=tinymce.models.HTMLField(verbose_name="Answer"),
),
]
3 changes: 2 additions & 1 deletion src/open_producten/producttypes/models/category.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from django.db import models
from django.utils.translation import gettext_lazy as _

from tinymce import models as tinymce_models
from treebeard.exceptions import InvalidMoveToDescendant
from treebeard.mp_tree import MP_MoveHandler, MP_Node

Expand All @@ -22,7 +23,7 @@ class Category(MP_Node, BasePublishableModel):
verbose_name=_("Name"), max_length=100, help_text=_("Name of the category")
)

description = models.TextField(
description = tinymce_models.HTMLField(
verbose_name=_("Description"),
blank=True,
default="",
Expand Down
8 changes: 5 additions & 3 deletions src/open_producten/producttypes/models/condition.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from django.db import models
from django.utils.translation import gettext_lazy as _

from tinymce import models as tinymce_models

from open_producten.utils.models import BaseModel


Expand All @@ -10,15 +12,15 @@ class Condition(BaseModel):
max_length=100,
help_text=_("Short name of the condition"),
)
question = models.TextField(
question = tinymce_models.HTMLField(
verbose_name=_("Question"),
help_text=_("Question used in the question-answer game"),
)
positive_text = models.TextField(
positive_text = tinymce_models.HTMLField(
verbose_name=_("Positive text"),
help_text=_("Description how to meet the condition"),
)
negative_text = models.TextField(
negative_text = tinymce_models.HTMLField(
verbose_name=_("Negative text"),
help_text=_("Description how not to meet the condition"),
)
Expand Down
4 changes: 3 additions & 1 deletion src/open_producten/producttypes/models/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from django.db import models
from django.utils.translation import gettext_lazy as _

from tinymce import models as tinymce_models

from open_producten.utils.models import BaseModel

from .producttype import ProductType
Expand Down Expand Up @@ -37,7 +39,7 @@ class Field(BaseModel):
name = models.CharField(
verbose_name=_("Name"), max_length=255, help_text=_("The name of the field")
)
description = models.TextField(
description = tinymce_models.HTMLField(
verbose_name=_("Description"),
help_text=_("Short description of the field"),
max_length=300,
Expand Down
8 changes: 6 additions & 2 deletions src/open_producten/producttypes/models/producttype.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from django.db import models
from django.utils.translation import gettext_lazy as _

from tinymce import models as tinymce_models

from open_producten.locations.models import Contact, Location, Organisation
from open_producten.utils.models import BasePublishableModel

Expand All @@ -12,6 +14,8 @@
from .tag import Tag
from .upn import UniformProductName

# from ...utils.models import HTMLField


class CategoryProductType(models.Model):
"""
Expand All @@ -27,7 +31,7 @@ class ProductType(BasePublishableModel):
verbose_name=_("Name"), max_length=100, help_text=_("Name of the product type")
)

summary = models.TextField(
summary = tinymce_models.HTMLField(
verbose_name=_("Summary"),
default="",
max_length=300,
Expand Down Expand Up @@ -57,7 +61,7 @@ class ProductType(BasePublishableModel):
help_text=_("Action link to request the product type."),
)

content = models.TextField(
content = tinymce_models.HTMLField(
verbose_name=_("Content"),
help_text=_("Product type content with build-in WYSIWYG editor."),
)
Expand Down
4 changes: 3 additions & 1 deletion src/open_producten/producttypes/models/question.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from django.db import models
from django.utils.translation import gettext_lazy as _

from tinymce import models as tinymce_models

from open_producten.utils.models import BaseModel

from .category import Category
Expand All @@ -26,7 +28,7 @@ class Question(BaseModel):
related_name="questions",
)
question = models.CharField(verbose_name=_("Question"), max_length=250)
answer = models.TextField(verbose_name=_("Answer"))
answer = tinymce_models.HTMLField(verbose_name=_("Answer"))

class Meta:
verbose_name = _("Question")
Expand Down
44 changes: 44 additions & 0 deletions src/open_producten/static/initTinymce.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Sets the dar/light mode based on the browser.
// Copied minimal needed stuff from open-forms

'use strict';
{
function initTinyMCE(el) {
if (el.closest('.empty-form') === null) {
// Don't do empty inlines
var mce_conf = JSON.parse(el.dataset.mceConf);
const useDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;

mce_conf = {
...mce_conf,
...{
skin: useDarkMode ? 'oxide-dark' : 'oxide',
content_css: useDarkMode ? 'dark' : 'default',
},
};

const id = el.id;

if (!tinyMCE.get(id)) {
tinyMCE.init(mce_conf);
}
}
}

function ready(fn) {
if (document.readyState !== 'loading') {
fn();
} else {
document.addEventListener('DOMContentLoaded', fn);
}
}

function initializeTinyMCE(element, formsetName) {
Array.from(element.querySelectorAll('.tinymce')).forEach(area => initTinyMCE(area));
}

ready(function () {
// initialize the TinyMCE editors on load
initializeTinyMCE(document);
});
}
2 changes: 0 additions & 2 deletions src/open_producten/templates/admin/base_site.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
{% block extrastyle %}
{{ block.super }}

<link rel="stylesheet" type="text/css" href="{% static 'bundles/admin_overrides.css' %}">

<link href="{% static 'ico/favicon.svg' %}" sizes="any" rel="icon" type="image/svg+xml" />
<link href="{% static 'ico/favicon-96x96.png' %}" sizes="96x96" rel="icon" type="image/png" />
<link href="{% static 'ico/favicon-32x32.png' %}" sizes="32x32" rel="icon" type="image/png" />
Expand Down
5 changes: 2 additions & 3 deletions src/open_producten/templates/master.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
<link href="{% static 'ico/favicon-32x32.png' %}" sizes="32x32" rel="icon" type="image/png" />
<link href="{% static 'ico/favicon.png' %}" sizes="16x16" rel="icon" type="image/png" />
<link href="{% static 'ico/favicon.png' %}" rel="shortcut icon">
<link href="{% static 'bundles/open_producten-css.css' %}" media="all" rel="stylesheet" />
{% block extra_css %}{% endblock %}
</head>

Expand All @@ -28,7 +27,7 @@
<p>
Developed by <a class="link" href="https://www.maykinmedia.nl">Maykin</a><br>
within the <a class="link" href="https://opengem.nl">Open Gemeente Initiatief</a> &copy; 2024<br>

</p>
</div>
<div class="footer__col">
Expand Down Expand Up @@ -56,7 +55,7 @@ <h5 class="footer__header">Other</h5>
</div>
</div>
</footer>

{% if dsn %}
<script src="https://browser.sentry-cdn.com/5.10.1/bundle.min.js" integrity="sha384-sAOze6ZTBIpiWBF3VlUteSInM4rYpjxrejp1wMmmKqA9clRZ1vZJ36Ihmt1ilTrG" crossorigin="anonymous"></script>
<script>Sentry.init({ dsn: '{{ dsn }}'});</script>
Expand Down
1 change: 1 addition & 0 deletions src/open_producten/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
]
),
),
path("tinymce/", include("tinymce.urls")),
]

# NOTE: The staticfiles_urlpatterns also discovers static files (ie. no need to run collectstatic). Both the static
Expand Down
Loading