163 lines
6.4 KiB
Python
163 lines
6.4 KiB
Python
# Copyright (c) 2025 Patrick Motsch
|
|
# All rights reserved.
|
|
"""
|
|
Notification model for in-app notifications.
|
|
Supports actionable notifications (e.g., invitation accept/decline).
|
|
"""
|
|
|
|
import uuid
|
|
from typing import Optional, List
|
|
from enum import Enum
|
|
from pydantic import BaseModel, Field, ConfigDict
|
|
from modules.datamodels.datamodelBase import PowerOnModel
|
|
from modules.shared.i18nRegistry import i18nModel
|
|
|
|
|
|
class NotificationType(str, Enum):
|
|
"""Types of notifications"""
|
|
INVITATION = "invitation" # Einladung zu Mandat/Feature
|
|
SYSTEM = "system" # System-Nachrichten
|
|
WORKFLOW = "workflow" # Workflow-Status Updates
|
|
MENTION = "mention" # Erwähnung in Chat/Kommentar
|
|
|
|
|
|
class NotificationStatus(str, Enum):
|
|
"""Status of a notification"""
|
|
UNREAD = "unread" # Noch nicht gelesen
|
|
READ = "read" # Gelesen
|
|
ACTIONED = "actioned" # Aktion wurde durchgeführt
|
|
DISMISSED = "dismissed" # Verworfen/Geschlossen
|
|
|
|
|
|
@i18nModel("Benachrichtigungs-Aktion")
|
|
class NotificationAction(BaseModel):
|
|
"""Possible action for a notification"""
|
|
actionId: str = Field(
|
|
description="Unique identifier for the action (e.g., 'accept', 'decline')",
|
|
json_schema_extra={"label": "Aktions-ID"},
|
|
)
|
|
label: str = Field(
|
|
description="Display label for the action button",
|
|
json_schema_extra={"label": "Bezeichnung"},
|
|
)
|
|
style: str = Field(
|
|
default="default",
|
|
description="Button style: 'primary', 'danger', 'default'",
|
|
json_schema_extra={"label": "Stil"},
|
|
)
|
|
|
|
|
|
@i18nModel("Benachrichtigung")
|
|
class UserNotification(PowerOnModel):
|
|
"""
|
|
In-app notification for a user.
|
|
Supports actionable notifications with accept/decline buttons.
|
|
"""
|
|
id: str = Field(
|
|
default_factory=lambda: str(uuid.uuid4()),
|
|
description="Unique ID of the notification",
|
|
json_schema_extra={"label": "ID", "frontend_type": "text", "frontend_readonly": True, "frontend_required": False}
|
|
)
|
|
userId: str = Field(
|
|
description="Target user ID for this notification",
|
|
json_schema_extra={
|
|
"label": "Benutzer",
|
|
"frontend_type": "text",
|
|
"frontend_readonly": True,
|
|
"frontend_required": True,
|
|
"fk_target": {"db": "poweron_app", "table": "User"},
|
|
},
|
|
)
|
|
|
|
type: NotificationType = Field(
|
|
default=NotificationType.SYSTEM,
|
|
description="Type of notification",
|
|
json_schema_extra={
|
|
"label": "Typ",
|
|
"frontend_type": "select",
|
|
"frontend_readonly": True,
|
|
"frontend_required": True,
|
|
"frontend_options": [
|
|
{"value": "invitation", "label": "Einladung"},
|
|
{"value": "system", "label": "System"},
|
|
{"value": "workflow", "label": "Workflow"},
|
|
{"value": "mention", "label": "Erwähnung"}
|
|
]
|
|
}
|
|
)
|
|
status: NotificationStatus = Field(
|
|
default=NotificationStatus.UNREAD,
|
|
description="Current status of the notification",
|
|
json_schema_extra={
|
|
"label": "Status",
|
|
"frontend_type": "select",
|
|
"frontend_readonly": True,
|
|
"frontend_required": False,
|
|
"frontend_options": [
|
|
{"value": "unread", "label": "Ungelesen"},
|
|
{"value": "read", "label": "Gelesen"},
|
|
{"value": "actioned", "label": "Bearbeitet"},
|
|
{"value": "dismissed", "label": "Verworfen"}
|
|
]
|
|
}
|
|
)
|
|
|
|
title: str = Field(
|
|
description="Notification title",
|
|
json_schema_extra={"label": "Titel", "frontend_type": "text", "frontend_readonly": True, "frontend_required": True}
|
|
)
|
|
message: str = Field(
|
|
description="Notification message/body",
|
|
json_schema_extra={"label": "Nachricht", "frontend_type": "textarea", "frontend_readonly": True, "frontend_required": True}
|
|
)
|
|
icon: Optional[str] = Field(
|
|
default=None,
|
|
description="Optional icon identifier (e.g., 'mail', 'warning', 'info')",
|
|
json_schema_extra={"label": "Symbol", "frontend_type": "text", "frontend_readonly": True, "frontend_required": False}
|
|
)
|
|
|
|
referenceType: Optional[str] = Field(
|
|
default=None,
|
|
description="Type of referenced object (e.g., 'Invitation', 'Workflow')",
|
|
json_schema_extra={"label": "Referenz-Typ", "frontend_type": "text", "frontend_readonly": True, "frontend_required": False}
|
|
)
|
|
referenceId: Optional[str] = Field(
|
|
default=None,
|
|
description="ID of referenced object",
|
|
json_schema_extra={"label": "Referenz-ID", "frontend_type": "text", "frontend_readonly": True, "frontend_required": False}
|
|
)
|
|
|
|
actions: Optional[List[NotificationAction]] = Field(
|
|
default=None,
|
|
description="List of possible actions for this notification",
|
|
json_schema_extra={"label": "Aktionen", "frontend_type": "json", "frontend_readonly": True, "frontend_required": False}
|
|
)
|
|
|
|
actionTaken: Optional[str] = Field(
|
|
default=None,
|
|
description="Which action was taken (actionId)",
|
|
json_schema_extra={"label": "Durchgefuehrte Aktion", "frontend_type": "text", "frontend_readonly": True, "frontend_required": False}
|
|
)
|
|
actionResult: Optional[str] = Field(
|
|
default=None,
|
|
description="Result message from the action",
|
|
json_schema_extra={"label": "Aktions-Ergebnis", "frontend_type": "textarea", "frontend_readonly": True, "frontend_required": False}
|
|
)
|
|
|
|
readAt: Optional[float] = Field(
|
|
default=None,
|
|
description="When the notification was read (UTC timestamp)",
|
|
json_schema_extra={"label": "Gelesen am", "frontend_type": "timestamp", "frontend_readonly": True, "frontend_required": False}
|
|
)
|
|
actionedAt: Optional[float] = Field(
|
|
default=None,
|
|
description="When action was taken (UTC timestamp)",
|
|
json_schema_extra={"label": "Bearbeitet am", "frontend_type": "timestamp", "frontend_readonly": True, "frontend_required": False}
|
|
)
|
|
expiresAt: Optional[float] = Field(
|
|
default=None,
|
|
description="When the notification expires (optional, UTC timestamp)",
|
|
json_schema_extra={"label": "Gueltig bis", "frontend_type": "timestamp", "frontend_readonly": True, "frontend_required": False}
|
|
)
|
|
|
|
model_config = ConfigDict(use_enum_values=True)
|