feat: Complete chat system implementation and password reset enhancement
- Add comprehensive chat system with modern UI design - Implement admin-based password reset system - Fix template syntax errors and 500 server errors - Add chat routes, API endpoints, and database models - Enhance user interface with Tailwind CSS card-based design - Implement community guidelines and quick action features - Add responsive design for mobile and desktop compatibility - Create support chat functionality with admin integration - Fix JavaScript inheritance in base template - Add database migration for chat system tables Features: ✅ Modern chat interface with room management ✅ Admin-based password reset workflow ✅ Real-time chat with mobile app support ✅ Professional UI with gradient cards and hover effects ✅ Community guidelines and safety features ✅ Responsive design for all devices ✅ Error-free template rendering
This commit is contained in:
131
app/models.py
131
app/models.py
@@ -305,3 +305,134 @@ class SentEmail(db.Model):
|
||||
|
||||
def __repr__(self):
|
||||
return f'<SentEmail to={self.recipient} subject={self.subject} status={self.status}>'
|
||||
|
||||
class ChatRoom(db.Model):
|
||||
__tablename__ = 'chat_rooms'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
name = db.Column(db.String(200), nullable=False)
|
||||
description = db.Column(db.Text)
|
||||
room_type = db.Column(db.String(50), default='general') # general, post_discussion, admin_support, password_reset
|
||||
is_private = db.Column(db.Boolean, default=False)
|
||||
is_active = db.Column(db.Boolean, default=True)
|
||||
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
last_activity = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
|
||||
# Foreign Keys
|
||||
created_by_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
|
||||
related_post_id = db.Column(db.Integer, db.ForeignKey('posts.id'), nullable=True) # For post discussions
|
||||
|
||||
# Relationships
|
||||
created_by = db.relationship('User', backref='created_chat_rooms')
|
||||
related_post = db.relationship('Post', backref='chat_rooms')
|
||||
messages = db.relationship('ChatMessage', backref='room', lazy='dynamic', cascade='all, delete-orphan')
|
||||
participants = db.relationship('ChatParticipant', backref='room', lazy='dynamic', cascade='all, delete-orphan')
|
||||
|
||||
def to_dict(self):
|
||||
"""Convert to dictionary for API responses"""
|
||||
return {
|
||||
'id': self.id,
|
||||
'name': self.name,
|
||||
'description': self.description,
|
||||
'room_type': self.room_type,
|
||||
'is_private': self.is_private,
|
||||
'is_active': self.is_active,
|
||||
'created_at': self.created_at.isoformat() if self.created_at else None,
|
||||
'last_activity': self.last_activity.isoformat() if self.last_activity else None,
|
||||
'created_by': {
|
||||
'id': self.created_by.id,
|
||||
'nickname': self.created_by.nickname
|
||||
} if self.created_by else None,
|
||||
'related_post': {
|
||||
'id': self.related_post.id,
|
||||
'title': self.related_post.title
|
||||
} if self.related_post else None,
|
||||
'participant_count': self.participants.count(),
|
||||
'message_count': self.messages.count()
|
||||
}
|
||||
|
||||
def __repr__(self):
|
||||
return f'<ChatRoom {self.name}>'
|
||||
|
||||
class ChatParticipant(db.Model):
|
||||
__tablename__ = 'chat_participants'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
joined_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
last_seen = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
is_muted = db.Column(db.Boolean, default=False)
|
||||
role = db.Column(db.String(50), default='member') # member, moderator, admin
|
||||
|
||||
# Foreign Keys
|
||||
room_id = db.Column(db.Integer, db.ForeignKey('chat_rooms.id'), nullable=False)
|
||||
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
|
||||
|
||||
# Relationships
|
||||
user = db.relationship('User', backref='chat_participations')
|
||||
|
||||
# Unique constraint
|
||||
__table_args__ = (db.UniqueConstraint('room_id', 'user_id', name='unique_room_participant'),)
|
||||
|
||||
def to_dict(self):
|
||||
"""Convert to dictionary for API responses"""
|
||||
return {
|
||||
'id': self.id,
|
||||
'user': {
|
||||
'id': self.user.id,
|
||||
'nickname': self.user.nickname,
|
||||
'is_admin': self.user.is_admin
|
||||
},
|
||||
'role': self.role,
|
||||
'joined_at': self.joined_at.isoformat() if self.joined_at else None,
|
||||
'last_seen': self.last_seen.isoformat() if self.last_seen else None,
|
||||
'is_muted': self.is_muted
|
||||
}
|
||||
|
||||
def __repr__(self):
|
||||
return f'<ChatParticipant {self.user.nickname} in {self.room.name}>'
|
||||
|
||||
class ChatMessage(db.Model):
|
||||
__tablename__ = 'chat_messages'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
content = db.Column(db.Text, nullable=False)
|
||||
message_type = db.Column(db.String(50), default='text') # text, system, file, image
|
||||
is_edited = db.Column(db.Boolean, default=False)
|
||||
is_deleted = db.Column(db.Boolean, default=False)
|
||||
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
# Foreign Keys
|
||||
room_id = db.Column(db.Integer, db.ForeignKey('chat_rooms.id'), nullable=False)
|
||||
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
|
||||
reply_to_id = db.Column(db.Integer, db.ForeignKey('chat_messages.id'), nullable=True) # For threaded replies
|
||||
|
||||
# Relationships
|
||||
user = db.relationship('User', backref='chat_messages')
|
||||
reply_to = db.relationship('ChatMessage', remote_side=[id], backref='replies')
|
||||
|
||||
def to_dict(self):
|
||||
"""Convert to dictionary for API responses"""
|
||||
return {
|
||||
'id': self.id,
|
||||
'content': self.content,
|
||||
'message_type': self.message_type,
|
||||
'is_edited': self.is_edited,
|
||||
'is_deleted': self.is_deleted,
|
||||
'created_at': self.created_at.isoformat() if self.created_at else None,
|
||||
'updated_at': self.updated_at.isoformat() if self.updated_at else None,
|
||||
'user': {
|
||||
'id': self.user.id,
|
||||
'nickname': self.user.nickname,
|
||||
'is_admin': self.user.is_admin
|
||||
},
|
||||
'reply_to': {
|
||||
'id': self.reply_to.id,
|
||||
'content': self.reply_to.content[:100] + '...' if len(self.reply_to.content) > 100 else self.reply_to.content,
|
||||
'user_nickname': self.reply_to.user.nickname
|
||||
} if self.reply_to else None
|
||||
}
|
||||
|
||||
def __repr__(self):
|
||||
return f'<ChatMessage {self.id} by {self.user.nickname}>'
|
||||
|
||||
Reference in New Issue
Block a user