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

1006.2 Partial #1044

Merged
merged 25 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
30806d3
Local commit:
mattburnett-repo Dec 7, 2024
84ed051
Local commit: Added Popup file.
mattburnett-repo Dec 7, 2024
9bf2b37
Merge branch 'main' into 1006.2
mattburnett-repo Dec 7, 2024
5bb2947
Local commit:
mattburnett-repo Dec 7, 2024
a567f76
Merge branch 'main' into 1006.2
mattburnett-repo Dec 8, 2024
2e1ccb6
Merge branch 'main' into 1006.2
mattburnett-repo Dec 14, 2024
fcd46e7
Merge branch 'main' into 1006.2
mattburnett-repo Dec 15, 2024
21d750b
Merge branch 'main' into 1006.2
mattburnett-repo Dec 20, 2024
6996ff3
Merge branch 'main' into 1006.2
andrewtavis Jan 12, 2025
a787b76
Merge branch 'main' into 1006.2
mattburnett-repo Jan 14, 2025
47f315c
Merge branch 'main' into 1006.2
andrewtavis Jan 18, 2025
ec94271
Fix Prettier issues on card connect
andrewtavis Jan 18, 2025
4c8e5ee
Merge branch 'main' into 1006.2
andrewtavis Jan 19, 2025
8ece7c9
Split social links model into entity based approach similar to texts
andrewtavis Jan 19, 2025
c462266
Fix mypy errors in backend population command
andrewtavis Jan 19, 2025
2b86417
1006.2 Partial commit. Chages to backend views, urls, etc.
mattburnett-repo Jan 19, 2025
d537716
WIP - All necessary changes for the modal based social link UI
andrewtavis Jan 21, 2025
4c5fb31
Merge branch 'main' into 1006.2
andrewtavis Jan 21, 2025
dbbedf3
WIP: UI changes for 1006.2
mattburnett-repo Jan 26, 2025
f31a8e6
WIP - frontend passes complete formData to backend.
mattburnett-repo Jan 27, 2025
4473500
Fixes for components and i18n check issues
andrewtavis Jan 27, 2025
57ed327
Merge branch 'main' into 1006.2
andrewtavis Jan 28, 2025
0c91247
WIP - Frontend and backend changes:
mattburnett-repo Jan 29, 2025
41283e0
WIP - added file that failed ruff validation.
mattburnett-repo Jan 29, 2025
ecd5d7b
Expand social links to also work for groups and events + test fixes
andrewtavis Jan 29, 2025
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
24 changes: 23 additions & 1 deletion backend/communities/groups/factories.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
import datetime
import random

import factory

from communities.groups.models import Group, GroupImage, GroupMember, GroupText
from communities.groups.models import (
Group,
GroupImage,
GroupMember,
GroupSocialLink,
GroupText,
)

# MARK: Main Tables

Expand Down Expand Up @@ -43,6 +50,21 @@ class Meta:
is_admin = factory.Faker("boolean")


class GroupSocialLinkFactory(factory.django.DjangoModelFactory):
class Meta:
model = GroupSocialLink

link = "https://www.activist.org"
label = "social link"
order = random.randint(0, 10)
creation_date = factory.LazyFunction(
lambda: datetime.datetime.now(tz=datetime.timezone.utc)
)
last_updated = factory.LazyFunction(
lambda: datetime.datetime.now(tz=datetime.timezone.utc)
)


class GroupTextFactory(factory.django.DjangoModelFactory):
class Meta:
model = GroupText
Expand Down
11 changes: 10 additions & 1 deletion backend/communities/groups/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from django.db import models

from content.models import SocialLink
from utils.models import ISO_CHOICES

# MARK: Main Tables
Expand All @@ -32,7 +33,6 @@ class Group(models.Model):
terms_checked = models.BooleanField(default=False)
creation_date = models.DateTimeField(auto_now_add=True)

social_links = models.ManyToManyField("content.SocialLink", blank=True)
topics = models.ManyToManyField("content.Topic", blank=True)
faqs = models.ManyToManyField("content.Faq", blank=True)
events = models.ManyToManyField("events.Event", blank=True)
Expand Down Expand Up @@ -71,6 +71,12 @@ def __str__(self) -> str:
return f"{self.id}"


class GroupSocialLink(SocialLink):
group = models.ForeignKey(
Group, on_delete=models.CASCADE, null=True, related_name="social_links"
)


