-
Notifications
You must be signed in to change notification settings - Fork 165
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Better summary and impact updates (#189)
* Better summary and impact updates Prior to this change, the summary and impact commands would overwrite whatever was currently set for the incident. In most cases, our understanding of these develops over time, so we'd like to be update and refine what we've previously set. This change introduces actions and dialogs to update the summary and impact from what was previously set, making it easier for us to develop meaningful and thorough statements over time.
- Loading branch information
Showing
4 changed files
with
221 additions
and
16 deletions.
There are no files selected for viewing
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,3 @@ | ||
from . import impact, incident_commands, summary | ||
|
||
__all__ = (impact, incident_commands, summary) |
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,106 @@ | ||
import json | ||
import logging | ||
|
||
from response.core.models import Incident | ||
from response.slack import block_kit, dialog_builder | ||
from response.slack.decorators import ActionContext, action_handler, dialog_handler | ||
from response.slack.decorators.incident_command import __default_incident_command | ||
from response.slack.models import CommsChannel | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
UPDATE_CURRENT_IMPACT_ACTION = "update-current-impact-action" | ||
SET_NEW_IMPACT_ACTION = "set-new-impact-action" | ||
PROPOSED_MESSAGE_BLOCK_ID = "proposed" | ||
UPDATE_IMPACT_DIALOG = "update-impact-dialog" | ||
|
||
NO_IMPACT_TEXT = "The impact of this incident hasn't been set yet." | ||
CURRENT_TITLE = "*This is the current impact:*\n" | ||
PROPOSED_TITLE = "*Or would you like to update the impact to this?*\n" | ||
IMPACT_UPDATED_TITLE = "*The impact has been updated to:*\n" | ||
CHANGE_BUTTON_TEXT = "Change" | ||
ACCEPT_PROPOSED_TEXT = "Yes" | ||
|
||
|
||
@__default_incident_command(["impact"], helptext="Explain the impact of this") | ||
def update_impact(incident: Incident, user_id: str, message: str): | ||
# Easy case. No impact currently and one has been provided | ||
if message and not incident.impact: | ||
incident.impact = message | ||
incident.save() | ||
return True, f"{IMPACT_UPDATED_TITLE}{message}" | ||
|
||
# Either no new impact has been provided, or one already exists | ||
msg = block_kit.Message() | ||
msg.add_block( | ||
block_kit.Section( | ||
block_id="update", | ||
text=block_kit.Text(f"{CURRENT_TITLE}{incident.impact or NO_IMPACT_TEXT}"), | ||
accessory=block_kit.Button( | ||
CHANGE_BUTTON_TEXT, UPDATE_CURRENT_IMPACT_ACTION, value=incident.pk | ||
), | ||
) | ||
) | ||
|
||
# if the user has supplied a message, provide the option for them to set it without | ||
# retyping in the dialog | ||
if message: | ||
msg.add_block( | ||
block_kit.Section( | ||
block_id=PROPOSED_MESSAGE_BLOCK_ID, | ||
text=block_kit.Text(f"{PROPOSED_TITLE}{message}"), | ||
accessory=block_kit.Button( | ||
ACCEPT_PROPOSED_TEXT, SET_NEW_IMPACT_ACTION, value=incident.pk | ||
), | ||
) | ||
) | ||
|
||
comms_channel = CommsChannel.objects.get(incident=incident) | ||
msg.send(comms_channel.channel_id) | ||
return True, None | ||
|
||
|
||
@action_handler(SET_NEW_IMPACT_ACTION) | ||
def handle_set_new_impact(action_context: ActionContext): | ||
for block in action_context.message["blocks"]: | ||
print("Looking at block", block) | ||
if block["block_id"] == PROPOSED_MESSAGE_BLOCK_ID: | ||
impact = block["text"]["text"].replace(PROPOSED_TITLE, "") | ||
action_context.incident.impact = impact | ||
action_context.incident.save() | ||
|
||
comms_channel = CommsChannel.objects.get(incident=action_context.incident) | ||
comms_channel.post_in_channel(f"{IMPACT_UPDATED_TITLE}{impact}") | ||
return | ||
|
||
|
||
@action_handler(UPDATE_CURRENT_IMPACT_ACTION) | ||
def handle_open_impact_dialog(action_context: ActionContext): | ||
dialog = dialog_builder.Dialog( | ||
title="Update Impact", | ||
submit_label="Update", | ||
state=action_context.incident.pk, | ||
elements=[ | ||
dialog_builder.TextArea( | ||
label="Impact", | ||
name="impact", | ||
optional=False, | ||
value=action_context.incident.impact, | ||
) | ||
], | ||
) | ||
|
||
dialog.send_open_dialog(UPDATE_IMPACT_DIALOG, action_context.trigger_id) | ||
|
||
|
||
@dialog_handler(UPDATE_IMPACT_DIALOG) | ||
def update_status_page( | ||
user_id: str, channel_id: str, submission: json, response_url: str, state: json | ||
): | ||
incident_id = state | ||
incident = Incident.objects.get(pk=incident_id) | ||
incident.impact = submission["impact"] | ||
incident.save() | ||
|
||
comms_channel = CommsChannel.objects.get(incident=incident) | ||
comms_channel.post_in_channel(f'{IMPACT_UPDATED_TITLE}{submission["impact"]}') |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import json | ||
import logging | ||
|
||
from response.core.models import Incident | ||
from response.slack import block_kit, dialog_builder | ||
from response.slack.decorators import ActionContext, action_handler, dialog_handler | ||
from response.slack.decorators.incident_command import __default_incident_command | ||
from response.slack.models import CommsChannel | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
UPDATE_CURRENT_SUMMARY_ACTION = "update-current-summary-action" | ||
SET_NEW_SUMMARY_ACTION = "set-new-summary-action" | ||
PROPOSED_MESSAGE_BLOCK_ID = "proposed" | ||
UPDATE_SUMMARY_DIALOG = "update-summary-dialog" | ||
|
||
NO_SUMMARY_TEXT = "This incident doesn't have a summary yet." | ||
CURRENT_TITLE = "*This is the current summary:*\n" | ||
PROPOSED_TITLE = "*Or would you like to update the summary to this?*\n" | ||
SUMMARY_UPDATED_TITLE = "*The summary has been updated to:*\n" | ||
CHANGE_BUTTON_TEXT = "Change" | ||
ACCEPT_PROPOSED_TEXT = "Yes" | ||
|
||
|
||
@__default_incident_command( | ||
["summary"], helptext="Provide a summary of what's going on" | ||
) | ||
def update_summary(incident: Incident, user_id: str, message: str): | ||
# Easy case. No summary currently and one has been provided | ||
if message and not incident.summary: | ||
incident.summary = message | ||
incident.save() | ||
return True, f"{SUMMARY_UPDATED_TITLE}{message}" | ||
|
||
# Either no new summary has been provided, or one already exists | ||
msg = block_kit.Message() | ||
|
||
msg.add_block( | ||
block_kit.Section( | ||
block_id="update", | ||
text=block_kit.Text( | ||
f"{CURRENT_TITLE}{incident.summary or NO_SUMMARY_TEXT}" | ||
), | ||
accessory=block_kit.Button( | ||
CHANGE_BUTTON_TEXT, UPDATE_CURRENT_SUMMARY_ACTION, value=incident.pk | ||
), | ||
) | ||
) | ||
|
||
# if the user has supplied a message, provide the option for them to set it without | ||
# retyping in the dialog | ||
if message: | ||
msg.add_block(block_kit.Divider()) | ||
msg.add_block( | ||
block_kit.Section( | ||
block_id=PROPOSED_MESSAGE_BLOCK_ID, | ||
text=block_kit.Text(f"{PROPOSED_TITLE}{message}"), | ||
accessory=block_kit.Button( | ||
ACCEPT_PROPOSED_TEXT, SET_NEW_SUMMARY_ACTION, value=incident.pk | ||
), | ||
) | ||
) | ||
|
||
comms_channel = CommsChannel.objects.get(incident=incident) | ||
msg.send(comms_channel.channel_id) | ||
return True, None | ||
|
||
|
||
@action_handler(SET_NEW_SUMMARY_ACTION) | ||
def handle_set_new_summary(action_context: ActionContext): | ||
for block in action_context.message["blocks"]: | ||
print("Looking at block", block) | ||
if block["block_id"] == PROPOSED_MESSAGE_BLOCK_ID: | ||
summary = block["text"]["text"].replace(PROPOSED_TITLE, "") | ||
action_context.incident.summary = summary | ||
action_context.incident.save() | ||
|
||
comms_channel = CommsChannel.objects.get(incident=action_context.incident) | ||
comms_channel.post_in_channel(f"{SUMMARY_UPDATED_TITLE}{summary}") | ||
return | ||
|
||
|
||
@action_handler(UPDATE_CURRENT_SUMMARY_ACTION) | ||
def handle_open_summary_dialog(action_context: ActionContext): | ||
dialog = dialog_builder.Dialog( | ||
title="Update Summary", | ||
submit_label="Update", | ||
state=action_context.incident.pk, | ||
elements=[ | ||
dialog_builder.TextArea( | ||
label="Summary", | ||
name="summary", | ||
optional=False, | ||
value=action_context.incident.summary, | ||
) | ||
], | ||
) | ||
|
||
dialog.send_open_dialog(UPDATE_SUMMARY_DIALOG, action_context.trigger_id) | ||
|
||
|
||
@dialog_handler(UPDATE_SUMMARY_DIALOG) | ||
def update_status_page( | ||
user_id: str, channel_id: str, submission: json, response_url: str, state: json | ||
): | ||
incident_id = state | ||
incident = Incident.objects.get(pk=incident_id) | ||
incident.summary = submission["summary"] | ||
incident.save() | ||
|
||
comms_channel = CommsChannel.objects.get(incident=incident) | ||
comms_channel.post_in_channel(f'{SUMMARY_UPDATED_TITLE}{submission["summary"]}') |