can now also order topics

This commit is contained in:
CDaut 2022-06-18 12:18:44 +02:00 committed by CDaut
parent ead8a3a2ef
commit eca6e5d716
8 changed files with 103 additions and 13 deletions

View file

@ -0,0 +1,28 @@
# Generated by Django 4.0.5 on 2022-06-18 08:15
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('blog', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='blogpost',
name='title',
field=models.CharField(max_length=255, unique=True),
),
migrations.AlterField(
model_name='tag',
name='name',
field=models.CharField(max_length=255, unique=True),
),
migrations.AlterField(
model_name='topic',
name='name',
field=models.CharField(max_length=255, unique=True),
),
]

View file

@ -2,7 +2,11 @@ from django.db import models
class Tag(models.Model): class Tag(models.Model):
name = models.CharField(max_length=255)
def __str__(self) -> str:
return str(self.name)
name = models.CharField(max_length=255, unique=True)
class Topic(models.Model): class Topic(models.Model):
@ -10,7 +14,7 @@ class Topic(models.Model):
def __str__(self) -> str: def __str__(self) -> str:
return str(self.name) return str(self.name)
name = models.CharField(max_length=255) name = models.CharField(max_length=255, unique=True)
numbered = models.BooleanField(default=False) numbered = models.BooleanField(default=False)
rootTopic = models.ForeignKey('self', blank=True, null=True, on_delete=models.CASCADE) rootTopic = models.ForeignKey('self', blank=True, null=True, on_delete=models.CASCADE)
@ -22,7 +26,7 @@ class Blogpost(models.Model):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
last_modified = models.DateTimeField(auto_now=True) last_modified = models.DateTimeField(auto_now=True)
title = models.CharField(max_length=255) title = models.CharField(max_length=255, unique=True)
tags = models.ManyToManyField(Tag) tags = models.ManyToManyField(Tag)
topic = models.ForeignKey(Topic, blank=True, null=True, on_delete=models.CASCADE) topic = models.ForeignKey(Topic, blank=True, null=True, on_delete=models.CASCADE)
mdfile = models.CharField(max_length=255) mdfile = models.CharField(max_length=255)

View file

@ -2,6 +2,7 @@ import os
import random import random
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.db import IntegrityError
from django.http import HttpResponse from django.http import HttpResponse
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from blog.factories import TopicFactory from blog.factories import TopicFactory
@ -21,17 +22,24 @@ def order(request):
if request.method == "POST": if request.method == "POST":
root_id = int(request.POST['rootID']) if request.POST['rootID'] != 'root_list' else None root_id = int(request.POST['rootID']) if request.POST['rootID'] != 'root_list' else None
child_id = int(request.POST['childID']) child_id = int(request.POST['childID'])
objtype = request.POST['relinkType']
if objtype == 'topic':
child_topic = Topic.objects.get(pk=child_id) child_topic = Topic.objects.get(pk=child_id)
child_topic.rootTopic = Topic.objects.get(pk=root_id) if root_id is not None else None child_topic.rootTopic = Topic.objects.get(pk=root_id) if root_id is not None else None
child_topic.save() child_topic.save()
elif objtype == 'post':
post = Blogpost.objects.get(pk=child_id)
post.topic = Topic.objects.get(pk=root_id) if root_id is not None else None
post.save()
context = {'roottopics': Topic.objects.all().filter(rootTopic=None)} context = {'roottopics': Topic.objects.all().filter(rootTopic=None), 'allposts': Blogpost.objects.all()}
return render(request, 'blog/order.html', context) return render(request, 'blog/order.html', context)
@login_required @login_required
def addpost(request) -> HttpResponse: def addpost(request) -> HttpResponse:
context = {'alltopics': Topic.objects.all().order_by('name').values(), 'markdown': ''}
if request.method == 'POST': if request.method == 'POST':
title = request.POST['title'] title = request.POST['title']
markdown = request.POST['markdown'] markdown = request.POST['markdown']
@ -46,15 +54,21 @@ def addpost(request) -> HttpResponse:
topicid = request.POST['topic'] topicid = request.POST['topic']
topic = None if topicid == "No topic" else Topic.objects.get(pk=topicid) topic = None if topicid == "No topic" else Topic.objects.get(pk=topicid)
try:
new_post = Blogpost.objects.create(title=title, topic=topic) new_post = Blogpost.objects.create(title=title, topic=topic)
new_post.tags.set(tags) new_post.tags.set(tags)
except IntegrityError:
context = {'alltopics': Topic.objects.all().order_by('name').values(),
'error': 'Blogpost titles need to be unique. No post created.',
"markdown": markdown}
return render(request, 'blog/addpost.html', context)
filepath = os.path.join(os.environ.get("MD_FILE_PATH"), title + ".md") filepath = os.path.join(os.environ.get("MD_FILE_PATH"), title + ".md")
with open(filepath, "w+") as mdfile: with open(filepath, "w+") as mdfile:
mdfile.write(markdown) mdfile.write(markdown)
mdfile.close() mdfile.close()
context['error'] = "Post " + title + " created."
context = {'alltopics': Topic.objects.all().order_by('name').values()}
return render(request, 'blog/addpost.html', context) return render(request, 'blog/addpost.html', context)

View file

@ -9,3 +9,11 @@
padding: 0.5em 0.5em 0.5em 1em; padding: 0.5em 0.5em 0.5em 1em;
margin: 0.5em 0.5em 0.5em 0; margin: 0.5em 0.5em 0.5em 0;
} }
#root_list {
box-shadow: 3px 3px 11px 4px rgb(231, 231, 231);
-webkit-box-shadow: 3px 3px 11px 4px rgb(231, 231, 231);
-moz-box-shadow: 3px 3px 11px 4px rgb(231, 231, 231);
padding: 0.5em 0.5em 0.5em 1em;
margin: 2em 0.5em 0.5em 0;
}

View file

@ -15,7 +15,7 @@
</head> </head>
<body> <body>
<header> <header>
<nav class="top-nav" style="background-color: #22db90"> <nav class="top-nav" style="background-color: #35aca1">
<a href="#" data-target="slide-out" class="sidenav-trigger full hide-on-large-only" id="open-sidenav-toggle"> <a href="#" data-target="slide-out" class="sidenav-trigger full hide-on-large-only" id="open-sidenav-toggle">
<i class="material-icons">menu</i> <i class="material-icons">menu</i>
</a> </a>

View file

@ -6,6 +6,7 @@
{% block includehere %} {% block includehere %}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css">
<link rel="stylesheet" href="{% static 'addpost.css' %}"> <link rel="stylesheet" href="{% static 'addpost.css' %}">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/highlight.js/latest/styles/github.min.css">
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div class="col s12"> <div class="col s12">
@ -70,6 +71,9 @@
enabled: true, enabled: true,
uniqueId: "mainBlogEditor" uniqueId: "mainBlogEditor"
}, },
renderingConfig: {
codeSyntaxHighlighting: true,
},
toolbar: [ toolbar: [
"heading-3", "heading-3",
"heading-smaller", "heading-smaller",
@ -102,7 +106,6 @@
} }
] ]
}); });
$("#mde").data({editor: simplemde}); $("#mde").data({editor: simplemde});
</script> </script>
<script> <script>
@ -110,6 +113,10 @@
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
var elems = document.querySelectorAll('select'); var elems = document.querySelectorAll('select');
M.FormSelect.init(elems); M.FormSelect.init(elems);
if ("{{ error }}" !== "") {
M.toast({html: '{{ error }}'});
}
}); });
</script> </script>
<script src="https://cdn.jsdelivr.net/highlight.js/latest/highlight.min.js"></script>
{% endblock %} {% endblock %}

View file

@ -13,6 +13,17 @@
{% for topic in roottopics %} {% for topic in roottopics %}
{% include "blog/tree_view_template.html" %} {% include "blog/tree_view_template.html" %}
{% endfor %} {% endfor %}
<ul class="topic_list" ondrop="drop(event)" ondragover="allowDrop(event)" id="list_posts_{{ topic.id }}">
{% for post in allposts %}
{% if post.topic == None %}
<li class="topic_list_element" draggable="true" ondragstart="drag(event)"
id="list_elem_post_{{ post.id }}">
Post: {{ post }}
</li>
{% endif %}
{% endfor %}
</ul>
</ul> </ul>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
@ -58,9 +69,16 @@
ev.target.style.backgroundColor = ""; ev.target.style.backgroundColor = "";
let fakeForm = new FormData() let fakeForm = new FormData()
fakeForm.append("childID", targetObject.replace("list_elem_", "")); fakeForm.append("childID", targetObject.replace("list_elem_", "").replace("post_", ""));
fakeForm.append("rootID", ev.target.id.replace("list_elem_", "")); fakeForm.append("rootID", ev.target.id.replace("list_elem_", ""));
if (targetObject.replace("list_elem_", "").startsWith("post_")) {
fakeForm.append("relinkType", "post")
} else {
fakeForm.append("relinkType", "topic")
}
fetch("{% url 'order' %}", { fetch("{% url 'order' %}", {
method: 'POST', method: 'POST',
body: fakeForm body: fakeForm

View file

@ -10,4 +10,15 @@
{% endfor %} {% endfor %}
</ul> </ul>
{% endif %} {% endif %}
<ul class="topic_list" ondrop="drop(event)" ondragover="allowDrop(event)" id="list_posts_{{ topic.id }}">
{% for post in allposts %}
{% if post.topic.id == topic.id %}
<li class="topic_list_element" draggable="true" ondragstart="drag(event)"
id="list_elem_post_{{ post.id }}">
Post: {{ post }}
</li>
{% endif %}
{% endfor %}
</ul>
</li> </li>