thread page mostly finished
This commit is contained in:
8
app/templates/common/404.html
Normal file
8
app/templates/common/404.html
Normal file
@@ -0,0 +1,8 @@
|
||||
{%- from 'common/macros.html' import subheader -%}
|
||||
{%- extends 'base.html' -%}
|
||||
{%- block title -%}Not found{%- endblock -%}
|
||||
{%- block content -%}
|
||||
{%- call() subheader('404 Not Found') -%}
|
||||
<span>The requested URL was not found.</span>
|
||||
{%- endcall -%}
|
||||
{%- endblock -%}
|
||||
@@ -65,3 +65,116 @@
|
||||
{%- endif -%}
|
||||
</span>
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro tabs(prefix='', labels = []) -%}
|
||||
<div class="tab-container">
|
||||
<div class="tab-bar" role="tablist">
|
||||
{%- for tab_label in labels -%}
|
||||
<button type="button" class="tab-button" role="tab" aria-selected="{{'true' if loop.index0==0 else 'false'}}" id="{{prefix+'-'+(tab_label | lower)+'-tab'}}" aria-controls="{{prefix+'-'+(tab_label | lower)+'-content'}}">{{tab_label}}</button>
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
{%- for tab_label in labels -%}
|
||||
<div class="plank secondary-bg even no-shadow tab-content {{'hidden' if loop.index0!=0 else ''}}" role="tabpanel" aria-labelledby="{{prefix+'-'+(tab_label | lower)+'-tab'}}" id="{{prefix+'-'+(tab_label | lower)+'-content'}}">
|
||||
{{- caller(loop.index0) -}}
|
||||
</div>
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro babycode_editor_component(
|
||||
placeholder='Post content',
|
||||
prefill=''
|
||||
) -%}
|
||||
{%- call(idx) tabs(prefix='babycode', labels=['Write', 'Preview']) -%}
|
||||
{%- if idx == 0 -%}
|
||||
<span class="babycode-editor-controls">
|
||||
<span class="button-row">
|
||||
<button type="button" class="minimal"><b>B</b></button>
|
||||
<button type="button" class="minimal"><i>i</i></button>
|
||||
<button type="button" class="minimal"><s>S</s></button>
|
||||
<button type="button" class="minimal"><u>U</u></button>
|
||||
<button type="button" class="minimal"><code>://</code></button>
|
||||
<button type="button" class="minimal"><code></></code></button>
|
||||
<button type="button" class="minimal">1.</button>
|
||||
<button type="button" class="minimal">•</button>
|
||||
<button type="button" class="minimal"><img src="/static/emoji/angry.png" class="emoji"></button>
|
||||
</span>
|
||||
<a href="##">babycode help</a>
|
||||
</span>
|
||||
<textarea name="babycode-content" class="babycode-editor" placeholder="{{placeholder}}" required>{{ prefill }}</textarea>
|
||||
{%- endif -%}
|
||||
{%- endcall -%}
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro full_post(
|
||||
post, render_sig=true, is_latest=false,
|
||||
show_toolbar=true, is_editing=false, thread=none,
|
||||
show_reactions=true
|
||||
) -%}
|
||||
{%- if is_logged_in() -%}
|
||||
{%- set can_delete = post.user_id == get_active_user().id or is_mod() -%}
|
||||
{%- else -%}
|
||||
{%- set show_toolbar = false -%}
|
||||
{%- endif -%}
|
||||
{%- set owns = is_logged_in() and post.user_id == get_active_user().id -%}
|
||||
{%- set can_reply = (is_logged_in()) and (not thread.locked or is_mod()) -%}
|
||||
<div class="usercard plank even contrast-bg minimal no-shadow">
|
||||
<div class="usercard-inner">
|
||||
<img src="{{post.avatar_path}}" class="avatar">
|
||||
<div class="usercard-rest">
|
||||
<a href="{{url_for('users.user_page', username=post.username)}}">{{post.display_name if post.display_name else post.username}}</a>
|
||||
<abbr title="mention">@{{post.username}}</abbr>
|
||||
<i>{{post.status}}</i>
|
||||
{%- set badges=post.badges_json | fromjson -%}
|
||||
<div class="badges-container">
|
||||
{%- for badge in badges -%}
|
||||
{%- if badge.link -%}<a href="{{badge.link}}">{%- endif -%}
|
||||
<img src="{{badge.file_path}}" alt="{{badge.label}}" title="{{badge.label}}" class="badge-button">
|
||||
{%- if badge.link -%}</a>{%- endif -%}
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="post-content">
|
||||
<div class="plank even minimal secondary-bg no-shadow post-info">
|
||||
<a href="{{get_post_url(post.id, _anchor=true)}}"><i>Posted on {{timestamp(post.created_at)}}</i></a>
|
||||
{%- if show_toolbar -%}
|
||||
<span class="thread-actions">
|
||||
{%- if owns -%}
|
||||
<a class="linkbutton" href="{{url_for('posts.edit', post_id=post.id)}}">Edit</a>
|
||||
{%- endif -%}
|
||||
{%- if can_reply -%}
|
||||
<button>Quote</button>
|
||||
{%- endif -%}
|
||||
{%- if can_delete -%}
|
||||
<button class="critical">Delete</button>
|
||||
{%- endif -%}
|
||||
<button>Bookmark…</button>
|
||||
</span>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
<div class="plank even no-shadow post-content-inner minimal">{{post.content | safe}}
|
||||
{%- if render_sig and post.signature_rendered -%}
|
||||
<div class="post-signature">{{post.signature_rendered | safe}}</div>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- if show_reactions -%}
|
||||
<div class="plank even secondary-bg minimal no-shadow">
|
||||
<span class="button-row">
|
||||
{%- for reaction in Reactions.for_post(post.id) -%}
|
||||
{% set reactors = Reactions.get_users(post.id, reaction.reaction_text) | map(attribute='username') | list %}
|
||||
{% set reactors_trimmed = reactors[:10] %}
|
||||
{% set reactors_str = reactors_trimmed | join (',\n') %}
|
||||
{% if reactors | count > 10 %}
|
||||
{% set reactors_str = reactors_str + '\n...and many others' %}
|
||||
{% endif %}
|
||||
{% set has_reacted = get_active_user() is not none and get_active_user().username in reactors %}
|
||||
<button {{'disabled' if not is_logged_in() else ''}} title="{{reactors_str}}" class="minimal {{'alt' if has_reacted else ''}}"><img src="/static/emoji/{{reaction.reaction_text}}.png">{{reaction.c}}</button>
|
||||
{%- endfor -%}
|
||||
</span>
|
||||
{%- if is_logged_in() -%}<button>Add reaction</button>{%- endif -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- endmacro %}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<input type="text" placeholder="Username" name="username" autocomplete="username" required>
|
||||
<input type="password" placeholder="Password" name="password" autocomplete="current-password" required>
|
||||
<input type="submit" value="Log in">
|
||||
<a href="{{url_for('users.sign_up')}}" class="linkbutton">Sign up</a>
|
||||
<a href="{{url_for('users.sign_up')}}" class="linkbutton alt">Sign up</a>
|
||||
</form>
|
||||
{%- endif -%}
|
||||
</nav>
|
||||
|
||||
66
app/templates/threads/thread.html
Normal file
66
app/templates/threads/thread.html
Normal file
@@ -0,0 +1,66 @@
|
||||
{%- from 'common/macros.html' import subheader, timestamp, pager, babycode_editor_component -%}
|
||||
{%- from 'common/macros.html' import full_post with context -%}
|
||||
{%- extends 'base.html' -%}
|
||||
{%- block title -%}{%- endblock -%}
|
||||
{%- block content -%}
|
||||
{%- set td -%}
|
||||
Started by <a href="{{url_for('users.user_page', username=started_by.username)}}">{{started_by.get_readable_name()}}</a> in topic <a href="{{url_for('topics.topic', slug=topic.slug)}}">{{topic.name}}</a>
|
||||
{%- endset -%}
|
||||
{%- call() subheader(thread.title, td) -%}
|
||||
<fieldset class="plank even no-shadow minimal thread-actions">
|
||||
<legend>Actions</legend>
|
||||
{%- if is_logged_in() -%}
|
||||
<button>Subscribe</button>
|
||||
<button>Bookmark…</button>
|
||||
{%- endif -%}
|
||||
<a href="{{url_for('threads.feed', slug=thread.slug)}}" class="linkbutton rss">Subscribe via RSS</a>
|
||||
</fieldset>
|
||||
{%- if is_mod() -%}
|
||||
<fieldset class="plank even no-shadow minimal thread-actions">
|
||||
<legend>Moderation actions</legend>
|
||||
<form method="POST">
|
||||
<input type="hidden" name="lock" value="{{not thread.locked()}}">
|
||||
<input type="hidden" name="sticky" value="{{not thread.stickied()}}">
|
||||
<input type="submit" class="warn" value="{{'Unlock' if thread.locked() else 'Lock'}}" formaction="{{url_for('mod.lock_thread', thread_id=thread.id)}}">
|
||||
<input type="submit" class="warn" value="{{'Unsticky' if thread.stickied() else 'Sticky'}}" formaction="{{url_for('mod.sticky_thread', thread_id=thread.id)}}">
|
||||
</form>
|
||||
<form class="horizontal wrap" method="POST" action="{{url_for('mod.move_thread', thread_id=thread.id)}}">
|
||||
<select name="new_topic_id" id="new_topic_id">
|
||||
{%- for t in topics -%}
|
||||
<option value="{{t.id}}" {{'selected disabled' if t.id == topic.id else ''}} autocomplete="off">{{t.name}}</option>
|
||||
{%- endfor -%}
|
||||
</select>
|
||||
<input type="submit" value="Move" class="warn">
|
||||
</form>
|
||||
</fieldset>
|
||||
<fieldset class="plank even no-shadow minimal thread-actions">
|
||||
<legend>Page</legend>
|
||||
{{- pager(page, page_count) -}}
|
||||
</fieldset>
|
||||
{%- endif -%}
|
||||
{%- endcall -%}
|
||||
<main>
|
||||
{%- for post in posts -%}
|
||||
<article id="post-{{post.id}}" class="post plank">
|
||||
{{full_post(post)}}
|
||||
</article>
|
||||
{%- endfor -%}
|
||||
</main>
|
||||
<div class="plank secondary-bg">
|
||||
<fieldset class="plank even no-shadow minimal thread-actions">
|
||||
<legend>Page</legend>
|
||||
{{- pager(page, page_count) -}}
|
||||
</fieldset>
|
||||
</div>
|
||||
{%- if is_logged_in() -%}
|
||||
<form action="{{url_for('threads.reply', slug=thread.slug)}}" method="POST" class="plank post-edit-form">
|
||||
<h2 class="info">Reply to "{{thread.title}}"</h2>
|
||||
{{- babycode_editor_component() -}}
|
||||
<span>
|
||||
<input type="checkbox" checked name="subscribe" id="subscribe">
|
||||
<label for="subscribe">Subscribe to thread</label>
|
||||
</span>
|
||||
<span><input type="submit" value="Post reply"></span>
|
||||
</form>
|
||||
{%- endif -%}
|
||||
{%- endblock -%}
|
||||
@@ -1,10 +1,13 @@
|
||||
{% from 'common/macros.html' import timestamp, subheader, pager %}
|
||||
{%- extends 'base.html' -%}
|
||||
{%- block title -%}browsing topic {{topic.name}}{%- endblock -%}
|
||||
{%- block content -%}
|
||||
{%- call() subheader(('Threads in "%s"' % topic.name), topic.description) -%}
|
||||
<fieldset class="plank even no-shadow minimal thread-actions">
|
||||
<legend>Actions</legend>
|
||||
{%- if is_logged_in() -%}
|
||||
<a href="{{url_for('threads.new', topic_id=topic.id)}}" class="linkbutton">New thread</a>
|
||||
{%- endif -%}
|
||||
<a href="{{url_for('topics.feed', slug=topic.slug)}}" class="linkbutton rss">Subscribe via RSS</a>
|
||||
<form method="GET">
|
||||
<select name="sort_by">
|
||||
@@ -14,11 +17,15 @@
|
||||
<input type="submit" value="Sort">
|
||||
</form>
|
||||
</fieldset>
|
||||
{%- if get_active_user().is_mod() -%}
|
||||
{%- if is_mod() -%}
|
||||
<fieldset class="plank even no-shadow minimal thread-actions">
|
||||
<legend>Moderation actions</legend>
|
||||
</fieldset>
|
||||
{%- endif -%}
|
||||
<fieldset class="plank even no-shadow minimal thread-actions">
|
||||
<legend>Page</legend>
|
||||
{{- pager(page, page_count, args=request.args) -}}
|
||||
</fieldset>
|
||||
{%- endcall -%}
|
||||
{%- for thread in threads -%}
|
||||
<div class="topic-info plank">
|
||||
@@ -30,9 +37,14 @@
|
||||
{%- endif -%}
|
||||
</div>
|
||||
<span>Started by <a href="{{url_for('users.user_page', username=thread.started_by)}}">{{thread.started_by_display_name if thread.started_by_display_name else thread.started_by}}</a> on {{timestamp(thread.created_at)}}</span>
|
||||
<span>{{thread.posts_count - 1}} {{'repl' | pluralize(thread.posts_count - 1, 'y', 'ies')}}</span>
|
||||
<span>Latest reply by <a href="{{get_post_url(thread.latest_post_id, _anchor=true)}}">{{thread.latest_post_display_name if thread.latest_post_display_name else thread.latest_post_username}} on {{timestamp(thread.latest_post_created_at)}}</a></span>
|
||||
<span>{{thread.posts_count}} {{'repl' | pluralize(thread.posts_count, 'y', 'ies')}}</span>
|
||||
<span>Latest post by <a href="{{get_post_url(thread.latest_post_id, _anchor=true)}}">{{thread.latest_post_display_name if thread.latest_post_display_name else thread.latest_post_username}} on {{timestamp(thread.latest_post_created_at)}}</a>{{' (OP)' if thread.posts_count == 1 else ''}}</span>
|
||||
</div>
|
||||
{%- endfor -%}
|
||||
{{pager(page, page_count, args=request.args)}}
|
||||
<div class="plank secondary-bg">
|
||||
<fieldset class="plank even no-shadow minimal thread-actions">
|
||||
<legend>Page</legend>
|
||||
{{- pager(page, page_count, args=request.args) -}}
|
||||
</fieldset>
|
||||
</div>
|
||||
{%- endblock -%}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{%- extends 'base.html' -%}
|
||||
{%- block content -%}
|
||||
{%- call() subheader('All topics') -%}
|
||||
{%- if get_active_user().is_mod() -%}
|
||||
{%- if is_mod() -%}
|
||||
<fieldset class="plank even no-shadow minimal thread-actions">
|
||||
<legend>Moderation actions</legend>
|
||||
<a href="{{url_for('mod.new_topic')}}" class="linkbutton">New topic</a>
|
||||
|
||||
Reference in New Issue
Block a user