From eb17b26cdef47d998b574b12d3edcf6ced0e5151 Mon Sep 17 00:00:00 2001 From: Nathan Chapman Date: Wed, 20 Jul 2022 11:07:06 -0600 Subject: [PATCH] Add basic styling to forum --- src/core/admin.py | 5 +- src/core/feeds.py | 2 +- src/core/forms.py | 3 - ..._remove_post_subtitle_topic_description.py | 22 ++ .../0003_topic_created_at_topic_updated_at.py | 25 ++ ...tions_remove_post_is_published_and_more.py | 25 ++ src/core/models.py | 22 +- src/core/templates/core/comment_detail.html | 8 +- .../templates/core/post_confirm_delete.html | 4 +- src/core/templates/core/post_create_form.html | 12 +- src/core/templates/core/post_detail.html | 31 ++- src/core/templates/core/topic_detail.html | 62 ++++- src/core/templates/core/topic_list.html | 44 ++- src/core/views.py | 21 +- src/static/styles/main.css | 255 ++++++++++++++---- src/templates/base.html | 6 +- 16 files changed, 447 insertions(+), 100 deletions(-) create mode 100644 src/core/migrations/0002_remove_post_subtitle_topic_description.py create mode 100644 src/core/migrations/0003_topic_created_at_topic_updated_at.py create mode 100644 src/core/migrations/0004_alter_post_options_remove_post_is_published_and_more.py diff --git a/src/core/admin.py b/src/core/admin.py index 47f03fd..8500654 100644 --- a/src/core/admin.py +++ b/src/core/admin.py @@ -1,4 +1,7 @@ from django.contrib import admin -from .models import Post +from .models import Topic, Tag, Comment, Post +admin.site.register(Topic) +admin.site.register(Tag) +admin.site.register(Comment) admin.site.register(Post) diff --git a/src/core/feeds.py b/src/core/feeds.py index 2560627..422d1d7 100644 --- a/src/core/feeds.py +++ b/src/core/feeds.py @@ -11,7 +11,7 @@ class RssLatestPostFeed(Feed): description = 'A list of the latest posts.' def items(self): - return Post.objects.order_by('-pub_date')[:5] + return Post.objects.order_by('-created_at')[:5] def item_title(self, item): return item.title diff --git a/src/core/forms.py b/src/core/forms.py index 94d7625..d007cce 100644 --- a/src/core/forms.py +++ b/src/core/forms.py @@ -28,10 +28,7 @@ class PostForm(forms.ModelForm): fields = [ 'author', 'title', - 'subtitle', 'content', - 'pub_date', - 'is_published', 'topic' ] labels = { diff --git a/src/core/migrations/0002_remove_post_subtitle_topic_description.py b/src/core/migrations/0002_remove_post_subtitle_topic_description.py new file mode 100644 index 0000000..3d1c752 --- /dev/null +++ b/src/core/migrations/0002_remove_post_subtitle_topic_description.py @@ -0,0 +1,22 @@ +# Generated by Django 4.0.6 on 2022-07-20 13:59 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0001_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='post', + name='subtitle', + ), + migrations.AddField( + model_name='topic', + name='description', + field=models.CharField(blank=True, max_length=500), + ), + ] diff --git a/src/core/migrations/0003_topic_created_at_topic_updated_at.py b/src/core/migrations/0003_topic_created_at_topic_updated_at.py new file mode 100644 index 0000000..42975bf --- /dev/null +++ b/src/core/migrations/0003_topic_created_at_topic_updated_at.py @@ -0,0 +1,25 @@ +# Generated by Django 4.0.6 on 2022-07-20 14:19 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0002_remove_post_subtitle_topic_description'), + ] + + operations = [ + migrations.AddField( + model_name='topic', + name='created_at', + field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), + preserve_default=False, + ), + migrations.AddField( + model_name='topic', + name='updated_at', + field=models.DateTimeField(auto_now=True), + ), + ] diff --git a/src/core/migrations/0004_alter_post_options_remove_post_is_published_and_more.py b/src/core/migrations/0004_alter_post_options_remove_post_is_published_and_more.py new file mode 100644 index 0000000..0dd0820 --- /dev/null +++ b/src/core/migrations/0004_alter_post_options_remove_post_is_published_and_more.py @@ -0,0 +1,25 @@ +# Generated by Django 4.0.6 on 2022-07-20 15:58 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0003_topic_created_at_topic_updated_at'), + ] + + operations = [ + migrations.AlterModelOptions( + name='post', + options={'ordering': ['-updated_at']}, + ), + migrations.RemoveField( + model_name='post', + name='is_published', + ), + migrations.RemoveField( + model_name='post', + name='pub_date', + ), + ] diff --git a/src/core/models.py b/src/core/models.py index 05dc210..7711054 100644 --- a/src/core/models.py +++ b/src/core/models.py @@ -18,12 +18,16 @@ class Topic(models.Model): a series of posts essays that are a part of a longer thread. """ name = models.CharField(max_length=255) + description = models.CharField(max_length=500, blank=True) + + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) def __str__(self): return self.name def get_absolute_url(self): - return reverse('core:tag-detail', kwargs={'topic_pk': self.pk}) + return reverse('core:topic-detail', kwargs={'topic_pk': self.pk}) class Tag(models.Model): @@ -87,7 +91,13 @@ class Comment(models.Model): class PostManager(models.Manager): def get_queryset(self): - return super().get_queryset().select_related('author') + return super().get_queryset().annotate( + models.Count('comments') + ).select_related( + 'author' + ).prefetch_related( + 'comments' + ) class Post(models.Model): @@ -101,10 +111,7 @@ class Post(models.Model): on_delete=models.SET_NULL ) title = models.CharField(max_length=255) - subtitle = models.CharField(max_length=255, blank=True) content = models.TextField(blank=True) - pub_date = models.DateTimeField(blank=True, null=True) - is_published = models.BooleanField(default=False) topic = models.ForeignKey( Topic, blank=True, @@ -126,5 +133,8 @@ class Post(models.Model): 'post_pk': self.pk }) + def __str__(self): + return self.title + class Meta: - ordering = ['-pub_date'] + ordering = ['-updated_at'] diff --git a/src/core/templates/core/comment_detail.html b/src/core/templates/core/comment_detail.html index 48e01e2..975da5e 100644 --- a/src/core/templates/core/comment_detail.html +++ b/src/core/templates/core/comment_detail.html @@ -2,11 +2,11 @@
- {{ comment.author }}
- +
+ {{ comment.author }} » +
-
+
{{ comment.content|markdown|safe }}
-
diff --git a/src/core/templates/core/post_confirm_delete.html b/src/core/templates/core/post_confirm_delete.html index eabf1be..1991dd0 100644 --- a/src/core/templates/core/post_confirm_delete.html +++ b/src/core/templates/core/post_confirm_delete.html @@ -2,12 +2,12 @@ {% block content %}

Delete Post

-
+ {% csrf_token %}

Are you sure you want to delete "{{ post }}"?

{{ form.as_p }}

- or cancel + or cancel

{% endblock %} diff --git a/src/core/templates/core/post_create_form.html b/src/core/templates/core/post_create_form.html index bb33cbb..cf3190d 100644 --- a/src/core/templates/core/post_create_form.html +++ b/src/core/templates/core/post_create_form.html @@ -1,12 +1,22 @@ {% extends 'base.html' %} +{% block breadcrumbs %} + +{% endblock breadcrumbs %} + {% block content %}

+ New Post

{% csrf_token %} {{ form.as_p }}

- or cancel + or cancel

{% endblock %} diff --git a/src/core/templates/core/post_detail.html b/src/core/templates/core/post_detail.html index 4a0f36b..fd0da7f 100644 --- a/src/core/templates/core/post_detail.html +++ b/src/core/templates/core/post_detail.html @@ -6,17 +6,29 @@ {% endblock head %} +{% block breadcrumbs %} + +{% endblock breadcrumbs %} + {% block content %}
-
-
- -
-

{{ post.title }}

-

- Edit - Delete -

+
+
+

{{ post.title }}

+

+ » +

+
+
+ Edit + Delete +
{{ post.content|markdown|safe }} @@ -27,7 +39,6 @@
{% for comment in post.comments.all %} {% include 'core/comment_detail.html' with comment=comment %} -
{% endfor %}
diff --git a/src/core/templates/core/topic_detail.html b/src/core/templates/core/topic_detail.html index 3337b7d..fc3a3d8 100644 --- a/src/core/templates/core/topic_detail.html +++ b/src/core/templates/core/topic_detail.html @@ -1,19 +1,55 @@ {% extends 'base.html' %} -{% block content %} -

Topic

-

- Edit - Delete -

-

{{ topic }}

+{% block breadcrumbs %} + +{% endblock breadcrumbs %} +{% block content %} +
+
+

{{ topic.name }}

+

{{ topic.description }} » {{ topic.created_at }}

+

+ + New post +

+
- + New post - {% for post in topic.post_list.all %} -

{{ post.title }}

- {% empty %} -

No posts

- {% endfor %} + + + + + + + + + {% for post in topic.post_set.all %} + + + + {% if post.comments.last is not None %} + {% with comment=post.comments.last %} + + {% endwith %} + {% else %} + + {% endif %} + + {% empty %} +

No posts

+ {% endfor %} + + + +
PostCommentsLast comment
+
{% endblock %} diff --git a/src/core/templates/core/topic_list.html b/src/core/templates/core/topic_list.html index c8cf46d..cfdbc50 100644 --- a/src/core/templates/core/topic_list.html +++ b/src/core/templates/core/topic_list.html @@ -2,21 +2,43 @@ {% block content %}
+

Topics

- + New topic +

+ + New topic +

+
- {% for topic in topic_list %} -

{{ topic.name }}

-
    - {% for post in topic.post_list.all %} -
  • {{ post.title }}
  • + + + + + + + + + + {% for topic in topic_list %} + + + + {% with post=topic.post_set.last %} + + {% endwith %} + {% empty %} -
  • No posts yet
  • + +
  • No topics yet
  • + {% endfor %} - - {% empty %} -

    No topics yet.

    - {% endfor %} + +
    TopicsPostsLast post
{% endblock %} diff --git a/src/core/views.py b/src/core/views.py index 5a8da52..620ec33 100644 --- a/src/core/views.py +++ b/src/core/views.py @@ -1,5 +1,6 @@ from django.shortcuts import render, reverse, redirect, get_object_or_404 from django.urls import reverse, reverse_lazy +from django.db import models from django.views.generic.base import TemplateView from django.views.generic.detail import DetailView from django.views.generic.list import ListView @@ -51,6 +52,12 @@ class CommentDeleteView(SuccessMessageMixin, DeleteView): class TopicListView(ListView): model = Topic + def get_queryset(self): + queryset = Topic.objects.annotate( + models.Count('post') + ) + return queryset + class TopicCreateView(SuccessMessageMixin, CreateView): model = Topic @@ -86,13 +93,23 @@ class PostCreateView(SuccessMessageMixin, CreateView): model = Post success_message = 'Post created.' template_name_suffix = '_create_form' - fields = '__all__' + fields = [ + 'title', + 'content', + ] def get_context_data(self, *args, **kwargs): context = super().get_context_data(*args, **kwargs) context['topic'] = get_object_or_404(Topic, pk=self.kwargs['topic_pk']) return context + def form_valid(self, form): + form.instance.author = self.request.user + form.instance.topic = get_object_or_404( + Topic, pk=self.kwargs['topic_pk'] + ) + return super().form_valid(form) + class PostDetailView(DetailView): model = Post @@ -120,4 +137,4 @@ class PostDeleteView(SuccessMessageMixin, DeleteView): model = Post pk_url_kwarg = 'post_pk' success_message = 'Post deleted.' - success_url = reverse_lazy('article-list') + success_url = reverse_lazy('core:topic-list') diff --git a/src/static/styles/main.css b/src/static/styles/main.css index c0477e2..97b08c0 100644 --- a/src/static/styles/main.css +++ b/src/static/styles/main.css @@ -1,3 +1,13 @@ +:root { + --color-white: white; + --color-blue: #0070ff; + --color-darkgrey: #393939; + --color-lightgrey: #f7f7f7; + --color-highlight: #c0deea; + + --table-border: black; +} + html { font-size: 75%; } @@ -6,18 +16,26 @@ body { background: white; font-family: 'Montserrat', serif; font-weight: 400; + margin: 0; + padding: 0; line-height: 1; color: #000000; } p { margin-bottom: 1rem; } +a { + color: inherit; +} +a:hover { + color: var(--color-blue); +} h1, h2, h3, h4, h5 { - margin: 3rem 0 1.38rem; + margin: 0 0 1rem; font-family: 'Montserrat', sans-serif; text-transform: uppercase; font-weight: 700; @@ -43,57 +61,204 @@ small { font-size: 0.889rem; } - -/* ========================================================================== - Article - ========================================================================== */ -.post { - font-family: 'STIX Two Text'; - max-width: 1024px; - margin: 0 auto; - font-size: 1.25rem; -} -.post p { - line-height: 1.75; - margin-bottom: 1rem; -} -.post h1, -.post h2, -.post h3, -.post h4, -.post h5 { - margin: 3rem 0 1.38rem; - font-family: 'Montserrat', serif; - line-height: 1.3; -} - -.post h1 { - margin-top: 0; -} - -.post__content { - max-width: 64ch; - margin: 2rem auto; -} - -.post blockquote { - padding: 0.5rem 1rem; - margin: 0 0 1rem; - padding-left: 2rem; - border-left: 0.0125rem solid black; -} - -.post figure { - width: 1000px; +figure { margin: 0; padding: 0; } -.post__image { + + +/* Lists + ========================================================================== */ +ul { + list-style-type: square; +} + + +/* Tables + ========================================================================== */ +table { + border-collapse: collapse; width: 100%; + text-align: left; + border-bottom: var(--table-border); + background-color: var(--color-lightgrey); +} +thead { + background-color: var(--color-darkgrey); + color: var(--color-white); + border-bottom: var(--table-border); +} +thead a { + color: inherit; + text-decoration: none; +} +tr:nth-child(even) { + /*background-color: var(--color-light-gray);*/ +} +th, td { + padding: 1rem; +} +tr { + /*border-bottom: var(--table-border);*/ +} +@media screen and (max-width: 600px) { + tr { + display: grid; + grid-template-columns: 1fr; + } +} +tbody tr { + border-bottom: 0.25rem solid var(--color-white); +} +tbody tr:hover { + background-color: var(--color-highlight); +} + +tbody tr.has-link { + cursor: pointer; +} + +/* ========================================================================== + Forms + ========================================================================== */ +textarea { + box-sizing: border-box; + font: inherit; + font-size: 1.25rem; + padding: 0.5rem 1rem; + width: 100%; + resize: vertical; + line-height: 1.75; +} + + +button, +.action-button { + cursor: pointer; + border: none; + font: inherit; + background-color: var(--color-darkgrey); + color: var(--color-white); + text-decoration: none; + padding: 0.5rem; + font-weight: bold; + box-sizing: border-box; + display: inline-block; +} + +.action-button:hover { + background-color: var(--color-highlight); +} + + +/* ========================================================================== + Block Elements + ========================================================================== */ +main { + max-width: 1200px; + margin: 0 auto; +} + + +/* ========================================================================== + Header + ========================================================================== */ + +.site__header { + margin-bottom: 1rem; + background-color: var(--color-darkgrey); + padding: 1rem; + display: flex; + justify-content: space-between; + align-items: center; + color: var(--color-white); +} +.site__header h1 { + margin: 0; +} +.site__header a { + text-transform: lowercase; + font-variant: small-caps; + text-decoration: none; +} + +/* Site Nav + ========================================================================== */ +.site__nav menu { + margin: 0; + padding: 0; + list-style: none; + display: flex; +} +.site__nav menu li:not(:last-child) { + margin-right: 1rem; +} + +.site__nav a { + font-weight: bold; +} + + +/* Breadcrumbs + ========================================================================== */ +.breadcrumbs { + background-color: var(--color-light-gray); +} +.breadcrumbs menu { + margin: 1rem 0; + padding: 0; + line-height: 1.75; + list-style: none; + display: flex; + /*justify-content: center;*/ + flex-wrap: wrap; +} +.breadcrumbs menu li:not(:last-child), +.breadcrumbs menu span:not(:last-child) { + margin-right: 0.5rem; +} + + +/* ========================================================================== + Post + ========================================================================== */ +.post__header { + display: flex; + justify-content: space-between; +} +.post__content { + font-family: 'STIX Two Text'; + font-size: 200%; + margin-bottom: 4rem; } /* ========================================================================== - Editor + Comments ========================================================================== */ +.comment { + margin: 2rem 0; + background-color: var(--color-lightgrey); + padding: 1rem; +} + +.comment__content { + font-family: 'STIX Two Text'; + font-size: 200%; + max-width: 64ch; +} + +.comment p { + line-height: 1.75; +} +.comment ul { + line-height: 1.75; +} + + +.comments__form textarea { + font-family: 'STIX Two Text'; + font-size: 200%; + line-height: 1.75; +} diff --git a/src/templates/base.html b/src/templates/base.html index 8123256..0097383 100644 --- a/src/templates/base.html +++ b/src/templates/base.html @@ -23,8 +23,12 @@