Skip to content

Commit

Permalink
Merge pull request #486 from pennlabs/pcp-schedule-sharing-frontend
Browse files Browse the repository at this point in the history
PCP - schedule sharing, friends, state changes
  • Loading branch information
andyjiang3 authored Oct 19, 2023
2 parents 6d26375 + 8a1f409 commit 64508b7
Show file tree
Hide file tree
Showing 52 changed files with 3,439 additions and 1,312 deletions.
1 change: 1 addition & 0 deletions backend/Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,3 +193,10 @@ If you don't want to use docker alone, you can also set up and run the dev envir
7. Running tests
- Run `python manage.py test` to run our test suite.
- To run a specific test, you can use the format `python manage.py test tests.review.test_api.OneReviewTestCase.test_course` (also note that in this example, you can use any prefix of that path to run a larger set of tests).

## Linting
```
pipenv run black -l100 .
pipenv run isort .
pipenv run flake8 .
```
20 changes: 20 additions & 0 deletions backend/courses/migrations/0054_alter_ngssrestriction_inclusive.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Generated by Django 4.1.1 on 2023-02-03 21:48

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("courses", "0053_alter_ngssrestriction_code"),
]

operations = [
migrations.AlterField(
model_name="ngssrestriction",
name="inclusive",
field=models.BooleanField(
help_text='\nWhether this is an include or exclude restriction. Corresponds to the `incl_excl_ind`\nresponse field. `True` if include (ie, `incl_excl_ind` is "I") and `False`\nif exclude ("E").\n'
),
),
]
51 changes: 51 additions & 0 deletions backend/courses/migrations/0054_friendship.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Generated by Django 4.0.5 on 2022-08-14 04:31

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("courses", "0053_alter_ngssrestriction_code"),
]

operations = [
migrations.CreateModel(
name="Friendship",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
(
"status",
models.IntegerField(
help_text="\nWhether the request was sent or accepted (0 if sent, \n1 if recieved and accepted, deleted if rejected)\n"
),
),
("accepted_at", models.DateTimeField(auto_now_add=True)),
("sent_at", models.DateTimeField()),
(
"requestReciever",
models.ForeignKey(
help_text="The person (user) who recieved the request.",
on_delete=django.db.models.deletion.CASCADE,
related_name="receiver",
to="courses.userprofile",
),
),
(
"requestSender",
models.ForeignKey(
help_text="The person (user) who sent the request.",
on_delete=django.db.models.deletion.CASCADE,
related_name="sender",
to="courses.userprofile",
),
),
],
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Generated by Django 4.0.5 on 2022-10-31 20:37

import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("courses", "0054_friendship"),
]

operations = [
migrations.AddField(
model_name="friendship",
name="recipient",
field=models.ForeignKey(
default=None,
help_text="The person (user) who recieved the request.",
on_delete=django.db.models.deletion.CASCADE,
related_name="received_friendships",
to=settings.AUTH_USER_MODEL,
),
preserve_default=False,
),
migrations.AddField(
model_name="friendship",
name="sender",
field=models.ForeignKey(
default=None,
help_text="The person (user) who sent the request.",
on_delete=django.db.models.deletion.CASCADE,
related_name="sent_friendships",
to=settings.AUTH_USER_MODEL,
),
preserve_default=False,
),
migrations.AlterField(
model_name="friendship",
name="accepted_at",
field=models.DateTimeField(),
),
migrations.AlterField(
model_name="friendship",
name="status",
field=models.CharField(
choices=[("S", "Sent"), ("A", "Accepted"), ("R", "Rejected")],
default="S",
max_length=1,
),
),
migrations.AlterUniqueTogether(
name="friendship",
unique_together={("sender", "recipient")},
),
migrations.RemoveField(
model_name="friendship",
name="requestReciever",
),
migrations.RemoveField(
model_name="friendship",
name="requestSender",
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Generated by Django 4.0.5 on 2022-11-04 21:02

import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("courses", "0055_friendship_recipient_friendship_sender_and_more"),
]

operations = [
migrations.AlterField(
model_name="friendship",
name="accepted_at",
field=models.DateTimeField(null=True),
),
migrations.AlterField(
model_name="friendship",
name="recipient",
field=models.ForeignKey(
help_text="The person (user) who recieved the request.",
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="received_friendships",
to=settings.AUTH_USER_MODEL,
),
),
migrations.AlterField(
model_name="friendship",
name="sender",
field=models.ForeignKey(
help_text="The person (user) who sent the request.",
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="sent_friendships",
to=settings.AUTH_USER_MODEL,
),
),
migrations.AlterField(
model_name="friendship",
name="sent_at",
field=models.DateTimeField(null=True),
),
]
20 changes: 20 additions & 0 deletions backend/courses/migrations/0057_alter_ngssrestriction_inclusive.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Generated by Django 4.0.5 on 2023-01-22 18:09

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("courses", "0056_alter_friendship_accepted_at_and_more"),
]

