Skip to content

Commit

Permalink
Added account, feedback form, edit profile
Browse files Browse the repository at this point in the history
  • Loading branch information
nilandev committed Jan 10, 2024
1 parent b48d02d commit 500b5b5
Show file tree
Hide file tree
Showing 56 changed files with 848 additions and 302 deletions.
3 changes: 2 additions & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
[MASTER]
ignore=migrations
ignore=migrations
disable=C0114, # missing-module-docstring
5 changes: 3 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"editor.formatOnSave": false,
"python.linting.enabled": true,
"python.linting.lintOnSave": true,
// "editor.fontFamily": "Dank Mono, JetBrains Mono NL, Fira Code, Menlo, Monaco, 'Courier New', monospace",
// "editor.fontSize": 14,
// "editor.fontFamily": "Dank Mono, JetBrains Mono NL, Fira Code, Menlo, Monaco, 'Courier New', monospace",
// "editor.fontSize": 14,
"python.linting.pylintArgs": ["--disable=C0111"]
}
30 changes: 30 additions & 0 deletions bloggy/forms/change_password_form.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from django import forms
from django.contrib.auth.forms import PasswordChangeForm


class ChangePasswordForm(PasswordChangeForm):
old_password = forms.CharField(
label="Old password",
strip=False,
widget=forms.PasswordInput(
attrs={"autocomplete": "current-password", "autofocus": True, 'class': 'form-control'}
),
)

new_password1 = forms.CharField(
label="New Password",
help_text='Please use 8 or more characters with a mix of letters, numbers & symbols',
widget=forms.PasswordInput(attrs={'class': 'form-control'}, )
)
new_password2 = forms.CharField(
label="Confirm New Password",
widget=forms.PasswordInput(attrs={'class': 'form-control'}),
)

def clean_new_password2(self):
new_password1 = self.cleaned_data.get('new_password1')
new_password2 = self.cleaned_data.get('new_password2')

if new_password1 and new_password2 and new_password1 != new_password2:
raise forms.ValidationError("Passwords do not match.")
return new_password2
3 changes: 3 additions & 0 deletions bloggy/forms/edit_profile_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ class NonClearableFileInput(ClearableFileInput):
class EditProfileForm(forms.ModelForm):
class Meta:
model = User
help_texts={
"bio": "This will be displayed publicly on your profile. Keep it short and crisp."
}
fields = [
'profile_photo',
'name',
Expand Down
31 changes: 31 additions & 0 deletions bloggy/forms/update_username_form.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from django import forms
from django.contrib.auth import get_user_model


class UpdateUsernameForm(forms.ModelForm):
class Meta:
model = get_user_model()
fields = ['username']
help_texts={
'username': 'Letters, digits and "_" only allowed.'
}
labels = {
"username": "New username",
}

widgets = {
'username': forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'Username',
}),
}

def clean_username(self):
new_username = self.cleaned_data['username']
user_model = get_user_model()

# Check if the new username is available
if user_model.objects.filter(username=new_username).exclude(pk=self.instance.pk).exists():
raise forms.ValidationError('This username is already in use. Please choose a different one.')

return new_username
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def handle(self, *args, **kwargs):
}

try:
email_service.send_custom_email(
email_service.send_html_email(
subject,
[user.email],
"email/account_activation_reminder_email.html",
Expand Down
2 changes: 1 addition & 1 deletion bloggy/management/commands/send_card.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def handle(self, *args, **options):
}

try:
email_service.send_custom_email(subject, [user.email], "email/wish_card_email.html", args)
email_service.send_html_email(subject, [user.email], "email/wish_card_email.html", args)
print('Success: Card sent to {}', user.email)
except Exception as ex:
print('Error sending card to {}: {}', user.email, ex)
Expand Down
2 changes: 1 addition & 1 deletion bloggy/management/commands/send_newsletter.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def handle(self, *args, **options):
}

try:
email_service.send_custom_email(subject, [user.email], "email/wish_card_email.html", args)
email_service.send_html_email(subject, [user.email], "email/wish_card_email.html", args)
print('Success: Card sent to {}', user.email)
except Exception as ex:
print('Error sending card to {}: {}', user.email, ex)
Expand Down
1 change: 0 additions & 1 deletion bloggy/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ def get_bookmarks_count(self):
def get_full_name_or_username(self):
if self.name:
return self.name

return self.username

def __str__(self):
Expand Down
57 changes: 19 additions & 38 deletions bloggy/services/email_service.py
Original file line number Diff line number Diff line change
@@ -1,55 +1,36 @@
from django.core.mail import send_mail
from django.template.loader import render_to_string
from django.urls import reverse

from bloggy import settings


def send_custom_email(subject, recipients, template, args, from_email=settings.DEFAULT_FROM_EMAIL):
def send_html_email(subject, to_email, template, args, from_email=settings.DEFAULT_FROM_EMAIL):
email_body = render_to_string(template, args)
send_mail(
subject,
email_body,
from_email,
recipients,
to_email,
fail_silently=False,
html_message=email_body
)


