forked from hacktoolkit/django-htk
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
adds conversations app for n-party communications
- Loading branch information
Showing
8 changed files
with
285 additions
and
37 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
# Django Imports | ||
from django.contrib import admin | ||
|
||
# HTK Imports | ||
from htk.utils import htk_setting | ||
from htk.utils.general import resolve_model_dynamically | ||
|
||
|
||
Conversation = resolve_model_dynamically(htk_setting('HTK_CONVERSATION_MODEL')) | ||
ConversationMessage = resolve_model_dynamically( | ||
htk_setting('HTK_CONVERSATION_MESSAGE_MODEL') | ||
) | ||
ConversationParticipant = resolve_model_dynamically( | ||
htk_setting('HTK_CONVERSATION_PARTICIPANT_MODEL') | ||
) | ||
|
||
|
||
class ConversationParticipantInline(admin.TabularInline): | ||
model = ConversationParticipant | ||
extra = 0 | ||
|
||
|
||
class ConversationMessageInline(admin.TabularInline): | ||
model = ConversationMessage | ||
extra = 0 | ||
|
||
|
||
class BaseConversationAdmin(admin.ModelAdmin): | ||
model = Conversation | ||
|
||
list_display = ( | ||
'id', | ||
'topic', | ||
'description', | ||
'num_participants', | ||
'num_messages', | ||
'created_by', | ||
'created_at', | ||
'updated_at', | ||
) | ||
|
||
inlines = ( | ||
ConversationParticipantInline, | ||
# NOTE: This will crash if the there are too many messages in the conversation | ||
ConversationMessageInline, | ||
) | ||
|
||
search_fields = ( | ||
'topic', | ||
'description', | ||
'created_by__username', | ||
'created_by__first_name', | ||
'created_by__last_name', | ||
) | ||
|
||
|
||
class BaseConversationParticipantAdmin(admin.ModelAdmin): | ||
model = ConversationParticipant | ||
|
||
list_display = ( | ||
'id', | ||
'conversation', | ||
'user', | ||
'joined_at', | ||
) | ||
|
||
search_fields = ( | ||
'conversation__topic', | ||
'user__username', | ||
'user__first_name', | ||
'user__last_name', | ||
) | ||
|
||
list_filters = ( | ||
'conversation', | ||
'user', | ||
) | ||
|
||
|
||
class BaseConversationMessageAdmin(admin.ModelAdmin): | ||
model = ConversationMessage | ||
|
||
list_display = ( | ||
'id', | ||
'conversation', | ||
'author', | ||
'reply_to', | ||
'content', | ||
'posted_at', | ||
'edited_at', | ||
'deleted_at', | ||
) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
HTK_CONVERSATION_MODEL = None | ||
HTK_CONVERSATION_PARTICIPANT_MODEL = None | ||
HTK_CONVERSATION_MESSAGE_MODEL = None | ||
HTK_CONVERSATION_MESSAGE_MAX_LENGTH = 2048 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Django Imports | ||
from django.db import models | ||
|
||
# HTK Imports | ||
from htk.models.fk_fields import build_kwargs | ||
from htk.utils import htk_setting | ||
|
||
|
||
def fk_conversation( | ||
related_name: str, | ||
required: bool = False, | ||
**kwargs, | ||
) -> models.ForeignKey: | ||
field = models.ForeignKey( | ||
htk_setting('HTK_CONVERSATION_MODEL'), | ||
related_name=related_name, | ||
**build_kwargs(required=required, **kwargs), | ||
) | ||
return field |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
# Django Imports | ||
from django.db import models | ||
|
||
# HTK Imports | ||
from htk.apps.conversations.fk_fields import fk_conversation | ||
from htk.models.fk_fields import fk_user | ||
from htk.utils import htk_setting | ||
|
||
|
||
# isort: off | ||
|
||
|
||
class BaseConversation(models.Model): | ||
"""A base conversation class which is extensible | ||
A conversation is a collection of messages between `n` participants, where `n >= 2`. | ||
When `n` is: | ||
- `2`, it is a private conversation, or a direct message ("DM") | ||
- `>2`, it is a group conversation | ||
""" | ||
|
||
topic = models.CharField(max_length=256, blank=True) | ||
description = models.TextField(max_length=1024, blank=True) | ||
created_by = fk_user(related_name='created_conversations', required=False) | ||
created_at = models.DateTimeField(auto_now_add=True) | ||
updated_at = models.DateTimeField(auto_now=True) | ||
|
||
class Meta: | ||
abstract = True | ||
|
||
def __str__(self): | ||
value = '%s (#%s)' % ( | ||
self.topic or '<No Topic>', | ||
self.id, | ||
) | ||
return value | ||
|
||
@property | ||
def num_participants(self): | ||
num = self.participants.count() | ||
return num | ||
|
||
@property | ||
def num_messages(self): | ||
num = self.messages.count() | ||
return num | ||
|
||
|
||
class BaseConversationParticipant(models.Model): | ||
"""A participant in a conversation | ||
This is a many-to-many relationship between a User and a Conversation | ||
For n-party conversations, there will be n-1 ConversationParticipants | ||
""" | ||
|
||
conversation = fk_conversation(related_name='participants', required=True) | ||
user = fk_user(related_name='conversation_participants', required=True) | ||
joined_at = models.DateTimeField(auto_now_add=True) | ||
|
||
class Meta: | ||
abstract = True | ||
|
||
def __str__(self): | ||
value = '%s - %s' % ( | ||
self.conversation, | ||
self.user, | ||
) | ||
return value | ||
|
||
|
||
class BaseConversationMessage(models.Model): | ||
"""A message in a conversation | ||
A conversation message is a message that belongs to a conversation. | ||
A conversation message is visible to all participants in the conversation. | ||
""" | ||
|
||
conversation = fk_conversation(related_name='messages', required=True) | ||
# `author` is not required when the message is system-generated | ||
author = fk_user( | ||
related_name='authored_conversation_messages', required=False | ||
) | ||
reply_to = models.ForeignKey( | ||
'self', | ||
related_name='replies', | ||
blank=True, | ||
null=True, | ||
on_delete=models.CASCADE, | ||
) | ||
content = models.TextField( | ||
max_length=htk_setting('HTK_CONVERSATION_MESSAGE_MAX_LENGTH') | ||
) | ||
posted_at = models.DateTimeField(auto_now_add=True) | ||
edited_at = models.DateTimeField(blank=True, null=True) | ||
# soft-deletion: app will hide messages that are "deleted"; but also allow for messages to be "undeleted" | ||
deleted_at = models.DateTimeField(blank=True, null=True) | ||
|
||
class Meta: | ||
abstract = True | ||
|
||
def __str__(self): | ||
value = '%s - %s' % ( | ||
self.conversation, | ||
self.author, | ||
) | ||
return value | ||
|
||
@property | ||
def was_edited(self): | ||
return self.edited_at is not None and self.edited_at > self.posted_at | ||
|
||
@property | ||
def is_deleted(self): | ||
return self.deleted_at is not None | ||
|
||
def save(self, **kwargs): | ||
"""Saves this message. | ||
Side effect: also performs any customizations, like updating cache, etc | ||
""" | ||
super().save(**kwargs) | ||
|
||
# force update on `Conversation.updated_at` | ||
self.conversation.save() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters