Browse Source

Redesign conversations

TODO: Viewing a conversation
sh4nks 9 years ago
parent
commit
c0868d982e

+ 2 - 2
flaskbb/templates/macros.html

@@ -306,9 +306,9 @@
     {%- endif -%}
     {%- endif -%}
 {% endmacro %}
 {% endmacro %}
 
 
-{% macro navlink(endpoint, name, active=False) %}
+{% macro navlink(endpoint, name, icon='', active=False) %}
 <li {% if endpoint == request.endpoint or active %}class="active"{% endif %}>
 <li {% if endpoint == request.endpoint or active %}class="active"{% endif %}>
-    <a href={{ url_for(endpoint) }}>{{ name }}</a>
+    <a href="{{ url_for(endpoint) }}">{% if icon %}<i class="{{ icon }}"></i> {% endif %} {{ name }}</a>
 </li>
 </li>
 {% endmacro %}
 {% endmacro %}
 
 

+ 35 - 18
flaskbb/themes/aurora/src/flaskbb.scss

@@ -171,10 +171,10 @@ body {
 
 
 
 
 // default values for the panels
 // default values for the panels
-.category-panel, .forum-panel, .topic-panel, .page-panel {
+.category-panel, .forum-panel, .topic-panel, .page-panel, .conversation-panel {
     border: 1px solid $panel-border;
     border: 1px solid $panel-border;
     border-radius: 0;
     border-radius: 0;
-    .category-head, .forum-head, .topic-head, .page-head {
+    .category-head, .forum-head, .topic-head, .page-head, .conversation-head {
         background-color: $panel-head-background;
         background-color: $panel-head-background;
         font-weight: bold;
         font-weight: bold;
     }
     }
@@ -199,7 +199,7 @@ body {
 
 
 }
 }
 
 
-.category-body, .forum-body, .topic-body, .page-body {
+.category-body, .forum-body, .topic-body, .page-body, .conversation-body {
     padding: 0;
     padding: 0;
     background-color: $panel-background;
     background-color: $panel-background;
     .category-meta, .forum-meta, .topic-meta, .page-meta {
     .category-meta, .forum-meta, .topic-meta, .page-meta {
@@ -209,7 +209,7 @@ body {
         background-color: $panel-meta-background;
         background-color: $panel-meta-background;
         border-bottom: 1px solid $panel-meta-border;
         border-bottom: 1px solid $panel-meta-border;
     }
     }
-    .category-row, .forum-row, .topic-row, .page-row, .post-row {
+    .category-row, .forum-row, .topic-row, .page-row, .post-row, .conversation-row {
         margin: 0;
         margin: 0;
         padding-top: 0.5em;
         padding-top: 0.5em;
         padding-bottom: 0.5em;
         padding-bottom: 0.5em;
@@ -460,6 +460,24 @@ body {
     }
     }
 }
 }
 
 
+// conversation specific values
+.conversation-panel {
+    border: 1px solid $page-border;
+    margin-bottom: 0;
+
+    .conversation-head {
+        background-color: $page-head-background;
+    }
+    .conversation-body {
+        background-color: $page-panel;
+        .row > .conversation-row {
+            &:not(:last-child) {
+                border-bottom: 1px solid $page-border;
+            }
+        }
+    }
+}
+
 
 
 p.flaskbb-stats {
 p.flaskbb-stats {
     margin: 0;
     margin: 0;
@@ -581,26 +599,26 @@ p.flaskbb-stats {
 /* Sidebar Nav */
 /* Sidebar Nav */
 .sidebar {
 .sidebar {
     padding-top: 1em;
     padding-top: 1em;
-    padding-bottom: 0;
+    padding-bottom: 1em;
     text-shadow: none;
     text-shadow: none;
     background-color: $navigation-background-color;
     background-color: $navigation-background-color;
     border: 1px solid $border-color;
     border: 1px solid $border-color;
 
 
     .sidenav-header {
     .sidenav-header {
-      display: block;
-      padding-left: 1.25em;
-      padding-bottom: 1em;
-      font-size: 12px;
-      font-weight: bold;
-      line-height: 20px;
-      color: #999999;
-      text-transform: uppercase;
+        display: block;
+        padding-left: 1.25em;
+        padding-bottom: 1em;
+        font-size: 12px;
+        font-weight: bold;
+        line-height: 20px;
+        color: #999999;
+        text-transform: uppercase;
     }
     }
 
 
-
-    .btn-compose {
-        margin-left: 20px;
-        margin-bottom: 5px;
+    .sidenav-btn {
+        padding-bottom: 1em;
+        text-transform: uppercase;
+        text-align: center;
     }
     }
 
 
     .nav > li > a {
     .nav > li > a {
@@ -623,7 +641,6 @@ p.flaskbb-stats {
 }
 }
 
 
 
 
-
 /* Markdown Editor */
 /* Markdown Editor */
 .editor-box .editor-submit .btn {
 .editor-box .editor-submit .btn {
     margin: 0.75em 0.25em 0 0;
     margin: 0.75em 0.25em 0 0;

+ 26 - 15
flaskbb/themes/aurora/static/css/flaskbb.css

@@ -67,40 +67,40 @@ body {
   border: 1px solid #cad7e1;
   border: 1px solid #cad7e1;
   border-radius: 0; }
   border-radius: 0; }
 
 
-.category-panel, .forum-panel, .topic-panel, .page-panel {
+.category-panel, .forum-panel, .topic-panel, .page-panel, .conversation-panel {
   border: 1px solid #cad7e1;
   border: 1px solid #cad7e1;
   border-radius: 0; }
   border-radius: 0; }
-  .category-panel .category-head, .category-panel .forum-head, .category-panel .topic-head, .category-panel .page-head, .forum-panel .category-head, .forum-panel .forum-head, .forum-panel .topic-head, .forum-panel .page-head, .topic-panel .category-head, .topic-panel .forum-head, .topic-panel .topic-head, .topic-panel .page-head, .page-panel .category-head, .page-panel .forum-head, .page-panel .topic-head, .page-panel .page-head {
+  .category-panel .category-head, .category-panel .forum-head, .category-panel .topic-head, .category-panel .page-head, .category-panel .conversation-head, .forum-panel .category-head, .forum-panel .forum-head, .forum-panel .topic-head, .forum-panel .page-head, .forum-panel .conversation-head, .topic-panel .category-head, .topic-panel .forum-head, .topic-panel .topic-head, .topic-panel .page-head, .topic-panel .conversation-head, .page-panel .category-head, .page-panel .forum-head, .page-panel .topic-head, .page-panel .page-head, .page-panel .conversation-head, .conversation-panel .category-head, .conversation-panel .forum-head, .conversation-panel .topic-head, .conversation-panel .page-head, .conversation-panel .conversation-head {
     background-color: #f5f5f5;
     background-color: #f5f5f5;
     font-weight: bold; }
     font-weight: bold; }
-  .category-panel > .panel-heading, .forum-panel > .panel-heading, .topic-panel > .panel-heading, .page-panel > .panel-heading {
+  .category-panel > .panel-heading, .forum-panel > .panel-heading, .topic-panel > .panel-heading, .page-panel > .panel-heading, .conversation-panel > .panel-heading {
     color: #333;
     color: #333;
     background-color: #f5f5f5;
     background-color: #f5f5f5;
     border-color: #cad7e1; }
     border-color: #cad7e1; }
-  .category-panel > .panel-heading + .panel-collapse > .panel-body, .forum-panel > .panel-heading + .panel-collapse > .panel-body, .topic-panel > .panel-heading + .panel-collapse > .panel-body, .page-panel > .panel-heading + .panel-collapse > .panel-body {
+  .category-panel > .panel-heading + .panel-collapse > .panel-body, .forum-panel > .panel-heading + .panel-collapse > .panel-body, .topic-panel > .panel-heading + .panel-collapse > .panel-body, .page-panel > .panel-heading + .panel-collapse > .panel-body, .conversation-panel > .panel-heading + .panel-collapse > .panel-body {
     border-top-color: #cad7e1; }
     border-top-color: #cad7e1; }
-  .category-panel > .panel-heading .badge, .forum-panel > .panel-heading .badge, .topic-panel > .panel-heading .badge, .page-panel > .panel-heading .badge {
+  .category-panel > .panel-heading .badge, .forum-panel > .panel-heading .badge, .topic-panel > .panel-heading .badge, .page-panel > .panel-heading .badge, .conversation-panel > .panel-heading .badge {
     color: #f5f5f5;
     color: #f5f5f5;
     background-color: #333; }
     background-color: #333; }
-  .category-panel > .panel-footer + .panel-collapse > .panel-body, .forum-panel > .panel-footer + .panel-collapse > .panel-body, .topic-panel > .panel-footer + .panel-collapse > .panel-body, .page-panel > .panel-footer + .panel-collapse > .panel-body {
+  .category-panel > .panel-footer + .panel-collapse > .panel-body, .forum-panel > .panel-footer + .panel-collapse > .panel-body, .topic-panel > .panel-footer + .panel-collapse > .panel-body, .page-panel > .panel-footer + .panel-collapse > .panel-body, .conversation-panel > .panel-footer + .panel-collapse > .panel-body {
     border-bottom-color: #cad7e1; }
     border-bottom-color: #cad7e1; }
 
 
-.category-body, .forum-body, .topic-body, .page-body {
+.category-body, .forum-body, .topic-body, .page-body, .conversation-body {
   padding: 0;
   padding: 0;
   background-color: #fff; }
   background-color: #fff; }
-  .category-body .category-meta, .category-body .forum-meta, .category-body .topic-meta, .category-body .page-meta, .forum-body .category-meta, .forum-body .forum-meta, .forum-body .topic-meta, .forum-body .page-meta, .topic-body .category-meta, .topic-body .forum-meta, .topic-body .topic-meta, .topic-body .page-meta, .page-body .category-meta, .page-body .forum-meta, .page-body .topic-meta, .page-body .page-meta {
+  .category-body .category-meta, .category-body .forum-meta, .category-body .topic-meta, .category-body .page-meta, .forum-body .category-meta, .forum-body .forum-meta, .forum-body .topic-meta, .forum-body .page-meta, .topic-body .category-meta, .topic-body .forum-meta, .topic-body .topic-meta, .topic-body .page-meta, .page-body .category-meta, .page-body .forum-meta, .page-body .topic-meta, .page-body .page-meta, .conversation-body .category-meta, .conversation-body .forum-meta, .conversation-body .topic-meta, .conversation-body .page-meta {
     font-weight: bold;
     font-weight: bold;
     padding-top: 0.5em;
     padding-top: 0.5em;
     height: 2.5em;
     height: 2.5em;
     background-color: #e8f1f2;
     background-color: #e8f1f2;
     border-bottom: 1px solid #cad7e1; }
     border-bottom: 1px solid #cad7e1; }
-  .category-body .category-row, .category-body .forum-row, .category-body .topic-row, .category-body .page-row, .category-body .post-row, .forum-body .category-row, .forum-body .forum-row, .forum-body .topic-row, .forum-body .page-row, .forum-body .post-row, .topic-body .category-row, .topic-body .forum-row, .topic-body .topic-row, .topic-body .page-row, .topic-body .post-row, .page-body .category-row, .page-body .forum-row, .page-body .topic-row, .page-body .page-row, .page-body .post-row {
+  .category-body .category-row, .category-body .forum-row, .category-body .topic-row, .category-body .page-row, .category-body .post-row, .category-body .conversation-row, .forum-body .category-row, .forum-body .forum-row, .forum-body .topic-row, .forum-body .page-row, .forum-body .post-row, .forum-body .conversation-row, .topic-body .category-row, .topic-body .forum-row, .topic-body .topic-row, .topic-body .page-row, .topic-body .post-row, .topic-body .conversation-row, .page-body .category-row, .page-body .forum-row, .page-body .topic-row, .page-body .page-row, .page-body .post-row, .page-body .conversation-row, .conversation-body .category-row, .conversation-body .forum-row, .conversation-body .topic-row, .conversation-body .page-row, .conversation-body .post-row, .conversation-body .conversation-row {
     margin: 0;
     margin: 0;
     padding-top: 0.5em;
     padding-top: 0.5em;
     padding-bottom: 0.5em; }
     padding-bottom: 0.5em; }
-    .category-body .category-row:not(:last-child), .category-body .forum-row:not(:last-child), .category-body .topic-row:not(:last-child), .category-body .page-row:not(:last-child), .category-body .post-row:not(:last-child), .forum-body .category-row:not(:last-child), .forum-body .forum-row:not(:last-child), .forum-body .topic-row:not(:last-child), .forum-body .page-row:not(:last-child), .forum-body .post-row:not(:last-child), .topic-body .category-row:not(:last-child), .topic-body .forum-row:not(:last-child), .topic-body .topic-row:not(:last-child), .topic-body .page-row:not(:last-child), .topic-body .post-row:not(:last-child), .page-body .category-row:not(:last-child), .page-body .forum-row:not(:last-child), .page-body .topic-row:not(:last-child), .page-body .page-row:not(:last-child), .page-body .post-row:not(:last-child) {
+    .category-body .category-row:not(:last-child), .category-body .forum-row:not(:last-child), .category-body .topic-row:not(:last-child), .category-body .page-row:not(:last-child), .category-body .post-row:not(:last-child), .category-body .conversation-row:not(:last-child), .forum-body .category-row:not(:last-child), .forum-body .forum-row:not(:last-child), .forum-body .topic-row:not(:last-child), .forum-body .page-row:not(:last-child), .forum-body .post-row:not(:last-child), .forum-body .conversation-row:not(:last-child), .topic-body .category-row:not(:last-child), .topic-body .forum-row:not(:last-child), .topic-body .topic-row:not(:last-child), .topic-body .page-row:not(:last-child), .topic-body .post-row:not(:last-child), .topic-body .conversation-row:not(:last-child), .page-body .category-row:not(:last-child), .page-body .forum-row:not(:last-child), .page-body .topic-row:not(:last-child), .page-body .page-row:not(:last-child), .page-body .post-row:not(:last-child), .page-body .conversation-row:not(:last-child), .conversation-body .category-row:not(:last-child), .conversation-body .forum-row:not(:last-child), .conversation-body .topic-row:not(:last-child), .conversation-body .page-row:not(:last-child), .conversation-body .post-row:not(:last-child), .conversation-body .conversation-row:not(:last-child) {
       border-bottom: 1px solid #cad7e1; }
       border-bottom: 1px solid #cad7e1; }
-    .category-body .category-row.hover:hover, .category-body .forum-row.hover:hover, .category-body .topic-row.hover:hover, .category-body .page-row.hover:hover, .category-body .post-row.hover:hover, .forum-body .category-row.hover:hover, .forum-body .forum-row.hover:hover, .forum-body .topic-row.hover:hover, .forum-body .page-row.hover:hover, .forum-body .post-row.hover:hover, .topic-body .category-row.hover:hover, .topic-body .forum-row.hover:hover, .topic-body .topic-row.hover:hover, .topic-body .page-row.hover:hover, .topic-body .post-row.hover:hover, .page-body .category-row.hover:hover, .page-body .forum-row.hover:hover, .page-body .topic-row.hover:hover, .page-body .page-row.hover:hover, .page-body .post-row.hover:hover {
+    .category-body .category-row.hover:hover, .category-body .forum-row.hover:hover, .category-body .topic-row.hover:hover, .category-body .page-row.hover:hover, .category-body .post-row.hover:hover, .category-body .conversation-row.hover:hover, .forum-body .category-row.hover:hover, .forum-body .forum-row.hover:hover, .forum-body .topic-row.hover:hover, .forum-body .page-row.hover:hover, .forum-body .post-row.hover:hover, .forum-body .conversation-row.hover:hover, .topic-body .category-row.hover:hover, .topic-body .forum-row.hover:hover, .topic-body .topic-row.hover:hover, .topic-body .page-row.hover:hover, .topic-body .post-row.hover:hover, .topic-body .conversation-row.hover:hover, .page-body .category-row.hover:hover, .page-body .forum-row.hover:hover, .page-body .topic-row.hover:hover, .page-body .page-row.hover:hover, .page-body .post-row.hover:hover, .page-body .conversation-row.hover:hover, .conversation-body .category-row.hover:hover, .conversation-body .forum-row.hover:hover, .conversation-body .topic-row.hover:hover, .conversation-body .page-row.hover:hover, .conversation-body .post-row.hover:hover, .conversation-body .conversation-row.hover:hover {
       background-color: #f8f8f8; }
       background-color: #f8f8f8; }
 
 
 .topic-panel {
 .topic-panel {
@@ -246,6 +246,16 @@ body {
     .page-panel .page-body > :not(.page-meta) {
     .page-panel .page-body > :not(.page-meta) {
       padding-top: 0.5em; }
       padding-top: 0.5em; }
 
 
+.conversation-panel {
+  border: 1px solid #cad7e1;
+  margin-bottom: 0; }
+  .conversation-panel .conversation-head {
+    background-color: #f5f5f5; }
+  .conversation-panel .conversation-body {
+    background-color: #fff; }
+    .conversation-panel .conversation-body .row > .conversation-row:not(:last-child) {
+      border-bottom: 1px solid #cad7e1; }
+
 p.flaskbb-stats {
 p.flaskbb-stats {
   margin: 0;
   margin: 0;
   padding: 0; }
   padding: 0; }
@@ -333,7 +343,7 @@ p.flaskbb-stats {
 /* Sidebar Nav */
 /* Sidebar Nav */
 .sidebar {
 .sidebar {
   padding-top: 1em;
   padding-top: 1em;
-  padding-bottom: 0;
+  padding-bottom: 1em;
   text-shadow: none;
   text-shadow: none;
   background-color: #f8f8f8;
   background-color: #f8f8f8;
   border: 1px solid #cad7e1; }
   border: 1px solid #cad7e1; }
@@ -346,9 +356,10 @@ p.flaskbb-stats {
     line-height: 20px;
     line-height: 20px;
     color: #999999;
     color: #999999;
     text-transform: uppercase; }
     text-transform: uppercase; }
-  .sidebar .btn-compose {
-    margin-left: 20px;
-    margin-bottom: 5px; }
+  .sidebar .sidenav-btn {
+    padding-bottom: 1em;
+    text-transform: uppercase;
+    text-align: center; }
   .sidebar .nav > li > a {
   .sidebar .nav > li > a {
     display: block; }
     display: block; }
   .sidebar .nav > li > a:hover,
   .sidebar .nav > li > a:hover,

+ 86 - 0
flaskbb/themes/aurora/templates/message/conversation.html

@@ -0,0 +1,86 @@
+{% extends theme("message/message_layout.html") %}
+
+{% block css %}
+    {{ super() }}
+    <link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap-markdown.min.css') }}">
+{% endblock %}
+
+{% block message_content %}
+<div class="panel conversation-panel">
+    <div class="panel-heading conversation-head">Subject: <strong>{{ conversation.subject }}</strong></div>
+    <div class="panel-body conversation-body">
+        <section class="conversation-list">
+            {% if conversation.draft %}
+                {% set messages = [conversation.first_message] %}
+            {% else %}
+                {% set messages = conversation.messages %}
+            {% endif %}
+            {% for message in messages %}
+            <!-- First Comment -->
+            <article class="row" id="mid{{message.id}}">
+                {% if current_user.id == message.user_id %}
+                <div class="col-md-2 col-sm-2 hidden-xs">
+                        <figure class="thumbnail">
+                        {% if message.user.avatar %}
+                            <img class="img-responsive" src="{{ message.user.avatar }}" />
+                        {% else %}
+                            <!-- "no" avatar proudly made with Google Drawing.. because lol -->
+                            <img src="{{ url_for('static', filename='img/avatar100x100.png') }}" class="img-responsive" alt="avatar" />
+                        {% endif %}
+                        <figcaption class="text-center"><strong><a href="{{ message.user.url }}" class="conversation-username">{{ message.user.username }}</a></strong></figcaption>
+                    </figure>
+                </div>
+                {% endif %}
+                <div class="col-md-10 col-sm-10">
+                    <div class="panel panel-default arrow {% if current_user.id == message.user_id %}left{% else %}right{% endif %}">
+                        <div class="panel-body">
+                            <header class="text-left">
+                                <time class="conversation-date" datetime="{{ message.date_created }}"><i class="fa fa-clock-o"></i> {{ message.date_created|format_date("%d %B %Y - %H:%M") }}</time>
+                            </header>
+                            <div class="conversation-message">
+                                {{ message.message|markup|safe }}
+                            </div>
+                            {% if conversation.draft %}
+                                <p class="text-right"><a href="{{ url_for('message.edit_conversation', conversation_id=conversation.id) }}" class="btn btn-default btn-sm"><i class="fa fa-pencil"></i> edit</a></p>
+                            {% else %}
+                                <p class="text-right"><a href="#" class="btn btn-default btn-sm reply-btn" data-message-id="{{ message.id }}"><i class="fa fa-reply"></i> reply</a></p>
+                            {% endif %}
+                        </div>
+                    </div>
+                </div>
+                {% if current_user.id != message.user_id %}
+                <div class="col-md-2 col-sm-2 hidden-xs">
+                        <figure class="thumbnail">
+                            {% if message.user.avatar %}
+                                <img class="img-responsive" src="{{ message.user.avatar }}" />
+                            {% else %}
+                                <img src="{{ url_for('static', filename='img/avatar100x100.png') }}" class="img-responsive" alt="avatar" />
+                            {% endif %}
+                        <figcaption class="text-center"><strong><a href="{{ message.user.url }}" class="conversation-username">{{ message.user.username }}</a></strong></figcaption>
+                    </figure>
+                </div>
+                {% endif %}
+            </article>
+        {% endfor %}
+        </section>
+    </div>
+</div>
+{% if not conversation.draft %}
+    {% from "macros.html" import render_field, render_submit_field %}
+    <form class="form" action="#" method="post">
+        {{ form.hidden_tag() }}
+
+        {{ render_field(form.message, div_class="col-sm-12 message-content", rows="10", placeholder="", **{'data-provide': 'markdown', 'data-autofocus': 'true', 'id': 'quickreply-editor'}) }}
+
+        <div class="col-sm-12" style="padding-top: 5px">
+        {{ render_submit_field(form.submit) }}
+        </div>
+    </form>
+{% endif %}
+
+{% endblock %}
+
+{% block scripts %}
+    <script type="text/javascript" src="{{ url_for('static', filename='js/marked.js') }}"></script>
+    <script type="text/javascript" src="{{ url_for('static', filename='js/bootstrap-markdown.js') }}"></script>
+{% endblock %}

+ 93 - 0
flaskbb/themes/aurora/templates/message/conversation_list.html

@@ -0,0 +1,93 @@
+<div class="panel conversation-panel">
+    <div class="panel-heading conversation-head">
+        <div class="row">
+            <div class="col-md-12 col-sm-12 col-xs-12">
+                <div class="pull-left">
+                    <span class="fa fa-comment"></span> {% trans %}Conversations{% endtrans %}
+                </div>
+
+                <div class="pull-right">
+                    <span class="label label-info">{{ message_count }}/{{ flaskbb_config["MESSAGE_QUOTA"] }}</span>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="panel-body conversation-body">
+        {% for conversation in conversations.items %}
+        <div class="row conversation-row hover">
+            <!-- avatar -->
+            <div class="col-md-1 col-sm-2 col-xs-2 conversation-avatar">
+                {% if conversation.from_user.avatar %}
+                <img src="{{ conversation.from_user.avatar }}" class="img-circle" alt="avatar" width="65px" height="65px" />
+                {% else %}
+                <img src="{{ url_for('static', filename='img/avatar80x80.png') }}" class="img-circle" alt="avatar" width="65px" height="65px" />
+                {% endif %}
+            </div>
+            <!-- other stuff -->
+            <div class="col-md-11 col-sm-10 col-xs-10 conversation-info">
+                <!-- subject -->
+                <div class="conversation-subject">
+                    <a href="{{ url_for('message.view_conversation', conversation_id=conversation.id) }}">
+                        {% if conversation.unread %}
+                            <strong>{{ conversation.subject }}</strong>
+                        {% else %}
+                            {{ conversation.subject }}
+                        {% endif %}
+                    </a>
+                </div>
+                <!-- meta info (date, user) -->
+                <div class="conversation-meta">
+                    From <a href="{{ conversation.from_user.url }}">{{ conversation.from_user.username }}</a>
+                    to <a href="{{ conversation.to_user.url }}">{{ conversation.to_user.username }}</a>
+                    on {{ conversation.date_created|format_date("%d %B %Y - %H:%M") }}
+                </div>
+                <!-- actual content -->
+                <div class="conversation-content">
+                    {{ conversation.first_message.message|crop_title(150)|markup|safe }}
+                </div>
+                <!-- actions -->
+                <div class="conversation-actions">
+                    {% if include_move %}
+                    <form class="inline-form" method="POST" action="{{ url_for('message.move_conversation', conversation_id=conversation.id) }}">
+                        <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
+                        <button type="submit" class="btn btn-info btn-xs" title="Move to Trash">
+                            <span class="fa fa-archive"></span>
+                        </button>
+                    </form>
+                    {% endif %}
+
+                    {% if include_delete %}
+                    <form class="inline-form" method="POST" action="{{ url_for('message.delete_conversation', conversation_id=conversation.id) }}">
+                        <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
+                        <button type="submit" class="btn btn-danger btn-xs" title="Delete">
+                            <span class="fa fa-trash"></span>
+                        </button>
+                    </form>
+                    {% endif %}
+
+                    {% if include_restore %}
+                    <form class="inline-form" method="POST" action="{{ url_for('message.restore_conversation', conversation_id=conversation.id) }}">
+                        <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
+                        <button type="submit" class="btn btn-success btn-xs" title="Restore">
+                            <span class="fa fa-undo"></span>
+                        </button>
+                    </form>
+                    {% endif %}
+
+                    {% if include_edit %}
+                    <a class="btn btn-success btn-xs" alt="Edit" title="Edit" href="{{ url_for('message.edit_conversation', conversation_id = conversation.id) }}">
+                        <span class="fa fa-pencil"></span>
+                    </a>
+                    {% endif %}
+                </div>
+            </div>
+        </div>
+        {% else %}
+        <div class="row conversation-row">
+            <div class="col-md-12 col-sm-12 col-xs-12">
+                {% trans %}No conversations found.{% endtrans %}
+            </div>
+        </div>
+        {% endfor %}
+    </div>
+</div>

+ 13 - 0
flaskbb/themes/aurora/templates/message/drafts.html

@@ -0,0 +1,13 @@
+{% set page_title = _("Drafts") %}
+
+{% from theme('macros.html') import render_pagination %}
+{% extends theme("message/message_layout.html") %}
+{% block message_content %}
+
+{% set include_move = True %}
+{% set include_edit = True %}
+{% include theme("message/conversation_list.html") %}
+
+{{ render_pagination(conversations, url_for("message.drafts")) }}
+
+{% endblock %}

+ 12 - 0
flaskbb/themes/aurora/templates/message/inbox.html

@@ -0,0 +1,12 @@
+{% set page_title = _("Inbox") %}
+
+{% from theme('macros.html') import render_pagination %}
+{% extends theme("message/message_layout.html") %}
+{% block message_content %}
+
+{% set include_move = True %}
+{% include theme("message/conversation_list.html") %}
+
+{{ render_pagination(conversations, url_for("message.inbox")) }}
+
+{% endblock %}

+ 21 - 0
flaskbb/themes/aurora/templates/message/message_form.html

@@ -0,0 +1,21 @@
+{% set page_title = title %}
+
+{% extends theme("message/message_layout.html") %}
+
+{% block message_content %}
+{% from theme("macros.html") import horizontal_field, render_submit_field %}
+<form class="form-horizontal" role="form" method="post" name="new">
+    <legend>{{ title }}</legend>
+    {{ form.hidden_tag() }}
+    {{ horizontal_field(form.to_user)}}
+    {{ horizontal_field(form.subject)}}
+    {{ horizontal_field(form.message, rows=7)}}
+
+    <div class="form-group row">
+        <div class="col-sm-offset-3 col-lg-9">
+            {{ render_submit_field(form.send_message, input_class="btn btn-success") }}
+            {{ render_submit_field(form.save_message, input_class="btn btn-info") }}
+        </div>
+    </div>
+</form>
+{% endblock %}

+ 29 - 0
flaskbb/themes/aurora/templates/message/message_layout.html

@@ -0,0 +1,29 @@
+{% extends theme("layout.html") %}
+{% block content %}
+{%- from theme('macros.html') import navlink with context -%}
+
+<ol class="breadcrumb flaskbb-breadcrumb">
+    <li><a href="{{ url_for('forum.index') }}">{% trans %}Forum{% endtrans %}</a></li>
+    <li><a href="{{ url_for('user.profile', username=current_user.username) }}">{{ current_user.username }}</a></li>
+    <li class="active">{% trans %}Private Message{% endtrans %}</li>
+</ol>
+
+<div class="row">
+    <div class="col-sm-3">
+        <div class="sidebar">
+            <ul class="nav sidenav">
+                <div class="sidenav-btn">
+                    <a href="{{ url_for('message.new_conversation') }}" class="btn btn-success">{% trans %}New Message{% endtrans %}</a>
+                </div>
+                {{ navlink('message.inbox', _('Inbox')) }}
+                {{ navlink('message.sent', _('Sent')) }}
+                {{ navlink('message.drafts', _('Drafts')) }}
+                {{ navlink('message.trash', _('Trash')) }}
+            </ul>
+        </div><!--/.sidebar -->
+    </div><!--/.col-sm-3 -->
+    <div class="col-sm-9">
+        {% block message_content %}{% endblock %}
+    </div><!--/.col-sm-9 -->
+</div><!--/.row -->
+{% endblock %}

+ 12 - 0
flaskbb/themes/aurora/templates/message/sent.html

@@ -0,0 +1,12 @@
+{% set page_title = _("Sent Messages") %}
+
+{% from theme('macros.html') import render_pagination %}
+{% extends theme("message/message_layout.html") %}
+{% block message_content %}
+
+{% set include_move = True %}
+{% include theme("message/conversation_list.html") %}
+
+{{ render_pagination(conversations, url_for("message.sent")) }}
+
+{% endblock %}

+ 13 - 0
flaskbb/themes/aurora/templates/message/trash.html

@@ -0,0 +1,13 @@
+{% set page_title = _("Trash") %}
+
+{% from theme('macros.html') import render_pagination %}
+{% extends theme("message/message_layout.html") %}
+{% block message_content %}
+
+{% set include_restore = True %}
+{% set include_delete = True %}
+{% include theme("message/conversation_list.html") %}
+
+{{ render_pagination(conversations, url_for("message.trash")) }}
+
+{% endblock %}