Skip to content

Commit

Permalink
feed
Browse files Browse the repository at this point in the history
  • Loading branch information
Nazarii committed Jan 1, 2024
1 parent 27aceb8 commit 0843c49
Show file tree
Hide file tree
Showing 14 changed files with 171 additions and 7 deletions.
5 changes: 5 additions & 0 deletions web/actions/choices.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,8 @@ class UserActionsChoice(IntegerChoices):
LIKED_ARTICLE = (3, _('User {user} liked article {article}'))
DISLIKED_ARTICLE = (4, _('User {user} disliked article {article}'))
LIKED_COMMENT = (5, _('User {user} liked comment {comment} from user {comment_owner}'))


class ActionFeed(TextChoices):
UPDATE_AVATAR = 'update_avatar'
CREATE_ARTICLE = 'create_article'
17 changes: 17 additions & 0 deletions web/actions/migrations/0002_alter_action_action.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 4.2.8 on 2024-01-01 15:56

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
('actions', '0001_initial'),
]

operations = [
migrations.AlterField(
model_name='action',
name='action',
field=models.CharField(choices=[('update_avatar', 'Update Avatar')], max_length=50),
),
]
4 changes: 2 additions & 2 deletions web/actions/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from django.contrib.contenttypes.models import ContentType
from django.db import models

from .choices import LikeStatus
from .choices import ActionFeed, LikeStatus
from .managers import FollowerManager, LikeDislikeManager

User = get_user_model()
Expand Down Expand Up @@ -49,7 +49,7 @@ def action_content_limit():

class Action(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='actions')
action = models.CharField(max_length=500)
action = models.CharField(max_length=50, choices=ActionFeed.choices)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, limit_choices_to=action_content_limit)
object_id = models.PositiveIntegerField(db_index=True)
content_object = GenericForeignKey()
Expand Down
8 changes: 8 additions & 0 deletions web/actions/static/actions/css/actionFeed.css
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,11 @@
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);
background-color: #555;
}


.center-image {
display: block;
margin-left: auto;
margin-right: auto;
width: 50%;
}
63 changes: 63 additions & 0 deletions web/actions/static/actions/js/actionFeed.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,66 @@
$(function () {
feedList();
});

function feedList() {
$.ajax({
url: '/api/v1/actions/feed',
type: 'get',
success: feedListHandler,
error: function (data) {
console.log('error', data)
}
})
}


function feedListHandler(data) {
const feedList = $('#feedList')
const template = data.results.map((feed) => feedTemplate(feed)).join('<hr>');
feedList.append(template);
}

function feedTemplate(feed) {
switch (feed.action) {
case 'update_avatar':
return updateAvatarTemplate(feed);
case 'create_article':
return updateAvatarTemplate(feed);
}
}

function updateAvatarTemplate(feed) {
return `
<div class="panel panel-default">
<div class="panel-heading">
User <a href="/user/${feed.user.id}/">${feed.user.full_name}</a> changed avatar
</div>
<div class="panel-image">
<img
src="${feed.user.avatar}"
class="img-circle img-responsive center-image"
/>
</div>
${feedPanel()}
</div>
`
}


function feedPanel() {
return `
<div class="panel-footer clearfix">
<a href="#download" class="btn btn-primary btn-sm btn-hover pull-left">Save <span class="fa fa-bookmark"></span></a>
<a href="#facebook" class="btn btn-success btn-sm btn-hover pull-left" style="margin-left: 5px;">Share <span
class="glyphicon glyphicon-send"></span></a>
<a class="btn comsys btn-danger btn-sm btn-hover pull-left" style="margin-left: 5px;">Cmt <span
class="fa fa-comment"></span></a>
<a href="#like" class="btn btn-warning btn-sm btn-hover pull-left" style="margin-left: 5px;">Like <span
class="fa fa-thumbs-up"></span></a>
</div>
`
}