def send_newsletter_verification_token(request, email, uuid, token):
subject = f'Confirm to {settings.SITE_TITLE} newsletter'

args = {
"email_subject": subject,
"app_name": settings.SITE_TITLE,
"verification_link": request.build_absolute_uri(reverse("newsletter_verification", args=[uuid, token]))
}

send_custom_email(subject, [email], "email/newsletter_verification_token.html", args)


def email_verification_token(request, new_user, token):
subject = f"{settings.SITE_TITLE} confirmation code: {token.code}"
args = {
"email_subject": subject,
"verification_code": token.code,
"app_name": settings.SITE_TITLE,
"verification_link": request.build_absolute_uri(reverse("otp_verification", args=[token.uuid]))
}
send_custom_email(subject, [new_user.email], "email/login_code_email.html", args)


def send_account_activation_email(request, new_user, verification_token):
subject = f'Welcome to {settings.SITE_TITLE}!'
args = {
"email_subject": subject,
"user_name": new_user.name,
"app_name": settings.SITE_TITLE,
"verification_link": request.build_absolute_uri(reverse("activate_account", args=[
verification_token.uuid,
verification_token.token
]))
}
def send_plain_email(subject, to_email, message_content, from_email=settings.DEFAULT_FROM_EMAIL):
send_mail(
subject,
message_content,
from_email,
to_email,
fail_silently=False,
)

send_custom_email(subject, [new_user.email], "email/account_activation_email.html", args)
# def email_verification_token(request, new_user, token):
# subject = f"{settings.SITE_TITLE} confirmation code: {token.code}"
# args = {
# "email_subject": subject,
# "verification_code": token.code,
# "app_name": settings.SITE_TITLE,
# "verification_link": request.build_absolute_uri(reverse("otp_verification", args=[token.uuid]))
# }
# send_html_email(subject, [new_user.email], "email/login_code_email.html", args)
Binary file added bloggy/templates/.DS_Store
Binary file not shown.
2 changes: 1 addition & 1 deletion bloggy/templates/auth/password_reset.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ <h2 class="display-3 lh-1 fw-normal mb-2">Forgot password</h2>

<div class="form-buttons">
<input type="submit" value="Reset my password" class="btn login-btn btn-primary w-100 my-2">
<a href="{% url 'login' %}" class="btn login-btn btn-secondary w-100">Back to login</a>
<a href="{% url 'login' %}" class="btn login-btn btn-secondary w-100 mt-2">Back to login</a>
</div>
</form>

