firefighter-incident 0.0.14__py3-none-any.whl → 0.0.16__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. firefighter/_version.py +2 -2
  2. firefighter/api/serializers.py +9 -0
  3. firefighter/confluence/signals/incident_updated.py +2 -2
  4. firefighter/incidents/enums.py +22 -2
  5. firefighter/incidents/forms/closure_reason.py +45 -0
  6. firefighter/incidents/forms/unified_incident.py +406 -0
  7. firefighter/incidents/forms/update_status.py +87 -1
  8. firefighter/incidents/migrations/0027_add_closure_fields.py +40 -0
  9. firefighter/incidents/migrations/0028_add_closure_reason_constraint.py +33 -0
  10. firefighter/incidents/migrations/0029_add_custom_fields_to_incident.py +22 -0
  11. firefighter/incidents/models/incident.py +32 -5
  12. firefighter/incidents/static/css/main.min.css +1 -1
  13. firefighter/incidents/templates/layouts/partials/status_pill.html +1 -1
  14. firefighter/incidents/views/reports.py +3 -3
  15. firefighter/raid/apps.py +9 -26
  16. firefighter/raid/client.py +2 -2
  17. firefighter/raid/forms.py +75 -238
  18. firefighter/raid/signals/incident_created.py +38 -13
  19. firefighter/raid/signals/incident_updated.py +3 -2
  20. firefighter/slack/messages/slack_messages.py +19 -4
  21. firefighter/slack/rules.py +1 -1
  22. firefighter/slack/signals/create_incident_conversation.py +6 -0
  23. firefighter/slack/signals/incident_updated.py +7 -1
  24. firefighter/slack/views/modals/__init__.py +4 -0
  25. firefighter/slack/views/modals/base_modal/form_utils.py +63 -0
  26. firefighter/slack/views/modals/close.py +15 -2
  27. firefighter/slack/views/modals/closure_reason.py +193 -0
  28. firefighter/slack/views/modals/open.py +60 -13
  29. firefighter/slack/views/modals/opening/details/unified.py +203 -0
  30. firefighter/slack/views/modals/opening/select_impact.py +1 -1
  31. firefighter/slack/views/modals/opening/set_details.py +3 -2
  32. firefighter/slack/views/modals/postmortem.py +10 -2
  33. firefighter/slack/views/modals/update_status.py +28 -2
  34. firefighter/slack/views/modals/utils.py +51 -0
  35. {firefighter_incident-0.0.14.dist-info → firefighter_incident-0.0.16.dist-info}/METADATA +1 -1
  36. {firefighter_incident-0.0.14.dist-info → firefighter_incident-0.0.16.dist-info}/RECORD +62 -38
  37. firefighter_tests/test_incidents/test_enums.py +100 -0
  38. firefighter_tests/test_incidents/test_forms/conftest.py +179 -0
  39. firefighter_tests/test_incidents/test_forms/test_closure_reason.py +91 -0
  40. firefighter_tests/test_incidents/test_forms/test_unified_incident_form.py +570 -0
  41. firefighter_tests/test_incidents/test_forms/test_unified_incident_form_integration.py +581 -0
  42. firefighter_tests/test_incidents/test_forms/test_unified_incident_form_p4_p5.py +410 -0
  43. firefighter_tests/test_incidents/test_forms/test_update_status_workflow.py +343 -0
  44. firefighter_tests/test_incidents/test_forms/test_workflow_transitions.py +167 -0
  45. firefighter_tests/test_incidents/test_models/test_incident_model.py +68 -0
  46. firefighter_tests/test_raid/conftest.py +154 -0
  47. firefighter_tests/test_raid/test_p1_p3_jira_fields.py +372 -0
  48. firefighter_tests/test_raid/test_raid_forms.py +10 -253
  49. firefighter_tests/test_raid/test_raid_signals.py +187 -0
  50. firefighter_tests/test_slack/messages/__init__.py +0 -0
  51. firefighter_tests/test_slack/messages/test_slack_messages.py +367 -0
  52. firefighter_tests/test_slack/views/modals/conftest.py +140 -0
  53. firefighter_tests/test_slack/views/modals/test_close.py +65 -3
  54. firefighter_tests/test_slack/views/modals/test_closure_reason_modal.py +138 -0
  55. firefighter_tests/test_slack/views/modals/test_form_utils_multiple_choice.py +249 -0
  56. firefighter_tests/test_slack/views/modals/test_open.py +146 -2
  57. firefighter_tests/test_slack/views/modals/test_opening_unified.py +421 -0
  58. firefighter_tests/test_slack/views/modals/test_update_status.py +327 -3
  59. firefighter_tests/test_slack/views/modals/test_utils.py +135 -0
  60. firefighter/raid/views/open_normal.py +0 -139
  61. firefighter/slack/views/modals/opening/details/critical.py +0 -88
  62. {firefighter_incident-0.0.14.dist-info → firefighter_incident-0.0.16.dist-info}/WHEEL +0 -0
  63. {firefighter_incident-0.0.14.dist-info → firefighter_incident-0.0.16.dist-info}/entry_points.txt +0 -0
  64. {firefighter_incident-0.0.14.dist-info → firefighter_incident-0.0.16.dist-info}/licenses/LICENSE +0 -0
@@ -217,7 +217,7 @@ class SelectImpactModal(
217
217
  logger.warning(f"Priority with value {suggested_priority_value} does not exist")
218
218
 
219
219
  # Fallback logic: P1/P2/P3 = critical, P4/P5 = normal
220
- return cast("ResponseType", "critical" if suggested_priority_value < 4 else "normal")
220
+ return "critical" if suggested_priority_value < 4 else "normal"
221
221
 
222
222
  @staticmethod
223
223
  def _update_private_metadata(
@@ -78,7 +78,7 @@ class SetIncidentDetails(ModalForm[T], Generic[T]):
78
78
  submit=self.submit_text[:24],
79
79
  close="Close details",
80
80
  callback_id=self.callback_id,
81
- blocks=self.get_form_class()(initial=details_form_data).slack_blocks(),
81
+ blocks=self.get_form_class()(initial=details_form_data, open_incident_context=open_incident_context, **kwargs).slack_blocks(),
82
82
  private_metadata=json.dumps(
83
83
  open_incident_context, cls=SlackFormJSONEncoder
84
84
  ),
@@ -99,7 +99,8 @@ class SetIncidentDetails(ModalForm[T], Generic[T]):
99
99
  priority = Priority.objects.get(pk=priority)
100
100
 
101
101
  slack_form = self.get_form_class()(
102
- data={**slack_view_submission_to_dict(body), "priority": priority}
102
+ data={**slack_view_submission_to_dict(body), "priority": priority},
103
+ open_incident_context=private_metadata,
103
104
  )
104
105
  form: T = slack_form.form
105
106
  if form.is_valid():
@@ -65,14 +65,22 @@ class PostMortemModal(
65
65
  )
66
66
 
67
67
  @staticmethod
68
- def handle_modal_fn(ack: Ack, incident: Incident) -> None: # type: ignore[override]
68
+ def handle_modal_fn(ack: Ack, body: dict[str, Any], incident: Incident) -> None: # type: ignore[override]
69
69
  if not apps.is_installed("firefighter.confluence"):
70
70
  ack(text="Confluence is not enabled!")
71
71
  return
72
72
  if hasattr(incident, "postmortem_for"):
73
73
  ack(text="Post-mortem has already been created.")
74
74
  return
75
- ack()
75
+
76
+ # Check if this modal was pushed on top of another modal
77
+ # If yes, clear the entire stack to avoid leaving stale modals visible
78
+ is_pushed = body.get("view", {}).get("previous_view_id") is not None
79
+ if is_pushed:
80
+ ack(response_action="clear")
81
+ else:
82
+ ack()
83
+
76
84
  PostMortem.objects.create_postmortem_for_incident(incident)
77
85
 
78
86
 
@@ -7,9 +7,11 @@ from django.conf import settings
7
7
  from slack_sdk.models.blocks.blocks import SectionBlock
8
8
  from slack_sdk.models.views import View
9
9
 
10
+ from firefighter.incidents.enums import IncidentStatus
10
11
  from firefighter.incidents.forms.update_status import UpdateStatusForm
11
12
  from firefighter.slack.slack_templating import slack_block_footer, slack_block_separator
12
13
  from firefighter.slack.views.modals.base_modal.base import ModalForm
14
+ from firefighter.slack.views.modals.utils import handle_update_status_close_request
13
15
 
14
16
  if TYPE_CHECKING:
15
17
  from slack_bolt.context.ack.ack import Ack
@@ -74,7 +76,8 @@ class UpdateStatusModal(ModalForm[UpdateStatusFormSlack]):
74
76
  "status": incident.status,
75
77
  "priority": incident.priority,
76
78
  "incident_category": incident.incident_category,
77
- }
79
+ },
80
+ incident=incident,
78
81
  ).slack_blocks()
