Compare commits

..

10 Commits

Author SHA1 Message Date
Nathan Chapman
6dd0631537 Update logging 2022-09-04 17:03:07 -06:00
Nathan Chapman
db45fd2d6f Update debug log 2022-09-04 17:00:54 -06:00
Nathan Chapman
ea028a7642 Update logging 2022-09-04 16:55:40 -06:00
Nathan Chapman
ceb0a40771 Update styles for better consistency in type handling 2022-08-02 10:31:23 -06:00
Nathan Chapman
3a940e8789 Fix font sizing for comments form textarea 2022-07-27 08:25:08 -06:00
Nathan Chapman
fd8de82a89 UI Fixes and updates 2022-07-27 08:18:29 -06:00
Nathan Chapman
c84243354e Add object support and add debug toolbar 2022-07-26 13:58:51 -06:00
Nathan Chapman
1de7ad09ec Add exclude so the current user doesn't see their name 2022-07-22 14:45:25 -06:00
Nathan Chapman
1d688a4123 Add recipient list to comment section 2022-07-22 14:33:30 -06:00
Nathan Chapman
08abb25ce8 Entitle everything 2022-07-22 14:03:17 -06:00
20 changed files with 184 additions and 47 deletions

View File

@ -2,6 +2,8 @@
{% load static %} {% load static %}
{% load helpers %} {% load helpers %}
{% block head_title %}{{ object }} | {% endblock head_title %}
{% block content %} {% block content %}
<article class="account"> <article class="account">
<header> <header>

View File

@ -28,8 +28,8 @@ class AccountDetailView(LoginRequiredMixin, DetailView):
def get_context_data(self, *args, **kwargs): def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs) context = super().get_context_data(*args, **kwargs)
context['posts'] = Post.objects.filter(author=self.object).order_by('-created_at') context['posts'] = Post.objects.filter(author=self.object).order_by('-updated_at')[:10]
context['comments'] = Comment.objects.filter(author=self.object).order_by('-created_at') context['comments'] = Comment.objects.filter(author=self.object).order_by('-updated_at')[:10]
return context return context

View File

@ -0,0 +1,20 @@
# Generated by Django 4.0.6 on 2022-07-26 13:45
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('core', '0008_alter_post_options'),
]
operations = [
migrations.AlterField(
model_name='post',
name='recipients',
field=models.ManyToManyField(blank=True, help_text='will be notified when creating or commenting on a post', related_name='subscriptions', to=settings.AUTH_USER_MODEL),
),
]

View File

@ -0,0 +1,17 @@
# Generated by Django 4.0.6 on 2022-07-26 13:47
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('core', '0009_alter_post_recipients'),
]
operations = [
migrations.AlterModelOptions(
name='post',
options={'ordering': ['-created_at']},
),
]

View File

@ -130,7 +130,8 @@ class Post(models.Model):
recipients = models.ManyToManyField( recipients = models.ManyToManyField(
User, User,
blank=True, blank=True,
related_name='subscriptions' related_name='subscriptions',
help_text='will be notified when creating or commenting on a post'
) )
tags = GenericRelation(Tag) tags = GenericRelation(Tag)
@ -149,4 +150,4 @@ class Post(models.Model):
return self.title return self.title
class Meta: class Meta:
ordering = ['-updated_at', '-created_at'] ordering = ['-created_at']

View File

@ -3,7 +3,7 @@
{% block content %} {% block content %}
<article> <article>
<h1>Update comment</h1> <h1>Update comment</h1>
<form method="POST" action="{% url 'core:comment-update' comment.pk %}"> <form method="POST" action="{% url 'core:comment-update' comment.pk %}" class="comments__form">
{% csrf_token %} {% csrf_token %}
{{ form.as_p }} {{ form.as_p }}
<p> <p>

View File

@ -1,5 +1,7 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block head_title %}Delete Post | {% endblock head_title %}
{% block content %} {% block content %}
<h1>Delete Post</h1> <h1>Delete Post</h1>
<form method="POST" action="{% url 'core:post-delete' post.topic.pk post.pk %}"> <form method="POST" action="{% url 'core:post-delete' post.topic.pk post.pk %}">

View File

@ -1,5 +1,7 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block head_title %}New Post | {% endblock head_title %}
{% block breadcrumbs %} {% block breadcrumbs %}
<div class="breadcrumbs"> <div class="breadcrumbs">
<menu> <menu>

