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

Use tomselect #421

Closed
wants to merge 7 commits into from
Closed
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
3 changes: 2 additions & 1 deletion myhpi/core/markdown/extensions.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import re
import xml.etree.ElementTree

from django.core.exceptions import ObjectDoesNotExist
from django.utils.translation import gettext_lazy as _
Expand Down Expand Up @@ -145,7 +146,7 @@ def decrease(self, match):

class InternalLinkPattern(LinkInlineProcessor):
def handleMatch(self, m, data=None):
el = util.etree.Element("a")
el = xml.etree.ElementTree.Element("a")
try:
el.set("href", self.url(m.group("id")))
el.text = util.AtomicString(m.group("title"))
Expand Down
72 changes: 72 additions & 0 deletions myhpi/core/migrations/0009_userprofile_for_minutes_display_name.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Generated by Django 4.0.7 on 2023-11-21 19:05

import django.db.models.deletion
import modelcluster.fields
from django.conf import settings
from django.db import migrations, models


def create_user_profiles(apps, schema_editor):
User = apps.get_model("auth", "User")
for user in User.objects.all():
UserProfile = apps.get_model("core", "UserProfile")
display_name = user.first_name + " " + user.last_name
UserProfile.objects.create(user=user, display_name=display_name)


class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("core", "0008_remove_footer_column_4"),
]

operations = [
migrations.CreateModel(
name="UserProfile",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("display_name", models.CharField(blank=True, max_length=255)),
(
"user",
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
],
),
migrations.AlterField(
model_name="minutes",
name="author",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.PROTECT,
related_name="author",
to="core.userprofile",
),
),
migrations.AlterField(
model_name="minutes",
name="moderator",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.PROTECT,
related_name="moderator",
to="core.userprofile",
),
),
migrations.AlterField(
model_name="minutes",
name="participants",
field=modelcluster.fields.ParentalManyToManyField(
related_name="minutes", to="core.userprofile"
),
),
migrations.RunPython(create_user_profiles),
]
56 changes: 40 additions & 16 deletions myhpi/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
from datetime import date

from django import forms
from django.contrib.auth.models import Group, User
from django.contrib.auth.models import Group, User, UserManager
from django.db import models
from django.db.models import BooleanField, CharField, DateField, ForeignKey, Model, Q
from django.db.models import BooleanField, CharField, DateField, F, ForeignKey, Model, Q, Value
from django.db.models.functions import Concat
from django.http import HttpResponseRedirect
from django_select2 import forms as s2forms
from django_tomselect.widgets import TomSelectMultipleWidget, TomSelectWidget
from modelcluster.contrib.taggit import ClusterTaggableManager
from modelcluster.fields import ParentalKey, ParentalManyToManyField
from taggit.models import ItemBase, TagBase
Expand All @@ -22,6 +23,36 @@
from myhpi.core.widgets import AttachmentSelectWidget


class UserProfile(models.Model):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally don't really like the proxy models and generally prefer substituting the user model as a whole. However, this seems to be a bit tricky for existing projects (https://docs.djangoproject.com/en/4.2/topics/auth/customizing/#changing-to-a-custom-user-model-mid-project).

user = models.OneToOneField(User, on_delete=models.CASCADE)
display_name = models.CharField(max_length=255, blank=True)

def __str__(self):
return self.display_name

def get_full_name(self):
return self.display_name

@staticmethod
def for_user(u):
return UserProfile.objects.get(user=u)


from django.db.models.signals import post_save
from django.dispatch import receiver


@receiver(post_save, sender=User)
def post_user_save(sender, instance, created, **kwargs):
display_name = instance.first_name + " " + instance.last_name
user_profile = UserProfile.objects.filter(user=instance.pk)
if user_profile:
user_profile[0].display_name = display_name
user_profile[0].save()
else:
UserProfile.objects.create(user=instance, display_name=display_name)


class BasePage(Page):
visible_for = ParentalManyToManyField(Group, blank=True, related_name="visible_basepages")
is_public = BooleanField()
Expand Down Expand Up @@ -170,32 +201,25 @@ def get_last_minutes(self):
return existing_minutes.last().specific


class UserSelectWidget(s2forms.ModelSelect2MultipleWidget):
search_fields = [
"username__icontains",
"email__icontains",
]


