From 98cc1ce205422e60fa81c5bfba82e7b8403ca5dc Mon Sep 17 00:00:00 2001 From: Angie Vanegas P Date: Mon, 27 Jan 2025 22:25:07 +0000 Subject: [PATCH 1/7] Add recording_url in backend --- breathecode/events/models.py | 8 ++++++++ breathecode/services/eventbrite/actions/event_created.py | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/breathecode/events/models.py b/breathecode/events/models.py index 7e3da8716..39128ec09 100644 --- a/breathecode/events/models.py +++ b/breathecode/events/models.py @@ -219,6 +219,14 @@ def __init__(self, *args, **kwargs): help_text="This URL should have the URL of the meeting if it is an online event, if it's not online it should be empty.", ) + recording_url = models.URLField( + max_length=255, + null=True, + blank=True, + default=None, + help_text="This will be the URL of the workshop's recording, added once it's finished", + ) + starting_at = models.DateTimeField(blank=False) ending_at = models.DateTimeField( blank=False, help_text="This field contains the value of when the event is supposed to be finished." diff --git a/breathecode/services/eventbrite/actions/event_created.py b/breathecode/services/eventbrite/actions/event_created.py index 3fd82ffb8..9c0ba528f 100644 --- a/breathecode/services/eventbrite/actions/event_created.py +++ b/breathecode/services/eventbrite/actions/event_created.py @@ -6,8 +6,8 @@ def event_created(self, webhook, payload: dict): # lazyload to fix circular import - from breathecode.events.models import Organization from breathecode.events.actions import update_or_create_event + from breathecode.events.models import Organization org = Organization.objects.filter(id=webhook.organization_id).first() From 31642ad4fcbb72c30023cb2aa87ca4a2956c521a Mon Sep 17 00:00:00 2001 From: Angie Vanegas P Date: Tue, 28 Jan 2025 16:02:51 +0000 Subject: [PATCH 2/7] Add url_recording Event model --- .../migrations/0062_event_recording_url.py | 24 +++++++++++++++++++ breathecode/events/serializers.py | 1 + 2 files changed, 25 insertions(+) create mode 100644 breathecode/events/migrations/0062_event_recording_url.py diff --git a/breathecode/events/migrations/0062_event_recording_url.py b/breathecode/events/migrations/0062_event_recording_url.py new file mode 100644 index 000000000..9c0dab18c --- /dev/null +++ b/breathecode/events/migrations/0062_event_recording_url.py @@ -0,0 +1,24 @@ +# Generated by Django 5.1.4 on 2025-01-28 12:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("events", "0061_event_is_public"), + ] + + operations = [ + migrations.AddField( + model_name="event", + name="recording_url", + field=models.URLField( + blank=True, + default=None, + help_text="This will be the URL of the workshop's recording, added once it's finished", + max_length=255, + null=True, + ), + ), + ] diff --git a/breathecode/events/serializers.py b/breathecode/events/serializers.py index 1133bbd37..11fb448d0 100644 --- a/breathecode/events/serializers.py +++ b/breathecode/events/serializers.py @@ -457,6 +457,7 @@ class EventPUTSerializer(serializers.ModelSerializer): ending_at = serializers.DateTimeField(required=False) online_event = serializers.BooleanField(required=False) status = serializers.CharField(required=False) + recording_url = serializers.URLfield(required=False) class Meta: model = Event From e9bb8437278d7648077df53b0c6bc4d48e89a59f Mon Sep 17 00:00:00 2001 From: Angie Vanegas P Date: Wed, 29 Jan 2025 00:10:17 +0000 Subject: [PATCH 3/7] Add serializer --- Pipfile | 11 +++++++++++ breathecode/events/serializers.py | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 Pipfile diff --git a/Pipfile b/Pipfile new file mode 100644 index 000000000..d61ea531d --- /dev/null +++ b/Pipfile @@ -0,0 +1,11 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] + +[dev-packages] + +[requires] +python_version = "3.13" diff --git a/breathecode/events/serializers.py b/breathecode/events/serializers.py index 11fb448d0..df83512d4 100644 --- a/breathecode/events/serializers.py +++ b/breathecode/events/serializers.py @@ -457,7 +457,7 @@ class EventPUTSerializer(serializers.ModelSerializer): ending_at = serializers.DateTimeField(required=False) online_event = serializers.BooleanField(required=False) status = serializers.CharField(required=False) - recording_url = serializers.URLfield(required=False) + recording_url = serializers.URLField(required=False) class Meta: model = Event From be2376c2fa6e21fe27384ddab3c4152813b1b461 Mon Sep 17 00:00:00 2001 From: Angie Vanegas P Date: Wed, 29 Jan 2025 20:58:47 +0000 Subject: [PATCH 4/7] Add recording_url in test --- breathecode/events/serializers.py | 20 +++++++++++++++++++ .../actions/tests_update_or_create_event.py | 2 ++ .../tests/mixins/new_events_tests_case.py | 1 + .../events/tests/urls/tests_academy_event.py | 9 +++++++++ .../tests/urls/tests_academy_event_id.py | 6 ++++++ breathecode/events/tests/urls/tests_all.py | 1 + breathecode/events/tests/urls/tests_me.py | 1 + .../events/tests/urls/tests_me_event_id.py | 1 + breathecode/events/views.py | 6 ++++++ 9 files changed, 47 insertions(+) diff --git a/breathecode/events/serializers.py b/breathecode/events/serializers.py index df83512d4..392ce9229 100644 --- a/breathecode/events/serializers.py +++ b/breathecode/events/serializers.py @@ -191,6 +191,7 @@ class EventSmallSerializer(EventTinySerializer): author = UserSerializer(required=False) asset = serpy.MethodField() is_public = serpy.Field() + recording_url = serpy.Field() def get_asset(self, obj): if obj.asset_slug is not None: @@ -247,6 +248,7 @@ class EventSmallSerializerNoAcademy(serpy.Serializer): eventbrite_sync_description = serpy.Field() tags = serpy.Field() is_public = serpy.Field() + recording_url = serpy.Field() class EventPublicBigSerializer(EventSmallSerializer): @@ -299,6 +301,7 @@ class AcademyEventSmallSerializer(serpy.Serializer): free_for_all = serpy.Field() asset = serpy.MethodField() is_public = serpy.Field() + recording_url = serpy.Field() def get_asset(self, obj): if obj.asset_slug is not None: @@ -358,11 +361,27 @@ class Meta: model = Event exclude = () + print("EVENT*******************", Event.recording_url) + def validate(self, data: dict[str, Any]): lang = data.get("lang", "en") academy = self.context.get("academy_id") + recording_url = data.get("recording_url") + if recording_url and not recording_url.startswith(("http://", "https://")): + raise ValidationException( + translation( + self.context.get("lang", "en"), + en="The recording URL must be a valid URL starting with http:// or https://", + es="La URL de la grabación debe ser una URL válida que comience con http:// o https://", + slug="invalid-recording-url", + ) + ) + if recording_url is None or recording_url == "": + print("No recording_url provided or it's empty", recording_url) + print("/////////////////////////////recording_url", recording_url) + if ("tags" not in data and self.instance.tags == "") or ("tags" in data and data["tags"] == ""): raise ValidationException( translation( @@ -377,6 +396,7 @@ def validate(self, data: dict[str, Any]): title = data.get("title") slug = data.get("slug") + print("TIIIIITTTTLEEEEEEEEEE", title) if slug and self.instance: raise ValidationException( diff --git a/breathecode/events/tests/actions/tests_update_or_create_event.py b/breathecode/events/tests/actions/tests_update_or_create_event.py index 4ec233191..9f5829c9d 100644 --- a/breathecode/events/tests/actions/tests_update_or_create_event.py +++ b/breathecode/events/tests/actions/tests_update_or_create_event.py @@ -201,6 +201,7 @@ def test_update_or_create_event__with_academy(self): "free_for_all": False, "uuid": uuid, "is_public": True, + "recording_url": None, } self.assertEqual(self.bc.database.list_of("events.Event"), [kwargs]) @@ -294,6 +295,7 @@ def test_update_or_create_event__with_event(self): "free_for_all": False, "uuid": uuid, "is_public": True, + "recording_url": None, } self.assertEqual(self.bc.database.list_of("events.Event"), [kwargs]) diff --git a/breathecode/events/tests/mixins/new_events_tests_case.py b/breathecode/events/tests/mixins/new_events_tests_case.py index 50d047987..cdc3d8ea7 100644 --- a/breathecode/events/tests/mixins/new_events_tests_case.py +++ b/breathecode/events/tests/mixins/new_events_tests_case.py @@ -81,6 +81,7 @@ def check_all_academy_events(self, models=None): "eventbrite_sync_description": model["event"].eventbrite_sync_description, "eventbrite_sync_status": model["event"].eventbrite_sync_status, "is_public": model["event"].is_public, + "recording_url": model["event"].recording_url, } for model in models ] diff --git a/breathecode/events/tests/urls/tests_academy_event.py b/breathecode/events/tests/urls/tests_academy_event.py index 47763d1e5..faa26efe1 100644 --- a/breathecode/events/tests/urls/tests_academy_event.py +++ b/breathecode/events/tests/urls/tests_academy_event.py @@ -54,6 +54,7 @@ def post_serializer(data={}): "live_stream_url": None, "host_user": None, "is_public": True, + "recording_url": None, **data, } @@ -97,6 +98,7 @@ def event_table(data={}): "sync_with_eventbrite": False, "currency": "", "is_public": True, + "recording_url": None, **data, } @@ -195,6 +197,7 @@ def test_all_academy_events_correct_city(self): "eventbrite_sync_description": model["event"].eventbrite_sync_description, "eventbrite_sync_status": model["event"].eventbrite_sync_status, "is_public": model["event"].is_public, + "recording_url": model["event"].recording_url, } ] @@ -269,6 +272,7 @@ def test_all_academy_events_correct_country(self): "eventbrite_sync_description": model["event"].eventbrite_sync_description, "eventbrite_sync_status": model["event"].eventbrite_sync_status, "is_public": model["event"].is_public, + "recording_url": model["event"].recording_url, } ] @@ -343,6 +347,7 @@ def test_all_academy_events_correct_zip_code(self): "eventbrite_sync_description": model["event"].eventbrite_sync_description, "eventbrite_sync_status": model["event"].eventbrite_sync_status, "is_public": model["event"].is_public, + "recording_url": model["event"].recording_url, } ] @@ -398,6 +403,7 @@ def test_all_academy_events_upcoming(self): "eventbrite_sync_description": model["event"].eventbrite_sync_description, "eventbrite_sync_status": model["event"].eventbrite_sync_status, "is_public": model["event"].is_public, + "recording_url": model["event"].recording_url, } ] @@ -687,6 +693,7 @@ def test_all_academy_events__post_with_event_is_public_true(self): "eventbrite_sync_description": model["event"].eventbrite_sync_description, "eventbrite_sync_status": model["event"].eventbrite_sync_status, "is_public": model["event"].is_public, + "recording_url": model["event"].recording_url, } ] self.assertEqual(json, expected) @@ -741,6 +748,7 @@ def test_all_academy_events__post_with_event_is_public_false(self): "eventbrite_sync_description": model["event"].eventbrite_sync_description, "eventbrite_sync_status": model["event"].eventbrite_sync_status, "is_public": model["event"].is_public, + "recording_url": model["event"].recording_url, } ] self.assertEqual(json, expected) @@ -794,6 +802,7 @@ def test_all_academy_events__post_with_event_is_public_empty(self): "eventbrite_sync_description": model["event"].eventbrite_sync_description, "eventbrite_sync_status": model["event"].eventbrite_sync_status, "is_public": model["event"].is_public, + "recording_url": model["event"].recording_url, } ] diff --git a/breathecode/events/tests/urls/tests_academy_event_id.py b/breathecode/events/tests/urls/tests_academy_event_id.py index a73072318..03a8a54b0 100644 --- a/breathecode/events/tests/urls/tests_academy_event_id.py +++ b/breathecode/events/tests/urls/tests_academy_event_id.py @@ -71,6 +71,7 @@ def get_serializer(event, academy, asset=None, data={}): "eventbrite_sync_description": event.eventbrite_sync_description, "asset": asset_serializer(asset) if asset else None, "is_public": event.is_public, + "recording_url": event.recording_url, **data, } @@ -218,6 +219,7 @@ def test_academy_event_id__put__is_public_true(self): "free_for_all": False, "uuid": str(uuid), "is_public": True, + "recording_url": None, **data, } @@ -316,6 +318,7 @@ def test_academy_event_id__put__is_public_false(self): "free_for_all": False, "uuid": str(uuid), "is_public": False, + "recording_url": None, **data, } @@ -666,6 +669,7 @@ def test_academy_cohort_id__put(self): "free_for_all": False, "uuid": str(uuid), "is_public": True, + "recording_url": None, **data, } @@ -900,6 +904,7 @@ def test_academy_cohort_id__put__with_tags(self): "free_for_all": False, "uuid": str(uuid), "is_public": True, + "recording_url": None, **data, } @@ -1001,6 +1006,7 @@ def test_academy_cohort_id__put__with_duplicate_tags(self): "free_for_all": False, "uuid": str(uuid), "is_public": True, + "recording_url": None, **data, } diff --git a/breathecode/events/tests/urls/tests_all.py b/breathecode/events/tests/urls/tests_all.py index be40d126a..b7754f6fd 100644 --- a/breathecode/events/tests/urls/tests_all.py +++ b/breathecode/events/tests/urls/tests_all.py @@ -35,6 +35,7 @@ def serialize_event(event): "ended_at": (event.ended_at.strftime("%Y-%m-%dT%H:%M:%S.%f") + "Z" if event.ended_at else None), "online_event": event.online_event, "is_public": event.is_public, + "recording_url": event.recording_url, "venue": ( None if not event.venue diff --git a/breathecode/events/tests/urls/tests_me.py b/breathecode/events/tests/urls/tests_me.py index 712132be9..2fa37a5c6 100644 --- a/breathecode/events/tests/urls/tests_me.py +++ b/breathecode/events/tests/urls/tests_me.py @@ -144,6 +144,7 @@ def get_serializer( "url": event.url, "venue": event.venue, "is_public": event.is_public, + "recording_url": event.recording_url, **data, } diff --git a/breathecode/events/tests/urls/tests_me_event_id.py b/breathecode/events/tests/urls/tests_me_event_id.py index 82af318a7..2bc05c5ce 100644 --- a/breathecode/events/tests/urls/tests_me_event_id.py +++ b/breathecode/events/tests/urls/tests_me_event_id.py @@ -146,6 +146,7 @@ def get_serializer( "url": event.url, "venue": event.venue, "is_public": event.is_public, + "recording_url": event.recording_url, **data, } diff --git a/breathecode/events/views.py b/breathecode/events/views.py index d3a70a2b3..c4edabb69 100644 --- a/breathecode/events/views.py +++ b/breathecode/events/views.py @@ -137,6 +137,12 @@ def get_events(request): elif is_public == "false": lookup["is_public"] = False + recording_url = request.GET.get("recording_url", None) + if recording_url == "true": + lookup["recording_url"] = True + elif recording_url == "false": + lookup["recording_url"] = False + if "technologies" in request.GET: values = request.GET.get("technologies").split(",") tech_query = Q() From 9c558fc66544093e86bad14c5f478be6ac16bed6 Mon Sep 17 00:00:00 2001 From: Angie Vanegas P Date: Wed, 29 Jan 2025 21:26:23 +0000 Subject: [PATCH 5/7] Fix code and remove print's --- breathecode/events/serializers.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/breathecode/events/serializers.py b/breathecode/events/serializers.py index 392ce9229..6194fc582 100644 --- a/breathecode/events/serializers.py +++ b/breathecode/events/serializers.py @@ -361,8 +361,6 @@ class Meta: model = Event exclude = () - print("EVENT*******************", Event.recording_url) - def validate(self, data: dict[str, Any]): lang = data.get("lang", "en") @@ -378,9 +376,6 @@ def validate(self, data: dict[str, Any]): slug="invalid-recording-url", ) ) - if recording_url is None or recording_url == "": - print("No recording_url provided or it's empty", recording_url) - print("/////////////////////////////recording_url", recording_url) if ("tags" not in data and self.instance.tags == "") or ("tags" in data and data["tags"] == ""): raise ValidationException( @@ -396,7 +391,6 @@ def validate(self, data: dict[str, Any]): title = data.get("title") slug = data.get("slug") - print("TIIIIITTTTLEEEEEEEEEE", title) if slug and self.instance: raise ValidationException( From f91d7140704ae3513758ccf3992087ad3e43b893 Mon Sep 17 00:00:00 2001 From: Angie Vanegas P Date: Thu, 30 Jan 2025 21:05:55 +0000 Subject: [PATCH 6/7] Fix the comments in pr --- Pipfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Pipfile b/Pipfile index d61ea531d..847b8203e 100644 --- a/Pipfile +++ b/Pipfile @@ -1,7 +1,6 @@ [[source]] url = "https://pypi.org/simple" verify_ssl = true -name = "pypi" [packages] From 8a4c9f4b1f05aea5b1538c4002e0904597e6503c Mon Sep 17 00:00:00 2001 From: Angie Vanegas P Date: Thu, 30 Jan 2025 22:13:20 +0000 Subject: [PATCH 7/7] Delete Pipfile --- Pipfile | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 Pipfile diff --git a/Pipfile b/Pipfile deleted file mode 100644 index 847b8203e..000000000 --- a/Pipfile +++ /dev/null @@ -1,10 +0,0 @@ -[[source]] -url = "https://pypi.org/simple" -verify_ssl = true - -[packages] - -[dev-packages] - -[requires] -python_version = "3.13"