Skip to content

Commit

Permalink
feat(buddy-system): refactored to standalone model for request matche…
Browse files Browse the repository at this point in the history
…s WIP
  • Loading branch information
thejoeejoee committed Sep 28, 2023
1 parent 4eb60b5 commit 0ec4069
Show file tree
Hide file tree
Showing 15 changed files with 187 additions and 81 deletions.
2 changes: 1 addition & 1 deletion fiesta/apps/accounts/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class Meta(AbstractUser.Meta):
verbose_name_plural = _("users")

# a few dynamic related models
buddy_system_matched_requests: models.QuerySet
buddy_system_request_matches: models.QuerySet
profile: UserProfile


Expand Down
9 changes: 7 additions & 2 deletions fiesta/apps/buddy_system/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

from django.contrib import admin

from ..fiestarequests.admin import BaseRequestAdmin
from ..fiestarequests.admin import BaseRequestAdmin, BaseRequestMatchAdmin
from ..plugins.admin import BaseChildConfigurationAdmin
from .models import BuddyRequest, BuddySystemConfiguration
from .models import BuddyRequest, BuddyRequestMatch, BuddySystemConfiguration


@admin.register(BuddySystemConfiguration)
Expand All @@ -15,3 +15,8 @@ class BuddySystemConfigurationAdmin(BaseChildConfigurationAdmin):
@admin.register(BuddyRequest)
class BuddyRequestAdmin(BaseRequestAdmin):
pass


@admin.register(BuddyRequestMatch)
class BuddyRequestMatchAdmin(BaseRequestMatchAdmin):
pass
42 changes: 17 additions & 25 deletions fiesta/apps/buddy_system/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
from django.utils.translation import gettext_lazy as _

from apps.accounts.models import UserProfile
from apps.buddy_system.models import BuddyRequest
from apps.buddy_system.models import BuddyRequest, BuddyRequestMatch
from apps.fiestaforms.fields.array import ChoicedArrayField
from apps.fiestaforms.fields.datetime import DateTimeLocalField
from apps.fiestaforms.forms import BaseModelForm
from apps.fiestaforms.widgets.models import ActiveLocalMembersFromSectionWidget, UserWidget

Expand All @@ -29,7 +28,7 @@ class NewBuddyRequestForm(BaseModelForm):
class Meta:
model = BuddyRequest
fields = (
"issuer_note",
"note",
"interests",
"responsible_section",
"issuer",
Expand All @@ -42,12 +41,12 @@ class Meta:
"issuer": HiddenInput,
}
labels = {
"issuer_note": _("Tell us about yourself"),
"note": _("Tell us about yourself"),
"interests": _("What are you into?"),
}
help_texts = {
"issuer_note": lazy(
lambda: render_to_string("buddy_system/parts/buddy_request_issuer_note_help.html"),
"note": lazy(
lambda: render_to_string("buddy_system/parts/buddy_request_note_help.html"),
str,
)
}
Expand All @@ -65,28 +64,28 @@ def __init__(self, *args, **kwargs):
self.fields["issuer"].disabled = True

if self.instance.state != BuddyRequest.State.CREATED:
self.fields["matched_by"].disabled = True
self.fields["matched_at"].disabled = True
self.fields["issuer_note"].disabled = True
# self.fields["matched_by"].disabled = True
# self.fields["matched_at"].disabled = True
self.fields["note"].disabled = True
self.fields["interests"].disabled = True

class Meta:
model = BuddyRequest
fields = (
"issuer",
"state",
"issuer_note",
"note",
"interests",
"matched_by",
"matched_at",
# "matched_by",
# "matched_at",
)
field_classes = {
"interests": ChoicedArrayField,
"matched_at": DateTimeLocalField,
# "matched_at": DateTimeLocalField,
}
widgets = {
"issuer": UserWidget,
"matched_by": ActiveLocalMembersFromSectionWidget,
# "matched_by": ActiveLocalMembersFromSectionWidget,
}


Expand All @@ -96,18 +95,11 @@ class QuickBuddyMatchForm(BaseModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

self.fields["issuer"].disabled = True

if self.instance.state != BuddyRequest.State.CREATED:
self.fields["matched_by"].disabled = True
# self.fields["issuer"].disabled = True

class Meta:
model = BuddyRequest
fields = (
"issuer",
"matched_by",
)
model = BuddyRequestMatch
fields = ("matcher",)
widgets = {
"issuer": UserWidget,
"matched_by": ActiveLocalMembersFromSectionWidget,
"matcher": ActiveLocalMembersFromSectionWidget,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Generated by Django 4.2.4 on 2023-09-24 19:17

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


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('buddy_system', '0020_rename_description_buddyrequest_issuer_note'),
]

operations = [
migrations.RemoveField(
model_name='buddyrequest',
name='issuer_note',
),
migrations.RemoveField(
model_name='buddyrequest',
name='matched_at',
),
migrations.RemoveField(
model_name='buddyrequest',
name='matched_by',
),
migrations.AddField(
model_name='buddyrequest',
name='note',
field=models.TextField(default='', verbose_name='text from issuer'),
preserve_default=False,
),
migrations.AddField(
model_name='buddysystemconfiguration',
name='enable_note_from_matcher',
field=models.BooleanField(default=True, help_text='Allows matcher to reply with custom notes to the request issuer'),
),
migrations.CreateModel(
name='BuddyRequestMatch',
fields=[
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, verbose_name='created')),
('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, verbose_name='modified')),
('note', models.TextField(blank=True, verbose_name='text from matcher')),
('matcher', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, related_name='buddy_system_request_matches', to=settings.AUTH_USER_MODEL, verbose_name='matched by')),
('request', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='match', to='buddy_system.buddyrequest', verbose_name='request')),
],
options={
'verbose_name': 'buddy request match',
'verbose_name_plural': 'buddy request matches',
'ordering': ('-created',),
'get_latest_by': 'modified',
'abstract': False,
},
),
]
3 changes: 2 additions & 1 deletion fiesta/apps/buddy_system/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from __future__ import annotations