$('.toggler').click(function() {
var tog = $(this);
var secondDiv = tog.parent().prev();
Expand Down
14 changes: 14 additions & 0 deletions web/actions/templates/actions/base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{% extends "base.html" %}
{% load static %}
{% block header %}
{% include 'includes/header.html' with selected='feed' %}
{% endblock header %}

{% block head %}
<link href="{% static 'actions/css/actionFeed.css' %}" rel="stylesheet">
{% endblock head %}

{% block container %}

{% endblock container %}

12 changes: 12 additions & 0 deletions web/actions/templates/actions/feed.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{% extends "actions/base.html" %}
{% load static main %}

{% block container %}
<div class="row form-group">
<div class="col-xs-12 col-md-offset-2 col-lg-offset-2 col-md-8 col-lg-8" id="feedList"></div>
</div>
{% endblock container %}

{% block jquery %}
$.getScript('{% static 'actions/js/actionFeed.js' %}');
{% endblock %}
2 changes: 2 additions & 0 deletions web/actions/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
from rest_framework.routers import DefaultRouter

from . import views
from main.views import TemplateAPIView

app_name = 'actions'

router = DefaultRouter()

urlpatterns = [
path('feed', TemplateAPIView.as_view(template_name='actions/feed.html'), name='feed'),
path('actions/', views.ActionListView.as_view(), name='action_list'),
]

Expand Down
23 changes: 22 additions & 1 deletion web/api/v1/actions/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from rest_framework import serializers

from actions.choices import FollowStatus, LikeObjChoice, LikeStatus
from actions.models import Action
from api.v1.actions.services import FollowService

if TYPE_CHECKING:
Expand Down Expand Up @@ -35,8 +36,28 @@ def get_follow_status(self, obj) -> Optional[FollowStatus]:
if user == obj:
return None
is_follow = FollowService(user=user, user_id=obj.id).is_user_subscribed()
return FollowStatus.UNFOLLOW if is_follow else FollowStatus.FOLLOW
return FollowStatus.UNFOLLOW.value if is_follow else FollowStatus.FOLLOW.value

class Meta:
model = User
fields = ('id', 'full_name', 'avatar', 'profile_url', 'follow')


class UserFeedSerializer(serializers.ModelSerializer):
avatar = serializers.URLField(source='avatar_url')

class Meta:
model = User
fields = (
'id',
'full_name',
'avatar',
)


class FeedListSerializer(serializers.ModelSerializer):
user = UserFeedSerializer()

class Meta:
model = Action
fields = ('id', 'user', 'action', 'date')
14 changes: 12 additions & 2 deletions web/api/v1/actions/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
from django.utils.translation import gettext_lazy as _
from rest_framework.exceptions import NotFound

from actions.choices import FollowStatus, LikeIconStatus, LikeObjChoice, LikeStatus
from actions.models import Follower, LikeDislike
from actions.choices import ActionFeed, FollowStatus, LikeIconStatus, LikeObjChoice, LikeStatus
from actions.models import Action, Follower, LikeDislike
from blog.models import Article, Comment

from main.decorators import except_shell
Expand Down Expand Up @@ -121,3 +121,13 @@ def get_user_followers(self, user: User) -> QuerySet[User]:

def get_user_following(self, user: User) -> QuerySet[User]:
return user.following.all()


class ActivityService:
def __init__(self, action: ActionFeed, user: User, content_object):
self.action = action
self.user = user
self.content_object = content_object

def create_activity(self) -> Action:
return Action.objects.create(user=self.user, action=self.action, content_object=self.content_object)
1 change: 1 addition & 0 deletions web/api/v1/actions/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@
views.UserFollowersView.as_view({'get': 'user_following_by_id'}),
name='following_by_user_id',
),
path('feed', views.FeedView.as_view(), name='feed'),
]
11 changes: 10 additions & 1 deletion web/api/v1/actions/views.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from rest_framework import status
from rest_framework.generics import GenericAPIView
from rest_framework.generics import GenericAPIView, ListAPIView
from rest_framework.mixins import ListModelMixin
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet

from actions.models import Action

from . import serializers
from .services import FollowersQueryService, FollowService, LikeService
from main.pagination import BasePageNumberPagination
Expand Down Expand Up @@ -68,3 +70,10 @@ def user_followers_by_id(self, request, user_id: int):

def user_following_by_id(self, request, user_id: int):
return self.list(request)


class FeedView(ListAPIView):
serializer_class = serializers.FeedListSerializer

def get_queryset(self):
return Action.objects.filter(user=self.request.user)
1 change: 0 additions & 1 deletion web/api/v1/profile/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers


User = get_user_model()


Expand Down
3 changes: 3 additions & 0 deletions web/templates/includes/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
<li {% if selected == 'profile' %}class="active"{% endif %}>
<a href="{% url 'user_profile:profile' %}"></i> Profile</a>
</li>
<li {% if selected == 'feed' %}class="active"{% endif %}>
<a href="{% url 'actions:feed' %}"></i> Feed</a>
</li>
{% endif %}
</ul>
{% include 'includes/header_sign_status.html' %}
Expand Down

0 comments on commit 0843c49

Please sign in to comment.