operations = [
migrations.AlterField(
model_name="ngssrestriction",
name="inclusive",
field=models.BooleanField(
help_text='\nWhether this is an include or exclude restriction. Corresponds to the `incl_excl_ind`\nresponse field. `True` if include (ie, `incl_excl_ind` is "I") and `False`\nif exclude ("E").\n'
),
),
]
13 changes: 13 additions & 0 deletions backend/courses/migrations/0058_merge_20230403_2310.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Generated by Django 3.2.18 on 2023-04-04 03:10

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("courses", "0054_alter_ngssrestriction_inclusive"),
("courses", "0057_alter_ngssrestriction_inclusive"),
]

operations = []
13 changes: 13 additions & 0 deletions backend/courses/migrations/0058_merge_20230712_1350.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Generated by Django 3.2.18 on 2023-07-12 17:50

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("courses", "0054_userprofile_uuid_secret_and_more"),
("courses", "0057_alter_ngssrestriction_inclusive"),
]

operations = []
13 changes: 13 additions & 0 deletions backend/courses/migrations/0059_merge_20230816_2208.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Generated by Django 3.2.18 on 2023-08-17 02:08

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("courses", "0058_merge_20230403_2310"),
("courses", "0058_merge_20230712_1350"),
]

operations = []
63 changes: 63 additions & 0 deletions backend/courses/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1424,3 +1424,66 @@ def create_or_update_user_profile(sender, instance, created, **kwargs):
if created and instance.email != "":
instance.profile.email = instance.email
instance.profile.save()


class Friendship(models.Model):
"""
Used to track friendships along with requests status
"""

sender = models.ForeignKey(
get_user_model(),
on_delete=models.CASCADE,
null=True,
related_name="sent_friendships",
help_text="The person (user) who sent the request.",
)

recipient = models.ForeignKey(
get_user_model(),
related_name="received_friendships",
on_delete=models.CASCADE,
null=True,
help_text="The person (user) who recieved the request.",
)

class Status(models.TextChoices):
SENT = "S", "Sent"
ACCEPTED = "A", "Accepted"
REJECTED = "R", "Rejected"

status = models.CharField(
max_length=1,
choices=Status.choices,
default=Status.SENT,
)

def are_friends(self, user1_id, user2_id):
"""
Checks if two users are friends (lookup by user id)
"""
return Friendship.objects.filter(
Q(sender_id=user1_id, recipient_id=user2_id, status=Friendship.Status.ACCEPTED)
| Q(sender_id=user2_id, recipient_id=user1_id, status=Friendship.Status.ACCEPTED)
).exists()

def save(self, *args, **kwargs):
if self.status == self.Status.ACCEPTED and self.accepted_at is None:
self.accepted_at = timezone.now()
if self.status == self.Status.REJECTED:
self.accepted_at = None
self.sent_at = None
if self.status == self.Status.SENT and self.sent_at is None:
self.sent_at = timezone.now()
super().save(*args, **kwargs)

accepted_at = models.DateTimeField(null=True)
sent_at = models.DateTimeField(null=True)

class Meta:
unique_together = (("sender", "recipient"),)

def __str__(self):
return (
f"Friendship(Sender: {self.sender}, Recipient: {self.recipient}, Status: {self.status})"
)
33 changes: 33 additions & 0 deletions backend/courses/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from courses.models import (
Attribute,
Course,
Friendship,
Instructor,
Meeting,
NGSSRestriction,
Expand Down Expand Up @@ -415,6 +416,13 @@ class Meta:
read_only_fields = ["username"]


class PublicUserSerializer(serializers.ModelSerializer):
class Meta:
model = get_user_model()
fields = ["username", "first_name", "last_name"]
read_only_fields = ["username"]


class StatusUpdateSerializer(serializers.ModelSerializer):
section = serializers.ReadOnlyField(
source="section__full_code",
Expand All @@ -432,3 +440,28 @@ class Meta:
model = StatusUpdate
fields = ["section", "old_status", "new_status", "created_at", "alert_sent"]
read_only_fields = fields


class FriendshipSerializer(serializers.ModelSerializer):
class Meta:
model = Friendship
fields = ["sender", "recipient", "status", "sent_at", "accepted_at"]

sender = PublicUserSerializer(
read_only=True,
help_text="The user that is sending the request.",
required=False,
)
recipient = PublicUserSerializer(
read_only=True,
help_text="The user that is recieving the request.",
required=False,
)


class FriendshipRequestSerializer(serializers.Serializer):
friend_id = serializers.IntegerField()

def to_representation(self, instance):
print("in representation function")
return super().to_representation(instance)
1 change: 1 addition & 0 deletions backend/courses/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@
name="restrictions-list",
),
path("statusupdate/<slug:full_code>/", views.StatusUpdateView.as_view(), name="statusupdate"),
path("friendship/", views.FriendshipView.as_view(), name="friendship"),
]
Loading

0 comments on commit 64508b7

Please sign in to comment.