add infobox support

This commit is contained in:
2026-04-25 16:15:37 +03:00
parent 3d7188eb71
commit 29f2318cba
7 changed files with 59 additions and 6 deletions

View File

@@ -1,6 +1,8 @@
from flask import Blueprint, abort, redirect, url_for, request, render_template
from flask import Blueprint, abort, redirect, url_for, request, render_template, flash
from ..constants import InfoboxKind
from ..auth import is_logged_in, get_active_user, csrf_verified
from ..models import Topics, Threads
from slugify import slugify
bp = Blueprint('mod', __name__, url_prefix='/mod/')
@bp.before_request
@@ -39,9 +41,21 @@ def edit_topic_post(topic_id):
topic = Topics.find({'id': topic_id})
if not topic:
abort(404)
target_name = request.form.get('name').strip()
name_exists = Topics.count([
('lower(name)', '=', target_name.lower()),
('id', '!=', topic.id)
]) > 0
if name_exists:
flash(f'A topic named "{target_name}" already exists.', InfoboxKind.ERROR)
return redirect(url_for('.edit_topic', topic_id=topic_id))
topic.update({
'name': request.form.get('name').strip(),
'name': target_name,
'description': request.form.get('description').strip(),
'slug': slugify(target_name[:50]),
})
return redirect(url_for('topics.topic_by_id', topic_id=topic.id))

View File

@@ -1,3 +1,4 @@
{%- from 'common/macros.html' import infobox with context -%}
<!DOCTYPE html>
<html lang="en">
<head>
@@ -13,6 +14,13 @@
</head>
<body>
{%- include 'common/topnav.html' -%}
{%- with messages = get_flashed_messages(with_categories=true) -%}
{%- if messages -%}
{%- for category, message in messages -%}
{{- infobox(message, category) -}}
{%- endfor -%}
{%- endif -%}
{%- endwith -%}
{%- block content -%}{%- endblock -%}
{%- include 'common/footer.html' -%}
</body>

View File