from .configuration import BuddySystemConfiguration
from .request import BuddyRequest
from .request import BuddyRequest, BuddyRequestMatch

__all__ = [
"BuddySystemConfiguration",
"BuddyRequest",
"BuddyRequestMatch",
]
14 changes: 13 additions & 1 deletion fiesta/apps/buddy_system/models/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
from apps.fiestarequests.models import base_request_model_factory
from apps.utils.models.fields import ArrayFieldWithDisplayableChoices

BaseRequestForBuddySystem = base_request_model_factory(related_base="buddy_system")
BaseRequestForBuddySystem, BaseRequestMatchForBuddySystem = base_request_model_factory(
final_request_model_name="buddy_system.BuddyRequest",
related_base="buddy_system",
)


class BuddyRequest(BaseRequestForBuddySystem):
Expand All @@ -29,3 +32,12 @@ class Meta(BaseRequestForBuddySystem.Meta):

def __str__(self):
return f"Buddy Request {self.issuer}: {self.get_state_display()}"


class BuddyRequestMatch(BaseRequestMatchForBuddySystem):
class Meta(BaseRequestForBuddySystem.Meta):
verbose_name = _("buddy request match")
verbose_name_plural = _("buddy request matches")

def __str__(self):
return f"Buddy Request Match {self.matcher}: {self.request}"
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@
<div class="Dashboard__tile__desc">
It's a match!
<br>
You have been matched with {{ br.matched_by }}.
You have been matched with {{ br.match.matcher }}.
</div>
{% endif %}
{% else %}
{% get_waiting_requests_to_match as waiting_brs %}
<div class="Dashboard__tile__value">
{% with waiting_brs.count as count %}
<span>{{ count }}</span> waiting request
{{ count|pluralize:"s" }}
<span>{{ count }}</span>
waiting request{{ count|pluralize:"s" }}
{% endwith %}
</div>
<div class="Dashboard__tile__actions text-right">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ <h2 class="card-title flex flex-row justify-between">
{% endif %}
</div>
</div>
<div class="chat-bubble">{{ br.issuer_note }}</div>
<div class="chat-bubble">{{ br.note }}</div>
</div>
<div class="chat chat-end">
<div class="chat-header">
Expand Down
8 changes: 4 additions & 4 deletions fiesta/apps/buddy_system/templatetags/buddy_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ def get_matched_buddy_requests(context):
request: HttpRequest = context["request"]

# TODO: limit by semester / time
return request.user.buddy_system_matched_requests.filter(
responsible_section=request.membership.section,
state=BuddyRequest.State.MATCHED,
).order_by("-matched_at")
return request.user.buddy_system_request_matches.filter(
request__responsible_section=request.membership.section,
request__state=BuddyRequest.State.MATCHED,
).order_by("-created")


