cleaner form layout: CSS, forum-form class, remove hardcoded sizes/br tags
This commit is contained in:
parent
6ea664cbf6
commit
ec9e1754e4
1 changed files with 42 additions and 31 deletions
|
|
@ -16,6 +16,17 @@ def esc(s):
|
||||||
return html.escape(str(s))
|
return html.escape(str(s))
|
||||||
|
|
||||||
|
|
||||||
|
FORUM_CSS = """
|
||||||
|
<style>
|
||||||
|
.forum-form { max-width: 500px; }
|
||||||
|
.forum-form input, .forum-form textarea { width: 100%; box-sizing: border-box; padding: 6px; margin-bottom: 8px; }
|
||||||
|
.forum-form button { padding: 6px 16px; }
|
||||||
|
.forum-form label { display: block; margin-bottom: 8px; }
|
||||||
|
.forum-form small { display: block; margin-bottom: 8px; }
|
||||||
|
</style>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class ForumHandlers:
|
class ForumHandlers:
|
||||||
def __init__(self, fdb, sync, identity, reticulum, site_name="me"):
|
def __init__(self, fdb, sync, identity, reticulum, site_name="me"):
|
||||||
self.fdb = fdb
|
self.fdb = fdb
|
||||||
|
|
@ -53,7 +64,7 @@ class ForumHandlers:
|
||||||
return {
|
return {
|
||||||
"status": status,
|
"status": status,
|
||||||
"content_type": "text/html; charset=utf-8",
|
"content_type": "text/html; charset=utf-8",
|
||||||
"body": body_html,
|
"body": FORUM_CSS + body_html,
|
||||||
"headers": {},
|
"headers": {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,14 +234,14 @@ class ForumHandlers:
|
||||||
def handle_new_form(self, msg=""):
|
def handle_new_form(self, msg=""):
|
||||||
return self._respond(
|
return self._respond(
|
||||||
f"<h1>new thread</h1>"
|
f"<h1>new thread</h1>"
|
||||||
f'<form method="post" action="/forum/new">'
|
f'<form class="forum-form" method="post" action="/forum/new">'
|
||||||
f'{self._csrf_field()}'
|
f'{self._csrf_field()}'
|
||||||
f'<input name="title" placeholder="title" size="50" required><br>'
|
f'<input name="title" placeholder="title" required>'
|
||||||
f"<small>max {MAX_TITLE_LENGTH} characters</small><br><br>"
|
f"<small>max {MAX_TITLE_LENGTH} characters</small>"
|
||||||
f'<input name="url" placeholder="URL you want to share (optional)" size="50"><br><br>'
|
f'<input name="url" placeholder="URL you want to share (optional)">'
|
||||||
f'<textarea name="body" rows="6" cols="50" placeholder="details or context (optional)"></textarea><br>'
|
f'<textarea name="body" rows="6" placeholder="details or context (optional)"></textarea>'
|
||||||
f"<small>max {MAX_BODY_LENGTH} characters</small><br><br>"
|
f"<small>max {MAX_BODY_LENGTH} characters</small>"
|
||||||
f'<input name="tags" placeholder="tags, comma-separated (optional)" size="50"><br><br>'
|
f'<input name="tags" placeholder="tags, comma-separated (optional)">'
|
||||||
f'<button type="submit">post</button>'
|
f'<button type="submit">post</button>'
|
||||||
f"</form>"
|
f"</form>"
|
||||||
f"<p>{msg}</p>"
|
f"<p>{msg}</p>"
|
||||||
|
|
@ -315,10 +326,10 @@ class ForumHandlers:
|
||||||
)
|
)
|
||||||
|
|
||||||
reply_form = (
|
reply_form = (
|
||||||
f'<form method="post" action="/forum/t/{thread["id"]}/reply">'
|
f'<form class="forum-form" method="post" action="/forum/t/{thread["id"]}/reply">'
|
||||||
f'{self._csrf_field()}'
|
f'{self._csrf_field()}'
|
||||||
f'<textarea name="body" rows="4" cols="50" placeholder="share a URL or reply..." required></textarea><br>'
|
f'<textarea name="body" rows="4" placeholder="share a URL or reply..." required></textarea>'
|
||||||
f"<small>max {MAX_BODY_LENGTH} characters</small><br><br>"
|
f"<small>max {MAX_BODY_LENGTH} characters</small>"
|
||||||
f'<button type="submit">reply</button>'
|
f'<button type="submit">reply</button>'
|
||||||
f"</form>"
|
f"</form>"
|
||||||
)
|
)
|
||||||
|
|
@ -374,14 +385,14 @@ class ForumHandlers:
|
||||||
return self._error(403)
|
return self._error(403)
|
||||||
return self._respond(
|
return self._respond(
|
||||||
f"<h1>edit thread</h1>"
|
f"<h1>edit thread</h1>"
|
||||||
f'<form method="post" action="/forum/t/{thread_id}/edit">'
|
f'<form class="forum-form" method="post" action="/forum/t/{thread_id}/edit">'
|
||||||
f'{self._csrf_field()}'
|
f'{self._csrf_field()}'
|
||||||
f'<input name="title" value="{esc(thread["title"])}" size="50" required><br>'
|
f'<input name="title" value="{esc(thread["title"])}" required>'
|
||||||
f"<small>max {MAX_TITLE_LENGTH} characters</small><br><br>"
|
f"<small>max {MAX_TITLE_LENGTH} characters</small>"
|
||||||
f'<input name="url" value="{esc(thread["url"] or "")}" placeholder="URL" size="50"><br><br>'
|
f'<input name="url" value="{esc(thread["url"] or "")}" placeholder="URL">'
|
||||||
f'<textarea name="body" rows="6" cols="50" placeholder="details or context">{esc(thread["body"] or "")}</textarea><br>'
|
f'<textarea name="body" rows="6" placeholder="details or context">{esc(thread["body"] or "")}</textarea>'
|
||||||
f"<small>max {MAX_BODY_LENGTH} characters</small><br><br>"
|
f"<small>max {MAX_BODY_LENGTH} characters</small>"
|
||||||
f'<input name="tags" value="{esc(thread["tags"] or "")}" placeholder="tags, comma-separated" size="50"><br><br>'
|
f'<input name="tags" value="{esc(thread["tags"] or "")}" placeholder="tags, comma-separated">'
|
||||||
f'<button type="submit">save</button>'
|
f'<button type="submit">save</button>'
|
||||||
f"</form>"
|
f"</form>"
|
||||||
f"<p>{msg}</p>"
|
f"<p>{msg}</p>"
|
||||||
|
|
@ -513,50 +524,50 @@ class ForumHandlers:
|
||||||
f"<p>{msg}</p>"
|
f"<p>{msg}</p>"
|
||||||
f'<p><a class="forum-action" href="/forum/sync/now">sync now</a></p>'
|
f'<p><a class="forum-action" href="/forum/sync/now">sync now</a></p>'
|
||||||
f"<h2>auto-discovery</h2>"
|
f"<h2>auto-discovery</h2>"
|
||||||
f'<form method="post" action="/forum/auto_discover">'
|
f'<form class="forum-form" method="post" action="/forum/auto_discover">'
|
||||||
f'{self._csrf_field()}'
|
f'{self._csrf_field()}'
|
||||||
f'<label><input type="checkbox" name="enabled" value="1"{auto_discover_checked}>'
|
f'<label><input type="checkbox" name="enabled" value="1"{auto_discover_checked}>'
|
||||||
f" automatically discover other forum instances on the mesh</label><br><br>"
|
f" automatically discover other forum instances on the mesh</label>"
|
||||||
f'<button>save</button>'
|
f'<button>save</button>'
|
||||||
f"</form>"
|
f"</form>"
|
||||||
f"<h2>auto-sync</h2>"
|
f"<h2>auto-sync</h2>"
|
||||||
f'<form method="post" action="/forum/auto_sync">'
|
f'<form class="forum-form" method="post" action="/forum/auto_sync">'
|
||||||
f'{self._csrf_field()}'
|
f'{self._csrf_field()}'
|
||||||
f'<label><input type="checkbox" name="enabled" value="1"{auto_sync_checked}>'
|
f'<label><input type="checkbox" name="enabled" value="1"{auto_sync_checked}>'
|
||||||
f" automatically sync content every 5 minutes</label><br><br>"
|
f" automatically sync content every 5 minutes</label>"
|
||||||
f'<button>save</button>'
|
f'<button>save</button>'
|
||||||
f"</form>"
|
f"</form>"
|
||||||
f"<h2>storage</h2>"
|
f"<h2>storage</h2>"
|
||||||
f'<form method="post" action="/forum/storage">'
|
f'<form class="forum-form" method="post" action="/forum/storage">'
|
||||||
f'{self._csrf_field()}'
|
f'{self._csrf_field()}'
|
||||||
f'<label>Keep threads for '
|
f'<label>Keep threads for '
|
||||||
f'<input name="retention_days" value="{esc(retention_days)}" size="4"> days</label>'
|
f'<input name="retention_days" value="{esc(retention_days)}" size="4"> days</label>'
|
||||||
f"<br><small>Older threads are pruned automatically (default: 30). Set to 0 to keep everything.</small><br><br>"
|
f"<small>Older threads are pruned automatically (default: 30). Set to 0 to keep everything.</small>"
|
||||||
f'<button>save</button>'
|
f'<button>save</button>'
|
||||||
f"</form>"
|
f"</form>"
|
||||||
f"<h2>blocked instances</h2>"
|
f"<h2>blocked instances</h2>"
|
||||||
f"{blocked_items}"
|
f"{blocked_items}"
|
||||||
f'<form method="post" action="/forum/block">'
|
f'<form class="forum-form" method="post" action="/forum/block">'
|
||||||
f'{self._csrf_field()}'
|
f'{self._csrf_field()}'
|
||||||
f'<input name="instance" placeholder="instance hash (32 hex chars)" size="40"><br><br>'
|
f'<input name="instance" placeholder="instance hash (32 hex chars)">'
|
||||||
f'<button>block</button>'
|
f'<button>block</button>'
|
||||||
f"</form>"
|
f"</form>"
|
||||||
f"<h2>peer reports</h2>"
|
f"<h2>peer reports</h2>"
|
||||||
f"{self._peer_reports_html()}"
|
f"{self._peer_reports_html()}"
|
||||||
f"<h2>keyword filters</h2>"
|
f"<h2>keyword filters</h2>"
|
||||||
f'<form method="post" action="/forum/filters">'
|
f'<form class="forum-form" method="post" action="/forum/filters">'
|
||||||
f'{self._csrf_field()}'
|
f'{self._csrf_field()}'
|
||||||
f'<input name="keywords" value="{esc(filters_str)}" placeholder="comma-separated keywords" size="50"><br><br>'
|
f'<input name="keywords" value="{esc(filters_str)}" placeholder="comma-separated keywords">'
|
||||||
f'<button>save</button>'
|
f'<button>save</button>'
|
||||||
f"</form>"
|
f"</form>"
|
||||||
f"<h2>synced instances</h2>"
|
f"<h2>synced instances</h2>"
|
||||||
f"{synced_items}"
|
f"{synced_items}"
|
||||||
f"<p><small>Instances are discovered automatically via mesh announces. "
|
f"<p><small>Instances are discovered automatically via mesh announces. "
|
||||||
f"You can also manually add a friend's instance hash to bootstrap.</small></p>"
|
f"You can also manually add a friend's instance hash to bootstrap.</small></p>"
|
||||||
f'<form method="post" action="/forum/sync/add">'
|
f'<form class="forum-form" method="post" action="/forum/sync/add">'
|
||||||
f'{self._csrf_field()}'
|
f'{self._csrf_field()}'
|
||||||
f'<input name="instance" placeholder="instance hash" size="40"><br><br>'
|
f'<input name="instance" placeholder="instance hash">'
|
||||||
f'<input name="name" placeholder="label (optional)" size="20"><br><br>'
|
f'<input name="name" placeholder="label (optional)">'
|
||||||
f'<button>add</button>'
|
f'<button>add</button>'
|
||||||
f"</form>"
|
f"</form>"
|
||||||
f'<hr>'
|
f'<hr>'
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue