Skip to content
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 apps/common/firebase.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class RelaxedModel(self.firebase_model_class):

# NOTE: we want to ignore extra fields from firebase
valid_fb_model = RelaxedModel.model_validate(obj=fb_model)
valid_fb_model = self.firebase_model_class.model_validate(valid_fb_model)
valid_fb_model = self.firebase_model_class.model_validate(obj=valid_fb_model)

self.handle_object_update_on_firebase(model_obj, valid_fb_model, model_ref)
except InvalidObjectPushException:
Expand Down
19 changes: 19 additions & 0 deletions apps/tutorial/migrations/0010_alter_tutorial_firebase_id.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 5.2.4 on 2025-08-03 16:00

import apps.tutorial.models
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('tutorial', '0009_merge_20250801_1651'),
]

operations = [
migrations.AlterField(
model_name='tutorial',
name='firebase_id',
field=models.CharField(default=apps.tutorial.models.generate_tutorial_firebase_id, max_length=40, unique=True),
),
]
22 changes: 22 additions & 0 deletions apps/tutorial/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ class TutorialStatusEnum(models.IntegerChoices):
"""


def generate_tutorial_firebase_id():
return f"tutorial_{ulid.ULID()}"


class Tutorial(UserResource, FirebasePushResource): # type: ignore[reportIncompatibleVariableOverride]
Status = TutorialStatusEnum

Expand All @@ -65,6 +69,8 @@ class Tutorial(UserResource, FirebasePushResource): # type: ignore[reportIncomp
default=TutorialStatusEnum.DRAFT,
)

firebase_id = models.CharField(max_length=40, unique=True, default=generate_tutorial_firebase_id)

# Type hints
project_id: int
scenarios: RelatedManager["TutorialScenarioPage"]
Expand Down Expand Up @@ -121,6 +127,22 @@ class Meta: # type: ignore[reportIncompatibleVariableOverride]
models.UniqueConstraint(fields=["tutorial", "scenario_page_number"], name="unique_scenario_on_tutorials"),
]

@property
def instructions_icon_enum(self) -> IconEnum:
return IconEnum(self.instructions_icon)

@property
def hint_icon_enum(self) -> IconEnum | None:
if self.hint_icon:
return IconEnum(self.hint_icon)
return None

@property
def success_icon_enum(self) -> IconEnum | None:
if self.success_icon:
return IconEnum(self.success_icon)
return None

@typing.override
def __str__(self):
return self.scenario_page_number
Expand Down
24 changes: 18 additions & 6 deletions main/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,27 +44,39 @@ def v2():
return "/v2"

@staticmethod
def project(project_id: str | int):
def project(project_id: str):
return f"/v2/projects/{project_id}"

@staticmethod
def project_groups(project_id: str | int):
def project_groups(project_id: str):
return f"/v2/groups/{project_id}/"

@staticmethod
def project_tasks(project_id: str | int):
def project_tasks(project_id: str):
return f"/v2/tasks/{project_id}/"

@staticmethod
def organization(organization_id: str | int):
def tutorial(tutorial_id: str):
return f"/v2/projects/{tutorial_id}"

@staticmethod
def tutorial_groups(tutorial_id: str):
return f"/v2/groups/{tutorial_id}/"

@staticmethod
def tutorial_tasks(tutorial_id: str):
return f"/v2/tasks/{tutorial_id}/"

@staticmethod
def organization(organization_id: str):
return f"/v2/organisation/{organization_id}/"

@staticmethod
def contributor_team(contributor_team_id: str | int):
def contributor_team(contributor_team_id: str):
return f"/v2/teams/{contributor_team_id}/"

@staticmethod
def contributor_user(user_id: str | int):
def contributor_user(user_id: str):
return f"/v2/users/{user_id}"


Expand Down
18 changes: 12 additions & 6 deletions project_types/base/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from django.contrib.gis.db.models.functions import Area
from django.db import models
from firebase_admin.db import Reference as FbReference
from pydantic import BaseModel
from pydantic import BaseModel, ConfigDict
from pyfirebase_mapswipe import extended_models as firebase_ext_models
from pyfirebase_mapswipe import models as firebase_models
from pyfirebase_mapswipe import utils as firebase_utils
Expand Down Expand Up @@ -251,11 +251,11 @@ def handle_new_project_on_firebase(self, project_ref: FbReference):
# NOTE: We are not reading data from group_ref as it's an expensive operation
# FIXME(tnagorra): We need to check if the key exists later
group_ref = self.firebase_helper.ref(
Config.FirebaseKeys.project_groups(self.project.id),
Config.FirebaseKeys.project_groups(self.project.firebase_id),
)
# FIXME(tnagorra): We need to check if the key exists later
task_ref = self.firebase_helper.ref(
Config.FirebaseKeys.project_tasks(self.project.id),
Config.FirebaseKeys.project_tasks(self.project.firebase_id),
)

# FIXME: If taskId is defined, should be private_inactive
Expand Down Expand Up @@ -353,7 +353,6 @@ def handle_project_update_on_firebase(self, project_ref: FbReference, fb_project
),
)

# FIXME(rup): use common method push_django_to_firebase()
def push_to_firebase(self):
if self.project.firebase_push_status_enum != FirebasePushStatusEnum.PENDING:
logger.warning("%s - push_to_firebase called when push is not required", self.project.pk)
Expand All @@ -363,7 +362,7 @@ def push_to_firebase(self):

try:
project_ref = self.firebase_helper.ref(
Config.FirebaseKeys.project(self.project.id),
Config.FirebaseKeys.project(self.project.firebase_id),
)
fb_project: typing.Any = project_ref.get()

Expand All @@ -382,7 +381,14 @@ def push_to_firebase(self):
extra=log_extra({"project": self.project.pk}),
)
raise InvalidProjectPushException
valid_project = firebase_ext_models.FbProject.model_validate(obj=fb_project)

class RelaxedModel(firebase_ext_models.FbProject):
model_config = ConfigDict(extra="ignore")

# NOTE: we want to ignore extra fields from firebase
valid_project = RelaxedModel.model_validate(obj=fb_project)
valid_project = firebase_ext_models.FbProject.model_validate(obj=valid_project)

self.handle_project_update_on_firebase(project_ref, valid_project)
except InvalidProjectPushException:
self.project.update_firebase_push_status(FirebasePushStatusEnum.FAILED)
Expand Down
Loading
Loading