class Minutes(BasePage):
date = DateField()
moderator = ForeignKey(
User, blank=True, null=True, on_delete=models.PROTECT, related_name="moderator"
UserProfile, blank=True, null=True, on_delete=models.PROTECT, related_name="moderator"
)
author = ForeignKey(
User, blank=True, null=True, on_delete=models.PROTECT, related_name="author"
UserProfile, blank=True, null=True, on_delete=models.PROTECT, related_name="author"
)
participants = ParentalManyToManyField(User, related_name="minutes")
participants = ParentalManyToManyField(UserProfile, related_name="minutes")
labels = ClusterTaggableManager(through=TaggedMinutes, blank=True)
body = CustomMarkdownField()
guests = models.JSONField(blank=True, default=[])
attachments = ParentalManyToManyField(Document, blank=True)

content_panels = Page.content_panels + [
FieldPanel("date"),
FieldPanel("moderator"),
FieldPanel("author"),
FieldPanel("participants", widget=UserSelectWidget({"data-width": "100%"})),
FieldPanel("moderator", widget=TomSelectWidget(label_field="display_name")),
FieldPanel("author", widget=TomSelectWidget(label_field="display_name")),
FieldPanel("participants", widget=TomSelectMultipleWidget(label_field="display_name")),
FieldPanel("labels"),
FieldPanel("body"),
FieldPanel("guests"),
Expand Down
2 changes: 1 addition & 1 deletion myhpi/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"django.contrib.staticfiles",
"django.contrib.messages",
"django_bootstrap_icons",
"django_select2",
"django_tomselect",
"modelcluster",
"mozilla_django_oidc",
"taggit",
Expand Down
31 changes: 16 additions & 15 deletions myhpi/tests/core/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
MinutesList,
RootPage,
SecondLevelMenuItem,
UserProfile,
)


Expand Down Expand Up @@ -171,9 +172,9 @@ def setup_minutes(group, students_group, parent, user):
date="2022-01-01",
is_public=False,
visible_for=[students_group, group],
moderator=user,
author=user,
participants=[user],
moderator=UserProfile.for_user(user),
author=UserProfile.for_user(user),
participants=[UserProfile.for_user(user)],
body="These are the first minutes.",
slug="first-minutes",
),
Expand All @@ -182,9 +183,9 @@ def setup_minutes(group, students_group, parent, user):
date="2022-02-02",
is_public=False,
visible_for=[students_group, group],
moderator=user,
author=user,
participants=[user],
moderator=UserProfile.for_user(user),
author=UserProfile.for_user(user),
participants=[UserProfile.for_user(user)],
body="These are the second minutes.",
slug="second-minutes",
),
Expand All @@ -193,9 +194,9 @@ def setup_minutes(group, students_group, parent, user):
date="2022-03-03",
is_public=False,
visible_for=[group],
moderator=user,
author=user,
participants=[user],
moderator=UserProfile.for_user(user),
author=UserProfile.for_user(user),
participants=[UserProfile.for_user(user)],
body="These minutes are private.",
slug="private-minutes",
),
Expand All @@ -205,9 +206,9 @@ def setup_minutes(group, students_group, parent, user):
is_public=False,
live=False,
visible_for=[group],
moderator=user,
author=user,
participants=[user],
moderator=UserProfile.for_user(user),
author=UserProfile.for_user(user),
participants=[UserProfile.for_user(user)],
body="These minutes are unpublished.",
slug="unpublished-minutes",
),
Expand All @@ -216,9 +217,9 @@ def setup_minutes(group, students_group, parent, user):
date="2022-05-05",
is_public=False,
visible_for=[students_group, group],
moderator=user,
author=user,
participants=[user],
moderator=UserProfile.for_user(user),
author=UserProfile.for_user(user),
participants=[UserProfile.for_user(user)],
body="These minutes are the most recent.",
slug="recent-minutes",
),
Expand Down
3 changes: 2 additions & 1 deletion myhpi/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from django.contrib.auth import views as auth_views
from django.urls import include, path, reverse_lazy
from django.views.generic import RedirectView
from django_tomselect.views import AutocompleteView
from wagtail import urls as wagtail_urls
from wagtail.admin import urls as wagtailadmin_urls
from wagtail.documents import urls as wagtaildocs_urls
Expand All @@ -25,7 +26,7 @@
),
name="login",
),
path("select2/", include("django_select2.urls")),
path("autocomplete/", AutocompleteView.as_view(), name="autocomplete"),
path("__debug__/", include("debug_toolbar.urls")),
path(
".well-known/security.txt",
Expand Down
Loading