79
82
  blocks.append(slack_block_separator())
80
83
  blocks.append(slack_block_footer())
@@ -98,7 +101,8 @@ class UpdateStatusModal(ModalForm[UpdateStatusFormSlack]):
98
101
  "status": incident.status,
99
102
  "priority": incident.priority,
100
103
  "incident_category": incident.incident_category,
101
- }
104
+ },
105
+ "incident": incident,
102
106
  },
103
107
  )
104
108
  if slack_form is None:
@@ -107,6 +111,28 @@ class UpdateStatusModal(ModalForm[UpdateStatusFormSlack]):
107
111
  if len(form.cleaned_data) == 0:
108
112
  # XXX We should have a prompt for empty forms
109
113
  return
114
+
115
+ # Check if user is trying to close and needs a closure reason
116
+ if "status" in form.changed_data:
117
+ target_status = form.cleaned_data["status"]
118
+ if handle_update_status_close_request(ack, body, incident, target_status):
119
+ return
120
+
121
+ # If trying to close, validate that incident can be closed
122
+ if target_status == IncidentStatus.CLOSED:
123
+ can_close, reasons = incident.can_be_closed
124
+ if not can_close:
125
+ # Build error message from reasons
126
+ error_messages = [reason[1] for reason in reasons]
127
+ error_text = "\n".join([f"• {msg}" for msg in error_messages])
128
+ ack(
129
+ response_action="errors",
130
+ errors={
131
+ "status": f"Cannot close this incident:\n{error_text}"
132
+ }
133
+ )
134
+ return
135
+
110
136
  update_kwargs: dict[str, Any] = {}
111
137
  for changed_key in form.changed_data:
112
138
  if changed_key in {"incident_category", "priority"}:
@@ -0,0 +1,51 @@
1
+ """Utilities for modal handling to avoid circular imports."""
2
+ from __future__ import annotations
3
+
4
+ from typing import TYPE_CHECKING, Any
5
+
6
+ from firefighter.incidents.enums import IncidentStatus
7
+ from firefighter.incidents.forms.update_status import UpdateStatusForm
8
+ from firefighter.slack.views.modals.closure_reason import modal_closure_reason
9
+
10
+ if TYPE_CHECKING:
11
+ from slack_sdk.models.views import View
12
+
13
+ from firefighter.incidents.models.incident import Incident
14
+
15
+
16
+ def get_close_modal_view(body: dict[str, Any], incident: Incident, **kwargs: Any) -> View | None:
17
+ """Get the appropriate modal view for closing an incident.
18
+
19
+ This function determines whether to show the closure reason modal
20
+ or delegate to the normal close modal.
21
+ """
22
+ # Check if closure reason is required
23
+ if UpdateStatusForm.requires_closure_reason(incident, IncidentStatus.CLOSED):
24
+ return modal_closure_reason.build_modal_fn(body, incident, **kwargs)
25
+
26
+ # Return None to indicate normal close modal should be used
27
+ return None
28
+
29
+
30
+ def handle_close_modal_callback(ack: Any, body: dict[str, Any], incident: Incident, user: Any) -> bool | None:
31
+ """Handle modal callback, delegating to closure reason modal if needed."""
32
+ # Check if this is a closure reason modal callback
33
+ if body.get("view", {}).get("callback_id") == "incident_closure_reason":
34
+ return modal_closure_reason.handle_modal_fn(ack, body, incident, user)
35
+
36
+ # Return None to indicate normal handling should continue
37
+ return None
38
+
39
+
40
+ def handle_update_status_close_request(ack: Any, body: dict[str, Any], incident: Incident, target_status: IncidentStatus) -> bool:
41
+ """Handle update status request to close incident, showing reason modal if needed.
42
+
43
+ Returns True if the request was handled (reason modal shown), False otherwise.
44
+ """
45
+ if (target_status == IncidentStatus.CLOSED and
46
+ UpdateStatusForm.requires_closure_reason(incident, target_status)):
47
+ # Show closure reason modal instead
48
+ ack(response_action="push", view=modal_closure_reason.build_modal_fn(body, incident))
49
+ return True
50
+
51
+ return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: firefighter-incident
3
- Version: 0.0.14
3
+ Version: 0.0.16
4
4
  Summary: Incident Management tool made for Slack using Django
5
5
  Project-URL: Repository, https://github.com/ManoManoTech/firefighter-incident
6
6
  Project-URL: Documentation, https://manomanotech.github.io/firefighter-incident/latest/
@@ -6,7 +6,7 @@ gunicorn.conf.py,sha256=vHsTGjaKOr8FDMp6fTKYTX4AtokmPgYvvt5Mr0Q6APc,273
6
6
  main.py,sha256=CsbprHoOYhjCLpTJmq9Z_aRYFoFgWxoz2pDLuwm8Eqg,1558
7
7
  manage.py,sha256=5ivHGD13C6nJ8QvltKsJ9T9akA5he8da70HLWaEP3k8,689
8
8
  firefighter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- firefighter/_version.py,sha256=YDX9ERYoOeE60PulkdUCy2JxmS89Xb_igX2wwbidLMQ,706
9
+ firefighter/_version.py,sha256=-Wsac7GwIa9vRUxL0XYF7OQESx0pigPYBlGyyiRu8nY,706
10
10
  firefighter/api/__init__.py,sha256=JQW0Bv6xwGqy7ioxx3h6UGMzkkJ4DntDpbvV1Ncgi8k,136
11
11
  firefighter/api/admin.py,sha256=x9Ysy-GiYjb0rynmFdS9g56e6n24fkN0ouGy5QD9Yrc,4629
12
12
  firefighter/api/apps.py,sha256=P5uU1_gMrDfzurdMbfqw1Bnb2uNKKcMq17WBPg2sLhc,204
@@ -14,7 +14,7 @@ firefighter/api/authentication.py,sha256=1OEeTF0NU54ZLgq2Vy3GxrR-7skj6HmobVp4UGP
14
14
  firefighter/api/models.py,sha256=HJh0PtlrUX8HVCdcdQlClwA6kIFVYnivnKmiQ30D0nQ,1533
15
15
  firefighter/api/permissions.py,sha256=1uxMg5ylFkmvIIonJVlQKL0RJAcgAY79a0y5ROiNrTg,608
16
16
  firefighter/api/renderer.py,sha256=RCQFnjZBIq9fF3dapu3kid2B1s0in8XOEBJmbh5cPlU,4057
17
- firefighter/api/serializers.py,sha256=PKvjmg4wJx9v4uLGUvL4UfQYWuqAcu-UhLA0yMGQhMU,10242
17
+ firefighter/api/serializers.py,sha256=DcPA22PuEyWrtdmYovuB4pi_RF1oSqc2d3a16pxJ-50,10586
18
18
  firefighter/api/urls.py,sha256=kjL6TwO836laVMn8e4fF4GiULyCXQkZiTDqXiVxrGtY,2103
19
19
  firefighter/api/migrations/0001_initial.py,sha256=8Q3Q_OUjAOsB_NzjYunAefC9WPk1FUwL3PA7N_gMylc,1496
20
20
  firefighter/api/migrations/0002_alter_apitokenproxy_options.py,sha256=BRuXscZS1gmcbF9mFlUyYy_Mwf-5xnUHcuFL2VA89eY,933
@@ -70,7 +70,7 @@ firefighter/confluence/management/commands/sync_runbooks.py,sha256=EgapI-TO9NXoH
70
70
  firefighter/confluence/migrations/0001_initial_oss.py,sha256=FdR7hie-0vwx_tcuYUziBZMSiIuQ-yNO5LRhizJ7CQg,3860
71
71
  firefighter/confluence/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
72
72
  firefighter/confluence/signals/__init__.py,sha256=nmuEEoawaYFVOlK880DT5-VOkXVIKYVLzrJIEnrXku0,121
73
- firefighter/confluence/signals/incident_updated.py,sha256=BR0qEos5fqW9gY8riNcKdxFaeBxi5Mk9JsicPsoqOnY,1797
73
+ firefighter/confluence/signals/incident_updated.py,sha256=2VQGNVW7DutQCDhfaBnxDQLhqlI8yQ_QzuzYIvsIUSU,1805
74
74
  firefighter/confluence/tasks/__init__.py,sha256=-NrthX2GIVmqjgiGAFg0r72Djc54Jl05k6Zb_UHUlf4,427
75
75
  firefighter/confluence/tasks/archive_postmortems.py,sha256=k2kgRaTC56SRzV9neGUZfvl8BpRZ_pKHoHr_sETykms,8098
76
76
  firefighter/confluence/tasks/sort_runbooks.py,sha256=rac-AjP14sYYulHHBbhuBbh9PK16Y3zBZ-7ywIdF5lo,2958
@@ -130,7 +130,7 @@ firefighter/firefighter/templates/admin/send_message_conversation.html,sha256=La
130
130
  firefighter/incidents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
131
131
  firefighter/incidents/admin.py,sha256=ZbGmAkR9xCIBvS2h18WaV21z4pNc516P98Z4JFBF9rk,22018
132
132
  firefighter/incidents/apps.py,sha256=GySoDZsz-BH-nsIZWTOd0H1hgL9s9il1BEuLC4gKTXs,378
133
- firefighter/incidents/enums.py,sha256=qRVpRvcCXEZ8xF6FTXmAtZjDxCj06hLDgEZlak6ket4,937
133
+ firefighter/incidents/enums.py,sha256=FsoxsZCBB_19MmxnxKu-hb4CzOJQjJVPtv1AwKjUAaI,1840
134
134
  firefighter/incidents/factories.py,sha256=EXrJ83H28QrD7J0SpzmO8rq2RgkQ8iRj8hmil4QD0Rs,3723
135
135
  firefighter/incidents/menus.py,sha256=pJVnLsxmXfltlNlfg5HeeWEYPDe2nIVc0F2IGNT4dWI,4140
136
136
  firefighter/incidents/signals.py,sha256=hUlPVVKSi9zuL4gz_Sa-HrDleYCASeMqKqA-kkHCaDQ,2128
@@ -138,12 +138,14 @@ firefighter/incidents/tables.py,sha256=00IRFri58YdO18g0C5yeiy0ESS9Qem5-UVLvijbrw
138
138
  firefighter/incidents/urls.py,sha256=21D1FNlqZPqT40T0bPaZWX0gyQgPR-38ZMFCRADlUjo,2129
139
139
  firefighter/incidents/forms/__init__.py,sha256=OU0r5eZc2A0UJNsL83n8AI5EvwUvg4Yx0GyPBI7R73M,111
140
140
  firefighter/incidents/forms/close_incident.py,sha256=wyLIlNXx6eU183SkR8H--k9YEOVehOWMecY82Bc2PmM,965
141
+ firefighter/incidents/forms/closure_reason.py,sha256=rwWC9Ks8iuuelCv2oqSpGUjL13yogpdbWHdG2yM23Rc,1564
141
142
  firefighter/incidents/forms/create_incident.py,sha256=cm5EWIvkJ1BZ-JfRJrh4TAE2wYYLV694gQ3MRIkcrGQ,2764
142
143
  firefighter/incidents/forms/edit.py,sha256=2rQkiKak-vac-K3cIsqlGv4R5nhI7JLxw3DhFMXbWms,956
143
144
  firefighter/incidents/forms/select_impact.py,sha256=jLbzVj4UeUGwOYYa5P92PXkEu1J_6H43UATZYzDgSLY,4630
145
+ firefighter/incidents/forms/unified_incident.py,sha256=duLMT_Jba3ZO8qMkP3Stdkd4f3tJpnvw-KjrIMSCfrk,14849
144
146
  firefighter/incidents/forms/update_key_events.py,sha256=1Xmnxe5OgZqLFS2HmMzQm3VGFPQipsdrLgKSwdh-fKc,4441
145
147
  firefighter/incidents/forms/update_roles.py,sha256=Q26UPfwAj-8N23RNZLQkvmHGnS1_j_X5KQWjJmPjMKY,3635
146
- firefighter/incidents/forms/update_status.py,sha256=f84X3mZWx60aFYa4z9zlI6oXWLwAi83pqNm9ODOaeK8,1059
148
+ firefighter/incidents/forms/update_status.py,sha256=LlQNufJ3YHbVnTk81WEwazds1JjbSzfaFjvvNW3q_oM,6196
147
149
  firefighter/incidents/forms/utils.py,sha256=g2azRXQE4GwBNvq47z_Q51yKcGYSBzFyITTDkLlC_Gk,3651
148
150
  firefighter/incidents/migrations/0001_initial_oss.py,sha256=OCrPbxf90h3NW9xolGGcsAryHKptD1TtKj5FucjBjg8,60311
149
151
  firefighter/incidents/migrations/0002_alter_severity_name_alter_user_password_featureteam.py,sha256=YfIJhw_-Yqm8qrkbp01461bkcUr7v5Zy90oHjkY3bSA,1113
@@ -171,12 +173,15 @@ firefighter/incidents/migrations/0023_populate_incident_category_references.py,s
171
173
  firefighter/incidents/migrations/0024_remove_component_fields_and_model.py,sha256=5CWUAXcezgC2QaLyWblEqgwSov_IJ19la3akn5ZDhJc,668
172
174
  firefighter/incidents/migrations/0025_make_incident_category_required.py,sha256=UmfZ0Vh56dADv-YbUPAOKmSlzlre0qyROf9o84x7xo0,706
173
175
  firefighter/incidents/migrations/0026_alter_incidentcategory_options_and_more.py,sha256=kitqppqhUlSiG3OIBZ87IECsR9Y0yCulYEtolFNYyS8,1116
176
+ firefighter/incidents/migrations/0027_add_closure_fields.py,sha256=MDWckXmjJNC2iVoFJD6IIwDmmqyeL1VG_pHR568JAtk,1344
177
+ firefighter/incidents/migrations/0028_add_closure_reason_constraint.py,sha256=z6FjCURDt9c-hyBeCvCKsbZOiuReYtbjtguIh3T6dnk,920
178
+ firefighter/incidents/migrations/0029_add_custom_fields_to_incident.py,sha256=G6DsnP5bM4Hy0s8IqXhLYzFKt3eumEsCnJfPIw5tcX4,567
174
179
  firefighter/incidents/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
175
180
  firefighter/incidents/models/__init__.py,sha256=FLVyBwIdyxLdgSvXRAKC3fry9YwwqlqhitTIuG0vWrk,877
176
181
  firefighter/incidents/models/environment.py,sha256=51txwua3dCrWZ1iSG3ZA8rbDn9c00pyMAZujl9gwE5c,827
177
182
  firefighter/incidents/models/group.py,sha256=VrVL315VFUvKW69AZuRUBg1h0jZJvn8zWeMxMOWec1Y,700
178
183
  firefighter/incidents/models/impact.py,sha256=URoMsQBJQnyfaNRpVl1o4A1IllM7dg94sd6tf5Ssr-k,4868
