Jul 22 - Update - add Rich-text editor, draft/publish, drag-to-reorder
This commit is contained in:
@@ -4,12 +4,12 @@ import re
|
||||
from functools import wraps
|
||||
|
||||
from flask import (
|
||||
Blueprint, current_app, flash, redirect, render_template,
|
||||
Blueprint, abort, current_app, flash, jsonify, redirect, render_template,
|
||||
request, session, url_for,
|
||||
)
|
||||
from werkzeug.security import check_password_hash
|
||||
|
||||
from app import db, log_action, AuditLog, Section, Topic
|
||||
from app import db, log_action, sanitize_html, AuditLog, Section, Topic
|
||||
|
||||
admin_bp = Blueprint("admin", __name__, url_prefix="/admin")
|
||||
|
||||
@@ -171,13 +171,14 @@ def topic_form(topic_id=None):
|
||||
topic.section_id = section_id
|
||||
topic.slug = slug
|
||||
topic.title = title
|
||||
topic.body_html = f.get("body_html", "").strip() or None
|
||||
topic.body_html = sanitize_html(f.get("body_html", ""))
|
||||
topic.link_url = f.get("link_url", "").strip() or None
|
||||
topic.link_label = f.get("link_label", "").strip() or None
|
||||
topic.media_type = media_type
|
||||
topic.media_url = f.get("media_url", "").strip() or None
|
||||
topic.media_caption = f.get("media_caption", "").strip() or None
|
||||
topic.sort_order = _int(f.get("sort_order"), 0)
|
||||
topic.is_published = f.get("is_published") == "1"
|
||||
|
||||
if is_new:
|
||||
db.session.add(topic)
|
||||
@@ -207,6 +208,66 @@ def topic_delete(topic_id):
|
||||
return redirect(url_for("admin.dashboard"))
|
||||
|
||||
|
||||
@admin_bp.route("/topic/<int:topic_id>/toggle", methods=["POST"])
|
||||
@login_required
|
||||
def topic_toggle(topic_id):
|
||||
topic = Topic.query.get_or_404(topic_id)
|
||||
topic.is_published = not topic.is_published
|
||||
db.session.commit()
|
||||
state = "published" if topic.is_published else "unpublished (draft)"
|
||||
log_action(session.get("admin"), "update", "topic", topic.id,
|
||||
f"{state}: {topic.title}")
|
||||
flash(f"'{topic.title}' is now {state}.", "ok")
|
||||
return redirect(url_for("admin.dashboard"))
|
||||
|
||||
|
||||
# ------------------------------------------------------------------ reorder
|
||||
@admin_bp.route("/reorder", methods=["POST"])
|
||||
@login_required
|
||||
def reorder():
|
||||
"""Persist drag-and-drop order. JSON body:
|
||||
{"type":"topic","section_id":N,"order":[id,...]} reorder within a section
|
||||
{"type":"section","order":[id,...]} reorder sections
|
||||
Sort values are rewritten to 10,20,30,... in the given order."""
|
||||
data = request.get_json(silent=True) or {}
|
||||
kind = data.get("type")
|
||||
order = data.get("order") or []
|
||||
if kind not in ("topic", "section") or not isinstance(order, list):
|
||||
abort(400)
|
||||
|
||||
ids = []
|
||||
for v in order:
|
||||
iv = _int(v, None)
|
||||
if iv is None:
|
||||
abort(400)
|
||||
ids.append(iv)
|
||||
|
||||
if kind == "topic":
|
||||
section_id = _int(data.get("section_id"), None)
|
||||
if section_id is None:
|
||||
abort(400)
|
||||
# Only reorder topics that actually belong to this section.
|
||||
rows = {t.id: t for t in Topic.query.filter(
|
||||
Topic.section_id == section_id, Topic.id.in_(ids)
|
||||
).all()}
|
||||
for i, tid in enumerate(ids):
|
||||
if tid in rows:
|
||||
rows[tid].sort_order = (i + 1) * 10
|
||||
detail = f"reordered {len(rows)} topics in section {section_id}"
|
||||
entity = "topic"
|
||||
else:
|
||||
rows = {s.id: s for s in Section.query.filter(Section.id.in_(ids)).all()}
|
||||
for i, sid in enumerate(ids):
|
||||
if sid in rows:
|
||||
rows[sid].sort_order = (i + 1) * 10
|
||||
detail = f"reordered {len(rows)} sections"
|
||||
entity = "section"
|
||||
|
||||
db.session.commit()
|
||||
log_action(session.get("admin"), "update", entity, None, detail)
|
||||
return jsonify(ok=True)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------ sections
|
||||
@admin_bp.route("/section/new", methods=["GET", "POST"])
|
||||
@admin_bp.route("/section/<int:section_id>", methods=["GET", "POST"])
|
||||
|
||||
Reference in New Issue
Block a user