class GroupText(models.Model):
group = models.ForeignKey(
Group, on_delete=models.CASCADE, null=True, related_name="texts"
Expand All @@ -80,3 +86,6 @@ class GroupText(models.Model):
description = models.TextField(max_length=500)
get_involved = models.TextField(max_length=500, blank=True)
donate_prompt = models.TextField(max_length=500, blank=True)

def __str__(self) -> str:
return f"{self.group} - {self.iso}"
8 changes: 8 additions & 0 deletions backend/communities/groups/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
Group,
GroupImage,
GroupMember,
GroupSocialLink,
GroupText,
)
from communities.organizations.models import Organization
Expand All @@ -20,6 +21,12 @@
# MARK: Main Tables


class GroupSocialLinkSerializer(serializers.ModelSerializer[GroupSocialLink]):
class Meta:
model = GroupSocialLink
fields = "__all__"


class GroupTextSerializer(serializers.ModelSerializer[GroupText]):
class Meta:
model = GroupText
Expand All @@ -34,6 +41,7 @@ class Meta:

class GroupSerializer(serializers.ModelSerializer[Group]):
texts = GroupTextSerializer(many=True, read_only=True)
social_links = GroupSocialLinkSerializer(many=True, read_only=True)
location = LocationSerializer(read_only=True)
resources = ResourceSerializer(many=True, read_only=True)
org = GroupOrganizationSerializer(read_only=True)
Expand Down
57 changes: 55 additions & 2 deletions backend/communities/groups/views.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
# mypy: disable-error-code="override"
import json
from typing import Dict, List
from uuid import UUID

from django.db import transaction
from rest_framework import status, viewsets
from rest_framework.request import Request
from rest_framework.response import Response

from communities.groups.models import Group, GroupText
from communities.groups.serializers import GroupSerializer, GroupTextSerializer
from communities.groups.models import Group, GroupSocialLink, GroupText
from communities.groups.serializers import (
GroupSerializer,
GroupSocialLinkSerializer,
GroupTextSerializer,
)
from core.paginator import CustomPagination

# MARK: Main Tables
Expand Down Expand Up @@ -119,6 +128,50 @@ def destroy(self, request: Request, *args: str, **kwargs: int) -> Response:
)


class GroupSocialLinkViewSet(viewsets.ModelViewSet[GroupSocialLink]):
queryset = GroupSocialLink.objects.all()
serializer_class = GroupSocialLinkSerializer

def update(self, request: Request, pk: UUID | str) -> Response:
group = Group.objects.filter(id=pk).first()
if not group:
return Response(
{"error": "Group not found"}, status=status.HTTP_404_NOT_FOUND
)

data = request.data
if isinstance(data, str):
data = json.loads(data)

try:
# Use transaction.atomic() to ensure nothing is saved if an error occurs.
with transaction.atomic():
# Delete all existing social links for this group.
GroupSocialLink.objects.filter(group=group).delete()

# Create new social links from the submitted data.
social_links: List[Dict[str, str]] = []
for link_data in data:
if isinstance(link_data, dict):
social_link = GroupSocialLink.objects.create(
group=group,
order=link_data.get("order"),
link=link_data.get("link"),
label=link_data.get("label"),
)
social_links.append(social_link)

serializer = self.get_serializer(social_links, many=True)

return Response(serializer.data, status=status.HTTP_200_OK)

except Exception as e:
return Response(
{"error": f"Failed to update social links: {str(e)}"},
status=status.HTTP_400_BAD_REQUEST,
)


class GroupTextViewSet(viewsets.ModelViewSet[GroupText]):
queryset = GroupText.objects.all()
serializer_class = GroupTextSerializer
17 changes: 17 additions & 0 deletions backend/communities/organizations/factories.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
import datetime
import random

import factory

Expand All @@ -9,6 +10,7 @@
OrganizationApplicationStatus,
OrganizationImage,
OrganizationMember,
OrganizationSocialLink,
OrganizationTask,
OrganizationText,
)
Expand Down Expand Up @@ -81,6 +83,21 @@ class Meta:
is_comms = factory.Faker("boolean")


class OrganizationSocialLinkFactory(factory.django.DjangoModelFactory):
class Meta:
model = OrganizationSocialLink

link = "https://www.activist.org"
label = "social link"
order = random.randint(0, 10)
creation_date = factory.LazyFunction(
lambda: datetime.datetime.now(tz=datetime.timezone.utc)
)
last_updated = factory.LazyFunction(
lambda: datetime.datetime.now(tz=datetime.timezone.utc)
)


class OrganizationTaskFactory(factory.django.DjangoModelFactory):
class Meta:
model = OrganizationTask
Expand Down
11 changes: 10 additions & 1 deletion backend/communities/organizations/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from django.db import models