179
- firefighter/incidents/models/incident.py,sha256=7L3jDxWgjHGjaZ7Cmtn8_KkYFbAg6qKx3Mjghky9Ldk,26280
184
+ firefighter/incidents/models/incident.py,sha256=Rory-6YF_iBuHMNTbV8VbHK77i1nu9NWF2cgYSQT-zg,27243
180
185
  firefighter/incidents/models/incident_category.py,sha256=g4OHv_XQhWcH6dvkqkyCgjlruo_1eih_CdtAPgPhaW4,7744
181
186
  firefighter/incidents/models/incident_cost.py,sha256=juwOfJKRaNQpOHkRUCHShDDba0FU98YjRPkU4I0ofAU,1346
182
187
  firefighter/incidents/models/incident_cost_type.py,sha256=wm8diry_VySJzIjC9M3Yavv2tYbvJgpN9UDb2gFRuH4,845
@@ -190,7 +195,7 @@ firefighter/incidents/models/severity.py,sha256=a9p0l8oexr1Ve6pBIz-1rpUzDJAZ-PxH
190
195
  firefighter/incidents/models/user.py,sha256=Aok7g3d0uB7_gq8aXSYjEt7ogPpCkGX9JxNyjjE8XsU,3193
191
196
  firefighter/incidents/static/css/incident.css,sha256=48f03RWvchTz2Te2xSBTRd28qOlLO212sxbGWBd7d2M,2811
192
197
  firefighter/incidents/static/css/main.css,sha256=ZYaP3CbVQ1PMjmaWq91SQAbUBhW1BciuzJ52dvJI0fM,48
193
- firefighter/incidents/static/css/main.min.css,sha256=jGk8IefCyy1fXxXfqjUso6gmTnLe5_niHViCIE62gxY,117526
198
+ firefighter/incidents/static/css/main.min.css,sha256=P9bd2u-TRtZClyutuYw7R5JT9YZtS-ogWiWhZVVAl0M,119104
194
199
  firefighter/incidents/static/css/tailwind.css,sha256=afzjUc4YqJ6TYcYEWJbEMyx6fZ4m9b1ORqMpGTdfps8,977
195
200
  firefighter/incidents/static/img/gameday.png,sha256=CaoUFsi5GsdcVOfLFOx-8zpux-gwbj4a4V8bmfWk-x0,6391
196
201
  firefighter/incidents/static/img/logo-firefighter.png,sha256=eN7FJa9I1rj6-ohk4nEah8v0aBfHheeShjFWGMciRz0,2090
@@ -232,7 +237,7 @@ firefighter/incidents/templates/layouts/partials/incident_update_key_events_view
232
237
  firefighter/incidents/templates/layouts/partials/partial_table_list_paginated.html,sha256=O4VGlObu4gBXx0tid-K04XMnJeKXsGBfywu4IXdVxqM,6411
233
238
  firefighter/incidents/templates/layouts/partials/priority_icon.html,sha256=oeLpPLGxvMCDWzuuhV95IgHbMaEaSbp4zi4T4SR4ifA,886
234
239
  firefighter/incidents/templates/layouts/partials/priority_pill.html,sha256=f6h8-W0KLorB9zfVepuKw2bBKYc4--iKpfM_cEhBtjg,152
235
- firefighter/incidents/templates/layouts/partials/status_pill.html,sha256=D9V8bnOAw7dH1T7vKlWV54ytlYs-_VX6MYNQjM5rmSI,672
240
+ firefighter/incidents/templates/layouts/partials/status_pill.html,sha256=-z2W4DKc3xjw4iaIX7W39q2FRlBWVZiTFCZAZF2DzNQ,676
236
241
  firefighter/incidents/templates/layouts/partials/table.html,sha256=eZE4kh0nQwGik6qc7A0O_jHyZcg32uzHc1pkjJRt6hw,1567
237
242
  firefighter/incidents/templates/layouts/partials/user_card.html,sha256=LgYHSpqC0BAhVENMSmLpow8jlPnh5uRvHzooJlJna6w,802
238
243
  firefighter/incidents/templates/layouts/partials/user_tooltip.html,sha256=KkVPpoODXIzrm6iItTg5RQphBGruQw4dFdOgAuGRt1E,562
@@ -253,7 +258,7 @@ firefighter/incidents/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMp
253
258
  firefighter/incidents/views/date_filter.py,sha256=fUhTjkBulMokI5tAHuqNDVv1dyspjmw3O2vzkkhqbUs,5648
254
259
  firefighter/incidents/views/date_utils.py,sha256=tiRTlh7PmRv4eAH0asiSX3Gn7ajsal9egm4S1d7s3_s,5759
255
260
  firefighter/incidents/views/errors.py,sha256=yDuH0YOdGf-voVNEC51yR9Ie3OU-az7g2EqWs_uV1Kk,7855
256
- firefighter/incidents/views/reports.py,sha256=9suCtnyZASHnHAH9Rlb2DPOso8esSf14XPP8emgL-R4,20961
261
+ firefighter/incidents/views/reports.py,sha256=1Iegx04w-oHw4cj7u9w2_s7T_e9FH5I6RRPTwDZwZhg,20973
257
262
  firefighter/incidents/views/views.py,sha256=-z-cfYJ8lIwORAkAxXRMCAg34RmwcPO3l0-VuDpEGyA,10543
258
263
  firefighter/incidents/views/components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
259
264
  firefighter/incidents/views/components/details.py,sha256=gFEezmL1TcVYnM_ryLNNMaynuIdjYV31Qzx_GfzrQiA,1040
@@ -305,9 +310,9 @@ firefighter/pagerduty/views/oncall_list.py,sha256=o8h0ln7YsYcJp_N8DePzIBO2NMc2bJ
305
310
  firefighter/pagerduty/views/oncall_trigger.py,sha256=LYHpWyEaR6O8NazmsTl5ydtw1XHynUfaTB1IU429eZ8,2526
306
311
  firefighter/raid/__init__.py,sha256=nMNmvHCSkyLQsdhTow7myMU62vXk1e755gUntVfFFlY,154
307
312
  firefighter/raid/admin.py,sha256=WhIHaRAv7JPp2NH27w7_0JfvGHrvoyRJhYr3_WwedrA,1117
308
- firefighter/raid/apps.py,sha256=BUkaZSu45Ghdpx1XnE3DaFD4SC2SeUtSDZOTYynte5k,1655
309
- firefighter/raid/client.py,sha256=zzEtu4hOyn0XocMlmGrwgWUE7E4CGNm8s9CgJ-K1QTk,8108
310
- firefighter/raid/forms.py,sha256=zjbVqsYXuPRWapTCX0SbVBD3VmqbYE-1_FUlf0Y_tsM,17282
313
+ firefighter/raid/apps.py,sha256=cMT87gw_Nur3Kx-Ws9spJWZQZ35SqcU-1_7oa5CEPc8,1147
314
+ firefighter/raid/client.py,sha256=ja_tiKAcBFpI5ZwbGxSVyf7_ETq2K1Qauq26pMR-Ze4,8124
315
+ firefighter/raid/forms.py,sha256=gbbXDizCYDs8vz33ZFClTVZ_yM3jqZtWFMYRy3K3xuM,11863
311
316
  firefighter/raid/messages.py,sha256=e75kwi0hCe5ChwU4t-_6Q3Rcy22MLLdVSsYyjvG2SCM,5542
312
317
  firefighter/raid/models.py,sha256=29Smci739K1ZdcMu7uXYvoVEhgDpwLQoCzBbc5wvwhs,2211
313
318
  firefighter/raid/resources.py,sha256=39GhITs3OAWA1eSPZme-rLd818kuz7gwYzdN38zNz8Y,436
@@ -321,16 +326,15 @@ firefighter/raid/migrations/0002_featureteam_remove_qualifierrotation_jira_user_
321
326
  firefighter/raid/migrations/0003_delete_raidarea.py,sha256=M_XkKCu73ib2H09co2L-ssLQakJJFNOfqJpKrzOYP2Y,332