Expand Down
10 changes: 1 addition & 9 deletions bloggy/templates/base-with-header-footer.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,7 @@
</a>
</div>
<main>
{% if messages %}
<div class="col-lg-5 mx-auto">
{% for message in messages %}
<div class="mt-3 alert alert-{{ message.tags }}">
{{ message }}
</div>
{% endfor %}
</div>
{% endif %}
{% include 'widgets/feedback-form.html' %}
{% block content %}{% endblock content %}
</main>
<footer class="footer mt-5">
Expand Down
10 changes: 1 addition & 9 deletions bloggy/templates/base-with-header.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,7 @@
{% include "partials/header.html" %}
</header>
<main>
{% if messages %}
<div class="col-lg-5 mx-auto">
{% for message in messages %}
<div class="mt-3 alert alert-{{ message.tags }}">
{{ message }}
</div>
{% endfor %}
</div>
{% endif %}
{% include 'widgets/feedback-form.html' %}
{% block content %}{% endblock content %}
</main>
</body>
Expand Down
12 changes: 11 additions & 1 deletion bloggy/templates/pages/home.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
{% extends "base-with-header-footer.html" %}
{% load custom_widgets %}
{#{% block base_css_class %}bg-white{% endblock base_css_class %}#}
{% load static %}
{% spaceless %}
{% block content %}
{% load static %}
{% if messages %}
<div class="col-lg-5 mx-auto">
{% for message in messages %}
<div class="mt-3 alert alert-{{ message.tags }}">
{{ message }}
</div>
{% endfor %}
</div>
{% endif %}

<section id="homeIntroSection" class="container homeIntro">
<div class="hero jumbotron py-lg-5 py-4 px-3 text-center">
<div class="container">
Expand Down
27 changes: 17 additions & 10 deletions bloggy/templates/pages/single/course.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,36 +25,40 @@
</div>
</section>


<div class="container">
{% with lessons_list=course.get_lessons.all %}
<div class="row">

<main id="main-content" class="hero col-12 col-md-8 col-lg-8 col-print-12 pe-lg-2">
<div class="article-details-card p-lg-5 p-3 ms-md-3 mb-4">
<div class="article-details-card p-lg-5 p-3 mb-4">
{% if user.is_authenticated and user.is_superuser %}
<a class="mb-3 btn btn-sm btn-secondary btn-xs" href="{{ course.get_admin_url }}">Edit course</a>
<a class="mb-3 btn btn-sm btn-secondary btn-xs" href="{{ course.get_admin_url }}">Edit
course</a>
{% endif %}

<div class="relative pb-2">
<div class="d-flex align-items-center">
<div class="flex-grow-1">

<h1 class="post-title display-2 fw-700 mt-0 mb-2">{{ course.title }}</h1>
<p class="lead fw-500 pt-0 mb-2">{{ course.excerpt }}</p>
<p class="text-muted my-2">
<small class="text-muted text-uppercase fw-bold"
style="font-size:0.7rem">
{{ lessons_list.count }} Lessons
<small class="text-muted text-uppercase fw-bold" style="font-size:0.7rem">
<i class="fa-solid fa-book"></i> {{ lessons_list.count }} Lessons
</small>
<span class="meta-seperator"></span>
<span class="meta-seperator px-2"></span>

{% with course.category as category %}
<small class="text-muted text-uppercase pe-1" style="font-size:0.7rem;"><i class="fa-solid fa-tag"></i></small>
<a class="text-decoration-none text-reset link-primary fw-bold"
style="z-index:999;position:relative"
href="{% url 'categories_single' slug=category.slug %}">
<small class="d-inline-block mb-1 text-primary text-uppercase fw-bold"
style="font-size:0.7rem;">{{ category.title }}</small>
</a>
{% endwith %}
<span class="meta-seperator"></span>
<span class="meta-seperator px-2"></span>

{% if course.difficulty %}
<span class="badge-meta-pill {{ course.difficulty }}">{{ course.difficulty | capfirst }} Level</span>
Expand All @@ -75,23 +79,26 @@ <h1 class="post-title display-2 fw-700 mt-0 mb-2">{{ course.title }}</h1>
<li class="list-group-item {% if request.get_full_path == current_url %}active{% endif %}">
<h3 class="">
<a href="{% url 'lesson_single' course=course.slug slug=lesson.slug %}"
class="text-decoration-none h3 text-dark p-0 m-0 w-500">{{ lesson.title }}</a>
class="text-decoration-none h3 text-dark p-0 m-0 w-500">{{ lesson.title }}</a>
</h3>
<p class="font-sm text-muted mb-3">{{ lesson.excerpt }}</p>
</li>
{% endfor %}
</ul>
</div>
</div>


</div>
</div>
</div>
</div>
</main>

<aside id="right-sidebar" class="col-12 col-md-3 col-lg-3 d-print-none">
{% if course.thumbnail and not hideThumbnail %}
<figure class="image mb-3">
<img src="{{ course.thumbnail.url }}" loading="lazy" width="100%">
</figure>
{% endif %}
{% include 'widgets/ad-unit-vertical-responsive.html' %}
{% related_quizzes_widget limit=5 widget_title="Related Quizzes" %}
</aside>
Expand Down
2 changes: 1 addition & 1 deletion bloggy/templates/pages/single/post-standard.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@

<div class="d-lg-flex justify-content-between align-items-center py-2 mb-2">
{% include 'partials/article_meta_container.html' with post=post %}
{% comment %}<div class="d-none d-md-inline" id="bookmarkContainer"></div>{% endcomment %}
{# <div class="d-none d-md-inline" id="bookmarkContainer"></div>#}
<div class="hero article-meta-container" style="font-size: 0.85rem">
{% if post.publish_status == "DRAFT" %}
<span class="badge rounded-pill text-bg-warning text-white">{{ post.publish_status }} / PREVIEW</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,23 @@
<div class="container py-4 px-5">
<div class="d-flex d-flex py-3">
<div class="user-avatar flex-shrink-0 ps-4">
<img src="{{ user.get_avatar }}"
alt="{{ user.name }}"
<img src="{{ userProfile.get_avatar }}"
alt="{{ userProfile.name }}"
class="img-fluid image-rounded-square"
style="box-shadow: 5px 15px 15px rgb(89 152 152 / 5%);"
height="250px"
width="200px">
</div>

<div class="flex-grow-1 profile-details ps-4">
{% if user.get_full_name %}
<h1 class="h1">{{ user.get_full_name }}</h1>
{% if userProfile.get_full_name %}
<h1 class="h1">{{ userProfile.get_full_name }}</h1>
{% else %}
<h1 class="h2 my-3">{{ user.username }}</h1>
<h1 class="h2 my-3">{{ userProfile.username }}</h1>
{% endif %}

{% if user.bio %}
<p class="mb-2">{{ user.bio | safe }}</p>
{% if userProfile.bio %}
<p class="mb-2">{{ userProfile.bio | safe }}</p>
{% endif %}

<div class="pt-1">
Expand Down
Loading

0 comments on commit 500b5b5

Please sign in to comment.