Skip to content

Commit

Permalink
feat(shares): implement share articles via email and social platforms
Browse files Browse the repository at this point in the history
- add share article via email
- add share article facebook and twitter
- add tests on share articles

[Starts #162949230]
  • Loading branch information
sylviawanjiku committed Feb 5, 2019
1 parent bc04c1a commit 2d2be77
Show file tree
Hide file tree
Showing 7 changed files with 426 additions and 35 deletions.
22 changes: 22 additions & 0 deletions authors/apps/articles/migrations/0007_auto_20190204_1801.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Generated by Django 2.1.4 on 2019-02-04 18:01

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('articles', '0006_merge_20190203_1152'),
]

operations = [
migrations.AlterModelOptions(
name='comments',
options={},
),
migrations.RenameField(
model_name='article',
old_name='tagList',
new_name='tag_list',
),
]
2 changes: 1 addition & 1 deletion authors/apps/articles/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class Meta:
model = Article

fields = ['slug', 'title', 'description', 'body',
'tag_list', 'created_at','updated_at',
'tag_list', 'created_at', 'updated_at',
'author', 'rating']


Expand Down
205 changes: 205 additions & 0 deletions authors/apps/articles/templates/share_article.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Password Reset</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type="text/css">
/**
* Google webfonts. Recommended to include the .woff version for cross-client compatibility.
*/
@media screen {
@font-face {
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 400;
src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'),
url(https://fonts.gstatic.com/s/sourcesanspro/v10/ODelI1aHBYDBqgeIAH2zlBM0YzuT7MdOe03otPbuUS0.woff) format('woff');
}
@font-face {
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 700;
src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'),
url(https://fonts.gstatic.com/s/sourcesanspro/v10/toadOcfmlt9b38dHJxOBGFkQc6VGVFSmCnC_l7QZG60.woff) format('woff');
}
}
/**
* Avoid browser level font resizing.
* 1. Windows Mobile
* 2. iOS / OSX
*/
body,
table,
td,
a {
-ms-text-size-adjust: 100%; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/**
* Remove extra space added to tables and cells in Outlook.
*/
table,
td {
mso-table-rspace: 0pt;
mso-table-lspace: 0pt;
}
/**
* Better fluid images in Internet Explorer.
*/
img {
-ms-interpolation-mode: bicubic;
}
/**
* Remove blue links for iOS devices.
*/
a[x-apple-data-detectors] {
font-family: inherit !important;
font-size: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
color: inherit !important;
text-decoration: none !important;
}
/**
* Fix centering issues in Android 4.4.
*/
div[style*="margin: 16px 0;"] {
margin: 0 !important;
}
body {
width: 100% !important;
height: 100% !important;
padding: 0 !important;
margin: 0 !important;
}
/**
* Collapse table borders to avoid space between cells.
*/
table {
border-collapse: collapse !important;
}
a {
color: #1a82e2;
}
img {
height: auto;
line-height: 100%;
text-decoration: none;
border: 0;
outline: none;
}
</style>
</head>
<body style="background-color: #e9ecef;">
<!-- start preheader -->
<div class="preheader" style="display: none; max-width: 0; max-height: 0; overflow: hidden;
font-size: 1px; line-height: 1px; color: #fff; opacity: 0;">
A preheader is the short summary text that follows the subject line when an email is viewed
in the inbox.
</div>
<!-- end preheader -->
<!-- start body -->
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<!-- start logo -->
<tr>
<td align="center" bgcolor="#e9ecef">
<!--[if (gte mso 9)|(IE)]>
<table align="center" border="0" cellpadding="0" cellspacing="0" width="600">
<tr>
<td align="center" valign="top" width="600">
<![endif]-->
<!--[if (gte mso 9)|(IE)]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
<!-- end logo -->
<!-- start hero -->
<tr>
<td align="center" bgcolor="#e9ecef">
<!--[if (gte mso 9)|(IE)]>
<table align="center" border="0" cellpadding="0" cellspacing="0" width="600">
<tr>
<td align="center" valign="top" width="600">
<![endif]-->
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;">
<tr>
<td align="left" bgcolor="#ffffff" style="padding: 36px 24px 0;
font-family: 'Source Sans Pro',Helvetica, Arial, sans-serif;
border-top: 3px solid #d4dadf;">
<h1 style="margin: 0; font-size: 28px; font-weight: 700;
letter-spacing: -1px; line-height: 48px;">
<center>Author's Haven</center></h1>
</td>
</tr>
</table>
<!--[if (gte mso 9)|(IE)]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
<!-- end hero -->
<!-- start copy block -->
<tr>
<td align="center" bgcolor="#e9ecef">
<!--[if (gte mso 9)|(IE)]>
<table align="center" border="0" cellpadding="0" cellspacing="0" width="600">
<tr>
<td align="center" valign="top" width="600">
<![endif]-->
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;">
<!-- start copy -->
<tr>
<td align="left" bgcolor="#ffffff" style="padding: 24px; font-family: 'Source Sans Pro',
Helvetica, Arial, sans-serif; font-size: 16px; line-height: 24px;">
<p style="margin: 0;">Hello,</b></p>
<p style="margin: 0;">{{username}} has shared an article,</b>
<a href="{{link}}" target="_blank">{{title}}</a></p>
<div style="padding:25px","background-color: lightblue"><div><p><b>{{title}}</b></p><p>
<img style="width:50px;height:50px;" src="{{author_image}}" alt="Author's image">
<i style="font-size:12px"> by:{{author}}</i></p>
<p>{{body}}...<a href="{{link}}" target="_blank">Read more</a></p></p></div></div>
</td>
</tr>
<tr>
<td align="center" bgcolor="#ffffff" style="padding: 24px;
font-family: 'Source Sans Pro',Helvetica, Arial, sans-serif;
font-size: 16px; line-height: 24px; border-bottom: 3px solid #d4dadf">
<p style="margin: 0;">Cheers,<br> The Author's Haven Team.</p>
</td>
</tr>
<!-- end copy -->
</table>
<!--[if (gte mso 9)|(IE)]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
<!-- end copy block -->
<!-- start footer -->
<tr>
<td align="center" bgcolor="#e9ecef" style="padding: 24px;">
<!--[if (gte mso 9)|(IE)]>
<table align="center" border="0" cellpadding="0" cellspacing="0" width="600">
<tr>
<td align="center" valign="top" width="600">
<![endif]-->
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
<!-- end footer -->
</table>
<!-- end body -->
</body>
</html>
18 changes: 17 additions & 1 deletion authors/apps/articles/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,14 @@
from authors.apps.articles.views.articles import (GetUpdateDeleteArticle,
CreateArticleView,
SearchFilter,
LikeDislikeArticleView)
LikeDislikeArticleView,
ShareArticleViaEmail,
ShareArticleViaFacebook,
ShareArticleViaTwitter
)
from authors.apps.articles.views.favorite import (FavouriteArticle,
GetFavouriteArticles
)


"""
Expand Down Expand Up @@ -44,4 +51,13 @@
path('/<slug>/comments/<comment_id>/history',
CommentHistoryListView.as_view(),
name='comment-history'),
path('/<slug>/email/share',
ShareArticleViaEmail.as_view(), name='email_share'
),
path('/<slug>/facebook/share',
ShareArticleViaFacebook.as_view(), name='facebook_share'
),
path('/<slug>/twitter/share',
ShareArticleViaTwitter.as_view(), name='twitter_share'
)
]
89 changes: 83 additions & 6 deletions authors/apps/articles/views/articles.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import re
import os
from urllib.parse import quote
from rest_framework.generics import (
RetrieveUpdateDestroyAPIView, ListCreateAPIView,
ListAPIView,
ListAPIView,CreateAPIView
)
from rest_framework.permissions import (
IsAuthenticatedOrReadOnly, IsAuthenticated
Expand All @@ -19,17 +21,22 @@
from authors.apps.articles.models import Article, LikeDislike
from authors.apps.articles.serializers import (
ArticleSerializer, UpdateArticleSerializer,
LikeDislikeSerializer, CustomTagSerializer,
UpdateArticleSerializer,
)
LikeDislikeSerializer, CustomTagSerializer
)
from authors.apps.authentication.serializers import EmailCheckSerializer
from authors.apps.articles.renderers import (
ArticleJSONRenderer,
LikeArticleJSONRenderer,
TagJSONRenderer
)
)
from authors.apps.articles.response_messages import (error_messages,
success_messages)
from authors.apps.core.pagination import CustomPagination
from django.core.mail import send_mail
from django.template.loader import render_to_string
from authors.apps.profiles.views import UserProfile
from authors.apps.profiles.serializers import ProfileSerialiazer
base_url = os.getenv('BASE_URL')


class CreateArticleView(ListCreateAPIView):
Expand Down Expand Up @@ -58,7 +65,7 @@ def post(self, request, *args, **kwargs):


class GetUpdateDeleteArticle(RetrieveUpdateDestroyAPIView):
permission_classes = (IsAuthenticated,)
permission_classes = (IsAuthenticatedOrReadOnly,)
renderer_classes = (ArticleJSONRenderer,)
queryset = Article.objects.all()
serializer_class = ArticleSerializer
Expand Down Expand Up @@ -254,3 +261,73 @@ def get_filterset_kwargs(self, request):
'data': request.query_params
}
return kwargs


class ShareArticleViaEmail(CreateAPIView):
permission_classes = (IsAuthenticated,)
serializer_class = EmailCheckSerializer

def post(self, request, *args, **kwargs):
try:
article = Article.objects.get(slug=kwargs['slug'])
except Article.DoesNotExist:
return Response(error_messages['article_404'],
status=status.HTTP_404_NOT_FOUND)
author = UserProfile.objects.get(user__username=request.user.username)
author_data = ProfileSerialiazer(author)
author_image = author_data.data['image']
hosting = request.get_host()
username = request.user.username
email_to = request.data.get('email', {})
article_link = 'https://' + hosting + '/api/articles/'+kwargs['slug']
email_subject = username + ' has shared an article with you:' + article.title
prev_body = article.body[0:300]
message = render_to_string(
'share_article.html', {
'title': article.title,
'username': username,
'link': article_link,
'body': prev_body,
'author': article.author,
'author_image': author_image,
})
send_mail(email_subject, email_subject, '', [email_to, ],
html_message=message,
fail_silently=False)
message = "Article successfully shared"
return Response(message, status.HTTP_200_OK)


class ShareArticleViaFacebook(CreateAPIView):
permission_classes = (IsAuthenticated,)

def post(self, request, *args, **kwargs):
try:
Article.objects.get(slug=kwargs['slug'])
except Article.DoesNotExist:
return Response(error_messages['article_404'],
status=status.HTTP_404_NOT_FOUND)
slug = kwargs['slug']
facebook_url = "https://www.facebook.com/sharer/sharer.php?u="
article_link = "{}api/articles/{}".format(base_url, slug)
url_link = facebook_url + article_link
shared_post_url = {'link': url_link}
return Response(shared_post_url, status.HTTP_200_OK)


class ShareArticleViaTwitter(CreateAPIView):
permission_classes = (IsAuthenticated,)

def post(self, request, *args, **kwargs):
try:
Article.objects.get(slug=kwargs['slug'])
except Article.DoesNotExist:
return Response(error_messages['article_404'],
status=status.HTTP_404_NOT_FOUND)
slug = kwargs['slug']
info = quote('The unsullied have shared ')
twitter_url = "https://twitter.com/home?status="
article_link = "{}{}api/articles/{}".format(info, base_url, slug)
url_link = twitter_url + article_link
shared_post_url = {'link': url_link}
return Response(shared_post_url, status=status.HTTP_200_OK)
Loading

0 comments on commit 2d2be77

Please sign in to comment.