322
327
  firefighter/raid/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
323
328
  firefighter/raid/signals/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
324
- firefighter/raid/signals/incident_created.py,sha256=s4PNNrXDmhAw_3NnDQenHbQl9WPMmN_OmYAGq7tueVk,3908
325
- firefighter/raid/signals/incident_updated.py,sha256=cLiqgCIKjGZpvkb7w3ASDtJ8tWP4agFpmgfmDnT3xOs,1330
329
+ firefighter/raid/signals/incident_created.py,sha256=_XVgS20fvB3Oy9xfDv8apX6ETpoG3mGxBFhZwfgD5qU,5261
330
+ firefighter/raid/signals/incident_updated.py,sha256=5LYeqvgTrfINu_SOwkZa3hD6rvTsl8BL8Py-immqK3I,1374
326
331
  firefighter/raid/tasks/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
327
332
  firefighter/raid/views/__init__.py,sha256=noK-M1X4L46OMAp6S29jqajovzL6sIMSnIBv5l9vxIM,5174
328
- firefighter/raid/views/open_normal.py,sha256=g8ajo-_bXxL7suaKW2HYbLQuh6DZPYdeNwYl9tMDV-k,4681
329
333
  firefighter/slack/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
330
334
  firefighter/slack/admin.py,sha256=pNJbA-szxUUrghxv_Z0BNezu6lULDzFcOu_K5i4m7Cs,13963
331
335
  firefighter/slack/apps.py,sha256=gR0zWTtqT58tjPayBX22ZSzMkLiNpmoOvLShNvhJA6Q,664
332
336
  firefighter/slack/factories.py,sha256=tnrUTbtgehCuBr24MtTyJ3uezKC6gJbOdHuYZ5JBoyU,3886
333
- firefighter/slack/rules.py,sha256=nt60Uwb_bTEZpLbUzdd9nqGRjkmuKxqZudm1mqEaSk8,1647
337
+ firefighter/slack/rules.py,sha256=PHbqi8sSTZi60TaahLfwdVr1B3GG_Rz1ldAT5q3XvG4,1651
334
338
  firefighter/slack/slack_app.py,sha256=mvaH0hPFaNIUxEB7J0fy6y-PNPGsdPqjXFVmpTQ_hCo,4201
335
339
  firefighter/slack/slack_incident_context.py,sha256=PjE7-w-pGFyV4faw8EMsEFp4RG_T251RhofmqrsDG7Q,7277
336
340
  firefighter/slack/slack_templating.py,sha256=rWe8m1n648wizw08U_vLz8daRnp4zmkcWRqocIBpQj4,3841
@@ -344,7 +348,7 @@ firefighter/slack/management/commands/generate_manifest.py,sha256=zFWHAC7ioozcDd
344
348
  firefighter/slack/management/commands/switch_test_users.py,sha256=2KTSvCBxsEvZa61J8p0r3huPNhwuytcj2J7IawwZWpQ,11064
345
349
  firefighter/slack/messages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
346
350
  firefighter/slack/messages/base.py,sha256=biH-YEAaldJ-OLHEs5ZjW-gtUYUbjOqxrAEflqV2XS0,4593
347
- firefighter/slack/messages/slack_messages.py,sha256=nN7lF81VqtkxFLOaWag3oNg-9FVdZyuuKQihhbR4z8g,33137
351
+ firefighter/slack/messages/slack_messages.py,sha256=AI6t5dnJKZKa1ZCQ1l_zmf_SBjT-aTlykBS9Wz8x7NA,34092
348
352
  firefighter/slack/migrations/0001_initial_oss.py,sha256=XmTPgq7zCME2xDwzRFoVi4OegSIG9eSKoyTNoW05Qtg,12933
349
353
  firefighter/slack/migrations/0002_usergroup_tag.py,sha256=098tmGA81mT-R2uhb6uQfZ7gKiRG9bFhEwQ8rrp4SKM,583
350
354
  firefighter/slack/migrations/0003_alter_usergroup_tag.py,sha256=ncH3KUWEPZHlbdcAtOJ0KGt5H6EX-cKspTGU3osrAhE,591
@@ -362,11 +366,11 @@ firefighter/slack/models/sos.py,sha256=Sji-7DxgsrLs7vFRJKPw7nmYyo2tIjNwoTcmdCmzE
362
366
  firefighter/slack/models/user.py,sha256=2Thcz5qQUsWGV9q77U5Z1b_jePZQJfE7BehwN_BlYH8,17230
363
367
  firefighter/slack/models/user_group.py,sha256=9bedrDwDwj641oTy65ucw63oQasCyKWhBZ1xx6peMBM,7141
364
368
  firefighter/slack/signals/__init__.py,sha256=dqMf2x-PVKgmwzH2d9uHuQ8hZ4fbu74eRd4Ij2_dNSg,186
365
- firefighter/slack/signals/create_incident_conversation.py,sha256=uybiqCgPlWYq2AA2FKNkEmqhDYxDy-h0ebT-RBVpx9I,4965
369
+ firefighter/slack/signals/create_incident_conversation.py,sha256=6oxNJzprU312-3Hd6ACijQcbmcHkm7ikJsWaQNo54ig,5224
366
370
  firefighter/slack/signals/get_users.py,sha256=-ZUI3ORJZJ4tLiGhVwIU-pWHoriALtOC7Kh_bFR4bGU,2287
367
371
  firefighter/slack/signals/handle_incident_channel_done.py,sha256=pYoS_ZJf2u9seHCqahfPHz4BrfvF1vIZjE1_yy0P5mY,1726
368
372
  firefighter/slack/signals/incident_closed.py,sha256=6QyUmTjEGVg0Wn5W-i2F8DlJuhvHjg3MxkcvAXFn9Bk,687
369
- firefighter/slack/signals/incident_updated.py,sha256=HLJS6HaZ9fthvobUEx-x-SAtyOsO8W2_utGP9i36h5Y,8123
373
+ firefighter/slack/signals/incident_updated.py,sha256=HiJlyHHzGhkip5v6aOky4xNzbrfG_kD4cqEnrASfr6g,8407
370
374
  firefighter/slack/signals/postmortem_created.py,sha256=XY8_lEmBEG3VSsankpbOWdEB9dom9Ke6u8ss4-aDX6Y,1152
371
375
  firefighter/slack/signals/roles_reminders.py,sha256=1Ef_J1PubY8WTVs2WDXz4KWa6X2Lvp1RFObIjSGpiOM,4041
372
376
  firefighter/slack/tasks/__init__.py,sha256=28QxZkakyi9l7Ae83fQuzOS-9EaBiwuh_peUZwIxCx4,179
@@ -394,33 +398,35 @@ firefighter/slack/views/events/member_left_channel.py,sha256=49CQxYvjJwFEBnnpgrL
394
398
  firefighter/slack/views/events/message.py,sha256=c8tvo0btOUu_5Bc83oiO3IQbaEyoRiUWFk118yqF90g,2068
395
399
  firefighter/slack/views/events/message_deleted.py,sha256=tyA1-sAlG9ImcKIhqSn6EgujHmbvj4Uw2QzQ4JH4QwI,747
396
400
  firefighter/slack/views/events/reaction_added.py,sha256=AipwBnrU5B35D97YIZCXdSW8W7-9QTIIQqUcrLTLQ5c,4241
397
- firefighter/slack/views/modals/__init__.py,sha256=fXecF962l_qsp-MK8u2Y84p49cDKyFDQXlWUEKME9XE,1833
398
- firefighter/slack/views/modals/close.py,sha256=TE9NXcpMk86yeV_zKxGKFeVhstdJCemghY6yVRuaGMQ,11630
401
+ firefighter/slack/views/modals/__init__.py,sha256=U9PapAIlpuYqBonOUmBGWT8_HjQa35ilMQJXGaFLgd0,1945
402
+ firefighter/slack/views/modals/close.py,sha256=4j5iA-lmIFuCz7B9pgDmjxrqmfWFysqWEn1YIsE75zc,12161
403
+ firefighter/slack/views/modals/closure_reason.py,sha256=eEBK1_sfY9TAKFsajS-As0kZgDPwuU_8DE0z2OANbvc,6943
399
404
  firefighter/slack/views/modals/downgrade_workflow.py,sha256=S0y0_GYH4q7ewZUr_eA9Ly2c1FQueZzNCTiuIiWYUoY,3109
400
405
  firefighter/slack/views/modals/edit.py,sha256=60xav4XG4KGS9KknqsQNCQjl3qQzk7OtmHiEYTQ9pUk,3861
401
406
  firefighter/slack/views/modals/key_event_message.py,sha256=ga3-ITZyzJExwzctX-GfgnDqyQaxTfcqpqnOwY2E38M,5620
402
- firefighter/slack/views/modals/open.py,sha256=VJUDVIEy0gcN7RrLOWfh621_1ElWbw1MNV6XosIcnV0,26383
403
- firefighter/slack/views/modals/postmortem.py,sha256=AeEtmiam_XgCRxDmltKluNT2VN1gcuCB2VbYeeATVcA,2525
407
+ firefighter/slack/views/modals/open.py,sha256=YIxpo8_C4cWCy_pQ3YRWl7NMyLmjqNjggTQINTBW6mo,29189
408
+ firefighter/slack/views/modals/postmortem.py,sha256=YlBZ1ziONmbA818hPo0H54deWogiH3Xy1jArMiazx-4,2851
404
409
  firefighter/slack/views/modals/select.py,sha256=Y-Ji_ALnzhYkXDBAyi497UL1Xn2vCGqXCtj8eog75Jk,3312
405
410
  firefighter/slack/views/modals/send_sos.py,sha256=bP6HgYyDwPrIcTq7n_sQz6UQsxhYbvBDS4HjM0uRccA,4838
406
411
  firefighter/slack/views/modals/status.py,sha256=C8-eJRtquSeaHe568SC7yCFef1k14m2_6lUqBezdSH8,3970
407
412
  firefighter/slack/views/modals/trigger_oncall.py,sha256=h_LAD5X5rjMFWiDYTEp5VB9OaF7sTvKZhNaW3KQkw5M,5065
408
413
  firefighter/slack/views/modals/update.py,sha256=OF9sf-Z6IiviNmjN28MQNYiUbJ5tha0MdHUQyPpVFiY,2150
409
414
  firefighter/slack/views/modals/update_roles.py,sha256=De3Gv67MZQHyNdonX3S99F5MtKF_Rj3y71gdWibxBaM,2419
410
- firefighter/slack/views/modals/update_status.py,sha256=gxjl7axpIk1b7yQ8dbnuOQp1fNPJJ0N4tBHU6IT5UHI,4520
415
+ firefighter/slack/views/modals/update_status.py,sha256=QZvJj5FzNNgsjJZi9I_GfAD6JpZYy821Z0V0SCSODcI,5708
416
+ firefighter/slack/views/modals/utils.py,sha256=zKLJD2KhTGcX2d9WCYwshYRa6ok_9-ED1_pgOLp028s,2133
411
417
  firefighter/slack/views/modals/base_modal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
412
418
  firefighter/slack/views/modals/base_modal/base.py,sha256=7mvOxZTtegSmitSMnDvu8BK0qLUXoudUsda6CaLjdkY,12479
413
419
  firefighter/slack/views/modals/base_modal/base_mixins.py,sha256=Xl1koQsPpHO_kKIiuSSJHJnIBmytDXseI1KcAZQZC3M,230
414
- firefighter/slack/views/modals/base_modal/form_utils.py,sha256=VJlqHo_VCTImKIbHq7slIBWXpFF7agB84hRRO6F_SK8,21800
420
+ firefighter/slack/views/modals/base_modal/form_utils.py,sha256=4-eBpOR770nMvYM6DF0yCe9P7PaIXMaedL4kQOkZRsE,25039
415
421
  firefighter/slack/views/modals/base_modal/mixins.py,sha256=c7WYs0aXKXVktEMNSZ8IUQbAmustrLbRzbOoo4nyYGA,1917
416
422
  firefighter/slack/views/modals/base_modal/modal_utils.py,sha256=1uHTlLxxeXUQttH3bHaehJwCuI6a-h04s-GzdnVA4sI,2459
417
423
  firefighter/slack/views/modals/opening/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
418
424
  firefighter/slack/views/modals/opening/check_current_incidents.py,sha256=4hFp6nEKH55j0BBYE2Ks9KNwCPImCKQdxyweIWmW5E4,2551
419
- firefighter/slack/views/modals/opening/select_impact.py,sha256=LoioV9IAGOVXzn6i60UDOKxp55qixDjQACuBalktvEk,11721
420
- firefighter/slack/views/modals/opening/set_details.py,sha256=i6zQM2FYz3Z6s5AZH7lXgB2e8yjS0rDwgfMBZaiOqIw,5791
425
+ firefighter/slack/views/modals/opening/select_impact.py,sha256=JFpStRhvGDcqR5DptJQajuA2VJOypM8r6_XnJcQMGB4,11699
426
+ firefighter/slack/views/modals/opening/set_details.py,sha256=oLFE6ZHtOp1hbZbu3COYP8_vfaV7FtCmzkLJbihAj3M,5899
421
427
  firefighter/slack/views/modals/opening/types.py,sha256=ETpp0DAz5OMI5h7iv62Of7yJCbI-Q4-3kKSS6msPQeY,563
422
428
  firefighter/slack/views/modals/opening/details/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
423
- firefighter/slack/views/modals/opening/details/critical.py,sha256=OY3IwXCoauv1ov5-HiE94sLdIJy-5xwQxvNWpAOf8qQ,2862
429
+ firefighter/slack/views/modals/opening/details/unified.py,sha256=Ubgu1It_SpxScmSChzVm8nScCqZ5TtFYJBEcUOA6XN8,7422
424
430
  firefighter_fixtures/incidents/environments.json,sha256=5H_F08x7moMKz-H6OIUVaJGtmyKEESXLlG5cfXX0IA4,1039
425
431
  firefighter_fixtures/incidents/groups.json,sha256=mwrpUk9tvZa0RnT1T0aec_nnMsVZhR2GXS7pmrAK0y8,2555
426
432
  firefighter_fixtures/incidents/impact_level.json,sha256=AsrcSrkHN8E-XWlekb6Pgt8m2Sg0HASNld0TRFHwIFQ,6930
@@ -440,38 +446,56 @@ firefighter_tests/test_firefighter/test_firefighter_utils.py,sha256=og79bkErCBQB
440
446
  firefighter_tests/test_firefighter/test_logging.py,sha256=4HUH73vLDwmOCpMiXwDasMLL7F0kA1B_DxE48mqswSk,878
441
447
  firefighter_tests/test_firefighter/test_sso.py,sha256=uX2ry0REDgXzQc9Y1BmAgI0OgbmzWoOv9H_GDyOqQmQ,5205
442
448
  firefighter_tests/test_firefighter/test_urls.py,sha256=UMGx4oW98RoL0ceePkIIKEVjbHdFECvQuGNXYAJForQ,4839
449
+ firefighter_tests/test_incidents/test_enums.py,sha256=wMxxL1uakrmzJIi-2xkAvG-Y3NDDmIt0PHyOAJBz0yQ,4341
443
450
  firefighter_tests/test_incidents/test_incident_urls.py,sha256=j663qeBkv31aMlA0sLfzBOmp0iEv9OB-xvIwzrjlSZk,3793
451
+ firefighter_tests/test_incidents/test_forms/conftest.py,sha256=YYF5Lm-Jmt-HM9zt_gjrNkiuqOaNMW8lLBr1crAP6J8,5423
452
+ firefighter_tests/test_incidents/test_forms/test_closure_reason.py,sha256=H6RObqazFAit_pvo7N-lotiSsLOYMafZIk23A5Wiodg,3533
444
453
  firefighter_tests/test_incidents/test_forms/test_form_select_impact.py,sha256=DTaPGrJi8mXHfh7mhvDTKYVvDCxqarILauE59UDlwqo,3210
445
454
  firefighter_tests/test_incidents/test_forms/test_form_utils.py,sha256=tisEDCacCrG5usEyPkFLCZeG9ebp9b9N27dcUtGmYA4,2467
455
+ firefighter_tests/test_incidents/test_forms/test_unified_incident_form.py,sha256=tb2LSn4rtGbYblAdYXthD0UlKL4h-_u-Bj8nqvDVlGM,22701
456
+ firefighter_tests/test_incidents/test_forms/test_unified_incident_form_integration.py,sha256=8_lbhnMO5FIJewYtxueRv2M6-mOBcdOjMIHRUGGzIHM,23860
457
+ firefighter_tests/test_incidents/test_forms/test_unified_incident_form_p4_p5.py,sha256=7x_JVsgnpJvxN-QSsD_JeEyZatsoVKj6vPMf4VXzsIQ,16364
446
458
  firefighter_tests/test_incidents/test_forms/test_update_key_events.py,sha256=rHRGRU9iFXDdMr_kK3pMB7gyeZuMf7Dyq8bRZkddBC4,1644
459
+ firefighter_tests/test_incidents/test_forms/test_update_status_workflow.py,sha256=OyFTcG3VCTIucdT7HfNgB6SDd1BmcukSRdwyw5q7xuY,15181
460
+ firefighter_tests/test_incidents/test_forms/test_workflow_transitions.py,sha256=wJd6CKuoN3NGR00eJjRLHJHSazzkymf-_z_2qgBSVSE,7068
447
461
  firefighter_tests/test_incidents/test_models/test_incident_category.py,sha256=aRoBOhb8fNjLF9CMPZ1FXM8AT51Cd80XPsY2Y3wHY_M,5701
448
- firefighter_tests/test_incidents/test_models/test_incident_model.py,sha256=PciIbyA4OFjzMpAIyjnXRRFwGoVYYXzAxDNN2o4qpiw,895
462
+ firefighter_tests/test_incidents/test_models/test_incident_model.py,sha256=c0A73G50SuzExHaEWJyByjmJmISChCClQYd2AydnYxY,3649
449
463
  firefighter_tests/test_incidents/test_models/test_migrations/test_incident_migrations.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
450
464
  firefighter_tests/test_incidents/test_utils/test_date_utils.py,sha256=ogP7qOEwItL4YGI5gbQPVssOS9ilwiuZC8OrT2qngBY,6568
451
465
  firefighter_tests/test_incidents/test_views/test_incident_detail_view.py,sha256=gKKFWIZVrD_P4p6DJjeHCW5uGXBUBVlCd95gJJYDpWQ,680
452
466
  firefighter_tests/test_incidents/test_views/test_index_view.py,sha256=InpxbaWOFwRn4YWeIKZhj17vMymrQQf2p2LFhe2Bcdw,816
467
+ firefighter_tests/test_raid/conftest.py,sha256=i_TOquYIMLDyVQ97uqxTqPJszVz4qq7L_Q7YJxTuS1o,4090
468
+ firefighter_tests/test_raid/test_p1_p3_jira_fields.py,sha256=eMicF70ov5jXGIvKwtZduRmTM7rXrphhj2gKJGSVD7s,17618
453
469
  firefighter_tests/test_raid/test_priority_mapping.py,sha256=h8YproDbCVbsP4DTmN0xFWfdHdhIy2Jdn7X4e4kqgYs,11969
454
470
  firefighter_tests/test_raid/test_raid_client.py,sha256=8iRBR4bKewPPbtz33hCLOHiZDTELPQBOrQb7EdNDS4c,21227
455
471
  firefighter_tests/test_raid/test_raid_client_users.py,sha256=9uma1wBhaiCoG75XAZHqpT8oGTnqFJRMCi7a3XctNtM,3631
456
- firefighter_tests/test_raid/test_raid_forms.py,sha256=iMI8oQwMVOZmcQxnoxG0UIHfUTYC7z0vBYVOwGrj-Y4,28999
472
+ firefighter_tests/test_raid/test_raid_forms.py,sha256=y89ZqP6Wf9h3S2hegJHVfVdCuVbfL4SvT-kPVoAYyy8,19618
457
473
  firefighter_tests/test_raid/test_raid_models.py,sha256=nq-fVClB_P24W8WrZruOPt8wlHUVGYI7wxJR7tH6AnM,5042
458
474
  firefighter_tests/test_raid/test_raid_serializers.py,sha256=nejl4ceBPegOcks6z6B8_7Ekg8ef18j3i7C8Y8dS8v0,20665
459
475
  firefighter_tests/test_raid/test_raid_service.py,sha256=AqVyrRjW2tr0sfbXS4lGlJ7mcxB2ACEXAR8Bv0pXnj0,16755
476
+ firefighter_tests/test_raid/test_raid_signals.py,sha256=twNxB3NQs58s8ZcP-wsZXG7iTHR4yKFC9x-zpq1ZuAo,7002
460
477
  firefighter_tests/test_raid/test_raid_transitions.py,sha256=mtmMKwukxmZSM-R619BQ3Z_2AB-qY6imvDgUF0A3_tw,4784
461
478
  firefighter_tests/test_raid/test_raid_utils.py,sha256=i6JBwim1G-qynwxprNZekxl9K7Vis4FFvNkw3wT2jTM,1016
462
479
  firefighter_tests/test_raid/test_raid_views.py,sha256=paAhh4k2EDlmG1ehwNhMuYIhr1okqrvM7xlkaTAo2V0,6825
463
480
  firefighter_tests/test_slack/conftest.py,sha256=MCg04JFQ0iBeYUN_moEvvH4PVA3wE48Q6LkrIw7Bic0,2015
464
481
  firefighter_tests/test_slack/test_slack_utils.py,sha256=9PLobMNXh3xDyFuwzcQFpKJhe4j__sIgf_WRHIpANJw,3957
482
+ firefighter_tests/test_slack/messages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
483
+ firefighter_tests/test_slack/messages/test_slack_messages.py,sha256=60ATcQKWVuLvBbyCEiSyzvR4cnDTgEEhDclg8jrE4Hg,14391
465
484
  firefighter_tests/test_slack/test_models/test_conversations.py,sha256=t3ttmgwiu7c-N55iU3XZPmrkEhvkTzJoXszJncy4Bts,793
466
485
  firefighter_tests/test_slack/test_models/test_incident_channel.py,sha256=qWoGe9iadmK6-R8usWvjH87AHRkvhG_dHQeC3kHeJrs,17487
467
486
  firefighter_tests/test_slack/test_models/test_slack_user.py,sha256=uzur-Rf03I5dpUTO4ZI6O1arBUrAorg1Zvgshf8M-J4,7000
468
- firefighter_tests/test_slack/views/modals/test_close.py,sha256=TXNt5KWiPkWvvh9FvQhDiaiOWh6W8OdxmPEpWeO7Taw,42958
469
- firefighter_tests/test_slack/views/modals/test_open.py,sha256=z3lvAPOXCUSt7i_9jWYcQWGIRwRg7Z1DT6AfMOK22_s,4900
487
+ firefighter_tests/test_slack/views/modals/conftest.py,sha256=TKJVQgqWaFs3Gg1T526pti9XpZBtQs47WBH6L_qSDeo,4532
488
+ firefighter_tests/test_slack/views/modals/test_close.py,sha256=wuqMkpyUWKvC_gaTnJvRmdm8-wsmbLpCU_ith4ihsLY,45447
489
+ firefighter_tests/test_slack/views/modals/test_closure_reason_modal.py,sha256=R-a8NJZmbNKZeVbAS3DFe_U7sw-GM4p_fKRkqBP6yPM,5099
490
+ firefighter_tests/test_slack/views/modals/test_form_utils_multiple_choice.py,sha256=Svab_ZyYTMf0T-uJEQcm7gS1WzxtC4gPh1W--Z2v_Y8,8415
491
+ firefighter_tests/test_slack/views/modals/test_open.py,sha256=IzgG9le5NN_CvltehAIqkj94ioTKCqdA6yoRp2NlNsE,10700
492
+ firefighter_tests/test_slack/views/modals/test_opening_unified.py,sha256=y-8WSqS7529_tDyz85MzVLKNGAR7NsGmjhvHfx5L2l0,15244
470
493
  firefighter_tests/test_slack/views/modals/test_send_sos.py,sha256=_rE6jD-gOzcGyhlY0R9GzlGtPx65oOOguJYdENgxtLc,1289
