sh4nks 10 лет назад
Родитель
Сommit
59de776d2f

+ 7 - 7
flaskbb/message/forms.py

@@ -38,8 +38,10 @@ class ConversationForm(Form):
         if user.id == current_user.id:
             raise ValidationError(_("You cannot send a PM to yourself."))
 
-    def save(self, from_user, to_user, user_id, unread, as_draft=False):
-        conversation = Conversation(subject=self.subject.data, draft=as_draft)
+    def save(self, from_user, to_user, user_id, unread, as_draft=False,
+             shared_id=None):
+        conversation = Conversation(subject=self.subject.data, draft=as_draft,
+                                    shared_id=shared_id)
         message = Message(message=self.message.data, user_id=from_user)
         return conversation.save(message=message, from_user=from_user,
                                  to_user=to_user, user_id=user_id)
@@ -50,7 +52,7 @@ class MessageForm(Form):
         DataRequired(message=_("A Message is required."))])
     submit = SubmitField(_("Send Message"))
 
-    def save(self, conversation, user_id, reciever=True):
+    def save(self, conversation, user_id, unread=False):
         """Saves the form data to the model.
         :param conversation: The Conversation object.
         :param user_id: The id from the user who sent the message.
@@ -58,10 +60,8 @@ class MessageForm(Form):
                          inbox.
         """
         message = Message(message=self.message.data, user_id=user_id)
-        conversation.save(message)
 
-        if reciever:
+        if unread:
             conversation.unread = True
-            conversation.save(message)
-
+            conversation.save()
         return message.save(conversation)

+ 3 - 2
flaskbb/message/models.py

@@ -1,5 +1,7 @@
 from datetime import datetime
 
+from sqlalchemy_utils import UUIDType
+
 from flaskbb.extensions import db
 
 
@@ -10,7 +12,7 @@ class Conversation(db.Model):
     user_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False)
     from_user_id = db.Column(db.Integer, db.ForeignKey("users.id"))
     to_user_id = db.Column(db.Integer, db.ForeignKey("users.id"))
-
+    shared_id = db.Column(UUIDType, nullable=False)
     subject = db.Column(db.String(255))
     date_created = db.Column(db.DateTime, default=datetime.utcnow())
     trash = db.Column(db.Boolean, nullable=False, default=False)
@@ -84,7 +86,6 @@ class Message(db.Model):
 
     # the user who wrote the message
     user_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False)
-
     message = db.Column(db.Text, nullable=False)
     date_created = db.Column(db.DateTime, default=datetime.utcnow())
 

+ 30 - 5
flaskbb/message/views.py

@@ -1,3 +1,4 @@
+import uuid
 from datetime import datetime
 
 from flask import Blueprint, redirect, request, url_for, flash, abort
@@ -60,11 +61,29 @@ def view_conversation(conversation_id):
             return redirect(url_for("message.view_conversation",
                                     conversation_id=conversation.id))
 
+        to_user_id = None
+        # If the current_user is the user who recieved the message
+        # then we have to change the id's a bit.
+        if current_user.id == conversation.to_user_id:
+            to_user_id = conversation.from_user_id
+        else:
+            to_user_id = conversation.to_user_id
+
+        form.save(conversation=conversation, user_id=current_user.id)
+
+        # save the message in the recievers conversation
+        old_conv = conversation
+        conversation = Conversation.query.\
+            filter(
+                Conversation.user_id == to_user_id,
+                Conversation.shared_id == conversation.shared_id
+            ).first()
+
         form.save(conversation=conversation, user_id=current_user.id,
-                  reciever=True)
+                  unread=True)
 
         return redirect(url_for("message.view_conversation",
-                                conversation_id=conversation.id))
+                                conversation_id=old_conv.id))
 
     return render_template("message/conversation.html",
                            conversation=conversation, form=form)
@@ -101,17 +120,23 @@ def new_conversation():
         if "send_message" in request.form and form.validate():
             to_user = User.query.filter_by(username=form.to_user.data).first()
 
+            # this is the shared id between conversations because the messages
+            # are saved on both ends
+            shared_id = uuid.uuid4()
+
             # Save the message in the current users inbox
             form.save(from_user=current_user.id,
                       to_user=to_user.id,
                       user_id=current_user.id,
-                      unread=False)
+                      unread=False,
+                      shared_id=shared_id)
 
             # Save the message in the recievers inbox
             form.save(from_user=current_user.id,
                       to_user=to_user.id,
                       user_id=to_user.id,
-                      unread=True)
+                      unread=True,
+                      shared_id=shared_id)
 
             flash(_("Message sent."), "success")
             return redirect(url_for("message.sent"))
@@ -156,7 +181,7 @@ def edit_conversation(conversation_id):
         if "save_message" in request.form:
             to_user = User.query.filter_by(username=form.to_user.data).first()
 
-            conversation.draft = False
+            conversation.draft = True
             conversation.to_user = to_user.id
             conversation.save()
 

+ 4 - 4
flaskbb/templates/message/conversation.html

@@ -13,7 +13,7 @@
             {% for message in conversation.messages %}
             <!-- First Comment -->
             <article class="row" id="mid{{message.id}}">
-                {% if message.conversation.from_user_id == message.user_id %}
+                {% if current_user.id == message.user_id %}
                 <div class="col-md-2 col-sm-2 hidden-xs">
                         <figure class="thumbnail">
                         <img class="img-responsive" src="http://www.keita-gaming.com/assets/profile/default-avatar-c5d8ec086224cb6fc4e395f4ba3018c2.jpg" />
@@ -22,7 +22,7 @@
                 </div>
                 {% endif %}
                 <div class="col-md-10 col-sm-10">