@register.filter
Expand Down
16 changes: 10 additions & 6 deletions fiesta/apps/buddy_system/views/editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
from django.contrib.messages.views import SuccessMessageMixin
from django.contrib.postgres.search import SearchVector
from django.forms import TextInput
from django.shortcuts import get_object_or_404
from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _
from django.views.generic import UpdateView
from django.views.generic import CreateView, UpdateView
from django_filters import CharFilter, ChoiceFilter, ModelChoiceFilter
from django_tables2 import Column, TemplateColumn, tables
from django_tables2.utils import Accessor

from apps.buddy_system.forms import BuddyRequestEditorForm, QuickBuddyMatchForm
from apps.buddy_system.models import BuddyRequest
from apps.buddy_system.models import BuddyRequest, BuddyRequestMatch
from apps.fiestaforms.views.htmx import HtmxFormMixin
from apps.fiestatables.columns import ImageColumn, NaturalDatetimeColumn
from apps.fiestatables.filters import BaseFilterSet, ProperDateFromToRangeFilter
Expand Down Expand Up @@ -153,17 +154,20 @@ class QuickBuddyMatchView(
SuccessMessageMixin,
HtmxFormMixin,
AjaxViewMixin,
UpdateView,
CreateView,
):
template_name = "buddy_system/editor/quick_match.html"
ajax_template_name = "buddy_system/editor/quick_match_form.html"
model = BuddyRequest
model = BuddyRequestMatch
form_class = QuickBuddyMatchForm

success_url = reverse_lazy("buddy_system:requests")
success_message = _("Buddy request has been matched.")

def form_valid(self, form):
form.instance.state = BuddyRequest.State.MATCHED
form.instance.save(update_fields=["state"])
request = get_object_or_404(BuddyRequest, pk=self.kwargs["pk"])
form.instance.request = request
request.state = BuddyRequest.State.MATCHED
request.save(update_fields=["state"])

return super().form_valid(form)
16 changes: 13 additions & 3 deletions fiesta/apps/buddy_system/views/matching.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from django.views.generic.detail import BaseDetailView
from django_htmx.http import HttpResponseClientRedirect

from apps.buddy_system.models import BuddyRequest, BuddySystemConfiguration
from apps.buddy_system.models import BuddyRequest, BuddyRequestMatch, BuddySystemConfiguration
from apps.files.views import NamespacedFilesServeView
from apps.plugins.middleware.plugin import HttpRequest
from apps.plugins.views import PluginConfigurationViewMixin
Expand Down Expand Up @@ -56,11 +56,21 @@ def get_queryset(self):
)

def post(self, request, pk: uuid.UUID):
BuddyRequest.objects.match_by(
request=self.get_object(),
br: BuddyRequest = self.get_object()

match = BuddyRequestMatch(
request=br,
matcher=self.request.user,
# TODO: better
note=self.request.POST.get("note"),
)

# TODO: check matcher relation to responsible section?
match.save()

br.match = match
br.state = BuddyRequest.State.MATCHED

messages.success(request, _("Request successfully matched!"))
# TODO: target URL?
return HttpResponseClientRedirect("/")
Expand Down
31 changes: 29 additions & 2 deletions fiesta/apps/fiestarequests/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@


class BaseRequestAdmin(ModelAdmin):
list_display = ["responsible_section", "issuer", "state", "matched_by", "matched_at", "created"]
# https://github.com/gitaarik/django-admin-relation-links

list_display = ["responsible_section", "issuer", "state", "match", "created"]

date_hierarchy = "created"

Expand All @@ -15,7 +17,7 @@ class BaseRequestAdmin(ModelAdmin):
"state",
]

autocomplete_fields = ["issuer", "matched_by"]
autocomplete_fields = ["issuer"]

search_fields = [
"issuer__username",
Expand All @@ -24,3 +26,28 @@ class BaseRequestAdmin(ModelAdmin):
"issuer__first_name",
"responsible_section__name",
]


class BaseRequestMatchAdmin(ModelAdmin):
list_display = ["matcher", "note", "created"]

date_hierarchy = "created"

list_filter = [
("request__responsible_section", admin.RelatedOnlyFieldListFilter),
("request__responsible_section__country", admin.AllValuesFieldListFilter),
]

autocomplete_fields = ["matcher"]

search_fields = [
"request__issuer__username",
"request__issuer__email",
"request__issuer__last_name",
"request__issuer__first_name",
"matcher__username",
"matcher__email",
"matcher__last_name",
"matcher__first_name",
"request_match__responsible_section__name",
]
Loading

0 comments on commit 0ec4069

Please sign in to comment.