Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable users to migrate a Case thread to a Case dedicated channel. #5207

Merged
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
375f658
Enable users to migrate a Case thread to a Case dedicated channel.
metroid-samus Sep 16, 2024
88305b1
Handle migrating dedicated channels from flows.
metroid-samus Sep 17, 2024
a234475
Merge branch 'master' into enhancement/create-case-conversation-chann…
metroid-samus Sep 17, 2024
1f33798
Adds Dispatch UI button to create dedicated channel.
metroid-samus Sep 17, 2024
27efa70
Remove unused import
metroid-samus Sep 17, 2024
baad11b
Update message.
metroid-samus Sep 17, 2024
d8cbf9b
Update src/dispatch/plugins/dispatch_slack/case/interactive.py
metroid-samus Sep 17, 2024
b178297
Remove unnecessary service calls.
metroid-samus Sep 18, 2024
e928725
Update src/dispatch/plugins/dispatch_slack/case/messages.py
metroid-samus Sep 18, 2024
c7c29df
Raise exceptions if conversation creation fails.
metroid-samus Sep 18, 2024
92f5780
Hide button if conversation channel is created.
metroid-samus Sep 18, 2024
39d8517
Update conversation thread when migrating conversation.
metroid-samus Sep 18, 2024
dcdd3b4
Merge branch 'master' into enhancement/create-case-conversation-chann…
metroid-samus Sep 18, 2024
937d59b
Dedicated channels should default to true.
metroid-samus Sep 18, 2024
01bd33b
Update src/dispatch/plugins/dispatch_slack/case/interactive.py
metroid-samus Sep 19, 2024
ce844e7
Update src/dispatch/case/flows.py
metroid-samus Sep 19, 2024
dea3b95
Merge branch 'master' into enhancement/create-case-conversation-chann…
metroid-samus Sep 19, 2024
11e6f23
Merge branch 'master' into enhancement/create-case-conversation-chann…
metroid-samus Sep 19, 2024
6a39c72
Merge branch 'master' into enhancement/create-case-conversation-chann…
metroid-samus Sep 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 39 additions & 21 deletions src/dispatch/case/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,41 @@ def case_assign_role_flow(
conversation_flows.set_conversation_topic(case, db_session)


def case_create_conversation_flow(
db_session: Session,
case: Case,
participant_emails: list[str],
conversation_target: str = None,
):
metroid-samus marked this conversation as resolved.
Show resolved Hide resolved
"""Runs the case conversation creation flow."""

conversation_flows.create_case_conversation(case, conversation_target, db_session)

event_service.log_case_event(
db_session=db_session,
source="Dispatch Core App",
description="Conversation added to case",
case_id=case.id,
)

for email in participant_emails:
# we don't rely on on this flow to add folks to the conversation because in this case
# we want to do it in bulk
case_add_or_reactivate_participant_flow(
db_session=db_session,
user_email=email,
case_id=case.id,
add_to_conversation=False,
)

# we add the participant to the conversation
conversation_flows.add_case_participants(
case=case,
participant_emails=participant_emails,
db_session=db_session,
)


def case_create_resources_flow(
db_session: Session,
case_id: int,
Expand Down Expand Up @@ -948,32 +983,15 @@ def case_create_resources_flow(
)

try:
# we create the conversation and add participants to the thread
conversation_flows.create_case_conversation(case, conversation_target, db_session)

event_service.log_case_event(
db_session=db_session,
source="Dispatch Core App",
description="Conversation added to case",
case_id=case.id,
)
# wait until all resources are created before adding suggested participants
individual_participants = [x.email for x, _ in individual_participants]

for email in individual_participants:
# we don't rely on on this flow to add folks to the conversation because in this case
# we want to do it in bulk
case_add_or_reactivate_participant_flow(
db_session=db_session,
user_email=email,
case_id=case.id,
add_to_conversation=False,
)
# # we add the participant to the conversation
conversation_flows.add_case_participants(
# we create the conversation and add participants to the thread
case_create_conversation_flow(
db_session=db_session,
case=case,
participant_emails=individual_participants,
db_session=db_session,
conversation_target=conversation_target,
)

for user_email in set(individual_participants):
Expand Down
30 changes: 30 additions & 0 deletions src/dispatch/case/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
case_new_create_flow,
case_triage_create_flow,
case_update_flow,
case_create_conversation_flow,
case_create_resources_flow,
get_case_participants_flow,
)
Expand Down Expand Up @@ -188,6 +189,35 @@ def create_case(
return case


@router.post(
"/{case_id}/resources/conversation",
response_model=CaseRead,
summary="Creates conversation channel for an existing case.",
)
def create_case_channel(
db_session: DbSession,
case_id: PrimaryKey,
current_case: CurrentCase,
background_tasks: BackgroundTasks,
):
"""Creates conversation channel for an existing case."""

case = get(case_id=case_id, db_session=db_session)
metroid-samus marked this conversation as resolved.
Show resolved Hide resolved
case.dedicated_channel = True

participant_emails = [participant.individual.email for participant in current_case.participants]
metroid-samus marked this conversation as resolved.
Show resolved Hide resolved

# Add all case participants to the case channel
case_create_conversation_flow(
db_session=db_session,
case=case,
participant_emails=participant_emails,
conversation_target=None,
)

return current_case


@router.post(
"/{case_id}/resources",
response_model=CaseRead,
Expand Down
106 changes: 90 additions & 16 deletions src/dispatch/conversation/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,18 @@
from dispatch.document.models import Document
from dispatch.event import service as event_service
from dispatch.incident.models import Incident
from dispatch.messaging.strings import MessageType
from dispatch.plugin import service as plugin_service
from dispatch.plugins.dispatch_slack.case import messages
from dispatch.storage.models import Storage
from dispatch.ticket.models import Ticket
from dispatch.service.models import Service
from dispatch.project.models import Project
from dispatch.utils import deslug_and_capitalize_resource_type
from dispatch.types import Subject

from .models import Conversation, ConversationCreate
from .service import create
from .models import Conversation, ConversationCreate, ConversationUpdate
from .service import create, update

log = logging.getLogger(__name__)

Expand All @@ -44,6 +46,13 @@ def create_case_conversation(

conversation = None

# Do not overwrite a case conversation with one of the same type (thread, channel)
if case.conversation:
if case.has_channel:
return case.conversation
if case.has_thread and not case.dedicated_channel:
return case.conversation
metroid-samus marked this conversation as resolved.
Show resolved Hide resolved

# This case is a thread version, we send a new messaged (threaded) to the conversation target
# for the configured case type
if conversation_target and not case.dedicated_channel:
Expand Down Expand Up @@ -73,21 +82,86 @@ def create_case_conversation(

conversation.update({"resource_type": plugin.plugin.slug, "resource_id": conversation["id"]})

conversation_in = ConversationCreate(
resource_id=conversation["resource_id"],
resource_type=conversation["resource_type"],
weblink=conversation["weblink"],
thread_id=conversation.get("timestamp"),
channel_id=conversation["id"],
)
case.conversation = create(db_session=db_session, conversation_in=conversation_in)
if not case.conversation:
conversation_in = ConversationCreate(
resource_id=conversation["resource_id"],
resource_type=conversation["resource_type"],
weblink=conversation["weblink"],
thread_id=conversation.get("timestamp"),
channel_id=conversation["id"],
)
case.conversation = create(db_session=db_session, conversation_in=conversation_in)

event_service.log_case_event(
db_session=db_session,
source=plugin.plugin.title,
description="Case conversation created",
case_id=case.id,
)
event_service.log_case_event(
db_session=db_session,
source=plugin.plugin.title,
description="Case conversation created",
case_id=case.id,
)
elif case.conversation.thread_id and case.dedicated_channel:
thread_conversation_channel_id = case.conversation.channel_id
thread_converstaion_thread_id = case.conversation.thread_id
thread_conversation_weblink = case.conversation.weblink

conversation_in = ConversationUpdate(
resource_id=conversation.get("resource_id"),
resource_type=conversation.get("resource_type"),
weblink=conversation.get("weblink"),
thread_id=conversation.get("timestamp"),
channel_id=conversation.get("id"),
)

update(
db_session=db_session, conversation=case.conversation, conversation_in=conversation_in
)

event_service.log_case_event(
db_session=db_session,
source=plugin.plugin.title,
description=f"Case conversation has migrated from thread [{thread_conversation_weblink}] to channel[{case.conversation.weblink}].",
case_id=case.id,
)

# Inform users in the case thread that the conversation has migrated to a channel
try:
plugin.instance.send(
thread_conversation_channel_id,
"Notify Case conversation migration",
[],
MessageType.case_notification,
blocks=messages.create_case_thread_migration_message(
channel_weblink=conversation.get("weblink")
),
ts=thread_converstaion_thread_id,
)
except Exception as e:
event_service.log_subject_event(
subject=case,
db_session=db_session,
source="Dispatch Core App",
description=f"Setting the incident/case conversation topic failed. Reason: {e}",
)
log.exception(e)

# Provide users in the case channel which thread the conversation originated from.
try:
plugin.instance.send(
case.conversation.channel_id,
"Maintain Case conversation context",
[],
MessageType.case_notification,
blocks=messages.create_case_channel_migration_message(
thread_weblink=thread_conversation_weblink
),
)
except Exception as e:
event_service.log_subject_event(
subject=case,
db_session=db_session,
source="Dispatch Core App",
description=f"Failed to send message to dedicated channel. Reason: {e}",
)
log.exception(e)

db_session.add(case)
db_session.commit()
Expand Down
5 changes: 5 additions & 0 deletions src/dispatch/plugins/dispatch_slack/case/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

class CaseNotificationActions(DispatchEnum):
edit = "case-notification-edit"
migrate = "case-notification-migrate"
escalate = "case-notification-escalate"
join_incident = "case-notification-join-incident"
reopen = "case-notification-reopen"
Expand All @@ -30,6 +31,10 @@ class CaseEscalateActions(DispatchEnum):
project_select = "case-notification-escalate-project-select"


class CaseMigrateActions(DispatchEnum):
submit = "case-notification-migrate-submit"


class CaseReportActions(DispatchEnum):
submit = "case-report-submit"
project_select = "case-report-project-select"
Expand Down
Loading
Loading