can now also order topics
This commit is contained in:
parent
ead8a3a2ef
commit
eca6e5d716
8 changed files with 103 additions and 13 deletions
|
|
@ -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),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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 %}
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue