diff --git a/src/dispatch/case/flows.py b/src/dispatch/case/flows.py
index 4f64d6ee717c..6c06cb88113d 100644
--- a/src/dispatch/case/flows.py
+++ b/src/dispatch/case/flows.py
@@ -6,8 +6,7 @@
from dispatch.case import service as case_service
from dispatch.case.models import CaseRead
-from dispatch.conversation import service as conversation_service
-from dispatch.conversation.models import ConversationCreate
+from dispatch.conversation import flows as conversation_flows
from dispatch.database.core import SessionLocal
from dispatch.decorators import background_task
from dispatch.document import flows as document_flows
@@ -154,26 +153,6 @@ def case_add_or_reactivate_participant_flow(
return participant
-def create_conversation(case: Case, conversation_target: str, db_session: SessionLocal):
- """Create external communication conversation."""
- plugin = plugin_service.get_active_instance(
- db_session=db_session, project_id=case.project.id, plugin_type="conversation"
- )
- conversation = plugin.instance.create_threaded(
- case=case, conversation_id=conversation_target, db_session=db_session
- )
- conversation.update({"resource_type": plugin.plugin.slug, "resource_id": conversation["id"]})
-
- event_service.log_case_event(
- db_session=db_session,
- source=plugin.plugin.title,
- description="Case conversation created",
- case_id=case.id,
- )
-
- return conversation
-
-
def update_conversation(case: Case, db_session: SessionLocal):
"""Updates external communication conversation."""
plugin = plugin_service.get_active_instance(
@@ -217,6 +196,7 @@ def case_new_create_flow(
case_id=case.id,
individual_participants=individual_participants,
team_participants=team_participants,
+ conversation_target=conversation_target,
)
if case.case_priority.page_assignee:
@@ -241,67 +221,6 @@ def case_new_create_flow(
else:
log.warning("Case assignee not paged. No plugin of type oncall enabled.")
- conversation_plugin = plugin_service.get_active_instance(
- db_session=db_session, project_id=case.project.id, plugin_type="conversation"
- )
- if conversation_plugin:
- if not conversation_target:
- conversation_target = case.case_type.conversation_target
- if conversation_target:
- try:
- # TODO: Refactor conversation creation using conversation_flows module
- conversation = create_conversation(case, conversation_target, db_session)
- conversation_in = ConversationCreate(
- resource_id=conversation["resource_id"],
- resource_type=conversation["resource_type"],
- weblink=conversation["weblink"],
- thread_id=conversation["timestamp"],
- channel_id=conversation["id"],
- )
- case.conversation = conversation_service.create(
- db_session=db_session, conversation_in=conversation_in
- )
-
- 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,
- )
- # explicitly add the assignee to the conversation
- all_participants = individual_participants + [case.assignee.individual.email]
- conversation_plugin.instance.add_to_thread(
- case.conversation.channel_id,
- case.conversation.thread_id,
- all_participants,
- )
- event_service.log_case_event(
- db_session=db_session,
- source="Dispatch Core App",
- description="Case participants added to conversation.",
- case_id=case.id,
- )
- except Exception as e:
- event_service.log_case_event(
- db_session=db_session,
- source="Dispatch Core App",
- description=f"Creation of case conversation failed. Reason: {e}",
- case_id=case.id,
- )
- log.exception(e)
-
db_session.add(case)
db_session.commit()
@@ -684,7 +603,12 @@ def case_assign_role_flow(
def case_create_resources_flow(
- db_session: Session, case_id: int, individual_participants: list, team_participants: list
+ db_session: Session,
+ case_id: int,
+ individual_participants: List[str],
+ team_participants: List[str],
+ conversation_target: str = None,
+ create_resources: bool = True,
) -> None:
"""Runs the case resource creation flow."""
case = get(db_session=db_session, case_id=case_id)
@@ -692,43 +616,93 @@ def case_create_resources_flow(
if case.assignee:
individual_participants.append((case.assignee.individual, None))
- # we create the tactical group
- direct_participant_emails = [i.email for i, _ in individual_participants]
+ if create_resources:
+ # we create the tactical group
+ direct_participant_emails = [i.email for i, _ in individual_participants]
- indirect_participant_emails = [t.email for t in team_participants]
+ indirect_participant_emails = [t.email for t in team_participants]
- group = group_flows.create_group(
- subject=case,
- group_type=GroupType.tactical,
- group_participants=list(set(direct_participant_emails + indirect_participant_emails)),
- db_session=db_session,
- )
+ if not case.groups:
+ group_flows.create_group(
+ subject=case,
+ group_type=GroupType.tactical,
+ group_participants=list(
+ set(direct_participant_emails + indirect_participant_emails)
+ ),
+ db_session=db_session,
+ )
- # we create the storage folder
- storage_members = []
- if group:
- storage_members = [group.email]
+ # we create the storage folder
+ storage_members = []
+ if case.tactical_group:
+ storage_members = [case.tactical_group.email]
+ # direct add members if not group exists
+ else:
+ storage_members = direct_participant_emails
- # direct add members if not group exists
- else:
- storage_members = direct_participant_emails
+ if not case.storage:
+ storage_flows.create_storage(
+ subject=case, storage_members=storage_members, db_session=db_session
+ )
- case.storage = storage_flows.create_storage(
- subject=case, storage_members=storage_members, db_session=db_session
- )
+ # we create the investigation document
+ if not case.case_document:
+ document_flows.create_document(
+ subject=case,
+ document_type=DocumentResourceTypes.case,
+ document_template=case.case_type.case_template_document,
+ db_session=db_session,
+ )
- # we create the investigation document
- document = document_flows.create_document(
- subject=case,
- document_type=DocumentResourceTypes.case,
- document_template=case.case_type.case_template_document,
- db_session=db_session,
- )
+ # we update the ticket
+ ticket_flows.update_case_ticket(case=case, db_session=db_session)
- # we update the ticket
- ticket_flows.update_case_ticket(case=case, db_session=db_session)
+ # we update the case document
+ document_flows.update_document(
+ document=case.case_document, project_id=case.project.id, db_session=db_session
+ )
- # we update the case document
- document_flows.update_document(
- document=document, project_id=case.project.id, db_session=db_session
- )
+ 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,
+ )
+ # explicitly add the assignee to the conversation
+ all_participants = individual_participants + [case.assignee.individual.email]
+
+ # # we add the participant to the conversation
+ conversation_flows.add_case_participants(
+ case=case, participant_emails=all_participants, db_session=db_session
+ )
+
+ event_service.log_case_event(
+ db_session=db_session,
+ source="Dispatch Core App",
+ description="Case participants added to conversation.",
+ case_id=case.id,
+ )
+ except Exception as e:
+ event_service.log_case_event(
+ db_session=db_session,
+ source="Dispatch Core App",
+ description=f"Creation of case conversation failed. Reason: {e}",
+ case_id=case.id,
+ )
+ log.exception(e)
diff --git a/src/dispatch/case/views.py b/src/dispatch/case/views.py
index 1d9e68f36e94..add6f8a5037a 100644
--- a/src/dispatch/case/views.py
+++ b/src/dispatch/case/views.py
@@ -34,6 +34,8 @@
case_new_create_flow,
case_triage_create_flow,
case_update_flow,
+ case_create_resources_flow,
+ get_case_participants,
)
from .models import Case, CaseCreate, CasePagination, CaseRead, CaseUpdate, CaseExpandedPagination
from .service import create, delete, get, update
@@ -145,6 +147,32 @@ def create_case(
return case
+@router.post(
+ "/{case_id}/resources",
+ response_model=CaseRead,
+ summary="Creates resources for an existing case.",
+)
+def create_case_resources(
+ db_session: DbSession,
+ case_id: PrimaryKey,
+ current_case: CurrentCase,
+ background_tasks: BackgroundTasks,
+):
+ """Creates resources for an existing case."""
+ individual_participants, team_participants = get_case_participants(
+ case=current_case, db_session=db_session
+ )
+ background_tasks.add_task(
+ case_create_resources_flow,
+ db_session=db_session,
+ case_id=case_id,
+ individual_participants=individual_participants,
+ team_participants=team_participants,
+ )
+
+ return current_case
+
+
@router.put(
"/{case_id}",
response_model=CaseRead,
diff --git a/src/dispatch/conversation/flows.py b/src/dispatch/conversation/flows.py
index ab14fbf4b4a3..dadba50ff470 100644
--- a/src/dispatch/conversation/flows.py
+++ b/src/dispatch/conversation/flows.py
@@ -2,6 +2,7 @@
from typing import TypeVar, List
+from dispatch.case.models import Case
from dispatch.conference.models import Conference
from dispatch.database.core import SessionLocal, resolve_attr
from dispatch.document.models import Document
@@ -22,7 +23,57 @@
Resource = TypeVar("Resource", Document, Conference, Storage, Ticket)
-def create_conversation(incident: Incident, db_session: SessionLocal):
+def create_case_conversation(case: Case, conversation_target: str, db_session: SessionLocal):
+ """Create external communication conversation."""
+
+ plugin = plugin_service.get_active_instance(
+ db_session=db_session, project_id=case.project.id, plugin_type="conversation"
+ )
+ if not plugin:
+ log.warning("Conversation not created. No conversation plugin enabled.")
+ return
+
+ if not conversation_target:
+ conversation_target = case.case_type.conversation_target
+
+ if conversation_target:
+ try:
+ conversation = plugin.instance.create_threaded(
+ case=case, conversation_id=conversation_target, db_session=db_session
+ )
+ except Exception as e:
+ # TODO: consistency across exceptions
+ log.exception(e)
+
+ if not conversation:
+ log.error(f"Conversation not created. Plugin {plugin.plugin.slug} encountered an error.")
+ return
+
+ 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["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,
+ )
+
+ db_session.add(case)
+ db_session.commit()
+
+ return case.conversation
+
+
+def create_incident_conversation(incident: Incident, db_session: SessionLocal):
"""Creates a conversation."""
plugin = plugin_service.get_active_instance(
db_session=db_session, project_id=incident.project.id, plugin_type="conversation"
@@ -59,8 +110,7 @@ def create_conversation(incident: Incident, db_session: SessionLocal):
weblink=external_conversation["weblink"],
channel_id=external_conversation["id"],
)
- conversation = create(conversation_in=conversation_in, db_session=db_session)
- incident.conversation = conversation
+ incident.conversation = create(conversation_in=conversation_in, db_session=db_session)
db_session.add(incident)
db_session.commit()
@@ -72,7 +122,7 @@ def create_conversation(incident: Incident, db_session: SessionLocal):
incident_id=incident.id,
)
- return conversation
+ return incident.conversation
def archive_conversation(incident: Incident, db_session: SessionLocal):
@@ -262,8 +312,43 @@ def add_conversation_bookmarks(incident: Incident, db_session: SessionLocal):
log.exception(e)
-def add_participants(incident: Incident, participant_emails: List[str], db_session: SessionLocal):
- """Adds one or more participants to the conversation."""
+def add_case_participants(case: Case, participant_emails: List[str], db_session: SessionLocal):
+ """Adds one or more participants to the case conversation."""
+ if not case.conversation:
+ log.warning(
+ "Case participant(s) not added to conversation. No conversation available for this case."
+ )
+ return
+
+ plugin = plugin_service.get_active_instance(
+ db_session=db_session, project_id=case.project.id, plugin_type="conversation"
+ )
+ if not plugin:
+ log.warning(
+ "Case participant(s) not added to conversation. No conversation plugin enabled."
+ )
+ return
+
+ try:
+ plugin.instance.add_to_thread(
+ case.conversation.channel_id,
+ case.conversation.thread_id,
+ participant_emails,
+ )
+ except Exception as e:
+ event_service.log_case_event(
+ db_session=db_session,
+ source="Dispatch Core App",
+ description=f"Adding participant(s) to case conversation failed. Reason: {e}",
+ case_id=case.id,
+ )
+ log.exception(e)
+
+
+def add_incident_participants(
+ incident: Incident, participant_emails: List[str], db_session: SessionLocal
+):
+ """Adds one or more participants to the incident conversation."""
if not incident.conversation:
log.warning(
"Incident participant(s) not added to conversation. No conversation available for this incident."
diff --git a/src/dispatch/incident/flows.py b/src/dispatch/incident/flows.py
index 84f553c20456..4585f5f5d4d6 100644
--- a/src/dispatch/incident/flows.py
+++ b/src/dispatch/incident/flows.py
@@ -140,68 +140,74 @@ def inactivate_incident_participants(incident: Incident, db_session: Session):
)
-@background_task
-def incident_create_flow(*, organization_slug: str, incident_id: int, db_session=None) -> Incident:
- """Creates all resources required for new incidents."""
- # we get the incident
- incident = incident_service.get(db_session=db_session, incident_id=incident_id)
-
+def incident_create_resources(*, incident: Incident, db_session=None) -> Incident:
+ """Creates all resources required for incidents."""
# we create the incident ticket
- ticket_flows.create_incident_ticket(incident=incident, db_session=db_session)
+ if not incident.ticket:
+ ticket_flows.create_incident_ticket(incident=incident, db_session=db_session)
# we resolve individual and team participants
individual_participants, team_participants = get_incident_participants(incident, db_session)
+ tactical_participant_emails = [i.email for i, _ in individual_participants]
# we create the tactical group
- tactical_participant_emails = [i.email for i, _ in individual_participants]
- tactical_group = group_flows.create_group(
- subject=incident,
- group_type=GroupType.tactical,
- group_participants=tactical_participant_emails,
- db_session=db_session,
- )
+ if not incident.tactical_group:
+ group_flows.create_group(
+ subject=incident,
+ group_type=GroupType.tactical,
+ group_participants=tactical_participant_emails,
+ db_session=db_session,
+ )
# we create the notifications group
- notification_participant_emails = [t.email for t in team_participants]
- notifications_group = group_flows.create_group(
- subject=incident,
- group_type=GroupType.notifications,
- group_participants=notification_participant_emails,
- db_session=db_session,
- )
+ if not incident.notifications_group:
+ notification_participant_emails = [t.email for t in team_participants]
+ group_flows.create_group(
+ subject=incident,
+ group_type=GroupType.notifications,
+ group_participants=notification_participant_emails,
+ db_session=db_session,
+ )
# we create the storage folder
- storage_members = []
- if tactical_group and notifications_group:
- storage_members = [tactical_group.email, notifications_group.email]
- else:
- storage_members = tactical_participant_emails
+ if not incident.storage:
+ storage_members = []
+ if incident.tactical_group and incident.notifications_group:
+ storage_members = [incident.tactical_group.email, incident.notifications_group.email]
+ else:
+ storage_members = tactical_participant_emails
- storage_flows.create_storage(
- subject=incident, storage_members=storage_members, db_session=db_session
- )
+ storage_flows.create_storage(
+ subject=incident, storage_members=storage_members, db_session=db_session
+ )
# we create the incident document
- document_flows.create_document(
- subject=incident,
- document_type=DocumentResourceTypes.incident,
- document_template=incident.incident_type.incident_template_document,
- db_session=db_session,
- )
+ if not incident.incident_document:
+ document_flows.create_document(
+ subject=incident,
+ document_type=DocumentResourceTypes.incident,
+ document_template=incident.incident_type.incident_template_document,
+ db_session=db_session,
+ )
# we create the conference room
- conference_participants = []
- if tactical_group and notifications_group:
- conference_participants = [tactical_group.email, notifications_group.email]
- else:
- conference_participants = tactical_participant_emails
+ if not incident.conference:
+ conference_participants = []
+ if incident.tactical_group and incident.notifications_group:
+ conference_participants = [
+ incident.tactical_group.email,
+ incident.notifications_group.email,
+ ]
+ else:
+ conference_participants = tactical_participant_emails
- conference_flows.create_conference(
- incident=incident, participants=conference_participants, db_session=db_session
- )
+ conference_flows.create_conference(
+ incident=incident, participants=conference_participants, db_session=db_session
+ )
# we create the conversation
- conversation_flows.create_conversation(incident=incident, db_session=db_session)
+ if not incident.conversation:
+ conversation_flows.create_incident_conversation(incident=incident, db_session=db_session)
# we update the incident ticket
ticket_flows.update_incident_ticket(incident_id=incident.id, db_session=db_session)
@@ -238,7 +244,7 @@ def incident_create_flow(*, organization_slug: str, incident_id: int, db_session
)
# we add the participant to the conversation
- conversation_flows.add_participants(
+ conversation_flows.add_incident_participants(
incident=incident, participant_emails=[user_email], db_session=db_session
)
@@ -272,14 +278,31 @@ def incident_create_flow(*, organization_slug: str, incident_id: int, db_session
incident_id=incident.id,
)
- send_incident_created_notifications(incident, db_session)
+ return incident
- event_service.log_incident_event(
- db_session=db_session,
- source="Dispatch Core App",
- description="Incident notifications sent",
- incident_id=incident.id,
- )
+
+@background_task
+def incident_create_resources_flow(
+ *, organization_slug: str, incident_id: int, db_session=None
+) -> Incident:
+ """Creates all resources required for an existing incident."""
+ # we get the incident
+ incident = incident_service.get(db_session=db_session, incident_id=incident_id)
+
+ # we create the incident resources
+ return incident_create_resources(incident=incident, db_session=db_session)
+
+
+@background_task
+def incident_create_flow(*, organization_slug: str, incident_id: int, db_session=None) -> Incident:
+ """Creates all resources required for new incidents and initiates incident response workflow."""
+ # we get the incident
+ incident = incident_service.get(db_session=db_session, incident_id=incident_id)
+
+ # we create the incident resources
+ incident_create_resources(incident=incident, db_session=db_session)
+
+ send_incident_created_notifications(incident, db_session)
# we page the incident commander based on incident priority
if incident.incident_priority.page_commander:
@@ -902,7 +925,7 @@ def incident_add_or_reactivate_participant_flow(
if incident.status != IncidentStatus.closed:
# we add the participant to the conversation
- conversation_flows.add_participants(
+ conversation_flows.add_incident_participants(
incident=incident, participant_emails=[user_email], db_session=db_session
)
@@ -942,7 +965,7 @@ def incident_remove_participant_flow(
for assignee in task.assignees:
if assignee == participant:
# we add the participant to the conversation
- conversation_flows.add_participants(
+ conversation_flows.add_incident_participants(
incident=incident, participant_emails=[user_email], db_session=db_session
)
@@ -954,7 +977,7 @@ def incident_remove_participant_flow(
if user_email == incident.commander.individual.email:
# we add the participant to the conversation
- conversation_flows.add_participants(
+ conversation_flows.add_incident_participants(
incident=incident, participant_emails=[user_email], db_session=db_session
)
diff --git a/src/dispatch/incident/messaging.py b/src/dispatch/incident/messaging.py
index 1c6f1d4b2575..994ae45d4564 100644
--- a/src/dispatch/incident/messaging.py
+++ b/src/dispatch/incident/messaging.py
@@ -11,6 +11,7 @@
from dispatch.conversation.enums import ConversationCommands
from dispatch.database.core import SessionLocal, resolve_attr
from dispatch.document import service as document_service
+from dispatch.event import service as event_service
from dispatch.incident.enums import IncidentStatus
from dispatch.incident.models import Incident, IncidentRead
from dispatch.notification import service as notification_service
@@ -347,6 +348,13 @@ def send_incident_created_notifications(incident: Incident, db_session: SessionL
notification_params=notification_params,
)
+ event_service.log_incident_event(
+ db_session=db_session,
+ source="Dispatch Core App",
+ description="Incident notifications sent",
+ incident_id=incident.id,
+ )
+
log.debug("Incident created notifications sent.")
diff --git a/src/dispatch/incident/views.py b/src/dispatch/incident/views.py
index 031909017f47..f8c740a70230 100644
--- a/src/dispatch/incident/views.py
+++ b/src/dispatch/incident/views.py
@@ -36,6 +36,7 @@
incident_delete_flow,
incident_subscribe_participant_flow,
incident_update_flow,
+ incident_create_resources_flow,
)
from .metrics import create_incident_metric_query, make_forecast
from .models import (
@@ -139,6 +140,25 @@ def create_incident(
return incident
+@router.post(
+ "/{incident_id}/resources",
+ response_model=IncidentRead,
+ summary="Creates resources for an existing incident.",
+)
+def create_incident_resources(
+ organization: OrganizationSlug,
+ incident_id: PrimaryKey,
+ current_incident: CurrentIncident,
+ background_tasks: BackgroundTasks,
+):
+ """Creates resources for an existing incident."""
+ background_tasks.add_task(
+ incident_create_resources_flow, organization_slug=organization, incident_id=incident_id
+ )
+
+ return current_incident
+
+
@router.put(
"/{incident_id}",
response_model=IncidentRead,
diff --git a/src/dispatch/plugins/dispatch_slack/case/interactive.py b/src/dispatch/plugins/dispatch_slack/case/interactive.py
index e4797c36d368..a49ad567497b 100644
--- a/src/dispatch/plugins/dispatch_slack/case/interactive.py
+++ b/src/dispatch/plugins/dispatch_slack/case/interactive.py
@@ -1032,7 +1032,7 @@ def handle_escalation_submission_event(
case=case, organization_slug=context["subject"].organization_slug, db_session=db_session
)
- conversation_flows.add_participants(
+ conversation_flows.add_incident_participants(
incident=incident, participant_emails=[user.email], db_session=db_session
)
@@ -1082,7 +1082,7 @@ def join_incident_button_click(
case = case_service.get(db_session=db_session, case_id=context["subject"].id)
# we add the user to the incident conversation
- conversation_flows.add_participants(
+ conversation_flows.add_incident_participants(
# TODO: handle case where there are multiple related incidents
incident=case.incidents[0],
participant_emails=[user.email],
diff --git a/src/dispatch/static/dispatch/src/case/ResourcesTab.vue b/src/dispatch/static/dispatch/src/case/ResourcesTab.vue
index ad7403449c82..a9eb2b5d5df4 100644
--- a/src/dispatch/static/dispatch/src/case/ResourcesTab.vue
+++ b/src/dispatch/static/dispatch/src/case/ResourcesTab.vue
@@ -65,23 +65,83 @@
+
+
+
+ Recreate Missing Resources
+ Initiate a retry for creating any missing or unsuccesfully created
+ resource(s).
+
+
+
+ refresh
+
+
+
+
+
+ Creating resources...
+ Initiate a retry for creating any missing or unsuccesfully created
+ resource(s).
+
+
+
diff --git a/src/dispatch/static/dispatch/src/case/api.js b/src/dispatch/static/dispatch/src/case/api.js
index 8a3b0d2abb61..2fc1a01f27e3 100644
--- a/src/dispatch/static/dispatch/src/case/api.js
+++ b/src/dispatch/static/dispatch/src/case/api.js
@@ -44,4 +44,8 @@ export default {
delete(caseId) {
return API.delete(`/${resource}/${caseId}`)
},
+
+ createAllResources(caseId, payload) {
+ return API.post(`/${resource}/${caseId}/resources`, payload)
+ },
}
diff --git a/src/dispatch/static/dispatch/src/case/store.js b/src/dispatch/static/dispatch/src/case/store.js
index bbe3ec901dac..6eda8cc9b416 100644
--- a/src/dispatch/static/dispatch/src/case/store.js
+++ b/src/dispatch/static/dispatch/src/case/store.js
@@ -3,6 +3,7 @@ import { debounce } from "lodash"
import SearchUtils from "@/search/utils"
import CaseApi from "@/case/api"
+import PluginApi from "@/plugin/api"
import router from "@/router"
const getDefaultSelectedState = () => {
@@ -253,6 +254,40 @@ const actions = {
commit("SET_SELECTED_LOADING", false)
})
},
+ createAllResources({ commit, dispatch }) {
+ commit("SET_SELECTED_LOADING", true)
+ return CaseApi.createAllResources(state.selected.id)
+ .then(() => {
+ CaseApi.get(state.selected.id).then((response) => {
+ commit("SET_SELECTED", response.data)
+ dispatch("getEnabledPlugins").then((enabledPlugins) => {
+ // Poll the server for resource creation updates.
+ var interval = setInterval(function () {
+ if (
+ state.selected.conversation ^ enabledPlugins.includes("conversation") ||
+ state.selected.documents ^ enabledPlugins.includes("document") ||
+ state.selected.storage ^ enabledPlugins.includes("storage") ||
+ state.selected.groups ^ enabledPlugins.includes("participant-group") ||
+ state.selected.ticket ^ enabledPlugins.includes("ticket")
+ ) {
+ dispatch("get").then(() => {
+ clearInterval(interval)
+ commit("SET_SELECTED_LOADING", false)
+ commit(
+ "notification_backend/addBeNotification",
+ { text: "Resources(s) created successfully.", type: "success" },
+ { root: true }
+ )
+ })
+ }
+ }, 5000)
+ })
+ })
+ })
+ .catch(() => {
+ commit("SET_SELECTED_LOADING", false)
+ })
+ },
save({ commit, dispatch }) {
commit("SET_SELECTED_LOADING", true)
if (!state.selected.id) {
@@ -330,6 +365,37 @@ const actions = {
)
})
},
+ getEnabledPlugins() {
+ if (!state.selected.project) {
+ return false
+ }
+ return PluginApi.getAllInstances({
+ filter: JSON.stringify({
+ and: [
+ {
+ model: "PluginInstance",
+ field: "enabled",
+ op: "==",
+ value: "true",
+ },
+ {
+ model: "Project",
+ field: "name",
+ op: "==",
+ value: state.selected.project.name,
+ },
+ ],
+ }),
+ itemsPerPage: 50,
+ }).then((response) => {
+ return response.data.items.reduce((result, item) => {
+ if (item.plugin) {
+ result.push(item.plugin.type)
+ }
+ return result
+ }, [])
+ })
+ },
}
const mutations = {
diff --git a/src/dispatch/static/dispatch/src/incident/ResourcesTab.vue b/src/dispatch/static/dispatch/src/incident/ResourcesTab.vue
index 9c1a3d2c9f15..b478fb9ecb6e 100644
--- a/src/dispatch/static/dispatch/src/incident/ResourcesTab.vue
+++ b/src/dispatch/static/dispatch/src/incident/ResourcesTab.vue
@@ -62,23 +62,83 @@
+
+
+
+ Recreate Missing Resources
+ Initiate a retry for creating any missing or unsuccesfully created
+ resource(s).
+
+
+
+ refresh
+
+
+
+
+
+ Creating resources...
+ Initiate a retry for creating any missing or unsuccesfully created
+ resource(s).
+
+
+
diff --git a/src/dispatch/static/dispatch/src/incident/api.js b/src/dispatch/static/dispatch/src/incident/api.js
index 0516aaa84cdf..1f77a9053460 100644
--- a/src/dispatch/static/dispatch/src/incident/api.js
+++ b/src/dispatch/static/dispatch/src/incident/api.js
@@ -58,4 +58,8 @@ export default {
createReport(incidentId, type, payload) {
return API.post(`/${resource}/${incidentId}/report/${type}`, payload)
},
+
+ createAllResources(incidentId, payload) {
+ return API.post(`/${resource}/${incidentId}/resources`, payload)
+ },
}
diff --git a/src/dispatch/static/dispatch/src/incident/store.js b/src/dispatch/static/dispatch/src/incident/store.js
index bf57d004f858..f43befd9717d 100644
--- a/src/dispatch/static/dispatch/src/incident/store.js
+++ b/src/dispatch/static/dispatch/src/incident/store.js
@@ -3,6 +3,7 @@ import { debounce } from "lodash"
import SearchUtils from "@/search/utils"
import IncidentApi from "@/incident/api"
+import PluginApi from "@/plugin/api"
import router from "@/router"
const getDefaultSelectedState = () => {
@@ -347,6 +348,40 @@ const actions = {
)
})
},
+ createAllResources({ commit, dispatch }) {
+ commit("SET_SELECTED_LOADING", true)
+ return IncidentApi.createAllResources(state.selected.id)
+ .then(() => {
+ IncidentApi.get(state.selected.id).then((response) => {
+ commit("SET_SELECTED", response.data)
+ dispatch("getEnabledPlugins").then((enabledPlugins) => {
+ // Poll the server for resource creation updates.
+ var interval = setInterval(function () {
+ if (
+ state.selected.conversation ^ enabledPlugins.includes("conversation") ||
+ state.selected.documents ^ enabledPlugins.includes("document") ||
+ state.selected.storage ^ enabledPlugins.includes("storage") ||
+ state.selected.conference ^ enabledPlugins.includes("conference") ||
+ state.selected.ticket ^ enabledPlugins.includes("ticket")
+ ) {
+ dispatch("get").then(() => {
+ clearInterval(interval)
+ commit("SET_SELECTED_LOADING", false)
+ commit(
+ "notification_backend/addBeNotification",
+ { text: "Resources(s) created successfully.", type: "success" },
+ { root: true }
+ )
+ })
+ }
+ }, 5000)
+ })
+ })
+ })
+ .catch(() => {
+ commit("SET_SELECTED_LOADING", false)
+ })
+ },
resetSelected({ commit }) {
commit("RESET_SELECTED")
},
@@ -371,6 +406,37 @@ const actions = {
)
})
},
+ getEnabledPlugins() {
+ if (!state.selected.project) {
+ return false
+ }
+ return PluginApi.getAllInstances({
+ filter: JSON.stringify({
+ and: [
+ {
+ model: "PluginInstance",
+ field: "enabled",
+ op: "==",
+ value: "true",
+ },
+ {
+ model: "Project",
+ field: "name",
+ op: "==",
+ value: state.selected.project.name,
+ },
+ ],
+ }),
+ itemsPerPage: 50,
+ }).then((response) => {
+ return response.data.items.reduce((result, item) => {
+ if (item.plugin) {
+ result.push(item.plugin.type)
+ }
+ return result
+ }, [])
+ })
+ },
}
const mutations = {