471
494
  firefighter_tests/test_slack/views/modals/test_status.py,sha256=oQzPfwdg2tkbo9nfkO1GfS3WydxqSC6vy1AZjZDKT30,2226
472
- firefighter_tests/test_slack/views/modals/test_update_status.py,sha256=T8sjYoPmllje5aNRHXlpsjiGe_hg7y2B50nivuG_vwk,39412
473
- firefighter_incident-0.0.14.dist-info/METADATA,sha256=8kEtQu-FUuMd7bXJhcVMCmSVdfXbrYKjpkCsgq6zxZc,5541
474
- firefighter_incident-0.0.14.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
475
- firefighter_incident-0.0.14.dist-info/entry_points.txt,sha256=c13meJbv7YNmYz7MipMOQwzQ5IeFOPXUBYAJ44XMQsM,61
476
- firefighter_incident-0.0.14.dist-info/licenses/LICENSE,sha256=krRiGp-a9-1nH1bWpBEdxyTKLhjLmn6DMVVoIb0zF90,1087
477
- firefighter_incident-0.0.14.dist-info/RECORD,,
495
+ firefighter_tests/test_slack/views/modals/test_update_status.py,sha256=FPyFwvr6f1C3RIRPJh0Kyy6xC_HfNHtTqqkqVbV_mOg,52543
496
+ firefighter_tests/test_slack/views/modals/test_utils.py,sha256=DJd2n9q6fFu8UuCRdiq9U_Cn19MdnC5c-ydLLrk6rkc,5218
497
+ firefighter_incident-0.0.16.dist-info/METADATA,sha256=DkJJ8Pm9Q18G7K_d0QmYYNzPiIRapidWrtXF7g7vzkk,5541
498
+ firefighter_incident-0.0.16.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
499
+ firefighter_incident-0.0.16.dist-info/entry_points.txt,sha256=c13meJbv7YNmYz7MipMOQwzQ5IeFOPXUBYAJ44XMQsM,61
500
+ firefighter_incident-0.0.16.dist-info/licenses/LICENSE,sha256=krRiGp-a9-1nH1bWpBEdxyTKLhjLmn6DMVVoIb0zF90,1087
501
+ firefighter_incident-0.0.16.dist-info/RECORD,,
@@ -0,0 +1,100 @@
1
+ """Test the incidents enums module."""
2
+ from __future__ import annotations
3
+
4
+ from firefighter.incidents.enums import ClosureReason, IncidentStatus
5
+
6
+
7
+ class TestIncidentStatus:
8
+ """Test IncidentStatus enum and its methods."""
9
+
10
+ def test_enum_values(self):
11
+ """Test that enum values are correctly defined."""
12
+ assert IncidentStatus.OPEN.value == 10
13
+ assert IncidentStatus.INVESTIGATING.value == 20
14
+ assert IncidentStatus.MITIGATING.value == 30
15
+ assert IncidentStatus.MITIGATED.value == 40
16
+ assert IncidentStatus.POST_MORTEM.value == 50
17
+ assert IncidentStatus.CLOSED.value == 60
18
+
19
+ def test_enum_labels(self):
20
+ """Test that enum labels are correctly defined."""
21
+ assert IncidentStatus.OPEN.label == "Open"
22
+ assert IncidentStatus.INVESTIGATING.label == "Investigating"
23
+ assert IncidentStatus.MITIGATING.label == "Mitigating"
24
+ assert IncidentStatus.MITIGATED.label == "Mitigated"
25
+ assert IncidentStatus.POST_MORTEM.label == "Post-mortem"
26
+ assert IncidentStatus.CLOSED.label == "Closed"
27
+
28
+ def test_lt_method(self):
29
+ """Test the lt static method."""
30
+ result = IncidentStatus.lt(30)
31
+ expected = [IncidentStatus.OPEN, IncidentStatus.INVESTIGATING]
32
+ assert result == expected
33
+
34
+ def test_lte_method(self):
35
+ """Test the lte static method."""
36
+ result = IncidentStatus.lte(30)
37
+ expected = [IncidentStatus.OPEN, IncidentStatus.INVESTIGATING, IncidentStatus.MITIGATING]
38
+ assert result == expected
39
+
40
+ def test_gt_method(self):
41
+ """Test the gt static method."""
42
+ result = IncidentStatus.gt(30)
43
+ expected = [IncidentStatus.MITIGATED, IncidentStatus.POST_MORTEM, IncidentStatus.CLOSED]
44
+ assert result == expected
45
+
46
+ def test_gte_method(self):
47
+ """Test the gte static method."""
48
+ result = IncidentStatus.gte(30)
49
+ expected = [IncidentStatus.MITIGATING, IncidentStatus.MITIGATED, IncidentStatus.POST_MORTEM, IncidentStatus.CLOSED]
50
+ assert result == expected
51
+
52
+ def test_choices_lt_method(self):
53
+ """Test the choices_lt static method."""
54
+ result = IncidentStatus.choices_lt(30)
55
+ expected = [(10, "Open"), (20, "Investigating")]
56
+ assert result == expected
57
+
58
+ def test_choices_lte_method(self):
59
+ """Test the choices_lte static method."""
60
+ result = IncidentStatus.choices_lte(30)
61
+ expected = [(10, "Open"), (20, "Investigating"), (30, "Mitigating")]
62
+ assert result == expected
63
+
64
+ def test_choices_lte_skip_postmortem_method(self):
65
+ """Test the choices_lte_skip_postmortem static method."""
66
+ result = IncidentStatus.choices_lte_skip_postmortem(60)
67
+ expected = [(10, "Open"), (20, "Investigating"), (30, "Mitigating"), (40, "Mitigated"), (60, "Closed")]
68
+ assert result == expected
69
+
70
+ # Test that POST_MORTEM is excluded
71
+ assert (50, "Post-mortem") not in result
72
+
73
+
74
+ class TestClosureReason:
75
+ """Test ClosureReason enum."""
76
+
77
+ def test_enum_values(self):
78
+ """Test that closure reason values are correctly defined."""
79
+ assert ClosureReason.RESOLVED.value == "resolved"
80
+ assert ClosureReason.DUPLICATE.value == "duplicate"
81
+ assert ClosureReason.FALSE_POSITIVE.value == "false_positive"
82
+ assert ClosureReason.SUPERSEDED.value == "superseded"
83
+ assert ClosureReason.EXTERNAL.value == "external"
84
+ assert ClosureReason.CANCELLED.value == "cancelled"
85
+
86
+ def test_enum_labels(self):
87
+ """Test that closure reason labels are correctly defined."""
88
+ assert ClosureReason.RESOLVED.label == "Resolved normally"
89
+ assert ClosureReason.DUPLICATE.label == "Duplicate incident"
90
+ assert ClosureReason.FALSE_POSITIVE.label == "False alarm - no actual issue"
91
+ assert ClosureReason.SUPERSEDED.label == "Superseded by another incident"
92
+ assert ClosureReason.EXTERNAL.label == "External dependency/known issue"
93
+ assert ClosureReason.CANCELLED.label == "Cancelled - no longer relevant"
94
+
95
+ def test_choices_available(self):
96
+ """Test that choices are available."""
97
+ choices = ClosureReason.choices
98
+ assert len(choices) == 6
99
+ assert ("resolved", "Resolved normally") in choices
100
+ assert ("duplicate", "Duplicate incident") in choices