-                    <div class="panel panel-default arrow {% if message.conversation.from_user_id == message.user_id %}left{% else %}right{% endif %}">
+                    <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>
@@ -34,11 +34,11 @@
                         </div>
                     </div>
                 </div>
-                {% if message.conversation.from_user_id != message.user_id %}
+                {% if current_user.id != message.user_id %}
                 <div class="col-md-2 col-sm-2 hidden-xs">
                         <figure class="thumbnail">
                         <img class="img-responsive" src="http://www.keita-gaming.com/assets/profile/default-avatar-c5d8ec086224cb6fc4e395f4ba3018c2.jpg" />
-                        <figcaption class="text-center">{{ message.user.username }}</figcaption>
+                        <figcaption class="text-center"><strong><a href="{{ message.user.url }}" class="conversation-username">{{ message.user.username }}</a></strong></figcaption>
                     </figure>
                 </div>
                 {% endif %}

+ 70 - 0
migrations/versions/514ca0a3282c_private_messages.py

@@ -0,0 +1,70 @@
+"""Private Messages
+
+Revision ID: 514ca0a3282c
+Revises: 8ad96e49dc6
+Create Date: 2015-03-22 21:57:57.444251
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '514ca0a3282c'
+down_revision = '8ad96e49dc6'
+
+from alembic import op
+import sqlalchemy as sa
+import sqlalchemy_utils
+
+
+def upgrade():
+    ### commands auto generated by Alembic - please adjust! ###
+    op.create_table('conversations',
+    sa.Column('id', sa.Integer(), nullable=False),
+    sa.Column('user_id', sa.Integer(), nullable=False),
+    sa.Column('from_user_id', sa.Integer(), nullable=True),
+    sa.Column('to_user_id', sa.Integer(), nullable=True),
+    sa.Column('shared_id', sqlalchemy_utils.types.uuid.UUIDType(binary=16), nullable=False),
+    sa.Column('subject', sa.String(length=255), nullable=True),
+    sa.Column('date_created', sa.DateTime(), nullable=True),
+    sa.Column('trash', sa.Boolean(), nullable=False),
+    sa.Column('draft', sa.Boolean(), nullable=False),
+    sa.Column('unread', sa.Boolean(), nullable=False),
+    sa.ForeignKeyConstraint(['from_user_id'], ['users.id'], ),
+    sa.ForeignKeyConstraint(['to_user_id'], ['users.id'], ),
+    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
+    sa.PrimaryKeyConstraint('id')
+    )
+    op.create_table('messages',
+    sa.Column('id', sa.Integer(), nullable=False),
+    sa.Column('conversation_id', sa.Integer(), nullable=False),
+    sa.Column('user_id', sa.Integer(), nullable=False),
+    sa.Column('message', sa.Text(), nullable=False),
+    sa.Column('date_created', sa.DateTime(), nullable=True),
+    sa.ForeignKeyConstraint(['conversation_id'], ['conversations.id'], ),
+    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
+    sa.PrimaryKeyConstraint('id')
+    )
+    op.drop_table('privatemessages')
+    ### end Alembic commands ###
+
+
+def downgrade():
+    ### commands auto generated by Alembic - please adjust! ###
+    op.create_table('privatemessages',
+    sa.Column('id', sa.INTEGER(), nullable=False),
+    sa.Column('user_id', sa.INTEGER(), nullable=False),
+    sa.Column('from_user_id', sa.INTEGER(), nullable=True),
+    sa.Column('to_user_id', sa.INTEGER(), nullable=True),
+    sa.Column('subject', sa.VARCHAR(length=255), nullable=True),
+    sa.Column('message', sa.TEXT(), nullable=True),
+    sa.Column('date_created', sa.DATETIME(), nullable=True),
+    sa.Column('trash', sa.BOOLEAN(), nullable=False),
+    sa.Column('draft', sa.BOOLEAN(), nullable=False),
+    sa.Column('unread', sa.BOOLEAN(), nullable=False),
+    sa.ForeignKeyConstraint(['from_user_id'], [u'users.id'], ),
+    sa.ForeignKeyConstraint(['to_user_id'], [u'users.id'], ),
+    sa.ForeignKeyConstraint(['user_id'], [u'users.id'], ),
+    sa.PrimaryKeyConstraint('id')
+    )
+    op.drop_table('messages')
+    op.drop_table('conversations')
+    ### end Alembic commands ###

+ 1 - 0
requirements.txt

@@ -35,5 +35,6 @@ redis==2.10.3
 requests==2.6.0
 simplejson==3.6.5
 speaklater==1.3
+sqlalchemy-utils==0.29.8
 https://github.com/sh4nks/flask-babelex/tarball/master#egg=Flask-BabelEx
 https://github.com/jshipley/Flask-WhooshAlchemy/archive/master.zip#egg=Flask-Whooshalchemy

+ 2 - 1
setup.py

@@ -77,7 +77,8 @@ setup(
         'redis',
         'requests',
         'simplejson',
-        'speaklater'
+        'speaklater',
+        'sqlalchemy-utils'
     ],
     dependency_links=[
         'https://github.com/jshipley/Flask-WhooshAlchemy/archive/master.zip#egg=Flask-WhooshAlchemy',

+ 2 - 1
tests/unit/utils/test_helpers.py

@@ -101,7 +101,8 @@ def test_format_date():
 
 def test_format_quote(topic):
     expected_markdown = "**[test_normal](http://localhost:5000/user/test_normal) wrote:**\n> Test Content Normal\n"
-    assert format_quote(topic.first_post) == expected_markdown
+    actual = format_quote(topic.first_post.username, topic.first_post.content)
+    assert actual == expected_markdown
 
 
 def test_get_image_info():