View File

@ -2,6 +2,8 @@
{% load static %} {% load static %}
{% load helpers %} {% load helpers %}
{% block head_title %}{{ post.title }} | {% endblock head_title %}
{% block head %} {% block head %}
<script type="module" src="{% static 'scripts/comments.js' %}" defer></script> <script type="module" src="{% static 'scripts/comments.js' %}" defer></script>
{% endblock head %} {% endblock head %}
@ -49,6 +51,20 @@
<form action="{% url 'core:comment-create' %}" method="POST"> <form action="{% url 'core:comment-create' %}" method="POST">
{% csrf_token %} {% csrf_token %}
{{ comment_create_form.as_p }} {{ comment_create_form.as_p }}
<p>
{% for recipient in post.recipients.all %}
{% if post.recipients.all|length > 2 %}
{% if not forloop.last %}{{ recipient }},{% else %}and {{ recipient }}{% endif %}
{% elif post.recipients.all|length is 2 %}
{% if forloop.last %}and {{ recipient }} {% else %} {{ recipient }}{% endif %}
{% else %}
{{ recipient }}
{% endif %}
{% empty %}
No one
{% endfor %}
will be notified when you post your comment.
</p>
<input class="action-button" type="submit" value="Post comment"> <input class="action-button" type="submit" value="Post comment">
</form> </form>
</div> </div>

View File

@ -1,6 +1,8 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load static %} {% load static %}
{% block head_title %}Edit Post | {% endblock head_title %}
{% block content %} {% block content %}
<article class="post"> <article class="post">
<h1>Update Post</h1> <h1>Update Post</h1>

View File

@ -1,5 +1,7 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block head_title %}Delete Topic | {% endblock head_title %}
{% block content %} {% block content %}
<h1>Delete Topic</h1> <h1>Delete Topic</h1>
<form method="POST" action="{% url 'core:topic-delete' topic.pk %}"> <form method="POST" action="{% url 'core:topic-delete' topic.pk %}">

View File

@ -1,5 +1,7 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block head_title %}New Topic | {% endblock head_title %}
{% block content %} {% block content %}
<h1>+ New Topic</h1> <h1>+ New Topic</h1>
<form method="POST" action="{% url 'core:topic-create' %}"> <form method="POST" action="{% url 'core:topic-create' %}">

View File

@ -1,5 +1,7 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block head_title %}{{ topic.name }} | {% endblock head_title %}
{% block breadcrumbs %} {% block breadcrumbs %}
<div class="breadcrumbs"> <div class="breadcrumbs">
<menu> <menu>

View File

@ -1,5 +1,7 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block head_title %}Edit Topic | {% endblock head_title %}
{% block content %} {% block content %}
<h1>Update Topic</h1> <h1>Update Topic</h1>
<form method="POST" action="{% url 'core:topic-update' topic.pk %}"> <form method="POST" action="{% url 'core:topic-update' topic.pk %}">

View File

@ -1,5 +1,7 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block head_title %}Topics | {% endblock head_title %}
{% block content %} {% block content %}
<article> <article>
<header> <header>

View File

@ -13,6 +13,7 @@ from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.messages.views import SuccessMessageMixin from django.contrib.messages.views import SuccessMessageMixin
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from accounts.models import User
from .models import Topic, Post, Comment from .models import Topic, Post, Comment
from .forms import PostForm, PostCreateForm, CommentCreateForm from .forms import PostForm, PostCreateForm, CommentCreateForm
@ -80,6 +81,17 @@ class TopicDetailView(LoginRequiredMixin, DetailView):
model = Topic model = Topic
pk_url_kwarg = 'topic_pk' pk_url_kwarg = 'topic_pk'
def get_queryset(self):
queryset = Topic.objects.all().prefetch_related(
models.Prefetch(
'post_set',
queryset=Post.objects.filter(
topic=self.kwargs['topic_pk']
).order_by('-created_at').prefetch_related('comments')
)
)
return queryset
class TopicUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView): class TopicUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
model = Topic model = Topic
@ -127,6 +139,15 @@ class PostDetailView(LoginRequiredMixin, DetailView):
model = Post model = Post
pk_url_kwarg = 'post_pk' pk_url_kwarg = 'post_pk'
def get_queryset(self):
queryset = Post.objects.all().prefetch_related(
models.Prefetch(
'recipients',
queryset=User.objects.exclude(pk=self.request.user.pk)
)
)
return queryset
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
object_content_type = ContentType.objects.get_for_model(self.object).pk object_content_type = ContentType.objects.get_for_model(self.object).pk

View File

@ -33,6 +33,7 @@ INSTALLED_APPS = [
'django.contrib.sites', 'django.contrib.sites',
# 3rd party # 3rd party
'debug_toolbar',
'django_filters', 'django_filters',
'compressor', 'compressor',
'anymail', 'anymail',
@ -44,6 +45,7 @@ INSTALLED_APPS = [
# Middlewares # Middlewares
MIDDLEWARE = [ MIDDLEWARE = [
'debug_toolbar.middleware.DebugToolbarMiddleware',
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
@ -130,34 +132,18 @@ USE_TZ = True
# Logging # Logging
LOGGING = { LOGGING = {
'version': 1, 'version': 1,
'disable_existing_loggers': False, 'disable_existing_loggers': True,
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse',
},
'require_debug_true': {
'()': 'django.utils.log.RequireDebugTrue',
},
},
'formatters': {
'verbose': {
'format': '{name} {levelname} {asctime} {module} {process:d} {thread:d} {message}',
'style': '{',
},
},
'handlers': { 'handlers': {
'file': { 'file': {
'level': 'DEBUG', 'level': 'DEBUG',
'class': 'logging.FileHandler', 'class': 'logging.FileHandler',
'filters': ['require_debug_false'], 'filename': '/home/nathanchapman/debug.log',
'filename': LOGGING_FILE_LOCATION,
'formatter': 'verbose',
}, },
}, },
'loggers': { 'loggers': {
'django.file': { 'django': {
'handlers': ['file'], 'handlers': ['file'],
'level': 'INFO', 'level': 'DEBUG',
'propagate': False, 'propagate': False,
}, },
}, },

View File

@ -11,5 +11,6 @@ urlpatterns = [
] ]
if settings.DEBUG: if settings.DEBUG:
urlpatterns += [path('__debug__/', include('debug_toolbar.urls'))]
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

View File

@ -24,6 +24,7 @@ body {
p { p {
margin-top: 0; margin-top: 0;
margin-bottom: 1rem; margin-bottom: 1rem;
text-rendering: optimizeLegibility;
} }
a { a {
color: inherit; color: inherit;
@ -41,6 +42,7 @@ h5 {
text-transform: uppercase; text-transform: uppercase;
font-weight: 700; font-weight: 700;
line-height: 1.3; line-height: 1.3;
text-rendering: optimizeLegibility;
} }
h1 { h1 {
margin-top: 0; margin-top: 0;
@ -78,6 +80,13 @@ iframe {
aspect-ratio: 16/9; aspect-ratio: 16/9;
} }
object {
width: 100%;
aspect-ratio: 4/3;
box-sizing: border-box;
border: 1px solid var(--table-border);
}
/* Lists /* Lists
========================================================================== */ ========================================================================== */
@ -137,7 +146,7 @@ textarea {
box-sizing: border-box; box-sizing: border-box;
font: inherit; font: inherit;
font-family: 'PT Mono', monospace; font-family: 'PT Mono', monospace;
font-size: 2rem; font-size: 2.5rem;
padding: 0.5rem 1rem; padding: 0.5rem 1rem;
width: 100%; width: 100%;
resize: vertical; resize: vertical;
@ -160,8 +169,11 @@ input[type=submit],
display: inline-block; display: inline-block;
} }
button:hover,
input[type=submit]:hover,
.action-button:hover { .action-button:hover {
background-color: var(--color-highlight); background-color: var(--color-highlight);
color: var(--color-blue);
} }
@ -174,6 +186,10 @@ main {
padding: 0 1rem; padding: 0 1rem;
} }
article {
margin-bottom: 1rem;
}
/* ========================================================================== /* ==========================================================================
Header Header
@ -219,6 +235,10 @@ main {
font-weight: bold; font-weight: bold;
} }
.messages {
font-weight: bold;
}
/* Breadcrumbs /* Breadcrumbs
========================================================================== */ ========================================================================== */
@ -260,19 +280,32 @@ main {
justify-content: space-between; justify-content: space-between;
margin-bottom: 2rem; margin-bottom: 2rem;
} }
@media screen and (max-width: 600px) {
.post__header {
flex-direction: column;
}
}
.post__content { .post__content {
font-family: 'STIX Two Text'; font-family: 'STIX Two Text', serif;
font-size: 2rem; font-size: 2.5rem;
margin-bottom: 4rem; margin-bottom: 4rem;
line-height: 1.75; line-height: 1.75;
} }
@media screen and (max-width: 600px) {
.post__content {
font-size: 1.75rem;
}
}
.post__content h1, .post__content h1,
.post__content h2, .post__content h2,
.post__content h3, .post__content h3,
.post__content h4, .post__content h4,
.post__content h5 { .post__content h5 {
font-family: 'STIX Two Text'; font-family: 'STIX Two Text', serif;
text-transform: unset; text-transform: unset;
margin: 2em 0 1em; margin: 2em 0 1em;
} }
@ -293,10 +326,14 @@ main {
font-size: 1.125em; font-size: 1.125em;
} }
.post__content p {
margin-bottom: 1em;
}
.post__content blockquote { .post__content blockquote {
font-size: 0.875em; padding: 0.25rem 1rem 0 2rem;
max-width: 80%; margin: 0 0 1rem;
margin: 0 auto 1rem; border-left: 0.25rem solid black;
} }
@ -305,29 +342,42 @@ main {
Comments Comments
========================================================================== */ ========================================================================== */
.comment { .comment {
margin: 2rem 0; margin: 2em 0;
background-color: var(--color-lightgrey); background-color: var(--color-lightgrey);
padding: 1rem; padding: 1em;
} }
.comment__header { .comment__header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
line-height: 1.3; line-height: 1.75;
}
@media screen and (max-width: 600px) {
.comment__header {
flex-direction: column;
margin-bottom: 1rem;
}
} }
.comment__content { .comment__content {
font-family: 'STIX Two Text'; font-family: 'STIX Two Text', serif;
font-size: 2rem; font-size: 2.5rem;
/*max-width: 64ch;*/ /*max-width: 64ch;*/
} }
@media screen and (max-width: 600px) {
.comment__content {
font-size: 1.75rem;
}
}
.comment__content h1, .comment__content h1,
.comment__content h2, .comment__content h2,
.comment__content h3, .comment__content h3,
.comment__content h4, .comment__content h4,
.comment__content h5 { .comment__content h5 {
font-family: 'STIX Two Text'; font-family: 'STIX Two Text', serif;
text-transform: unset; text-transform: unset;
margin: 2em 0 1em; margin: 2em 0 1em;
} }
@ -348,22 +398,29 @@ main {
font-size: 1.125em; font-size: 1.125em;
} }
.comment__content blockquote {
font-size: 1.75rem;
max-width: 80%;
margin: 0 auto 1rem;
}
.comment p { .comment p {
margin-bottom: 1em;
line-height: 1.75; line-height: 1.75;
} }
.comment ul { .comment ul {
line-height: 1.75; line-height: 1.75;
} }
.comment__content blockquote {
padding: 0.25rem 1rem 0 2rem;
margin: 0 0 1rem;
border-left: 0.25rem solid black;
}
.comments__form textarea { .comments__form textarea {
font-family: 'PT Mono'; font-family: 'PT Mono';
font-size: 2rem; font-size: 2.5rem;
line-height: 1.75; line-height: 1.75;
} }
@media screen and (max-width: 600px) {
.comments__form textarea {
font-size: 1.75rem;
}
}

View File

@ -11,10 +11,10 @@
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,300;0,400;0,700;0,900;1,400;1,700;1,900&family=PT+Mono&family=STIX+Two+Text:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,300;0,400;0,700;0,900;1,400;1,700;1,900&family=PT+Mono&family=STIX+Two+Text:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet">
{% compress css %} {% compress css %}
<link rel="stylesheet" type="text/css" href="{% static "styles/main.css" %}"> <link rel="stylesheet" type="text/css" href="{% static 'styles/main.css' %}">
{% endcompress %} {% endcompress %}
<script type="module" defer src="{% static 'scripts/timezone.js' %}"></script> <script type="module" defer src="{% static 'scripts/timezone.js' %}"></script>