Skip to content

Commit

Permalink
Merge 8fa5527 into 18f36cb
Browse files Browse the repository at this point in the history
  • Loading branch information
njeri-ngigi committed Nov 14, 2018
2 parents 18f36cb + 8fa5527 commit 8eb9412
Show file tree
Hide file tree
Showing 13 changed files with 511 additions and 25 deletions.
27 changes: 27 additions & 0 deletions authors/apps/articles/migrations/0006_highlight.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 2.1.2 on 2018-11-12 08:26

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


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('articles', '0005_comment'),
]

operations = [
migrations.CreateModel(
name='Highlight',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('index_start', models.IntegerField(default=0)),
('index_stop', models.IntegerField()),
('comment', models.CharField(max_length=200)),
('article', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='articles.Article')),
('highlighter', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 2.1.2 on 2018-11-12 09:08

from django.db import migrations, models


class Migration(migrations.Migration):

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

operations = [
migrations.AddField(
model_name='highlight',
name='highlighted_article_piece',
field=models.CharField(blank=True, max_length=200),
),
]
30 changes: 30 additions & 0 deletions authors/apps/articles/migrations/0008_auto_20181112_1055.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Generated by Django 2.1.2 on 2018-11-12 10:55

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


class Migration(migrations.Migration):

dependencies = [
('articles', '0007_highlight_highlighted_article_piece'),
]

operations = [
migrations.AlterField(
model_name='highlight',
name='article',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='highlights', to='articles.Article'),
),
migrations.AlterField(
model_name='highlight',
name='comment',
field=models.CharField(blank=True, max_length=200),
),
migrations.AlterField(
model_name='highlight',
name='highlighter',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='highlights', to=settings.AUTH_USER_MODEL),
),
]
20 changes: 20 additions & 0 deletions authors/apps/articles/migrations/0009_auto_20181112_1057.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Generated by Django 2.1.2 on 2018-11-12 10:57

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


class Migration(migrations.Migration):

dependencies = [
('articles', '0008_auto_20181112_1055'),
]

operations = [
migrations.AlterField(
model_name='article',
name='author',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='articles', to=settings.AUTH_USER_MODEL),
),
]
39 changes: 39 additions & 0 deletions authors/apps/articles/migrations/0010_auto_20181112_2048.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Generated by Django 2.1.2 on 2018-11-12 20:48

from django.db import migrations, models
import django.utils.timezone


class Migration(migrations.Migration):

dependencies = [
('articles', '0009_auto_20181112_1057'),
]

operations = [
migrations.AlterModelOptions(
name='article',
options={'ordering': ('time_updated',)},
),
migrations.AlterModelOptions(
name='highlight',
options={'ordering': ('time_updated',)},
),
migrations.AddField(
model_name='highlight',
name='comment_slug',
field=models.SlugField(default='comment', max_length=40, unique=True),
preserve_default=False,
),
migrations.AddField(
model_name='highlight',
name='time_created',
field=models.DateTimeField(auto_now_add=True, db_index=True, default=django.utils.timezone.now),
preserve_default=False,
),
migrations.AddField(
model_name='highlight',
name='time_updated',
field=models.DateTimeField(auto_now=True, db_index=True),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 2.1.2 on 2018-11-12 21:09

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('articles', '0010_auto_20181112_2048'),
]

operations = [
migrations.RemoveField(
model_name='highlight',
name='comment_slug',
),
]
14 changes: 14 additions & 0 deletions authors/apps/articles/migrations/0012_merge_20181114_1252.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Generated by Django 2.1.2 on 2018-11-14 12:52

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('articles', '0006_commenthistory'),
('articles', '0011_remove_highlight_comment_slug'),
]

operations = [
]
30 changes: 24 additions & 6 deletions authors/apps/articles/models.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
'''articles/models.py'''
from django.db import models
from django.contrib.postgres.fields import ArrayField
from django.utils.text import slugify
from authors.apps.authentication.models import User


class Article(models.Model):
'''Model representing articles'''
title = models.CharField(db_index=True, max_length=255)
Expand All @@ -20,12 +18,12 @@ class Article(models.Model):
time_created = models.DateTimeField(auto_now_add=True, db_index=True)
# auto_now will update every time you save the model.
time_updated = models.DateTimeField(auto_now=True, db_index=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name="articles")
average_rating = models.IntegerField(default=0)

class Meta():
'''Meta class defining order'''
ordering = ('time_created', 'time_updated',)
ordering = ('time_updated',)

def save(self, *args, **kwargs):
'''override save from super'''
Expand All @@ -42,7 +40,7 @@ class Comment(models.Model):
This table has seven fields one is automatically generated by django
The relationship between articles and comments is one to many
The relationship between comment and reply is one to many.
the relationship between Author and comments is one to many
the relationship between Author and comments is one to many
"""
parent = models.ForeignKey(
'self', null=True, blank=False, on_delete=models.CASCADE, related_name='thread')
Expand All @@ -57,7 +55,6 @@ class Comment(models.Model):
def __str__(self):
return self.body


class CommentHistory(models.Model):
"""
implements comment edit history table
Expand All @@ -67,3 +64,24 @@ class CommentHistory(models.Model):
on_delete=models.CASCADE,
db_column='parent_comment')
date_created = models.DateTimeField(auto_now=True)
class Highlight(models.Model):
"""
Table representing highlights and comments made on articles
"""
article = models.ForeignKey(Article, on_delete=models.CASCADE,
related_name="highlights")
highlighter = models.ForeignKey(User, on_delete=models.CASCADE,
related_name="highlights")
index_start = models.IntegerField(default=0)
index_stop = models.IntegerField()
highlighted_article_piece = models.CharField(blank=True, max_length=200)
comment = models.CharField(blank=True, max_length=200)
time_created = models.DateTimeField(auto_now_add=True, db_index=True)
time_updated = models.DateTimeField(auto_now=True, db_index=True)

class Meta():
'''Meta class defining order'''
ordering = ('time_updated',)

def __str__(self):
return self.comment
48 changes: 45 additions & 3 deletions authors/apps/articles/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@
from authors.apps.authentication.models import User
from authors.apps.profiles.serializers import ProfileSerializer
from authors.apps.profiles.models import Profile
# django.forms.fields.ImageField

from .models import Article, Comment, CommentHistory
from .models import Article, Comment, CommentHistory, Highlight
from ..rating.models import Rating


Expand Down Expand Up @@ -161,9 +160,52 @@ def create(self, valid_input):
instance = Comment.objects.create(parent=parent, **valid_input)
return instance


class CommentHistorySerializer(serializers.ModelSerializer):
"""comment history serializer"""
class Meta:
model = CommentHistory
fields = ('id', 'comment', 'date_created', 'parent_comment')

class HighlightSerializer(serializers.ModelSerializer):
'''Highlight model serializer'''
article = ArticleSerializer(read_only=True)
highlighter = UserSerializer(read_only=True)
index_start = serializers.IntegerField()
index_stop = serializers.IntegerField()
highlighted_article_piece = serializers.CharField(
required=False, max_length=200)
comment = serializers.CharField(required=False, max_length=200)

class Meta:
model = Highlight
fields = ('article', 'highlighter', 'index_start',
'index_stop', 'highlighted_article_piece', 'comment')

def create(self, validated_data):
'''method creating a new highlight'''
validated_data["highlighter"] = self.context.get('highlighter')
validated_data["article"] = self.context.get('article')
highlight_text = validated_data["article"].body[
validated_data["index_start"]:validated_data["index_stop"]]
if not highlight_text:
raise serializers.ValidationError("Text doesn't exist on this article")
validated_data["highlighted_article_piece"] = highlight_text

return Highlight.objects.create(**validated_data)

def update(self, instance, validated_data):
'''method updating highlights'''
user = self.context.get('user')
if user != instance.highlighter:
raise PermissionDenied
index_start = validated_data.get('index_start', instance.index_start)
index_stop = validated_data.get('index_stop', instance.index_stop)
highlight_text = instance.article.body[index_start:index_stop]
if not highlight_text:
raise serializers.ValidationError("Text doesn't exist on this article")
instance.comment = validated_data.get('comment', instance.comment)
instance.index_start = index_start
instance.index_stop = index_stop
instance.highlighted_article_piece = highlight_text
instance.save()
return instance
31 changes: 28 additions & 3 deletions authors/apps/articles/tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class BaseTest(TestCase):

def setUp(self):
"""Define the test client"""
# define constant urls used throughout tests
self.SIGN_IN_URL = '/api/users/login/'
self.SIGN_UP_URL = '/api/users/'
self.ARTICLES = '/api/articles/'
Expand All @@ -26,16 +27,25 @@ def setUp(self):
self.UPDATE_A_COMMENT = '/api/articles/{}/comment/{}/'
self.DELETE_A_COMMENT = '/api/articles/{}/comment/{}/'

self.HIGHLIGHT = '/api/articles/test-title/highlight/'
self.HIGHLIGHT_2 = '/api/articles/test-title1/highlight/'
self.HIGHLIGHT_ID = '/api/articles/test-title/highlight/{}/'
self.HIGHLIGHT_ID_2 = '/api/articles/test-title1/highlight/{}/'

# define test client
self.client = APIClient()

# define user data for signup
test_user = {
"email": "njery.ngigi@gmail.com",
"username": "test_user",
"password": "test1234"}
"password": "test1234"
}

test_non_author_user = {
"email": "njeringigi59@gmail.com",
"username": "non_user",
"password": "test1234"

}

self.fav_test_user = {
Expand All @@ -44,14 +54,28 @@ def setUp(self):
"password": "test1234"
}

# define article data for create an article
self.test_article_data = {
"title": "test title",
"body": "This is me testing",
"body": "This is me testing. This line should be long enough to pass as a story.",
"description": "testing",
"time_to_read": 1,
"tags": ["TDD"]
}

# define highlight data
self.highlight_data = {
"index_start": 1,
"index_stop": 10,
"comment": "goodie"
}
self.out_of_index_highlight_data = {
"index_start": 100,
"index_stop": 200,
"comment": "goodie"
}

# signup and login 2 test users (author and non-article-author) to obtain 2 tokens for tesing
self.client.post(self.SIGN_UP_URL, test_user, format="json")
response = self.client.post(self.SIGN_IN_URL, test_user, format="json")
self.token = "bearer " + json.loads(response.content)["user"]["token"]
Expand All @@ -62,6 +86,7 @@ def setUp(self):
self.non_user_token = "bearer " + \
json.loads(response.content)["user"]["token"]

# create 2 articles
self.client.post(self.ARTICLES, self.test_article_data,
HTTP_AUTHORIZATION=self.token, format="json")
self.client.post(self.ARTICLES, self.test_article_data,
Expand Down
Loading

0 comments on commit 8eb9412

Please sign in to comment.