Skip to content

Commit 3a40c3a

Browse files
committed
Merge remote-tracking branch 'origin/feature/add-participant-portal-app'
2 parents 4205417 + 813e63a commit 3a40c3a

18 files changed

Lines changed: 478 additions & 1 deletion

File tree

app/core/const/tag.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,7 @@ class OpenAPITag:
1111
ADMIN_EVENT_PRESENTATION = "Admin > Event > Presentation"
1212
ADMIN_EVENT_SPONSOR = "Admin > Event > Sponsor"
1313
ADMIN_JSON_SCHEMA = "Admin > JSON Schema"
14+
15+
PARTICIPANT_PORTAL_USER = "Participant Portal > Sign-In & Sign-Out & My Profile"
16+
PARTICIPANT_PORTAL_PUBLIC_FILE = "Participant Portal > Public File"
17+
PARTICIPANT_PORTAL_PRESENTATION = "Participant Portal > Presentation"

app/core/settings.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@
161161
"event.presentation",
162162
"event.sponsor",
163163
"admin_api",
164+
"participant_portal_api",
164165
# django-constance
165166
"constance",
166167
]

app/core/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
v1_apis: list[resolvers.URLPattern | resolvers.URLResolver] = [
2727
path("cms/", include("cms.urls")),
2828
path("admin-api/", include("admin_api.urls")),
29+
path("participant-portal/", include("participant_portal_api.urls")),
2930
path("event/presentation/", include("event.presentation.urls")),
3031
path("event/sponsor/", include("event.sponsor.urls")),
3132
]
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Generated by Django 5.2 on 2025-06-29 10:49
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
dependencies = [
8+
("presentation", "0006_remove_historicalpresentation_page_and_more"),
9+
]
10+
11+
operations = [
12+
migrations.AddField(
13+
model_name="historicalpresentation",
14+
name="summary",
15+
field=models.TextField(blank=True, default=""),
16+
),
17+
migrations.AddField(
18+
model_name="historicalpresentation",
19+
name="summary_en",
20+
field=models.TextField(blank=True, default="", null=True),
21+
),
22+
migrations.AddField(
23+
model_name="historicalpresentation",
24+
name="summary_ko",
25+
field=models.TextField(blank=True, default="", null=True),
26+
),
27+
migrations.AddField(
28+
model_name="presentation",
29+
name="summary",
30+
field=models.TextField(blank=True, default=""),
31+
),
32+
migrations.AddField(
33+
model_name="presentation",
34+
name="summary_en",
35+
field=models.TextField(blank=True, default="", null=True),
36+
),
37+
migrations.AddField(
38+
model_name="presentation",
39+
name="summary_ko",
40+
field=models.TextField(blank=True, default="", null=True),
41+
),
42+
]

app/event/presentation/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ def __str__(self) -> str:
6262
class Presentation(BaseAbstractModel):
6363
type = models.ForeignKey(PresentationType, on_delete=models.PROTECT)
6464
title = models.CharField(max_length=256)
65+
summary = models.TextField(blank=True, default="")
6566
description = MarkdownField(blank=True, default="")
6667
image = models.ForeignKey(PublicFile, on_delete=models.PROTECT, null=True, blank=True)
6768
categories = models.ManyToManyField(to="PresentationCategory", through="PresentationCategoryRelation")

app/event/presentation/translation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class PresentationCategoryTranslationOptions(TranslationOptions):
1414

1515
@register(Presentation)
1616
class PresentationTranslationOptions(TranslationOptions):
17-
fields = ("title", "description")
17+
fields = ("title", "summary", "description")
1818

1919

2020
@register(PresentationSpeaker)

app/participant_portal_api/__init__.py

Whitespace-only changes.

app/participant_portal_api/apps.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from django.apps import AppConfig
2+
3+
4+
class ParticipantPortalApiConfig(AppConfig):
5+
name = "participant_portal_api"
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from event.presentation.models import PresentationSpeaker
2+
from rest_framework import permissions, request, views
3+
from user.models import UserExt
4+
5+
6+
class IsSessionSpeaker(permissions.BasePermission):
7+
message = "You do not have permission to perform this action."
8+
9+
def has_permission(self, request: request.Request, view: views.APIView) -> bool:
10+
if not (isinstance(request.user, UserExt) and request.user.is_active and request.user.is_authenticated):
11+
return False
12+
13+
return (
14+
PresentationSpeaker.objects.filter_active()
15+
.filter(
16+
user=request.user,
17+
presentation__deleted_at__isnull=True,
18+
)
19+
.exists()
20+
)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from file.models import PublicFile
2+
from rest_framework import serializers
3+
4+
5+
class PublicFilePortalSerializer(serializers.ModelSerializer):
6+
file = serializers.FileField(read_only=True)
7+
name = serializers.CharField(read_only=True, source="file.name")
8+
9+
class Meta:
10+
model = PublicFile
11+
fields = ("id", "file", "name", "created_at")
12+
13+
14+
class PublicFilePortalUploadSerializer(serializers.Serializer):
15+
file = serializers.FileField()
16+
17+
def create(self, validated_data: dict) -> PublicFile:
18+
new_file = PublicFile(file=validated_data["file"])
19+
new_file.clean()
20+
21+
if new_file.hash and PublicFile.objects.filter(hash=new_file.hash).exists():
22+
raise serializers.ValidationError({"file": "A file with the same hash already exists."})
23+
24+
new_file.save()
25+
return new_file

0 commit comments

Comments
 (0)