from authentication import enums
from content.models import SocialLink
from utils.models import ISO_CHOICES

# MARK: Main Tables
Expand Down Expand Up @@ -43,7 +44,6 @@ class Organization(models.Model):
acceptance_date = models.DateTimeField(blank=True, null=True)
deletion_date = models.DateTimeField(blank=True, null=True)

social_links = models.ManyToManyField("content.SocialLink", blank=True)
topics = models.ManyToManyField("content.Topic", blank=True)
faqs = models.ManyToManyField("content.Faq", blank=True)
resources = models.ManyToManyField("content.Resource", blank=True)
Expand Down Expand Up @@ -99,6 +99,12 @@ def __str__(self) -> str:
return f"{self.id}"


class OrganizationSocialLink(SocialLink):
org = models.ForeignKey(
Organization, on_delete=models.CASCADE, null=True, related_name="social_links"
)


class OrganizationTask(models.Model):
id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
org = models.ForeignKey(Organization, on_delete=models.CASCADE)
Expand All @@ -120,3 +126,6 @@ class OrganizationText(models.Model):
description = models.TextField(max_length=2500)
get_involved = models.TextField(max_length=500, blank=True)
donate_prompt = models.TextField(max_length=500, blank=True)

def __str__(self) -> str:
return f"{self.org} - {self.iso}"
10 changes: 10 additions & 0 deletions backend/communities/organizations/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
OrganizationApplication,
OrganizationImage,
OrganizationMember,
OrganizationSocialLink,
OrganizationTask,
OrganizationText,
)
Expand All @@ -22,6 +23,14 @@
# MARK: Main Tables


class OrganizationSocialLinkSerializer(
serializers.ModelSerializer[OrganizationSocialLink]
):
class Meta:
model = OrganizationSocialLink
fields = "__all__"


class OrganizationTextSerializer(serializers.ModelSerializer[OrganizationText]):
class Meta:
model = OrganizationText
Expand All @@ -30,6 +39,7 @@ class Meta:

class OrganizationSerializer(serializers.ModelSerializer[Organization]):
texts = OrganizationTextSerializer(many=True, read_only=True)
social_links = OrganizationSocialLinkSerializer(many=True, read_only=True)
location = LocationSerializer(read_only=True)
resources = ResourceSerializer(many=True, read_only=True)
groups = GroupSerializer(many=True, read_only=True)
Expand Down
51 changes: 51 additions & 0 deletions backend/communities/organizations/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
# mypy: disable-error-code="override"
import json
from typing import Dict, List
from uuid import UUID

from django.db import transaction
from django.utils import timezone
from rest_framework import status, viewsets
from rest_framework.request import Request
Expand All @@ -9,10 +14,12 @@
from communities.organizations.models import (
Organization,
OrganizationApplication,
OrganizationSocialLink,
OrganizationText,
)
from communities.organizations.serializers import (
OrganizationSerializer,
OrganizationSocialLinkSerializer,
OrganizationTextSerializer,
)
from core.paginator import CustomPagination
Expand Down Expand Up @@ -137,6 +144,50 @@ def destroy(self, request: Request, pk: str | None = None) -> Response:
)


class OrganizationSocialLinkViewSet(viewsets.ModelViewSet[OrganizationSocialLink]):
queryset = OrganizationSocialLink.objects.all()
serializer_class = OrganizationSocialLinkSerializer

def update(self, request: Request, pk: UUID | str) -> Response:
org = Organization.objects.filter(id=pk).first()
if not org:
return Response(
{"error": "Organization not found"}, status=status.HTTP_404_NOT_FOUND
)

data = request.data
if isinstance(data, str):
data = json.loads(data)

try:
# Use transaction.atomic() to ensure nothing is saved if an error occurs.
with transaction.atomic():
# Delete all existing social links for this org.
OrganizationSocialLink.objects.filter(org=org).delete()

# Create new social links from the submitted data.
social_links: List[Dict[str, str]] = []
for link_data in data:
if isinstance(link_data, dict):
social_link = OrganizationSocialLink.objects.create(
org=org,
order=link_data.get("order"),
link=link_data.get("link"),
label=link_data.get("label"),
)
social_links.append(social_link)

serializer = self.get_serializer(social_links, many=True)

return Response(serializer.data, status=status.HTTP_200_OK)

except Exception as e:
return Response(
{"error": f"Failed to update social links: {str(e)}"},
status=status.HTTP_400_BAD_REQUEST,
)


class OrganizationTextViewSet(viewsets.ModelViewSet[OrganizationText]):
queryset = OrganizationText.objects.all()
serializer_class = OrganizationTextSerializer
Loading