695 lines
31 KiB
Python
695 lines
31 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
from flask_sqlalchemy import SQLAlchemy
|
|
from flask_login import UserMixin
|
|
from datetime import datetime
|
|
from werkzeug.security import generate_password_hash, check_password_hash
|
|
from enum import Enum
|
|
import uuid as uuid_pkg
|
|
import os
|
|
|
|
db = SQLAlchemy()
|
|
|
|
# Beziehungstypen für Gedankenverknüpfungen
|
|
class RelationType(Enum):
|
|
SUPPORTS = "stützt"
|
|
CONTRADICTS = "widerspricht"
|
|
BUILDS_UPON = "baut auf auf"
|
|
GENERALIZES = "verallgemeinert"
|
|
SPECIFIES = "spezifiziert"
|
|
INSPIRES = "inspiriert"
|
|
|
|
# Beziehungstabelle für viele-zu-viele Beziehung zwischen MindMapNodes
|
|
node_relationship = db.Table('node_relationship',
|
|
db.Column('parent_id', db.Integer, db.ForeignKey('mind_map_node.id'), primary_key=True),
|
|
db.Column('child_id', db.Integer, db.ForeignKey('mind_map_node.id'), primary_key=True)
|
|
)
|
|
|
|
# Beziehungstabelle für öffentliche Knoten und Gedanken
|
|
node_thought_association = db.Table('node_thought_association',
|
|
db.Column('node_id', db.Integer, db.ForeignKey('mind_map_node.id'), primary_key=True),
|
|
db.Column('thought_id', db.Integer, db.ForeignKey('thought.id'), primary_key=True)
|
|
)
|
|
|
|
# Beziehungstabelle für Benutzer-spezifische Mindmap-Knoten und Gedanken
|
|
user_mindmap_thought_association = db.Table('user_mindmap_thought_association',
|
|
db.Column('user_mindmap_id', db.Integer, db.ForeignKey('user_mindmap.id'), primary_key=True),
|
|
db.Column('thought_id', db.Integer, db.ForeignKey('thought.id'), primary_key=True)
|
|
)
|
|
|
|
# Beziehungstabelle für Benutzer-Bookmarks von Gedanken
|
|
user_thought_bookmark = db.Table('user_thought_bookmark',
|
|
db.Column('user_id', db.Integer, db.ForeignKey('user.id'), primary_key=True),
|
|
db.Column('thought_id', db.Integer, db.ForeignKey('thought.id'), primary_key=True),
|
|
db.Column('created_at', db.DateTime, default=datetime.utcnow)
|
|
)
|
|
|
|
# Beziehungstabelle für Benutzer-Freundschaften
|
|
user_friendships = db.Table('user_friendships',
|
|
db.Column('user_id', db.Integer, db.ForeignKey('user.id'), primary_key=True),
|
|
db.Column('friend_id', db.Integer, db.ForeignKey('user.id'), primary_key=True),
|
|
db.Column('created_at', db.DateTime, default=datetime.utcnow),
|
|
db.Column('status', db.String(20), default='pending') # pending, accepted, blocked
|
|
)
|
|
|
|
# Beziehungstabelle für Benutzer-Follows
|
|
user_follows = db.Table('user_follows',
|
|
db.Column('follower_id', db.Integer, db.ForeignKey('user.id'), primary_key=True),
|
|
db.Column('followed_id', db.Integer, db.ForeignKey('user.id'), primary_key=True),
|
|
db.Column('created_at', db.DateTime, default=datetime.utcnow)
|
|
)
|
|
|
|
# Beziehungstabelle für Post-Likes
|
|
post_likes = db.Table('post_likes',
|
|
db.Column('user_id', db.Integer, db.ForeignKey('user.id'), primary_key=True),
|
|
db.Column('post_id', db.Integer, db.ForeignKey('social_post.id'), primary_key=True),
|
|
db.Column('created_at', db.DateTime, default=datetime.utcnow)
|
|
)
|
|
|
|
# Beziehungstabelle für Comment-Likes
|
|
comment_likes = db.Table('comment_likes',
|
|
db.Column('user_id', db.Integer, db.ForeignKey('user.id'), primary_key=True),
|
|
db.Column('comment_id', db.Integer, db.ForeignKey('social_comment.id'), primary_key=True),
|
|
db.Column('created_at', db.DateTime, default=datetime.utcnow)
|
|
)
|
|
|
|
class User(db.Model, UserMixin):
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
username = db.Column(db.String(80), unique=True, nullable=False)
|
|
email = db.Column(db.String(120), unique=True, nullable=False)
|
|
password = db.Column(db.String(512), nullable=False)
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
|
is_active = db.Column(db.Boolean, default=True)
|
|
role = db.Column(db.String(20), default="user") # 'user', 'admin', 'moderator'
|
|
bio = db.Column(db.Text, nullable=True) # Profil-Bio
|
|
location = db.Column(db.String(100), nullable=True) # Standort
|
|
website = db.Column(db.String(200), nullable=True) # Website
|
|
avatar = db.Column(db.String(200), nullable=True) # Profilbild-URL
|
|
last_login = db.Column(db.DateTime, nullable=True) # Letzter Login
|
|
|
|
# Social Network Felder
|
|
display_name = db.Column(db.String(100), nullable=True) # Anzeigename
|
|
birth_date = db.Column(db.Date, nullable=True) # Geburtsdatum
|
|
gender = db.Column(db.String(20), nullable=True) # Geschlecht
|
|
phone = db.Column(db.String(20), nullable=True) # Telefonnummer
|
|
is_verified = db.Column(db.Boolean, default=False) # Verifizierter Account
|
|
is_private = db.Column(db.Boolean, default=False) # Privater Account
|
|
follower_count = db.Column(db.Integer, default=0) # Follower-Anzahl
|
|
following_count = db.Column(db.Integer, default=0) # Following-Anzahl
|
|
post_count = db.Column(db.Integer, default=0) # Post-Anzahl
|
|
online_status = db.Column(db.String(20), default='offline') # online, offline, away
|
|
last_seen = db.Column(db.DateTime, nullable=True) # Zuletzt gesehen
|
|
|
|
# Beziehungen
|
|
threads = db.relationship('Thread', backref='creator', lazy=True)
|
|
messages = db.relationship('Message', backref='author', lazy=True)
|
|
projects = db.relationship('Project', backref='owner', lazy=True)
|
|
mindmaps = db.relationship('UserMindmap', backref='user', lazy=True)
|
|
thoughts = db.relationship('Thought', backref='author', lazy=True)
|
|
bookmarked_thoughts = db.relationship('Thought', secondary=user_thought_bookmark,
|
|
lazy='dynamic', backref=db.backref('bookmarked_by', lazy='dynamic'))
|
|
|
|
# Social Network Beziehungen
|
|
posts = db.relationship('SocialPost', backref='author', lazy=True, cascade="all, delete-orphan")
|
|
comments = db.relationship('SocialComment', backref='author', lazy=True, cascade="all, delete-orphan")
|
|
notifications = db.relationship('Notification', foreign_keys='Notification.user_id', backref='user', lazy=True, cascade="all, delete-orphan")
|
|
|
|
# Freundschaften (bidirektional)
|
|
friends = db.relationship(
|
|
'User',
|
|
secondary=user_friendships,
|
|
primaryjoin=id == user_friendships.c.user_id,
|
|
secondaryjoin=id == user_friendships.c.friend_id,
|
|
backref='friend_of',
|
|
lazy='dynamic'
|
|
)
|
|
|
|
# Following/Followers
|
|
following = db.relationship(
|
|
'User',
|
|
secondary=user_follows,
|
|
primaryjoin=id == user_follows.c.follower_id,
|
|
secondaryjoin=id == user_follows.c.followed_id,
|
|
backref=db.backref('followers', lazy='dynamic'),
|
|
lazy='dynamic'
|
|
)
|
|
|
|
# Liked Posts und Comments
|
|
liked_posts = db.relationship('SocialPost', secondary=post_likes,
|
|
backref=db.backref('liked_by', lazy='dynamic'), lazy='dynamic')
|
|
liked_comments = db.relationship('SocialComment', secondary=comment_likes,
|
|
backref=db.backref('liked_by', lazy='dynamic'), lazy='dynamic')
|
|
|
|
def __repr__(self):
|
|
return f'<User {self.username}>'
|
|
|
|
def set_password(self, password):
|
|
self.password = generate_password_hash(password)
|
|
|
|
def check_password(self, password):
|
|
return check_password_hash(self.password, password)
|
|
|
|
@property
|
|
def is_admin(self):
|
|
return self.role == 'admin'
|
|
|
|
@is_admin.setter
|
|
def is_admin(self, value):
|
|
self.role = 'admin' if value else 'user'
|
|
|
|
# Social Network Methoden
|
|
def follow(self, user):
|
|
"""Folgt einem anderen Benutzer"""
|
|
if not self.is_following(user):
|
|
self.following.append(user)
|
|
user.follower_count += 1
|
|
user.following_count += 1
|
|
|
|
# Notification erstellen
|
|
notification = Notification(
|
|
user_id=user.id,
|
|
type='follow',
|
|
message=f'{self.username} folgt dir jetzt',
|
|
related_user_id=self.id
|
|
)
|
|
db.session.add(notification)
|
|
|
|
def unfollow(self, user):
|
|
"""Entfolgt einem Benutzer"""
|
|
if self.is_following(user):
|
|
self.following.remove(user)
|
|
user.follower_count -= 1
|
|
user.following_count -= 1
|
|
|
|
def is_following(self, user):
|
|
"""Prüft ob der Benutzer einem anderen folgt"""
|
|
return self.following.filter(user_follows.c.followed_id == user.id).count() > 0
|
|
|
|
def get_feed_posts(self, limit=20):
|
|
"""Holt Posts für den Feed (von gefolgten Benutzern)"""
|
|
# Hole alle User-IDs von Benutzern, denen ich folge + meine eigene
|
|
followed_user_ids = [user.id for user in self.following]
|
|
all_user_ids = followed_user_ids + [self.id]
|
|
|
|
# Hole Posts von diesen Benutzern
|
|
return SocialPost.query.filter(
|
|
SocialPost.user_id.in_(all_user_ids)
|
|
).order_by(SocialPost.created_at.desc()).limit(limit)
|
|
|
|
class Category(db.Model):
|
|
"""Wissenschaftliche Kategorien für die Gliederung der öffentlichen Mindmap"""
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
name = db.Column(db.String(100), unique=True, nullable=False)
|
|
description = db.Column(db.Text)
|
|
color_code = db.Column(db.String(7)) # Hex color
|
|
icon = db.Column(db.String(50))
|
|
parent_id = db.Column(db.Integer, db.ForeignKey('category.id'), nullable=True)
|
|
|
|
# Beziehungen
|
|
children = db.relationship('Category', backref=db.backref('parent', remote_side=[id]))
|
|
nodes = db.relationship('MindMapNode', backref='category', lazy=True)
|
|
|
|
def __repr__(self):
|
|
return f'<Category {self.name}>'
|
|
|
|
class MindMapNode(db.Model):
|
|
"""Öffentliche Mindmap-Knoten, die für alle Benutzer sichtbar sind"""
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
name = db.Column(db.String(100), nullable=False)
|
|
description = db.Column(db.Text)
|
|
color_code = db.Column(db.String(7))
|
|
icon = db.Column(db.String(50))
|
|
is_public = db.Column(db.Boolean, default=True)
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
|
created_by_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=True)
|
|
category_id = db.Column(db.Integer, db.ForeignKey('category.id'), nullable=True)
|
|
|
|
__table_args__ = {'extend_existing': True}
|
|
|
|
# Beziehungen für Baumstruktur (mehrere Eltern möglich)
|
|
parents = db.relationship(
|
|
'MindMapNode',
|
|
secondary=node_relationship,
|
|
primaryjoin=(node_relationship.c.child_id == id),
|
|
secondaryjoin=(node_relationship.c.parent_id == id),
|
|
backref=db.backref('children', lazy='dynamic'),
|
|
lazy='dynamic'
|
|
)
|
|
|
|
# Beziehungen zu Gedanken
|
|
thoughts = db.relationship('Thought',
|
|
secondary=node_thought_association,
|
|
backref=db.backref('nodes', lazy='dynamic'))
|
|
|
|
# Beziehung zum Ersteller
|
|
created_by = db.relationship('User', backref='created_nodes')
|
|
|
|
def __repr__(self):
|
|
return f'<MindMapNode {self.name}>'
|
|
|
|
def to_dict(self):
|
|
return {
|
|
'id': self.id,
|
|
'name': self.name,
|
|
'description': self.description,
|
|
'color_code': self.color_code,
|
|
'icon': self.icon,
|
|
'category_id': self.category_id,
|
|
'created_at': self.created_at.isoformat() if self.created_at else None
|
|
}
|
|
|
|
class UserMindmap(db.Model):
|
|
"""Benutzerspezifische Mindmap, die vom Benutzer personalisierbar ist"""
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
name = db.Column(db.String(100), nullable=False)
|
|
description = db.Column(db.Text)
|
|
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
|
last_modified = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
is_private = db.Column(db.Boolean, default=True)
|
|
|
|
# Beziehungen zu öffentlichen Knoten
|
|
public_nodes = db.relationship('MindMapNode',
|
|
secondary='user_mindmap_node',
|
|
backref=db.backref('in_user_mindmaps', lazy='dynamic'))
|
|
|
|
# Beziehungen zu Gedanken
|
|
thoughts = db.relationship('Thought',
|
|
secondary=user_mindmap_thought_association,
|
|
backref=db.backref('in_user_mindmaps', lazy='dynamic'))
|
|
|
|
# Notizen zu dieser Mindmap
|
|
notes = db.relationship('MindmapNote', backref='mindmap', lazy=True)
|
|
|
|
# Beziehungstabelle für benutzerorientierte Mindmaps und öffentliche Knoten
|
|
class UserMindmapNode(db.Model):
|
|
"""Speichert die Beziehung zwischen Benutzer-Mindmaps und öffentlichen Knoten inkl. Position"""
|
|
user_mindmap_id = db.Column(db.Integer, db.ForeignKey('user_mindmap.id'), primary_key=True)
|
|
node_id = db.Column(db.Integer, db.ForeignKey('mind_map_node.id'), primary_key=True)
|
|
x_position = db.Column(db.Float, default=0) # Position X auf der Mindmap
|
|
y_position = db.Column(db.Float, default=0) # Position Y auf der Mindmap
|
|
scale = db.Column(db.Float, default=1.0) # Größe des Knotens
|
|
added_at = db.Column(db.DateTime, default=datetime.utcnow)
|
|
|
|
class MindmapNote(db.Model):
|
|
"""Private Notizen der Benutzer zu ihrer Mindmap"""
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
|
mindmap_id = db.Column(db.Integer, db.ForeignKey('user_mindmap.id'), nullable=False)
|
|
node_id = db.Column(db.Integer, db.ForeignKey('mind_map_node.id'), nullable=True)
|
|
thought_id = db.Column(db.Integer, db.ForeignKey('thought.id'), nullable=True)
|
|
content = db.Column(db.Text, nullable=False)
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
|
last_modified = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
color_code = db.Column(db.String(7), default="#FFF59D") # Farbe der Notiz
|
|
|
|
class Thought(db.Model):
|
|
"""Gedanken und Inhalte, die in der Mindmap verknüpft werden können"""
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
title = db.Column(db.String(200), nullable=False)
|
|
content = db.Column(db.Text, nullable=False)
|
|
abstract = db.Column(db.Text)
|
|
keywords = db.Column(db.String(500))
|
|
color_code = db.Column(db.String(7)) # Hex color code
|
|
source_type = db.Column(db.String(50)) # PDF, Markdown, Text etc.
|
|
branch = db.Column(db.String(100), nullable=False)
|
|
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
|
last_modified = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
|
|
# Beziehungen
|
|
comments = db.relationship('Comment', backref='thought', lazy=True, cascade="all, delete-orphan")
|
|
ratings = db.relationship('ThoughtRating', backref='thought', lazy=True)
|
|
|
|
outgoing_relations = db.relationship(
|
|
'ThoughtRelation',
|
|
foreign_keys='ThoughtRelation.source_id',
|
|
backref='source_thought',
|
|
lazy=True
|
|
)
|
|
incoming_relations = db.relationship(
|
|
'ThoughtRelation',
|
|
foreign_keys='ThoughtRelation.target_id',
|
|
backref='target_thought',
|
|
lazy=True
|
|
)
|
|
|
|
@property
|
|
def average_rating(self):
|
|
if not self.ratings:
|
|
return 0
|
|
return sum(r.relevance_score for r in self.ratings) / len(self.ratings)
|
|
|
|
class ThoughtRelation(db.Model):
|
|
"""Beziehungen zwischen Gedanken"""
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
source_id = db.Column(db.Integer, db.ForeignKey('thought.id'), nullable=False)
|
|
target_id = db.Column(db.Integer, db.ForeignKey('thought.id'), nullable=False)
|
|
relation_type = db.Column(db.Enum(RelationType), nullable=False)
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
|
created_by_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
|
|
|
# Beziehung zum Ersteller
|
|
created_by = db.relationship('User', backref='created_relations')
|
|
|
|
class ThoughtRating(db.Model):
|
|
"""Bewertungen von Gedanken durch Benutzer"""
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
thought_id = db.Column(db.Integer, db.ForeignKey('thought.id'), nullable=False)
|
|
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
|
relevance_score = db.Column(db.Integer, nullable=False) # 1-5
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
|
|
|
__table_args__ = (
|
|
db.UniqueConstraint('thought_id', 'user_id', name='unique_thought_rating'),
|
|
)
|
|
|
|
# Beziehung zum Benutzer
|
|
user = db.relationship('User', backref='ratings')
|
|
|
|
class Comment(db.Model):
|
|
"""Kommentare zu Gedanken"""
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
content = db.Column(db.Text, nullable=False)
|
|
thought_id = db.Column(db.Integer, db.ForeignKey('thought.id'), nullable=False)
|
|
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
|
last_modified = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
|
|
# Thread model
|
|
class Thread(db.Model):
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
title = db.Column(db.String(200), nullable=False)
|
|
description = db.Column(db.Text)
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
|
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
|
|
|
# Relationships
|
|
messages = db.relationship('Message', backref='thread', lazy=True, cascade="all, delete-orphan")
|
|
|
|
def __repr__(self):
|
|
return f'<Thread {self.title}>'
|
|
|
|
# Message model
|
|
class Message(db.Model):
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
content = db.Column(db.Text, nullable=False)
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
|
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
|
thread_id = db.Column(db.Integer, db.ForeignKey('thread.id'), nullable=False)
|
|
role = db.Column(db.String(20), default="user") # 'user', 'assistant', 'system'
|
|
|
|
def __repr__(self):
|
|
return f'<Message {self.id} by {self.user_id}>'
|
|
|
|
# Project model
|
|
class Project(db.Model):
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
title = db.Column(db.String(150), nullable=False)
|
|
description = db.Column(db.Text)
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
|
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
|
category_id = db.Column(db.Integer, db.ForeignKey('category.id'))
|
|
|
|
# Relationships
|
|
documents = db.relationship('Document', backref='project', lazy=True, cascade="all, delete-orphan")
|
|
|
|
def __repr__(self):
|
|
return f'<Project {self.title}>'
|
|
|
|
# Document model
|
|
class Document(db.Model):
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
title = db.Column(db.String(150), nullable=False)
|
|
content = db.Column(db.Text)
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
|
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
project_id = db.Column(db.Integer, db.ForeignKey('project.id'), nullable=False)
|
|
filename = db.Column(db.String(150), nullable=True)
|
|
file_path = db.Column(db.String(300), nullable=True)
|
|
file_type = db.Column(db.String(50), nullable=True)
|
|
file_size = db.Column(db.Integer, nullable=True)
|
|
|
|
def __repr__(self):
|
|
return f'<Document {self.title}>'
|
|
|
|
# Forum-Kategorie-Modell - entspricht den Hauptknotenpunkten der Mindmap
|
|
class ForumCategory(db.Model):
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
node_id = db.Column(db.Integer, db.ForeignKey('mind_map_node.id'), nullable=False)
|
|
title = db.Column(db.String(200), nullable=False)
|
|
description = db.Column(db.Text)
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
|
is_active = db.Column(db.Boolean, default=True)
|
|
|
|
# Beziehungen
|
|
node = db.relationship('MindMapNode', backref='forum_category')
|
|
posts = db.relationship('ForumPost', backref='category', lazy=True, cascade="all, delete-orphan")
|
|
|
|
def __repr__(self):
|
|
return f'<ForumCategory {self.title}>'
|
|
|
|
# Forum-Beitrag-Modell
|
|
class ForumPost(db.Model):
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
title = db.Column(db.String(200), nullable=False)
|
|
content = db.Column(db.Text, nullable=False)
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
|
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
|
category_id = db.Column(db.Integer, db.ForeignKey('forum_category.id'), nullable=False)
|
|
parent_id = db.Column(db.Integer, db.ForeignKey('forum_post.id'), nullable=True)
|
|
is_pinned = db.Column(db.Boolean, default=False)
|
|
is_locked = db.Column(db.Boolean, default=False)
|
|
view_count = db.Column(db.Integer, default=0)
|
|
|
|
# Beziehungen
|
|
author = db.relationship('User', backref='forum_posts')
|
|
replies = db.relationship('ForumPost', backref=db.backref('parent', remote_side=[id]), lazy=True)
|
|
|
|
def __repr__(self):
|
|
return f'<ForumPost {self.title}>'
|
|
|
|
# Berechtigungstypen für Mindmap-Freigaben
|
|
class PermissionType(Enum):
|
|
READ = "Nur-Lesen"
|
|
EDIT = "Bearbeiten"
|
|
ADMIN = "Administrator"
|
|
|
|
# Freigabemodell für Mindmaps
|
|
class MindmapShare(db.Model):
|
|
"""Speichert Informationen über freigegebene Mindmaps und Berechtigungen"""
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
mindmap_id = db.Column(db.Integer, db.ForeignKey('user_mindmap.id'), nullable=False)
|
|
shared_by_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
|
shared_with_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
|
permission_type = db.Column(db.Enum(PermissionType), nullable=False, default=PermissionType.READ)
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
|
last_accessed = db.Column(db.DateTime, nullable=True)
|
|
|
|
# Beziehungen
|
|
mindmap = db.relationship('UserMindmap', backref=db.backref('shares', lazy='dynamic'))
|
|
shared_by = db.relationship('User', foreign_keys=[shared_by_id], backref=db.backref('shared_mindmaps', lazy='dynamic'))
|
|
shared_with = db.relationship('User', foreign_keys=[shared_with_id], backref=db.backref('accessible_mindmaps', lazy='dynamic'))
|
|
|
|
__table_args__ = (
|
|
db.UniqueConstraint('mindmap_id', 'shared_with_id', name='unique_mindmap_share'),
|
|
)
|
|
|
|
def __repr__(self):
|
|
return f'<MindmapShare: {self.mindmap_id} - {self.shared_with_id} - {self.permission_type.name}>'
|
|
|
|
class SocialPost(db.Model):
|
|
"""Posts im Social Network"""
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
content = db.Column(db.Text, nullable=False)
|
|
image_url = db.Column(db.String(500), nullable=True) # Bild-URL
|
|
video_url = db.Column(db.String(500), nullable=True) # Video-URL
|
|
link_url = db.Column(db.String(500), nullable=True) # Link-URL
|
|
link_title = db.Column(db.String(200), nullable=True) # Link-Titel
|
|
link_description = db.Column(db.Text, nullable=True) # Link-Beschreibung
|
|
post_type = db.Column(db.String(20), default='text') # text, image, video, link, thought_share
|
|
visibility = db.Column(db.String(20), default='public') # public, friends, private
|
|
is_pinned = db.Column(db.Boolean, default=False)
|
|
like_count = db.Column(db.Integer, default=0)
|
|
comment_count = db.Column(db.Integer, default=0)
|
|
share_count = db.Column(db.Integer, default=0)
|
|
view_count = db.Column(db.Integer, default=0)
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
|
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
|
|
|
# Verknüpfung zu Gedanken (falls der Post einen Gedanken teilt)
|
|
shared_thought_id = db.Column(db.Integer, db.ForeignKey('thought.id'), nullable=True)
|
|
shared_thought = db.relationship('Thought', backref='shared_in_posts')
|
|
|
|
# Verknüpfung zu Mindmap-Knoten
|
|
shared_node_id = db.Column(db.Integer, db.ForeignKey('mind_map_node.id'), nullable=True)
|
|
shared_node = db.relationship('MindMapNode', backref='shared_in_posts')
|
|
|
|
# Kommentare zu diesem Post
|
|
comments = db.relationship('SocialComment', backref='post', lazy=True, cascade="all, delete-orphan")
|
|
|
|
def __repr__(self):
|
|
return f'<SocialPost {self.id} by {self.author.username}>'
|
|
|
|
def to_dict(self):
|
|
return {
|
|
'id': self.id,
|
|
'content': self.content,
|
|
'post_type': self.post_type,
|
|
'image_url': self.image_url,
|
|
'video_url': self.video_url,
|
|
'link_url': self.link_url,
|
|
'link_title': self.link_title,
|
|
'link_description': self.link_description,
|
|
'visibility': self.visibility,
|
|
'is_pinned': self.is_pinned,
|
|
'like_count': self.like_count,
|
|
'comment_count': self.comment_count,
|
|
'share_count': self.share_count,
|
|
'view_count': self.view_count,
|
|
'created_at': self.created_at.isoformat(),
|
|
'updated_at': self.updated_at.isoformat(),
|
|
'author': {
|
|
'id': self.author.id,
|
|
'username': self.author.username,
|
|
'display_name': self.author.display_name or self.author.username,
|
|
'avatar': self.author.avatar,
|
|
'is_verified': self.author.is_verified
|
|
},
|
|
'shared_thought': self.shared_thought.to_dict() if self.shared_thought else None,
|
|
'shared_node': self.shared_node.to_dict() if self.shared_node else None
|
|
}
|
|
|
|
class SocialComment(db.Model):
|
|
"""Kommentare zu Posts"""
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
content = db.Column(db.Text, nullable=False)
|
|
like_count = db.Column(db.Integer, default=0)
|
|
reply_count = db.Column(db.Integer, default=0)
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
|
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
|
post_id = db.Column(db.Integer, db.ForeignKey('social_post.id'), nullable=False)
|
|
parent_id = db.Column(db.Integer, db.ForeignKey('social_comment.id'), nullable=True)
|
|
|
|
# Antworten auf diesen Kommentar
|
|
replies = db.relationship('SocialComment', backref=db.backref('parent', remote_side=[id]), lazy=True)
|
|
|
|
def __repr__(self):
|
|
return f'<SocialComment {self.id} by {self.author.username}>'
|
|
|
|
def to_dict(self):
|
|
return {
|
|
'id': self.id,
|
|
'content': self.content,
|
|
'like_count': self.like_count,
|
|
'reply_count': self.reply_count,
|
|
'created_at': self.created_at.isoformat(),
|
|
'updated_at': self.updated_at.isoformat(),
|
|
'author': {
|
|
'id': self.author.id,
|
|
'username': self.author.username,
|
|
'display_name': self.author.display_name or self.author.username,
|
|
'avatar': self.author.avatar,
|
|
'is_verified': self.author.is_verified
|
|
},
|
|
'parent_id': self.parent_id
|
|
}
|
|
|
|
class Notification(db.Model):
|
|
"""Benachrichtigungen für Benutzer"""
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
type = db.Column(db.String(50), nullable=False) # follow, like, comment, mention, friend_request, etc.
|
|
message = db.Column(db.String(500), nullable=False)
|
|
is_read = db.Column(db.Boolean, default=False)
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
|
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
|
|
|
# Verknüpfungen zu anderen Entitäten
|
|
related_user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=True)
|
|
related_post_id = db.Column(db.Integer, db.ForeignKey('social_post.id'), nullable=True)
|
|
related_comment_id = db.Column(db.Integer, db.ForeignKey('social_comment.id'), nullable=True)
|
|
related_thought_id = db.Column(db.Integer, db.ForeignKey('thought.id'), nullable=True)
|
|
|
|
# Beziehungen
|
|
related_user = db.relationship('User', foreign_keys=[related_user_id])
|
|
related_post = db.relationship('SocialPost', foreign_keys=[related_post_id])
|
|
related_comment = db.relationship('SocialComment', foreign_keys=[related_comment_id])
|
|
related_thought = db.relationship('Thought', foreign_keys=[related_thought_id])
|
|
|
|
def __repr__(self):
|
|
return f'<Notification {self.id} for {self.user.username}>'
|
|
|
|
def to_dict(self):
|
|
return {
|
|
'id': self.id,
|
|
'type': self.type,
|
|
'message': self.message,
|
|
'is_read': self.is_read,
|
|
'created_at': self.created_at.isoformat(),
|
|
'related_user': self.related_user.username if self.related_user else None,
|
|
'related_post_id': self.related_post_id,
|
|
'related_comment_id': self.related_comment_id,
|
|
'related_thought_id': self.related_thought_id
|
|
}
|
|
|
|
class UserSettings(db.Model):
|
|
"""Benutzereinstellungen"""
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False, unique=True)
|
|
|
|
# Datenschutz-Einstellungen
|
|
profile_visibility = db.Column(db.String(20), default='public') # public, friends, private
|
|
show_email = db.Column(db.Boolean, default=False)
|
|
show_birth_date = db.Column(db.Boolean, default=False)
|
|
show_location = db.Column(db.Boolean, default=True)
|
|
allow_friend_requests = db.Column(db.Boolean, default=True)
|
|
allow_messages = db.Column(db.String(20), default='everyone') # everyone, friends, none
|
|
|
|
# Benachrichtigungs-Einstellungen
|
|
email_notifications = db.Column(db.Boolean, default=True)
|
|
push_notifications = db.Column(db.Boolean, default=True)
|
|
notify_on_follow = db.Column(db.Boolean, default=True)
|
|
notify_on_like = db.Column(db.Boolean, default=True)
|
|
notify_on_comment = db.Column(db.Boolean, default=True)
|
|
notify_on_mention = db.Column(db.Boolean, default=True)
|
|
notify_on_friend_request = db.Column(db.Boolean, default=True)
|
|
|
|
# Interface-Einstellungen
|
|
dark_mode = db.Column(db.Boolean, default=False)
|
|
language = db.Column(db.String(10), default='de')
|
|
|
|
# Beziehung
|
|
user = db.relationship('User', backref=db.backref('settings', uselist=False))
|
|
|
|
def __repr__(self):
|
|
return f'<UserSettings for {self.user.username}>'
|
|
|
|
class Activity(db.Model):
|
|
"""Aktivitätsprotokoll für Benutzer"""
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
|
action = db.Column(db.String(100), nullable=False) # login, logout, post_created, thought_shared, etc.
|
|
description = db.Column(db.String(500), nullable=True)
|
|
ip_address = db.Column(db.String(45), nullable=True) # IPv4/IPv6
|
|
user_agent = db.Column(db.String(500), nullable=True)
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
|
|
|
# Verknüpfungen zu anderen Entitäten
|
|
related_post_id = db.Column(db.Integer, db.ForeignKey('social_post.id'), nullable=True)
|
|
related_thought_id = db.Column(db.Integer, db.ForeignKey('thought.id'), nullable=True)
|
|
related_mindmap_id = db.Column(db.Integer, db.ForeignKey('user_mindmap.id'), nullable=True)
|
|
|
|
# Beziehungen
|
|
user = db.relationship('User', backref='activities')
|
|
related_post = db.relationship('SocialPost')
|
|
related_thought = db.relationship('Thought')
|
|
related_mindmap = db.relationship('UserMindmap')
|
|
|
|
def __repr__(self):
|
|
return f'<Activity {self.action} by {self.user.username}>' |