@@ -0,0 +1,11 @@
{%- macro icn_info(width=48) -%}
<svg height="{{width}}" viewBox="0 0 32 32" width="{{width}}" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><filter id="if1" color-interpolation-filters="sRGB" height="1.09976" width="1" x="0" y="0"><feFlood flood-opacity=".14902" in="SourceGraphic" result="flood"/><feGaussianBlur in="SourceGraphic" result="blur" stdDeviation="0"/><feOffset dx="0" dy="1.5" in="blur" result="offset"/><feComposite in="flood" in2="offset" operator="in" result="comp1"/><feComposite in="SourceGraphic" in2="comp1" operator="over" result="comp2"/></filter><linearGradient id="ilg1" gradientTransform="matrix(.921875 0 0 .9225 1.249998 1.239999)" gradientUnits="userSpaceOnUse" x1="16" x2="16" y1="0" y2="32"><stop offset=".15427744" stop-color="#4b8be1" stop-opacity=".992157"/><stop offset="1" stop-color="#1078e8" stop-opacity=".992157"/></linearGradient><linearGradient id="ilg2" gradientUnits="userSpaceOnUse" x1="15.99999832" x2="15.99999832" y1=".126983" y2="31.87301564"><stop offset="0" stop-color="#a9cef8"/><stop offset=".73127526" stop-color="#4f99e7"/></linearGradient><g><circle cx="16" cy="16" fill="#0e3459" fill-opacity=".500866" r="16"/><circle cx="16" cy="16" fill="url(#ilg2)" r="15.625" stroke="#4d677d" stroke-linecap="round" stroke-linejoin="round" stroke-width=".25"/><ellipse cx="16" cy="16" fill="url(#ilg1)" rx="14.75" ry="14.76"/><g fill="#fff" stroke-linecap="round" stroke-linejoin="round"><path d="m29.494141 10.042735a14.75 14.76 0 0 0 -13.494141-8.8027352 14.75 14.76 0 0 0 -13.49414 8.8027352c2.987994-2.3171382 8.240661-4.0429692 13.49414-4.0429692s10.506146 1.725831 13.494141 4.0429692z" fill-opacity=".216645"/><path d="m15.716477 10.189534q-.789603 0-1.344793-.5428521-.542852-.5551897-.542852-1.3447928 0-.7772656.542852-1.3201177.55519-.5551897 1.344793-.5551897.777266 0 1.320118.5551897.55519.5428521.55519 1.3201177 0 .7896031-.55519 1.3447928-.542852.5428521-1.320118.5428521zm1.529856 14.780383h-2.282446v-11.091456h-1.233755v-1.86297h3.516201z" filter="url(#if1)" stroke-width=".25"/></g></g></svg>
{%- endmacro -%}
{%- macro icn_warn(width=48) -%}
<svg height="{{width}}" viewBox="0 0 32 32" width="{{width}}" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><filter id="wf1" color-interpolation-filters="sRGB" height="1.09976" width="1" x="0" y="0"><feFlood flood-opacity=".14902" in="SourceGraphic" result="flood"/><feGaussianBlur in="SourceGraphic" result="blur" stdDeviation="0"/><feOffset dx="0" dy="1.5" in="blur" result="offset"/><feComposite in="flood" in2="offset" operator="in" result="comp1"/><feComposite in="SourceGraphic" in2="comp1" operator="over" result="comp2"/></filter><linearGradient id="wlg1" gradientTransform="matrix(1.01415 0 0 .99686492 -.226398 -.52981)" gradientUnits="userSpaceOnUse" x1="16" x2="15.999999" y1="1.302475" y2="30.000002"><stop offset="0" stop-color="#f4f4ed"/><stop offset=".72657222" stop-color="#ddcf76"/></linearGradient><linearGradient id="wlg2" gradientUnits="userSpaceOnUse" x1="16" x2="16" y1="2.369791" y2="29.630209"><stop offset=".25" stop-color="#edd86d"/><stop offset="1" stop-color="#d5901a"/></linearGradient><g><path d="m14.960961 2.718822-14.675898 25.36219a1.2153386 1.2001658 0 0 0 1.055209 1.795616h29.319455a1.2153386 1.2001658 0 0 0 1.05521-1.795616l-14.6759-25.36219a1.1967125 1.1817724 0 0 0 -2.078076 0z" fill="#443c09" fill-opacity=".500632"/><path d="m14.99368 3.1949619-14.21375986 24.4501341a1.1770681 1.1570063 0 0 0 1.02198136 1.731044h28.3961965a1.1770681 1.1570063 0 0 0 1.021982-1.731044l-14.213761-24.4501341a1.1590285 1.1392744 0 0 0 -2.012639 0z" fill="url(#wlg1)" stroke="#6b5b07" stroke-linecap="round" stroke-linejoin="round" stroke-width=".25"/><path d="m15.11254 4.0052032-12.6044459 22.9058128c-.3954388.72251.1042399 1.621487.901271 1.621487l25.1812709-.0031c.79703-.000097 1.296709-.898977.90127-1.621487l-12.604448-22.9027128c-.39239-.7169421-1.382527-.7169421-1.774918 0z" fill="url(#wlg2)"/><g stroke-linecap="round" stroke-linejoin="round"><path d="m11.150645 10.205078c1.849355-1.205078 3.775283-1.205078 4.848141-1.205078 1.072971 0 3.001214 0 4.851104 1.205078l-3.962432-6.1998748c-.39239-.716943-1.383-.716943-1.775391 0z" fill="#fff" fill-opacity=".397479"/><path d="m16.00535 25.361656q-.620708 0-1.059484-.428074-.428074-.438776-.428074-1.059484 0-.610006.428074-1.03808.438776-.438776 1.059484-.438776.610005 0 1.03808.438776.438776.428074.438776 1.03808 0 .620708-.438776 1.059484-.428075.428074-1.03808.428074zm.791937-4.494779h-1.551769l-.310354-10.541328h2.129669z" fill="#443c09" filter="url(#wf1)" stroke-width=".220327" transform="matrix(1.1346739 0 0 1.1346739 -2.154783 -2.497989)"/></g></g></svg>
{%- endmacro -%}
{%- macro icn_error(width=48) -%}
<svg height="{{width}}" viewBox="0 0 32 32" width="{{width}}" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="elg1" gradientTransform="matrix(.921875 0 0 .9225 1.249998 1.239999)" gradientUnits="userSpaceOnUse" x1="16" x2="16" y1="0" y2="32"><stop offset=".15427744" stop-color="#de4747"/><stop offset="1" stop-color="#b52222"/></linearGradient><linearGradient id="elg2" gradientUnits="userSpaceOnUse" x1="15.99999832" x2="15.99999832" y1=".126983" y2="31.87301564"><stop offset="0" stop-color="#f09797"/><stop offset=".73127526" stop-color="#d24141"/></linearGradient><filter id="ef1" color-interpolation-filters="sRGB" height="1.09976" width="1" x="0" y="0"><feFlood flood-opacity=".14902" in="SourceGraphic" result="flood"/><feGaussianBlur in="SourceGraphic" result="blur" stdDeviation="0"/><feOffset dx="0" dy="1.5" in="blur" result="offset"/><feComposite in="flood" in2="offset" operator="in" result="comp1"/><feComposite in="SourceGraphic" in2="comp1" operator="over" result="comp2"/></filter><g><circle cx="16" cy="16" fill="#590e0e" fill-opacity=".500866" r="16"/><circle cx="16" cy="16" fill="url(#elg2)" r="15.625" stroke="#7d4d4d" stroke-linecap="round" stroke-linejoin="round" stroke-width=".25"/><ellipse cx="16" cy="16" fill="url(#elg1)" rx="14.75" ry="14.76"/><g fill="#fff"><path d="m8 10 2-2 6 6 6-6 2 2-6 6 6 6-2 2-6-6-6 6-2-2 6-6z" filter="url(#ef1)"/><path d="m29.494141 10.042735a14.75 14.76 0 0 0 -13.494141-8.8027352 14.75 14.76 0 0 0 -13.49414 8.8027352c2.987994-2.3171382 8.240661-4.0429692 13.49414-4.0429692s10.506146 1.725831 13.494141 4.0429692z" fill-opacity=".216645" stroke-linecap="round" stroke-linejoin="round"/></g></g></svg>
{%- endmacro -%}

View File

@@ -1,3 +1,5 @@
{%- from 'common/icons.html' import icn_info, icn_warn, icn_error -%}
{% macro timestamp(unix_ts) -%}
<span class="timestamp" data-utc="{{ unix_ts }}">{{ unix_ts | ts_datetime('%Y-%m-%d %H:%M')}} <abbr title="Server Time">ST</abbr></span>
{%- endmacro %}
@@ -180,3 +182,20 @@
{%- endif -%}
</div>
{%- endmacro %}
{% macro infobox(message, kind=InfoboxKind.INFO) -%}
<div class="infobox plank top contain-svg horizontal {{InfoboxHTMLClass[kind]}}">
{%- if kind == InfoboxKind.INFO -%}
{{- icn_info() -}}
{%- elif kind == InfoboxKind.WARN -%}
{{- icn_warn() -}}
{%- elif kind == InfoboxKind.ERROR -%}
{{- icn_error() -}}
{%- endif -%}
{%- set m = message.split(';', maxsplit=1) -%}
<strong>{{m[0]}}</strong>
{%- if m[1] -%}
{{m[1]}}
{%- endif -%}
</div>
{%- endmacro %}

View File

@@ -21,7 +21,7 @@
<legend>Actions</legend>
{%- if is_logged_in() -%}
{%- if thread.user_id == get_active_user().id -%}
<a class="linkbutton" href="{{url_for('threads.edit', thread_id=thread.id)}}">Edit&hellip;</a>
<a class="linkbutton" href="{{url_for('threads.edit', thread_id=thread.id)}}">Edit</a>
{%- endif -%}
<button>Subscribe</button>
<button disabled title="This feature requires JavaScript to be enabled.">Bookmark&hellip;</button>
@@ -32,7 +32,7 @@
<fieldset class="plank even no-shadow minimal thread-actions">
<legend>Moderation actions</legend>
{%- if thread.user_id != get_active_user().id -%}
<a class="linkbutton warn" href="{{url_for('threads.edit', thread_id=thread.id)}}">Edit&hellip;</a>
<a class="linkbutton warn" href="{{url_for('threads.edit', thread_id=thread.id)}}">Edit</a>
{%- endif -%}
<form method="POST">
<input type="hidden" name="lock" value="{{(not thread.locked()) | int}}">

View File

@@ -1,4 +1,5 @@
{% from 'common/macros.html' import timestamp, subheader %}
{% from 'common/icons.html' import icn_info, icn_warn, icn_error %}
{%- extends 'base.html' -%}
{%- block content -%}
{%- call() subheader('All topics') -%}

View File

@@ -411,11 +411,11 @@ ul.horizontal, ol.horizontal {
color: oklch(from var(--main-color) round(1.21 - L) 0 0);
&.critical {
--main-color: hsl(from var(--critical-color) h 50% calc(l * 0.7));
--main-color: hsl(from var(--critical-color) h 50% l);
}
&.warn {
--main-color: hsl(from var(--warn-color) h 50% calc(l * 1.2));
--main-color: hsl(from var(--warn-color) h 50% 75%);
}
}