diff options
| author | Bobby <[email protected]> | 2022-09-20 02:03:36 -0400 |
|---|---|---|
| committer | Bobby <[email protected]> | 2022-09-20 02:03:36 -0400 |
| commit | c5254b6f39939bc0bc6719b854b67928af74c9ea (patch) | |
| tree | 692510e10ba5619f70b1b3df23352721cfac7159 | |
| parent | e29f7902c8d6dc6e6ee02964b56284d2f69f1ac5 (diff) | |
| download | thatcomputerscientist-c5254b6f39939bc0bc6719b854b67928af74c9ea.tar.xz thatcomputerscientist-c5254b6f39939bc0bc6719b854b67928af74c9ea.zip | |
Added Edit post function
| -rw-r--r-- | blog_admin/urls.py | 1 | ||||
| -rw-r--r-- | blog_admin/views.py | 37 | ||||
| -rw-r--r-- | static/css/main.css | 7 | ||||
| -rw-r--r-- | templates/blog/post.html | 7 | ||||
| -rw-r--r-- | templates/blog_admin/edit_post.html | 253 | ||||
| -rw-r--r-- | templates/blog_admin/posts.html | 2 |
6 files changed, 302 insertions, 5 deletions
diff --git a/blog_admin/urls.py b/blog_admin/urls.py index b0710851..a8f6bc49 100644 --- a/blog_admin/urls.py +++ b/blog_admin/urls.py @@ -10,6 +10,7 @@ urlpatterns = [ path('posts', views.posts, name='posts'), path('posts/new', views.new_post, name='new-post'), path('posts/search', views.posts_search, name='posts-search'), + path('posts/<str:slug>/edit', views.edit_post, name='edit-post'), path('comments', views.comments, name='comments'), path('categories', views.categories, name='categories'), path('categories/new', views.new_category, name='new-category'), diff --git a/blog_admin/views.py b/blog_admin/views.py index 7732866a..ca107390 100644 --- a/blog_admin/views.py +++ b/blog_admin/views.py @@ -43,7 +43,6 @@ def new_post(request): if request.method == 'POST': title = request.POST.get('title') body = request.POST.get('body') - print(body) category = request.POST.get('category') tags = request.POST.get('tags') slug = request.POST.get('slug') @@ -69,6 +68,42 @@ def new_post(request): else: return redirect('blog:home') +def edit_post(request, slug): + if request.user.is_authenticated and (request.user.is_superuser or request.user.is_staff): + categories = Category.objects.all() + post = Post.objects.get(slug = slug) + if request.method == 'POST': + title = request.POST.get('title') + body = request.POST.get('body') + category = request.POST.get('category') + tags = request.POST.get('tags') + slug = request.POST.get('slug') + if title and body and category and tags and slug: + try: + category = Category.objects.get(slug = category) + tags = tags.split(',') + tags = [tag.strip() for tag in tags] + tags = [Tag.objects.get_or_create(slug = tag, name = tag)[0] for tag in tags] + post.title = title + post.body = body + post.category = category + post.slug = slug + post.author = request.user + post.tags.set(tags) + post.save() + messages.success(request, 'Post edited successfully!') + return redirect('blog-admin:posts') + except Exception as e: + messages.error(request, 'Error: {}'.format(e), extra_tags='edit_post_create_error') + return render(request, 'blog_admin/edit_post.html', { 'title': 'Edit Post', 'categories': categories, 'blog_title': title, 'blog_body': body, 'blog_category': category, 'blog_tags': tags, 'blog_slug': slug, 'post': post }) + else: + messages.error(request, 'Error: All fields are required!', extra_tags='edit_post_create_error') + return render(request, 'blog_admin/edit_post.html', { 'title': 'Edit Post', 'categories': categories, 'blog_title': title, 'blog_body': body, 'blog_category': category, 'blog_tags': tags, 'blog_slug': slug, 'post': post }) + else: + return render(request, 'blog_admin/edit_post.html', { 'title': 'Edit Post', 'categories': categories, 'blog_title': post.title, 'blog_body': post.body, 'blog_category': post.category.slug, 'blog_tags': ','.join([tag.slug for tag in post.tags.all()]), 'blog_slug': post.slug, 'post': post }) + else: + return redirect('blog:home') + def comments(request): pass diff --git a/static/css/main.css b/static/css/main.css index 494f3197..9210d2ad 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -253,6 +253,13 @@ summary { margin-top: 0px; } +.article-body > p > img { + display: block; + margin: 0px auto 10px auto; + max-height: 50vh; + max-width: 100%; +} + /* Optimize for phones */ @media only screen and (max-width: 480px) { body { diff --git a/templates/blog/post.html b/templates/blog/post.html index 0fe9ee07..948ebb95 100644 --- a/templates/blog/post.html +++ b/templates/blog/post.html @@ -1,6 +1,6 @@ {% extends 'blog/partials/base.html' %} {% block content %} <div class="main"> - <section> + <article> <h1 style="margin-bottom: 12px">{{ post.title }}</h1> <p style="line-height: 1.6em;"> Posted on <em><u>{{ post.date | date:"M d, Y" }}</u></em> by <em><a href="#">{{ post.author }}</a> in <a href="#">{{ post.category }}</a></em> @@ -12,7 +12,7 @@ </p> <hr> - <div>{{ post.body | safe }}</div> + <div class="article-body">{{ post.body | safe }}</div> <div id="comments" style="margin-top: 3rem;"> <h3>Comments</h3> {% for comment in comments %} @@ -48,6 +48,7 @@ <p><em>You must be logged in to comment.</em></p> {% endif %} </div> - </section> +</article> + <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script> </div> {% endblock %} diff --git a/templates/blog_admin/edit_post.html b/templates/blog_admin/edit_post.html new file mode 100644 index 00000000..09bba62c --- /dev/null +++ b/templates/blog_admin/edit_post.html @@ -0,0 +1,253 @@ +{% extends 'blog/partials/base.html' %} {% block content %} +<link + rel="stylesheet" + href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/monokai-sublime.min.css" +/> +<link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet" /> +<style> + .ql-editor { + font-family: "Times New Roman", Times, serif; + } +</style> +<div class="main"> + <section> + {% include 'blog_admin/partials/posts_topbar.html' %} + <form action="{% url 'blog-admin:edit-post' blog_slug %}" method="post"> + {% csrf_token %} + <div class="form-group"> + <label for="title">Title</label> + <input + style="display: inline-block" + type="text" + class="form-control" + id="title" + name="title" + placeholder="Enter an Amazing Title" + value="{{ blog_title }}" + /> + </div> + <div class="form-group"> + <label for="slug">Slug</label> + <input + style="display: inline-block" + type="text" + class="form-control" + id="slug" + name="slug" + placeholder="Enter an Amazing Slug" + value="{{ blog_slug }}" + /> + </div> + <div class="form-group"> + <div id="toolbar-container"> + <span class="ql-formats"> + <button class="ql-header" value="1"></button> + <button class="ql-header" value="2"></button> + </span> + <span class="ql-formats"> + <button class="ql-bold"></button> + <button class="ql-italic"></button> + <button class="ql-underline"></button> + <button class="ql-strike"></button> + </span> + <span class="ql-formats"> + <button class="ql-blockquote"></button> + <button class="ql-code-block"></button> + </span> + <span class="ql-formats"> + <button class="ql-script" value="sub"></button> + <button class="ql-script" value="super"></button> + </span> + + <span class="ql-formats"> + <button class="ql-list" value="ordered"></button> + <button class="ql-list" value="bullet"></button> + </span> + <span class="ql-formats"> + <select class="ql-align"></select> + </span> + <span class="ql-formats"> + <button class="ql-link"></button> + <button class="ql-image"></button> + <button class="ql-formula"></button> + {% load static %} + <button class="ql-formula-block"> + <img + style="height: 32px; position: relative; top: -6px; left: 4px" + src="{% static 'images/icons/formula.png' %}" + alt="Block Formula" + /> + </button> + </span> + <span class="ql-formats"> + <button class="ql-clean"></button> + </span> + </div> + <div id="editor-container" style="height: 60vh"></div> + </div> + <div class="form-group"> + <label for="tags">Tags</label> + <input + style="display: inline-block" + type="text" + class="form-control" + id="tags" + name="tags" + placeholder="Enter Tags" + value="{{ blog_tags }}" + /> + </div> + <div class="form-group"> + <label for="category">Category</label> + <select class="form-control" id="category" name="category" style = "display: inline-block"> + {% for category in categories %} + <option value="{{ category.slug }}" {% if category.slug == blog_category %} selected {% endif %}>{{ category.name }}</option> + {% endfor %} + </select> + </div> + <div class="form-group" style="display: none;"> + <textarea name="body" id="body">{{ blog_body }}</textarea> + </div> + <div class="form-group"> + <button type="submit" class="btn btn-primary">Submit</button> + </div> + </form> + </section> +</div> +<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script> +<script src="https://cdn.quilljs.com/1.3.6/quill.min.js"></script> +<script src="https://cdn.jsdelivr.net/gh/T-vK/DynamicQuillTools@master/DynamicQuillTools.js"></script> +<script> + const Parchment = Quill.import("parchment"); + const Delta = Quill.import("delta"); + class MathjaxInline extends Parchment.Embed { + static create(value) { + const node = super.create(value); + if (typeof value === "string") { + node.innerHTML = "" + this.tex2svg(value) + ""; + node.contentEditable = "false"; + node.setAttribute("data-value", value); + } + return node; + } + + static value(domNode) { + return domNode.getAttribute("data-value"); + } + + static tex2svg(latex) { + let MathJaxNode = document.createElement("DIV"); + MathJaxNode.style.visibility = "hidden"; + MathJaxNode.innerHTML = "\\(" + latex + "\\)"; + document.body.appendChild(MathJaxNode); + MathJax.typeset(); + let svg = MathJaxNode.innerHTML; + document.body.removeChild(MathJaxNode); + return svg; + } + } + + class MathjaxBlock extends Parchment.Embed { + static create(value) { + const node = super.create(value); + if (typeof value === "string") { + node.innerHTML = "" + this.tex2svg(value) + ""; + node.contentEditable = "false"; + node.setAttribute("data-value", value); + } + return node; + } + + static value(domNode) { + return domNode.getAttribute("data-value"); + } + + static tex2svg(latex) { + let MathJaxNode = document.createElement("DIV"); + MathJaxNode.style.visibility = "hidden"; + MathJaxNode.innerHTML = "\\[" + latex + "\\]"; + document.body.appendChild(MathJaxNode); + MathJax.typeset(); + let svg = MathJaxNode.innerHTML; + document.body.removeChild(MathJaxNode); + return svg; + } + } + + // Set module properties + MathjaxInline.blotName = "mathjax-inline"; + MathjaxInline.className = "ql-mathjax-inline"; + MathjaxInline.tagName = "SPAN"; + MathjaxBlock.blotName = "mathjax-block"; + MathjaxBlock.className = "ql-mathjax-block"; + MathjaxBlock.tagName = "DIV"; + + // Register the module + Quill.register(MathjaxInline); + Quill.register(MathjaxBlock); + + function insertFormula(quill, block) { + var range = quill.getSelection(); + var latex = prompt( + "Enter a LaTeX formula", + quill.getText(range) == "" ? "e=mc^2" : quill.getText(range) + ); + quill.deleteText(range.index, range.length); + if (block) { + quill.insertEmbed(range.index, "mathjax-block", latex); + } else { + quill.insertEmbed(range.index, "mathjax-inline", latex); + } + quill.insertText(range.index + range.length + 1, " "); + quill.setSelection(range.index + range.length + 1); + } + + var quill = new Quill("#editor-container", { + modules: { + syntax: true, + toolbar: { + container: "#toolbar-container", + handlers: { + formula: function () { + insertFormula(quill, false); + }, + "formula-block": function () { + insertFormula(quill, true); + }, + }, + }, + }, + placeholder: "Compose an epic...", + theme: "snow", + }); + + // update body on text change + quill.on("text-change", function (delta, oldDelta, source) { + document.getElementById("body").value = quill.root.innerHTML; + }); + + function slugify(text) { + return text + .toString() + .toLowerCase() + .replace(/\s+/g, "-") // Replace spaces with - + .replace(/[^\w\-]+/g, "") // Remove all non-word chars + .replace(/\-\-+/g, "-") // Replace multiple - with single - + .replace(/^-+/, "") // Trim - from start of text + .replace(/-+$/, ""); // Trim - from end of text + } + + // slugify title + document.getElementById("title").addEventListener("input", function () { + document.getElementById("slug").value = slugify(this.value); + }); + + try { + const delta = quill.clipboard.convert(document.getElementById("body").value); + quill.setContents(delta, "silent"); + } catch (e) { + console.log(e); + } +</script> +{% endblock %} diff --git a/templates/blog_admin/posts.html b/templates/blog_admin/posts.html index 8c1e14aa..5d56f0c5 100644 --- a/templates/blog_admin/posts.html +++ b/templates/blog_admin/posts.html @@ -25,7 +25,7 @@ <td><a href="#">{{ post.category }}</a></td> <td style="position: relative;"> {% if post.is_public %} <span class="label label-success">Published</span> {% else %} <span class="label label-warning">Draft</span> {% endif %} </td> <td> - <a href="#">Edit</a> + <a href="{% url 'blog-admin:edit-post' post.slug %}">Edit</a> <a href="#" class="error">Delete</a> {% if post.is_public %} <a href="#" class="error">UnPublish</a> |
