summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshen2019-03-05 11:33:41 +0530
committerAkshen2019-03-05 11:33:41 +0530
commitefda4b675ab162346a72abf0ceee29cfc0f99001 (patch)
tree72b1f971823ecb1aed88ce793c69921f66e4291e
parenteed46efdccfb2821cb07b6a189f439ba6f7bb3f2 (diff)
downloadFOSSEE_animations-efda4b675ab162346a72abf0ceee29cfc0f99001.tar.gz
FOSSEE_animations-efda4b675ab162346a72abf0ceee29cfc0f99001.tar.bz2
FOSSEE_animations-efda4b675ab162346a72abf0ceee29cfc0f99001.zip
Major Update 1
- User can register/login/logout - Contributor can send proposal and comment on it - Reviewer can comment/approve/reject proposals
-rw-r--r--fossee_anime/settings.py8
-rw-r--r--fossee_manim/admin.py18
-rw-r--r--fossee_manim/forms.py83
-rw-r--r--fossee_manim/models.py84
-rw-r--r--fossee_manim/send_mails.py83
-rw-r--r--fossee_manim/templates/fossee_manim/base.html34
-rw-r--r--fossee_manim/templates/fossee_manim/edit_proposal.html97
-rw-r--r--fossee_manim/templates/fossee_manim/proposal_status.html53
-rw-r--r--fossee_manim/templates/fossee_manim/search_results.html13
-rw-r--r--fossee_manim/templates/fossee_manim/send_proposal.html41
-rw-r--r--fossee_manim/templates/password_reset_confirm.html15
-rw-r--r--fossee_manim/urls.py15
-rw-r--r--fossee_manim/views.py142
-rw-r--r--requirements.txt2
14 files changed, 585 insertions, 103 deletions
diff --git a/fossee_anime/settings.py b/fossee_anime/settings.py
index c448124..53b200b 100644
--- a/fossee_anime/settings.py
+++ b/fossee_anime/settings.py
@@ -18,7 +18,8 @@ from local_settings import (
EMAIL_HOST_USER,
EMAIL_HOST_PASSWORD,
EMAIL_USE_TLS,
- SENDER_EMAIL
+ SENDER_EMAIL,
+ SECRET_KEY_SETTINGS
)
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
@@ -29,7 +30,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
-SECRET_KEY = 'axx=vuttrki_26n0l!cx569(h_ze)981u+9_@mw35^^b!l5g)y'
+SECRET_KEY = SECRET_KEY_SETTINGS
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
@@ -47,6 +48,8 @@ INSTALLED_APPS = [
'django.contrib.messages',
'django.contrib.staticfiles',
'fossee_manim',
+ 'taggit',
+ 'simple_history'
]
MIDDLEWARE_CLASSES = [
@@ -58,6 +61,7 @@ MIDDLEWARE_CLASSES = [
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
+ 'simple_history.middleware.HistoryRequestMiddleware',
]
ROOT_URLCONF = 'fossee_anime.urls'
diff --git a/fossee_manim/admin.py b/fossee_manim/admin.py
index f076a3c..35bf57b 100644
--- a/fossee_manim/admin.py
+++ b/fossee_manim/admin.py
@@ -1,16 +1,16 @@
from django.contrib import admin
import csv
from django.http import HttpResponse
-from .models import (
- Profile
- )
+from .models import (Category, Profile, User, Animation, Comment,
+ AnimationStats)
# Register your models here.
try:
- from StringIO import StringIO as string_io
+ from StringIO import StringIO as string_io
except ImportError:
- from io import BytesIO as string_io
+ from io import BytesIO as string_io
-#Custom Classes
+
+# Custom Classes
class ProfileAdmin(admin.ModelAdmin):
list_display = ['title','user', 'institute','location','department',
'phone_number','position']
@@ -41,6 +41,10 @@ class ProfileAdmin(admin.ModelAdmin):
download_csv.short_description = "Download CSV file for selected stats."
+class CategoryAdmin(admin.ModelAdmin):
+ list_display = ['name', 'created', 'description']
+ list_filter = ['name']
-admin.site.register(Profile, ProfileAdmin)
+admin.site.register(Category, CategoryAdmin)
+admin.site.register(Profile, ProfileAdmin) \ No newline at end of file
diff --git a/fossee_manim/forms.py b/fossee_manim/forms.py
index 177e01f..ec7568d 100644
--- a/fossee_manim/forms.py
+++ b/fossee_manim/forms.py
@@ -1,7 +1,8 @@
from django import forms
from django.utils import timezone
from .models import (
- Profile, User
+ Profile, User, Animation,
+ Comment
)
from string import punctuation, digits
try:
@@ -13,7 +14,6 @@ from django.contrib.auth.models import User
from django.contrib.auth import authenticate
from .send_mails import generate_activation_key
-
UNAME_CHARS = letters + "._" + digits
PWD_CHARS = letters + punctuation + digits
@@ -63,8 +63,8 @@ states = (
("IN-AS", "Assam"),
("IN-BR", "Bihar"),
("IN-CT", "Chhattisgarh"),
- ("IN-GA", "Goa"),
- ("IN-GJ", "Gujarat"),
+ ("IN-GA", "Goa"),
+ ("IN-GJ", "Gujarat"),
("IN-HR", "Haryana"),
("IN-HP", "Himachal Pradesh"),
("IN-JK", "Jammu and Kashmir"),
@@ -87,7 +87,7 @@ states = (
("IN-UT", "Uttarakhand"),
("IN-UP", "Uttar Pradesh"),
("IN-WB", "West Bengal"),
- ("IN-AN", "Andaman and Nicobar Islands"),
+ ("IN-AN", "Andaman and Nicobar Islands"),
("IN-CH", "Chandigarh"),
("IN-DN", "Dadra and Nagar Haveli"),
("IN-DD", "Daman and Diu"),
@@ -107,19 +107,22 @@ class UserRegistrationForm(forms.Form):
period and underscore only.''')
email = forms.EmailField()
password = forms.CharField(max_length=32, widget=forms.PasswordInput())
- confirm_password = forms.CharField\
- (max_length=32, widget=forms.PasswordInput())
+ confirm_password = forms.CharField(
+ max_length=32, widget=forms.PasswordInput())
title = forms.ChoiceField(choices=title)
first_name = forms.CharField(max_length=32)
last_name = forms.CharField(max_length=32)
- phone_number = forms.RegexField(regex=r'^.{10}$',
- error_messages={'invalid':"Phone number must be entered \
- in the format: '9999999999'.\
- Up to 10 digits allowed."})
- institute = forms.CharField(max_length=128,
- help_text='Please write full name of your Institute/Organization')
+ phone_number = forms.RegexField(regex=r'^.{10}$',
+ error_messages={'invalid': "Phone number\
+ must be entered \
+ in the format: '9999999999'.\
+ Up to 10 digits allowed."})
+ institute = forms.CharField(max_length=128,
+ help_text='Please write full name of your\
+ Institute/Organization'
+ )
department = forms.ChoiceField(help_text='Department you work/study',
- choices=department_choices)
+ choices=department_choices)
location = forms.CharField(max_length=255, help_text="Place/City")
state = forms.ChoiceField(choices=states)
how_did_you_hear_about_us = forms.ChoiceField(choices=source)
@@ -176,10 +179,11 @@ class UserRegistrationForm(forms.Form):
new_profile.location = cleaned_data["location"]
new_profile.title = cleaned_data["title"]
new_profile.state = cleaned_data["state"]
- new_profile.how_did_you_hear_about_us = cleaned_data["how_did_you_hear_about_us" ]
+ new_profile.how_did_you_hear_about_us = cleaned_data
+ ["how_did_you_hear_about_us"]
new_profile.activation_key = generate_activation_key(new_user.username)
- new_profile.key_expiry_time = timezone.now() + \
- timezone.timedelta(days=1)
+ new_profile.key_expiry_time = timezone.now() + timezone.timedelta(
+ days=1)
new_profile.save()
key = Profile.objects.get(user=new_user).activation_key
return u_name, pwd, key
@@ -189,10 +193,10 @@ class UserLoginForm(forms.Form):
"""Creates a form which will allow the user to log into the system."""
username = forms.CharField(max_length=32,
- widget=forms.TextInput())
+ widget=forms.TextInput())
password = forms.CharField(max_length=32,
- widget=forms.PasswordInput())
+ widget=forms.PasswordInput())
def clean(self):
super(UserLoginForm, self).clean()
@@ -224,4 +228,43 @@ class ProfileForm(forms.ModelForm):
user = kwargs.pop('user')
super(ProfileForm, self).__init__(*args, **kwargs)
self.fields['first_name'].initial = user.first_name
- self.fields['last_name'].initial = user.last_name \ No newline at end of file
+ self.fields['last_name'].initial = user.last_name
+
+
+class AnimationProposal(forms.ModelForm):
+ """Animation form """
+ required_css_class = 'required'
+ errorlist_css_class = 'errorlist'
+
+ def __init__(self, *args, **kwargs):
+ super(AnimationProposal, self).__init__(*args, **kwargs)
+ self.fields['github'].widget.attrs['rows'] = 1
+ self.fields['github'].widget.attrs['cols'] = 50
+ self.fields['github'].widget.attrs['placeholder'] = 'Put your repo\
+ link here'
+ self.fields['description'].widget.attrs['placeholder'] = 'NOTE:-Do\
+ add info about prerequisites if any also possible textbooks or \
+ other related information'
+
+ class Meta:
+ model = Animation
+ fields = ['category', 'title', 'description', 'github', 'tags']
+
+
+class CommentForm(forms.ModelForm):
+ """
+ Instructors will post comments on Coordinators profile
+ """
+
+ def __init__(self, *args, **kwargs):
+ super(CommentForm, self).__init__(*args, **kwargs)
+ self.fields['comment'].label = ""
+ self.fields['comment'].widget.attrs['rows'] = 5
+ self.fields['comment'].widget.attrs['cols'] = 95
+
+ class Meta:
+ model = Comment
+ exclude = ['animation', 'created_date', 'commentor']
+ widgets = {
+ 'comments': forms.CharField(),
+ } \ No newline at end of file
diff --git a/fossee_manim/models.py b/fossee_manim/models.py
index dd3f6b3..77c7552 100644
--- a/fossee_manim/models.py
+++ b/fossee_manim/models.py
@@ -1,12 +1,16 @@
from django.db import models
from django.contrib.auth.models import User
from django.core.validators import RegexValidator
+from taggit.managers import TaggableManager
+from simple_history.models import HistoricalRecords
+from django.utils import timezone
+
position_choices = (
("contributor", "Contributor"),
("reviewer", "Reviewer")
)
-
+
department_choices = (
("computer engineering", "Computer Science"),
("information technology", "Information Technology"),
@@ -79,6 +83,14 @@ states = (
("IN-PY", "Puducherry")
)
+status = (
+ ("pending", "Pending Acceptance"),
+ ("rejected", "Rejected"),
+ ("changes", "Changes Required"),
+ ("released", "Released")
+)
+
+
def has_profile(user):
""" check if user has profile """
return True if hasattr(user, 'profile') else False
@@ -88,23 +100,30 @@ class Profile(models.Model):
"""Profile for users(instructors and coordinators)"""
user = models.OneToOneField(User)
- title = models.CharField(max_length=32,blank=True, choices=title)
- institute = models.CharField(max_length=150)
+ title = models.CharField(max_length=32, blank=True, choices=title)
+ institute = models.CharField(max_length=150, blank=True)
department = models.CharField(max_length=150, choices=department_choices)
phone_number = models.CharField(
max_length=10,
validators=[RegexValidator(
regex=r'^.{10}$', message=(
- "Phone number must be entered \
+ "Phone number must be entered \
in the format: '9999999999'.\
Up to 10 digits allowed.")
- )]
- ,null=False)
+ )], null=False)
position = models.CharField(max_length=32, choices=position_choices,
- default='contributor')
- how_did_you_hear_about_us = models.CharField(max_length=255, blank=True,choices=source)
- location = models.CharField(max_length=255,blank=True, help_text="Place/City")
+ default='contributor')
+ how_did_you_hear_about_us = models.CharField(max_length=255, blank=True,
+ choices=source)
+ location = models.CharField(max_length=255, blank=True,
+ help_text="Place/City")
state = models.CharField(max_length=255, choices=states, default="IN-MH")
+ pincode = models.CharField(max_length=6, blank=True,
+ validators=[RegexValidator(
+ regex=r'^.{6}$', message=(
+ "Please enter valid PINCODE"
+ )
+ )])
is_email_verified = models.BooleanField(default=False)
activation_key = models.CharField(max_length=255, blank=True, null=True)
key_expiry_time = models.DateTimeField(blank=True, null=True)
@@ -116,3 +135,50 @@ class Profile(models.Model):
self.user.last_name,
self.user.email
)
+
+
+class Category(models.Model):
+ name = models.CharField(max_length=255, unique=True)
+ created = models.DateTimeField(default=timezone.now)
+ description = models.TextField()
+
+ def __str__(self):
+ return u"{0}".format(self.name)
+
+
+class Animation(models.Model):
+ title = models.CharField(max_length=255)
+ contributor = models.ForeignKey(User, on_delete=models.CASCADE)
+ reviewer = models.ForeignKey(User, null=True, on_delete=models.CASCADE,
+ related_name="%(app_label)s_%(class)s_related")
+ description = models.TextField()
+ status = models.CharField(max_length=255, choices=status)
+ github = models.TextField()
+ category = models.ForeignKey(Category, on_delete=models.CASCADE)
+ created = models.DateTimeField(default=timezone.now)
+ updated = models.DateTimeField(default=timezone.now)
+ tags = TaggableManager()
+ history = HistoricalRecords()
+
+ def __str__(self):
+ return u"{0} | {1}".format(self.title, self.status)
+
+
+class Comment(models.Model):
+ comment = models.TextField()
+ commentor = models.ForeignKey(User, on_delete=models.CASCADE)
+ animation = models.ForeignKey(Animation, on_delete=models.CASCADE)
+ created_date = models.DateTimeField(default=timezone.now)
+
+ def __str__(self):
+ return u"{1} | {0}".format(
+ self.created_date,
+ self.commentor
+ )
+
+
+class AnimationStats(models.Model):
+ animation = models.ForeignKey(Animation, on_delete=models.CASCADE)
+ views = models.PositiveIntegerField(default=0)
+ like = models.PositiveIntegerField(default=0)
+ dislike = models.PositiveIntegerField(default=0) \ No newline at end of file
diff --git a/fossee_manim/send_mails.py b/fossee_manim/send_mails.py
index b2bf80d..f9f7a75 100644
--- a/fossee_manim/send_mails.py
+++ b/fossee_manim/send_mails.py
@@ -1,5 +1,11 @@
-__author__ = "Akshen Doke"
-
+from django.core.mail import EmailMultiAlternatives
+from django.conf import settings
+from os import listdir, path
+from email.mime.multipart import MIMEMultipart
+from email.mime.text import MIMEText
+from email.mime.base import MIMEBase
+from email import encoders
+from time import sleep
import hashlib
import logging.config
import re
@@ -23,14 +29,7 @@ from fossee_anime.settings import (
SENDER_EMAIL,
ADMIN_EMAIL
)
-from django.core.mail import EmailMultiAlternatives
-from django.conf import settings
-from os import listdir, path
-from email.mime.multipart import MIMEMultipart
-from email.mime.text import MIMEText
-from email.mime.base import MIMEBase
-from email import encoders
-from time import sleep
+__author__ = "Akshen Doke"
def validateEmail(email):
@@ -48,15 +47,13 @@ def generate_activation_key(username):
return hashlib.sha256((secret_key + username).encode('utf-8')).hexdigest()
-
-def send_email(request, call_on,
- user_name=None, other_email=None,
- institute=None, key=None
- ):
+def send_email(request, call_on, contributor=None, key=None, proposal=None):
'''
'''
+
try:
- with open(path.join(settings.LOG_FOLDER, 'emailconfig.yaml'), 'r') as configfile:
+ with open(path.join(settings.LOG_FOLDER,
+ 'emailconfig.yaml'), 'r') as configfile:
config_dict = yaml.load(configfile)
logging.config.dictConfig(config_dict)
except:
@@ -76,12 +73,60 @@ def send_email(request, call_on,
logging.info("New Registration from: %s", request.user.email)
try:
send_mail(
- "User/Contributor Registration at FOSSEE, IIT Bombay", message, SENDER_EMAIL,
- [request.user.email], fail_silently=True
- )
+ "User/Contributor Registration at FOSSEE, IIT Bombay", message,
+ SENDER_EMAIL, [request.user.email], fail_silently=True)
except Exception:
send_smtp_email(request=request,
subject="User/Contributor Registration - FOSSEE, IIT Bombay",
message=message, other_email=request.user.email,
+ )
+ elif call_on == 'released':
+ message = dedent("""\
+ Hey {0},
+
+ Congratulations! your animations has been released on
+ FOSSEE's website.
+ Please start with your honouriam process
+
+ In case of queries, please revert to this
+ email.""".format(contributor.profile.user.username))
+
+ logging.info("Released Animation: %s", request.user.email)
+ send_mail(
+ "Congratulations! Animation Released!", message, SENDER_EMAIL,
+ [contributor.profile.user.email], fail_silently=True
+ )
+ elif call_on == 'rejected':
+ message = dedent("""\
+ Hey {0},
+
+ We are sorry to inform you that your proposal for
+ FOSSEE Animation is rejected.
+ You can work on the feedback given by the reviewer or
+ send us another proposal on a different topic!
+
+ In case of queries, please revert to this
+ email.""".format(contributor.profile.user.username))
+
+ logging.info("Animation Rejected: %s", request.user.email)
+ send_mail(
+ "FOSSEE Animation Status Update", message, SENDER_EMAIL,
+ [contributor.profile.user.email], fail_silently=True
+ )
+ elif call_on == 'changes':
+ message = dedent("""\
+ Hey {0},
+
+ Please check your proposal {1}
+ for comments by our reviewers
+
+ In case of queries, please revert to this
+ email.""".format(contributor.profile.user.username,
+ proposal.title))
+
+ logging.info("Changes Required: %s", request.user.email)
+ send_mail(
+ "FOSSEE Animation Changes required", message, SENDER_EMAIL,
+ [contributor.profile.user.email], fail_silently=True
) \ No newline at end of file
diff --git a/fossee_manim/templates/fossee_manim/base.html b/fossee_manim/templates/fossee_manim/base.html
index 0e86ecc..c9d6242 100644
--- a/fossee_manim/templates/fossee_manim/base.html
+++ b/fossee_manim/templates/fossee_manim/base.html
@@ -9,7 +9,6 @@
</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
- <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.bundle.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
@@ -20,7 +19,8 @@
</head>
<!-- For js/ajax and other related scripts -->
- {% block extra %}
+ {% block extra %}
+
{% endblock %}
<body style="overflow: scroll;">
@@ -33,12 +33,12 @@
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
- <ul class="navbar-nav mr-auto">
-
- <form class="form-inline">
- <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
- <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
- </form>
+ <ul class="navbar-nav mr-auto">
+ <form class="form-inline" method="POST" action="/search/">
+ {% csrf_token %}
+ <input class="form-control mr-sm-2" id="sbox" name="sbox" type="search" placeholder="Search" aria-label="Search">
+ <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
+ </form>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Categories
@@ -59,16 +59,16 @@
</a>
{% if request.user.profile.position == 'contributor' %}
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
- <a class="dropdown-item" href="#">Send Proposal</a>
- <a class="dropdown-item" href="#">Proposal Status</a>
- <a class="dropdown-item" href="{{URL_ROOT}}/view_profile">View Profile</a>
- <a class="dropdown-item" href="{{URL_ROOT}}/logout">Logout</a>
+ <a class="dropdown-item" href="{% url 'send_proposal' %}">Send Proposal</a>
+ <a class="dropdown-item" href="{% url 'proposal_status' %}">Proposal Status</a>
+ <a class="dropdown-item" href="{% url 'view_profile' %}">View Profile</a>
+ <a class="dropdown-item" href="{% url 'logout' %}">Logout</a>
</div>
{% else %}
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
- <a class="dropdown-item" href="#">Proposal Status</a>
- <a class="dropdown-item" href="{{URL_ROOT}}/view_profile">View Profile</a>
- <a class="dropdown-item" href="{{URL_ROOT}}/logout">Logout</a>
+ <a class="dropdown-item" href="{% url 'proposal_status' %}">Proposal Status</a>
+ <a class="dropdown-item" href="{% url 'view_profile' %}">View Profile</a>
+ <a class="dropdown-item" href="{% url 'logout' %}">Logout</a>
</div>
{% endif %}
</li>
@@ -76,10 +76,10 @@
{% else %}
<ul class="navbar-nav ml-auto">
<li class="nav-item">
- <a class="nav-link" href="{{ URL_ROOT}}/register">Register</a>
+ <a class="nav-link" href="{% url 'register' %}">Register</a>
</li>
<li class="nav-item">
- <a class="nav-link" href="{{ URL_ROOT}}/login">Login</a>
+ <a class="nav-link" href="{% url 'login' %}">Login</a>
</li>
</ul>
{% endif %}
diff --git a/fossee_manim/templates/fossee_manim/edit_proposal.html b/fossee_manim/templates/fossee_manim/edit_proposal.html
new file mode 100644
index 0000000..c73071b
--- /dev/null
+++ b/fossee_manim/templates/fossee_manim/edit_proposal.html
@@ -0,0 +1,97 @@
+{% extends 'fossee_manim/base.html' %}
+
+ {% block title %}
+ Edit Proposal
+ {% endblock %}
+
+{% block content %}
+<script type="text/javascript">
+ var url = window.location.href.split('/').pop();
+</script>
+<br>
+<div class="container">
+ <form method="POST" >
+ {% csrf_token %}
+
+ <table class="table table-bordered">
+ {{ proposal_form.as_table }}
+ </table>
+
+ <br>
+ <button class="btn btn-primary pull-right" type="submit">Save</button>
+ </form>
+
+ <br><br>
+ {% if request.user.profile.position == 'reviewer' %}
+ <form method="POST" >
+ {% csrf_token %}
+ <div class="form-group">
+ <div class="row">
+ <button class="btn btn-success pull-left" type="submit" name="release" value="1">Approve</button>
+ <button class="btn btn-danger pull-left" type="submit" name="rejected" value="2" style="margin-left: 3%">Reject</button>
+ </div>
+ </div>
+ </form>
+ {% endif %}
+ <br><br>
+
+ <h2>Comments</h2>
+ <div>
+ <form method="POST">
+ <br>
+ {% csrf_token %}
+ {{ comment_form.as_p }}
+ <button type="submit" class="btn btn-default">Post</button>
+ </form>
+
+ </div>
+ <hr style="background-color: #fff;
+ border-top: 5px double #8c8b8b;">
+ <table>
+ {% for comment in comments %}
+ <tbody>
+ <tr>
+ <td>
+ <h5>{{ comment.commentor.profile.user.get_full_name }} | {{ comment.created_date | date }}</h5>
+ <h6 style="background-color: #ecf0f1; padding:10px;">{{ comment.comment }}</h6>
+ <hr style="border-top: 0.5px solid #8c8b8b;">
+ </td>
+ </tr>
+ </tbody>
+ {% endfor %}
+ </table>
+
+<br><br>
+ </div>
+
+ <!-- Page Navigation -->
+ <div class="container">
+ <div class="Page-Nav" align="center">
+ <nav aria-label="Page navigation">
+ <ul class="pagination pagination-sm">
+ <li class="page-item">
+ {% if comments.has_previous %}
+ <a class="page-link" tabindex="-1"
+ href="?page={{ comments.previous_page_number }}">Previous</a>
+ {% endif %}
+ </li>
+ <li class="page-item">
+ <span class="current">
+ Page {{ comments.number }} of {{ comments.paginator.num_pages }}
+ </span>
+ </li>
+ <li class="page-item">
+ {% if comments.has_next %}
+ <a class="page-link" href="?page={{ comments.next_page_number }}">Next
+ </a>
+ {% endif %}
+ </li>
+ </ul>
+ </nav>
+ </div>
+ <br>
+ </div>
+
+</div>
+
+{% endblock %} \ No newline at end of file
diff --git a/fossee_manim/templates/fossee_manim/proposal_status.html b/fossee_manim/templates/fossee_manim/proposal_status.html
new file mode 100644
index 0000000..b7a62f6
--- /dev/null
+++ b/fossee_manim/templates/fossee_manim/proposal_status.html
@@ -0,0 +1,53 @@
+{% extends 'fossee_manim/base.html' %}
+
+ {% block title %}
+ Proposal Status
+ {% endblock %}
+
+{% block content %}
+ <br>
+ <div class="container" align="center">
+ {% if request.user.profile.position == 'contributor' %}
+ <table class="table table-hover">
+ <thead>
+ <tr>
+ <th>Title</th>
+ <th>Status</th>
+ </tr>
+ </thead>
+ {% for an in anime %}
+ <tbody>
+ <tr>
+ <td>{{ an.title }}</td>
+ <td><span class="badge">{{ an.status }}</span></td>
+ <td><a href="{% url 'edit_proposal' an.id %}"><button type="button" class="btn btn-info">Edit</button></a></td>
+ </tr>
+ </tbody>
+ {% endfor %}
+ </table>
+ {% else %}
+
+ <table class="table table-hover">
+ <thead>
+ <tr>
+ <th>Title</th>
+ <th>Contributor Name</th>
+ <th>Status</th>
+ </tr>
+ </thead>
+ {% for an in anime_list %}
+ <tbody>
+ <tr>
+ <td>{{ an.title }}</td>
+ <td>{{ an.contributor.get_full_name }}</td>
+ <td><span class="badge">{{ an.status }}</span></td>
+ <td><a href="{% url 'edit_proposal' an.id %}"><button type="button" class="btn btn-info">View</button></a></td>
+ </tr>
+ </tbody>
+ {% endfor %}
+ {% endif %}
+
+ </table>
+ </div>
+
+ {% endblock %} \ No newline at end of file
diff --git a/fossee_manim/templates/fossee_manim/search_results.html b/fossee_manim/templates/fossee_manim/search_results.html
new file mode 100644
index 0000000..2e70f78
--- /dev/null
+++ b/fossee_manim/templates/fossee_manim/search_results.html
@@ -0,0 +1,13 @@
+{% extends 'fossee_manim/base.html' %}
+
+ {% block title %}
+ Login
+ {% endblock %}
+
+{% block content %}
+ <br>
+ <div class="container" align="center">
+ {{ args }}
+ </div>
+
+ {% endblock %} \ No newline at end of file
diff --git a/fossee_manim/templates/fossee_manim/send_proposal.html b/fossee_manim/templates/fossee_manim/send_proposal.html
new file mode 100644
index 0000000..bd56ede
--- /dev/null
+++ b/fossee_manim/templates/fossee_manim/send_proposal.html
@@ -0,0 +1,41 @@
+{% extends 'fossee_manim/base.html' %}
+
+ {% block title %}
+ Send Proposals
+ {% endblock %}
+
+ {% block content %}
+ <br>
+ {% if messages %}
+ <ul class="messages">
+ {% for message in messages %}
+ <div class="alert alert-{{ message.tags }}">
+ <li {% if message.tags %} class="{{ message.tags }}"{% endif %}> {{ message }}
+ </li>
+ </div>
+ {% endfor %}
+ </ul>
+ {% endif %}
+ <br>
+
+ <div class="container" align="center">
+ <div class="alert alert-info">
+ Please Note: If you're not serious about the animation then do not send us a proposal,
+ fake/time wasting submissions will result in permanent ban.
+ </div>
+ <br>
+
+ <form method="post">
+ {% csrf_token %}
+ <br/>
+ <table>
+ {{ form.as_table }}
+ </table>
+ <br>
+ <br>
+ <button class="btn btn-success" type="submit">Save</button>
+ </form>
+
+
+ </div>
+ {% endblock %} \ No newline at end of file
diff --git a/fossee_manim/templates/password_reset_confirm.html b/fossee_manim/templates/password_reset_confirm.html
deleted file mode 100644
index 9f5b47a..0000000
--- a/fossee_manim/templates/password_reset_confirm.html
+++ /dev/null
@@ -1,15 +0,0 @@
-{% extends "base.html" %}
-{% block pagetitle %}Reset Password{% endblock %}
-
-{% block content %}
- {% if validlink %}
- <p>Please enter your new password twice so we can verify you typed it in correctly</p>.
- <form method="post">
- {% csrf_token %}
- {{ form.as_p }}
- <button class= "btn" type="submit">Submit</button>
- </form>
- {% else %}
- <p>This reset link is no longer valid!</p>
- {% endif %}
-{% endblock %} \ No newline at end of file
diff --git a/fossee_manim/urls.py b/fossee_manim/urls.py
index abdc74b..7bc7740 100644
--- a/fossee_manim/urls.py
+++ b/fossee_manim/urls.py
@@ -3,11 +3,16 @@ from fossee_manim import views
urlpatterns = [
url(r'^$', views.index, name='index'),
- url(r'^register/$', views.user_register),
+ url(r'^register/$', views.user_register, name='register'),
url(r'^activate_user/(?P<key>.+)$', views.activate_user),
url(r'^activate_user/$', views.activate_user),
- url(r'^login/$', views.user_login),
- url(r'^logout/$', views.user_logout),
- url(r'^view_profile/$', views.view_profile),
- url(r'^edit_profile/$', views.edit_profile)
+ url(r'^login/$', views.user_login, name='login'),
+ url(r'^logout/$', views.user_logout, name='logout'),
+ url(r'^send_proposal/$', views.send_proposal, name='send_proposal'),
+ url(r'^edit_proposal/([1-9][0-9]*)$', views.edit_proposal,
+ name='edit_proposal'),
+ url(r'^proposal_status/$', views.proposal_status, name='proposal_status'),
+ url(r'^search/$', views.search, name='search'),
+ url(r'^view_profile/$', views.view_profile, name='view_profile'),
+ url(r'^edit_profile/$', views.edit_profile, name='edit_profile')
] \ No newline at end of file
diff --git a/fossee_manim/views.py b/fossee_manim/views.py
index 6ba5d68..d9b27b2 100644
--- a/fossee_manim/views.py
+++ b/fossee_manim/views.py
@@ -1,11 +1,12 @@
from django.shortcuts import render
from .forms import (
UserRegistrationForm, UserLoginForm,
- ProfileForm
+ ProfileForm, AnimationProposal,
+ CommentForm
)
from .models import (
- Profile, User,
- has_profile
+ Profile, User, AnimationStats,
+ has_profile, Animation, Comment
)
from datetime import datetime, date
from django.contrib.auth import login, logout, authenticate
@@ -21,13 +22,19 @@ from django.conf import settings
from os import listdir, path, sep
from zipfile import ZipFile
from django.contrib import messages
+from django.db.models import Q
import datetime as dt
+import os
try:
from StringIO import StringIO as string_io
except ImportError:
from io import BytesIO as string_io
+def check_repo(link):
+ return True if 'github.com' in link else False
+
+
def is_email_checked(user):
if hasattr(user, 'profile'):
return True if user.profile.is_email_verified else False
@@ -46,7 +53,7 @@ def index(request):
form = UserLoginForm()
if user.is_authenticated() and is_email_checked(user):
if user.groups.filter(name='reviewer').count() > 0:
- return redirect('/manage/')
+ return redirect('/view_profile/')
return redirect('/view_profile/')
elif request.method == "POST":
form = UserLoginForm(request.POST)
@@ -56,7 +63,7 @@ def index(request):
if is_superuser(user):
return redirect("/admin")
if user.groups.filter(name='reviewer').count() > 0:
- return redirect('/manage/')
+ return redirect('/view_profile/')
return redirect('/view_profile/')
return render(request, "fossee_manim/index.html", {"form": form})
@@ -167,7 +174,6 @@ def user_register(request):
return render(request, "fossee_manim/registration/register.html", {"form": form})
-
@login_required
def view_profile(request):
""" view instructor and coordinator profile """
@@ -196,9 +202,9 @@ def edit_profile(request):
return redirect('/admin')
if is_email_checked(user):
if is_reviewer(user):
- template = 'fossee_manim/manage.html'
+ template = 'fossee_manim/view_profile.html'
else:
- template = 'fossee_manim/booking.html'
+ template = 'fossee_manim/proposal_status.html'
else:
try:
logout(request)
@@ -230,4 +236,122 @@ def edit_profile(request):
return render(request, 'fossee_manim/edit_profile.html', context)
else:
form = ProfileForm(user=user, instance=profile)
- return render(request, 'fossee_manim/edit_profile.html', {'form': form})
+ return render(request, 'fossee_manim/edit_profile.html', {'form': form}
+ )
+
+
+@login_required
+def send_proposal(request):
+ user = request.user
+ if request.method == 'POST':
+ form = AnimationProposal(request.POST)
+ if form.is_valid():
+ form_data = form.save(commit=False)
+ form_data.contributor = user
+ form_data.status = "pending"
+ if check_repo(form_data.github):
+ form_data.save()
+ form.save_m2m()
+ else:
+ messages.warning(request, 'Please enter valid github details')
+ return render(request, 'fossee_manim/send_proposal.html',
+ {'form': form})
+ return redirect('/proposal_status/')
+ else:
+ form = AnimationProposal()
+ return render(request, 'fossee_manim/send_proposal.html',
+ {'form': form})
+
+
+@login_required
+def proposal_status(request):
+ user = request.user
+ profile = Profile.objects.get(user_id=user)
+ anime = {}
+ anime_list = {}
+ if profile.position == 'contributor':
+ anime = Animation.objects.filter(contributor_id=user)
+ else:
+ anime_list = Animation.objects.filter(Q(status='pending') |
+ Q(status='changes'))
+ return render(request, 'fossee_manim/proposal_status.html',
+ {'anime': anime, 'anime_list': anime_list})
+
+
+@login_required
+def edit_proposal(request, proposal_id=None):
+ user = request.user
+ comment_form = CommentForm()
+ proposal = Animation.objects.get(id=proposal_id)
+ proposal_form = AnimationProposal(instance=proposal)
+ try:
+ comments = Comment.objects.all().order_by('-created_date')
+ except:
+ comments = None
+ if request.method == 'POST':
+ text = request.POST.get('comment')
+ s1 = request.POST.get('release')
+ s2 = request.POST.get('rejected')
+
+ if s1 or s2 is not None:
+ if s1:
+ proposal.status = 'released'
+ proposal.reviewer = user
+ proposal.save()
+ send_email(request, call_on='released',
+ contributor=proposal.contributor)
+ else:
+ proposal.status = 'rejected'
+ proposal.reviewer = user
+ proposal.save()
+ send_email(request, call_on='rejected',
+ contributor=proposal.contributor)
+ return redirect('/proposal_status/')
+
+ if text is not None:
+ comment_form = CommentForm(request.POST)
+ form_data = comment_form.save(commit=False)
+ form_data.commentor = user
+ form_data.animation = proposal
+ if user.profile.position == 'reviewer':
+ proposal.status = 'changes'
+ send_email(request, call_on='changes',
+ contributor=proposal.contributor,
+ proposal=proposal)
+ form_data.save()
+ return redirect('/edit_proposal/{}'.format(proposal_id))
+ proposal_form = AnimationProposal(request.POST, instance=proposal)
+ if proposal_form.is_valid():
+ p_f = proposal_form.save(commit=False)
+ p_f.contributor = user
+ p_f.save()
+ proposal_form.save_m2m()
+ else:
+ if user.profile.position == 'contributor':
+ if user.id != proposal.contributor_id:
+ return redirect('/logout/')
+
+ if comments is not None:
+ #Show upto 12 Workshops per page
+ paginator = Paginator(comments, 9)
+ page = request.GET.get('page')
+ try:
+ comments = paginator.page(page)
+ except PageNotAnInteger:
+ #If page is not an integer, deliver first page.
+ comments = paginator.page(1)
+ except EmptyPage:
+ #If page is out of range(e.g 999999), deliver last page.
+ comments = paginator.page(paginator.num_pages)
+ return render(request, 'fossee_manim/edit_proposal.html',
+ {'proposal_form': proposal_form,
+ "comments": comments,
+ "comment_form": comment_form})
+
+
+def search(request):
+ if request.method == 'POST':
+ word = request.POST.get('sbox')
+
+ return render(request, 'fossee_manim/search_results.html')
+
diff --git a/requirements.txt b/requirements.txt
index 1efdb8d..85b47d2 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,4 @@
Django==1.11
+django-simple-history==2.7.0
+django-taggit==0.23.0
pytz==2018.9