firefighter-incident 0.0.6__py3-none-any.whl → 0.0.8__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.
- firefighter/_version.py +2 -2
- firefighter/components/avatar/avatar.py +2 -2
- firefighter/components/card/card.py +2 -2
- firefighter/components/export_button/export_button.py +2 -2
- firefighter/components/form/form.py +2 -2
- firefighter/components/form_field/form_field.py +2 -2
- firefighter/components/messages/messages.py +2 -2
- firefighter/components/modal/modal.py +2 -2
- firefighter/incidents/forms/select_impact.py +4 -4
- firefighter/incidents/menus.py +1 -1
- firefighter/incidents/migrations/0008_impact_level.py +54 -22
- firefighter/incidents/migrations/0012_alter_impactlevel.py +2 -2
- firefighter/incidents/migrations/0015_update_impact_level.py +136 -0
- firefighter/incidents/migrations/0016_update_business_incidents_and_level.py +84 -0
- firefighter/incidents/models/impact.py +8 -4
- firefighter/incidents/templates/pages/component_list.html +1 -1
- firefighter/slack/views/modals/open.py +6 -1
- firefighter/slack/views/modals/opening/select_impact.py +35 -4
- {firefighter_incident-0.0.6.dist-info → firefighter_incident-0.0.8.dist-info}/METADATA +1 -1
- {firefighter_incident-0.0.6.dist-info → firefighter_incident-0.0.8.dist-info}/RECORD +24 -22
- firefighter_tests/test_incidents/test_forms/test_form_select_impact.py +3 -3
- {firefighter_incident-0.0.6.dist-info → firefighter_incident-0.0.8.dist-info}/WHEEL +0 -0
- {firefighter_incident-0.0.6.dist-info → firefighter_incident-0.0.8.dist-info}/entry_points.txt +0 -0
- {firefighter_incident-0.0.6.dist-info → firefighter_incident-0.0.8.dist-info}/licenses/LICENSE +0 -0
firefighter/_version.py
CHANGED
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
from typing import Any, NotRequired, Required, TypedDict
|
|
5
5
|
|
|
6
|
-
from django_components import
|
|
6
|
+
from django_components import component
|
|
7
7
|
|
|
8
8
|
from firefighter.incidents.models.user import User
|
|
9
9
|
|
|
@@ -25,7 +25,7 @@ class Kwargs(TypedDict, total=False):
|
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
@component.register("avatar")
|
|
28
|
-
class Avatar(component.Component[
|
|
28
|
+
class Avatar(component.Component[tuple[()], Kwargs, Data, Any]): # type: ignore[type-var]
|
|
29
29
|
template_name = "avatar/avatar.html"
|
|
30
30
|
|
|
31
31
|
def get_context_data(self, user: User, **kwargs: Any) -> Data:
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
from typing import Any, NotRequired, Required, TypedDict, Unpack
|
|
5
5
|
|
|
6
|
-
from django_components import
|
|
6
|
+
from django_components import component
|
|
7
7
|
|
|
8
8
|
logger = logging.getLogger(__name__)
|
|
9
9
|
|
|
@@ -14,7 +14,7 @@ class Data(TypedDict, total=False):
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
@component.register("card")
|
|
17
|
-
class Card(component.Component[
|
|
17
|
+
class Card(component.Component[tuple[()], Data, Data, Any]): # type: ignore[type-var]
|
|
18
18
|
template_name = "card/card.html"
|
|
19
19
|
|
|
20
20
|
def get_context_data(self, *args: Any, **kwargs: Unpack[Data]) -> Data:
|
|
@@ -4,7 +4,7 @@ from collections.abc import Mapping, Sequence
|
|
|
4
4
|
from typing import Any, NotRequired, Required, TypedDict
|
|
5
5
|
|
|
6
6
|
from django.urls import reverse
|
|
7
|
-
from django_components import
|
|
7
|
+
from django_components import component
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class _Format(TypedDict):
|
|
@@ -27,7 +27,7 @@ class Kwargs(TypedDict, total=False):
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
@component.register("export_button")
|
|
30
|
-
class ExportButton(component.Component[
|
|
30
|
+
class ExportButton(component.Component[tuple[()], Kwargs, Data, Any]): # type: ignore[type-var]
|
|
31
31
|
template_name = "export_button/export_button.html"
|
|
32
32
|
|
|
33
33
|
def get_context_data(
|
|
@@ -4,7 +4,7 @@ import logging
|
|
|
4
4
|
from typing import Any, NotRequired, TypedDict
|
|
5
5
|
|
|
6
6
|
from django import forms
|
|
7
|
-
from django_components import
|
|
7
|
+
from django_components import component
|
|
8
8
|
from django_components.slots import SlotContent
|
|
9
9
|
|
|
10
10
|
logger = logging.getLogger(__name__)
|
|
@@ -19,7 +19,7 @@ class Data(TypedDict):
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
@component.register("form")
|
|
22
|
-
class Form(component.Component[
|
|
22
|
+
class Form(component.Component[tuple[()], Data, Data, Slots]): # type: ignore[type-var] # type: ignore[override]
|
|
23
23
|
template_name = "form/form.html"
|
|
24
24
|
|
|
25
25
|
def get_context_data(self, form: forms.Form, **kwargs: Any) -> Data: # type: ignore[override]
|
|
@@ -8,7 +8,7 @@ from typing import (
|
|
|
8
8
|
)
|
|
9
9
|
|
|
10
10
|
from django import forms
|
|
11
|
-
from django_components import
|
|
11
|
+
from django_components import component
|
|
12
12
|
|
|
13
13
|
logger = logging.getLogger(__name__)
|
|
14
14
|
|
|
@@ -23,7 +23,7 @@ class Kwargs(TypedDict, total=True):
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
@component.register("form_field")
|
|
26
|
-
class FormField(component.Component[
|
|
26
|
+
class FormField(component.Component[tuple[()], Kwargs, Data, Any]): # type: ignore[type-var]
|
|
27
27
|
template_name = "form_field/form_field.html"
|
|
28
28
|
|
|
29
29
|
def get_context_data(
|
|
@@ -4,7 +4,7 @@ import logging
|
|
|
4
4
|
from typing import Any, TypedDict
|
|
5
5
|
|
|
6
6
|
from django.contrib.messages.storage.base import BaseStorage
|
|
7
|
-
from django_components import
|
|
7
|
+
from django_components import component
|
|
8
8
|
|
|
9
9
|
logger = logging.getLogger(__name__)
|
|
10
10
|
|
|
@@ -14,7 +14,7 @@ class Data(TypedDict):
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
@component.register("messages")
|
|
17
|
-
class Messages(component.Component[
|
|
17
|
+
class Messages(component.Component[tuple[()], Data, Data, Any]): # type: ignore[type-var]
|
|
18
18
|
template_name = "messages/messages.html"
|
|
19
19
|
|
|
20
20
|
def get_context_data(self, messages: BaseStorage, **kwargs: Any) -> Data:
|
|
@@ -4,7 +4,7 @@ import logging
|
|
|
4
4
|
from typing import Any, NotRequired, Required, TypedDict, Unpack
|
|
5
5
|
|
|
6
6
|
from django.utils.safestring import SafeString
|
|
7
|
-
from django_components import
|
|
7
|
+
from django_components import component
|
|
8
8
|
from django_components.slots import SlotFunc
|
|
9
9
|
|
|
10
10
|
logger = logging.getLogger(__name__)
|
|
@@ -28,7 +28,7 @@ class Slots(TypedDict):
|
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
@component.register("modal")
|
|
31
|
-
class Modal(component.Component[
|
|
31
|
+
class Modal(component.Component[tuple[()], Kwargs, Data, Any]): # type: ignore[type-var]
|
|
32
32
|
template_name = "modal/modal.html"
|
|
33
33
|
|
|
34
34
|
def get_context_data(self, *args: Any, **kwargs: Unpack[Kwargs]) -> Data:
|
|
@@ -45,21 +45,21 @@ class SelectImpactForm(forms.Form):
|
|
|
45
45
|
label=impact_type.emoji + " " + impact_type.name,
|
|
46
46
|
queryset=impact_type.levels.all().order_by("-order"),
|
|
47
47
|
help_text=impact_type.help_text,
|
|
48
|
-
initial=impact_type.levels.get(value=LevelChoices.
|
|
48
|
+
initial=impact_type.levels.get(value=LevelChoices.NONE.value),
|
|
49
49
|
)
|
|
50
50
|
self.fields[field_name].label_from_instance = ( # type: ignore[attr-defined]
|
|
51
51
|
lambda obj: obj.emoji + " " + obj.name
|
|
52
52
|
)
|
|
53
53
|
|
|
54
54
|
def suggest_priority_from_impact(self) -> int:
|
|
55
|
-
"""Suggest a priority from 1 (highest) to
|
|
55
|
+
"""Suggest a priority from 1 (highest) to 5 (lowest) based on the impact choices."""
|
|
56
56
|
if self.is_valid():
|
|
57
57
|
impact: dict[str, ImpactLevel] = self.cleaned_data
|
|
58
58
|
|
|
59
59
|
impact_values = [impact_type.value for impact_type in impact.values()]
|
|
60
60
|
priorities = [level.priority for level in LevelChoices if level in impact_values]
|
|
61
|
-
return min(priorities) if priorities else LevelChoices.
|
|
62
|
-
return LevelChoices.
|
|
61
|
+
return min(priorities) if priorities else LevelChoices.NONE.priority
|
|
62
|
+
return LevelChoices.NONE.priority
|
|
63
63
|
|
|
64
64
|
@property
|
|
65
65
|
def business_impact_new(self) -> str | None:
|
firefighter/incidents/menus.py
CHANGED
|
@@ -53,6 +53,7 @@ def update_impact_levels(apps, schema_editor):
|
|
|
53
53
|
"MD": "▶️",
|
|
54
54
|
"LO": "🔽",
|
|
55
55
|
"LT": "⏬",
|
|
56
|
+
"NO": "",
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
updates = [
|
|
@@ -61,105 +62,105 @@ def update_impact_levels(apps, schema_editor):
|
|
|
61
62
|
"old_value": "HI",
|
|
62
63
|
"new_name": None,
|
|
63
64
|
"new_value": "HT",
|
|
64
|
-
"new_order":
|
|
65
|
+
"new_order": 5,
|
|
65
66
|
},
|
|
66
67
|
{
|
|
67
68
|
"old_name": "Some customers have issues",
|
|
68
69
|
"old_value": "MD",
|
|
69
70
|
"new_name": "Some customers with major issues",
|
|
70
71
|
"new_value": "HI",
|
|
71
|
-
"new_order":
|
|
72
|
+
"new_order": 4,
|
|
72
73
|
},
|
|
73
74
|
{
|
|
74
75
|
"old_name": "Few customers with minor issues",
|
|
75
76
|
"old_value": "LO",
|
|
76
77
|
"new_name": "Some customers with significant issues",
|
|
77
78
|
"new_value": "MD",
|
|
78
|
-
"new_order":
|
|
79
|
+
"new_order": 3,
|
|
79
80
|
},
|
|
80
81
|
{
|
|
81
82
|
"old_name": "No impact on customers",
|
|
82
83
|
"old_value": "N/A",
|
|
83
84
|
"new_name": None,
|
|
84
85
|
"new_value": "LT",
|
|
85
|
-
"new_order":
|
|
86
|
+
"new_order": 1,
|
|
86
87
|
},
|
|
87
88
|
{
|
|
88
89
|
"old_name": "Key services inaccessible for most",
|
|
89
90
|
"old_value": "HI",
|
|
90
91
|
"new_name": "Critical issues for many sellers",
|
|
91
92
|
"new_value": "HT",
|
|
92
|
-
"new_order":
|
|
93
|
+
"new_order": 5,
|
|
93
94
|
},
|
|
94
95
|
{
|
|
95
96
|
"old_name": "Some sellers have significant issues",
|
|
96
97
|
"old_value": "MD",
|
|
97
98
|
"new_name": "Some sellers with major issues",
|
|
98
99
|
"new_value": "HI",
|
|
99
|
-
"new_order":
|
|
100
|
+
"new_order": 4,
|
|
100
101
|
},
|
|
101
102
|
{
|
|
102
103
|
"old_name": "Few sellers with minor issues",
|
|
103
104
|
"old_value": "LO",
|
|
104
105
|
"new_name": "Some sellers with significant issues",
|
|
105
106
|
"new_value": "MD",
|
|
106
|
-
"new_order":
|
|
107
|
+
"new_order": 3,
|
|
107
108
|
},
|
|
108
109
|
{
|
|
109
110
|
"old_name": "No impact on sellers",
|
|
110
111
|
"old_value": "N/A",
|
|
111
112
|
"new_name": None,
|
|
112
113
|
"new_value": "LT",
|
|
113
|
-
"new_order":
|
|
114
|
+
"new_order": 1,
|
|
114
115
|
},
|
|
115
116
|
{
|
|
116
117
|
"old_name": "Significant issues for some employees",
|
|
117
118
|
"old_value": "MD",
|
|
118
119
|
"new_name": "Major issues for internal users",
|
|
119
120
|
"new_value": "LO",
|
|
120
|
-
"new_order":
|
|
121
|
+
"new_order": 2,
|
|
121
122
|
},
|
|
122
123
|
{
|
|
123
124
|
"old_name": "Critical internal tools down",
|
|
124
125
|
"old_value": "HI",
|
|
125
126
|
"new_name": "Critical issues for internal users",
|
|
126
127
|
"new_value": "MD",
|
|
127
|
-
"new_order":
|
|
128
|
+
"new_order": 3,
|
|
128
129
|
},
|
|
129
130
|
{
|
|
130
131
|
"old_name": "No impact on employees",
|
|
131
132
|
"old_value": "N/A",
|
|
132
133
|
"new_name": "Minor issues for internal users",
|
|
133
134
|
"new_value": "LT",
|
|
134
|
-
"new_order":
|
|
135
|
+
"new_order": 1,
|
|
135
136
|
},
|
|
136
137
|
{
|
|
137
138
|
"old_name": "Whole business or revenue at risk",
|
|
138
139
|
"old_value": "HI",
|
|
139
140
|
"new_name": "Critical business impact",
|
|
140
141
|
"new_value": "HT",
|
|
141
|
-
"new_order":
|
|
142
|
+
"new_order": 5,
|
|
142
143
|
},
|
|
143
144
|
{
|
|
144
145
|
"old_name": "Significant business or revenue loss",
|
|
145
146
|
"old_value": "MD",
|
|
146
147
|
"new_name": "Major business impact",
|
|
147
148
|
"new_value": "HI",
|
|
148
|
-
"new_order":
|
|
149
|
+
"new_order": 4,
|
|
149
150
|
},
|
|
150
151
|
{
|
|
151
152
|
"old_name": "Minor impact on business or revenue",
|
|
152
153
|
"old_value": "LO",
|
|
153
154
|
"new_name": "Significant business impact",
|
|
154
155
|
"new_value": "MD",
|
|
155
|
-
"new_order":
|
|
156
|
+
"new_order": 3,
|
|
156
157
|
},
|
|
157
158
|
{
|
|
158
159
|
"old_name": "No impact on business or revenue",
|
|
159
160
|
"old_value": "N/A",
|
|
160
161
|
"new_name": None,
|
|
161
162
|
"new_value": "LT",
|
|
162
|
-
"new_order":
|
|
163
|
+
"new_order": 1,
|
|
163
164
|
},
|
|
164
165
|
]
|
|
165
166
|
|
|
@@ -192,38 +193,69 @@ def add_impact_levels(apps, schema_editor):
|
|
|
192
193
|
|
|
193
194
|
"name": "Some customers with minor issues",
|
|
194
195
|
"value": LevelChoices.LOW.value,
|
|
195
|
-
"order":
|
|
196
|
+
"order": 2,
|
|
196
197
|
"impact_type_id": 3,
|
|
197
198
|
"emoji": LevelChoices.LOW.emoji
|
|
198
199
|
},
|
|
199
200
|
{
|
|
200
201
|
"name": "Some sellers with minor issues",
|
|
201
202
|
"value": LevelChoices.LOW.value,
|
|
202
|
-
"order":
|
|
203
|
+
"order": 2,
|
|
203
204
|
"impact_type_id": 2,
|
|
204
205
|
"emoji": LevelChoices.LOW.emoji
|
|
205
206
|
},
|
|
206
207
|
{
|
|
207
208
|
"name": "Minor business impact",
|
|
208
209
|
"value": LevelChoices.LOW.value,
|
|
209
|
-
"order":
|
|
210
|
+
"order": 2,
|
|
210
211
|
"impact_type_id": 1,
|
|
211
212
|
"emoji": LevelChoices.LOW.emoji
|
|
212
213
|
},
|
|
214
|
+
{
|
|
215
|
+
|
|
216
|
+
"name": "N/A",
|
|
217
|
+
"value": LevelChoices.NONE.value,
|
|
218
|
+
"order": 0,
|
|
219
|
+
"impact_type_id": 1,
|
|
220
|
+
"emoji": LevelChoices.NONE.emoji
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
|
|
224
|
+
"name": "N/A",
|
|
225
|
+
"value": LevelChoices.NONE.value,
|
|
226
|
+
"order": 0,
|
|
227
|
+
"impact_type_id": 2,
|
|
228
|
+
"emoji": LevelChoices.NONE.emoji
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
|
|
232
|
+
"name": "N/A",
|
|
233
|
+
"value": LevelChoices.NONE.value,
|
|
234
|
+
"order": 0,
|
|
235
|
+
"impact_type_id": 3,
|
|
236
|
+
"emoji": LevelChoices.NONE.emoji
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
|
|
240
|
+
"name": "N/A",
|
|
241
|
+
"value": LevelChoices.NONE.value,
|
|
242
|
+
"order": 0,
|
|
243
|
+
"impact_type_id": 4,
|
|
244
|
+
"emoji": LevelChoices.NONE.emoji
|
|
245
|
+
},
|
|
213
246
|
]
|
|
214
247
|
|
|
215
248
|
for add in adds:
|
|
216
249
|
name = add["name"]
|
|
217
250
|
try:
|
|
218
|
-
impact_level = ImpactLevel.objects.filter(name=name).first()
|
|
219
|
-
|
|
220
251
|
impact_type_id = add["impact_type_id"]
|
|
252
|
+
impact_level = ImpactLevel.objects.filter(name=name, impact_type_id=impact_type_id).first()
|
|
221
253
|
impact_type = ImpactType.objects.filter(id=impact_type_id).first()
|
|
222
254
|
if not impact_type:
|
|
223
255
|
logger.error(f"There is no impact type id:'{impact_type_id}'.")
|
|
224
256
|
continue
|
|
225
257
|
if impact_level:
|
|
226
|
-
logger.error(f"There is already an impact level with name:'{name}'.")
|
|
258
|
+
logger.error(f"There is already an impact level with name:'{name}' and type:'{impact_type_id}'.")
|
|
227
259
|
continue
|
|
228
260
|
new_impact_level = ImpactLevel(
|
|
229
261
|
name=name,
|
|
@@ -249,7 +281,7 @@ class Migration(migrations.Migration):
|
|
|
249
281
|
migrations.AlterField(
|
|
250
282
|
model_name="impactlevel",
|
|
251
283
|
name="emoji",
|
|
252
|
-
field=models.CharField(default="
|
|
284
|
+
field=models.CharField(default="", max_length=5),
|
|
253
285
|
),
|
|
254
286
|
migrations.RemoveConstraint(
|
|
255
287
|
model_name="impactlevel",
|
|
@@ -30,13 +30,13 @@ class Migration(migrations.Migration):
|
|
|
30
30
|
("LT", "Lowest"),
|
|
31
31
|
("NO", "N/A"),
|
|
32
32
|
],
|
|
33
|
-
default="
|
|
33
|
+
default="NO",
|
|
34
34
|
max_length=2,
|
|
35
35
|
),
|
|
36
36
|
),
|
|
37
37
|
migrations.AlterField(
|
|
38
38
|
model_name="impacttype",
|
|
39
39
|
name="emoji",
|
|
40
|
-
field=models.CharField(default="
|
|
40
|
+
field=models.CharField(default="", max_length=5),
|
|
41
41
|
),
|
|
42
42
|
]
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Generated by Django 4.2.7 on 2023-12-04 11:09
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import logging
|
|
5
|
+
|
|
6
|
+
from django.db import migrations, models
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
# Mapping for updating ImpactLevel names based on value and impact_type
|
|
11
|
+
IMPACT_LEVEL_NAME_MAPPING = {
|
|
12
|
+
# Format: (value, impact_type): (new_name, description)
|
|
13
|
+
("LT", "business_impact"): (
|
|
14
|
+
"Business Lowest Not measurable",
|
|
15
|
+
"Lowest business impact, not measurable."
|
|
16
|
+
),
|
|
17
|
+
("LO", "business_impact"): (
|
|
18
|
+
"Business Lower Not measurable",
|
|
19
|
+
"Lower business impact, not measurable."
|
|
20
|
+
),
|
|
21
|
+
("MD", "business_impact"): (
|
|
22
|
+
"Uncertain Business Impact",
|
|
23
|
+
"Uncertain business value daily loss."
|
|
24
|
+
),
|
|
25
|
+
("HI", "business_impact"): (
|
|
26
|
+
"Major Business Impact (<5% BV daily loss)",
|
|
27
|
+
"Major business impact, less than 5% business value daily loss."
|
|
28
|
+
),
|
|
29
|
+
("HT", "business_impact"): (
|
|
30
|
+
"Critical Business Impact (>5% BV daily loss)",
|
|
31
|
+
"Critical business impact, more than 5% business value daily loss."
|
|
32
|
+
),
|
|
33
|
+
("NO", "business_impact"): (
|
|
34
|
+
"No impact on business.",
|
|
35
|
+
""
|
|
36
|
+
),
|
|
37
|
+
("LT", "customers_impact"): (
|
|
38
|
+
"Cosmetic issues for few customers",
|
|
39
|
+
"Minor functional affecting few users / cosmetic issues."
|
|
40
|
+
),
|
|
41
|
+
("LO", "customers_impact"): (
|
|
42
|
+
"Minor functional issues for many customers",
|
|
43
|
+
"Minor functional issues affecting many customers."
|
|
44
|
+
),
|
|
45
|
+
("MD", "customers_impact"): (
|
|
46
|
+
"Major functional issues for many customers",
|
|
47
|
+
"Many customer with major functional issues (no affecting BV)."
|
|
48
|
+
),
|
|
49
|
+
("HI", "customers_impact"): (
|
|
50
|
+
"Some customers have major issues",
|
|
51
|
+
"Purchase flow experience with major experience issues impacting <5% of customers.\nAccess to product not working affecting <5% of customers/errors\nMarketplace unstable <30% errors."
|
|
52
|
+
),
|
|
53
|
+
("HT", "customers_impact"): (
|
|
54
|
+
"Critical issue for many customers",
|
|
55
|
+
"Purchase flow experience with major experience issues impacting >5% of customers.\nAccess to product not working affecting >5% of customers/errors\nMarketplace unstable >30% errors."
|
|
56
|
+
),
|
|
57
|
+
("NO", "customers_impact"): (
|
|
58
|
+
"No impact for customers.",
|
|
59
|
+
""
|
|
60
|
+
),
|
|
61
|
+
("LT", "sellers_impact"): (
|
|
62
|
+
"Cosmetic issues for few sellers",
|
|
63
|
+
"Minor cosmetic issues affecting few sellers."
|
|
64
|
+
),
|
|
65
|
+
("LO", "sellers_impact"): (
|
|
66
|
+
"Minor functional issues for many sellers",
|
|
67
|
+
"Minor functional issues affecting many sellers."
|
|
68
|
+
),
|
|
69
|
+
("MD", "sellers_impact"): (
|
|
70
|
+
"Major functional issues for many sellers",
|
|
71
|
+
"Many sellers with major functional issues (no affecting fulfillment / catalog availability / order).\nIssues affecting commercial operations (e.g. wrong pricing on inventory / offers / etc) of big part of our inventory (e.g. big / important sellers)."
|
|
72
|
+
),
|
|
73
|
+
("HI", "sellers_impact"): (
|
|
74
|
+
"Some sellers have major issues",
|
|
75
|
+
"Toolbox access hindered affecting <20% of sellers.\nImpossibility of publishing / modifying catalogue affecting <20% of sellers."
|
|
76
|
+
),
|
|
77
|
+
("HT", "sellers_impact"): (
|
|
78
|
+
"Critical issue for many sellers",
|
|
79
|
+
"Toolbox access hindered affecting >20% of sellers.\nImpossibility of publishing / modifying catalogue affecting >20% of sellers."
|
|
80
|
+
),
|
|
81
|
+
("NO", "sellers_impact"): (
|
|
82
|
+
"No impact for sellers.",
|
|
83
|
+
""
|
|
84
|
+
),
|
|
85
|
+
("LT", "employees_impact"): (
|
|
86
|
+
"Degraded service for MM workers or partners but not blocked",
|
|
87
|
+
"Service is degraded for MM workers or partners, but they are not blocked."
|
|
88
|
+
),
|
|
89
|
+
("LO", "employees_impact"): (
|
|
90
|
+
"Few MM workers or partners affected systematically or blocked",
|
|
91
|
+
"A few MM workers or partners are systematically affected or blocked."
|
|
92
|
+
),
|
|
93
|
+
("MD", "employees_impact"): (
|
|
94
|
+
"Full departments blocked on their work.",
|
|
95
|
+
"Entire departments are blocked in their work."
|
|
96
|
+
),
|
|
97
|
+
("NO", "employees_impact"): (
|
|
98
|
+
"No impact for employee.",
|
|
99
|
+
""
|
|
100
|
+
),
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def update_impact_level_names(apps, _schema_editor):
|
|
105
|
+
ImpactLevel = apps.get_model("incidents", "ImpactLevel")
|
|
106
|
+
ImpactType = apps.get_model("incidents", "ImpactType")
|
|
107
|
+
for (value, impact_type_value), (new_name, description) in IMPACT_LEVEL_NAME_MAPPING.items():
|
|
108
|
+
try:
|
|
109
|
+
impact_type = ImpactType.objects.filter(value=impact_type_value).first()
|
|
110
|
+
if not impact_type:
|
|
111
|
+
logger.warning(f"ImpactType '{impact_type}' does not exist. Skipping update for value '{value}' and impact_type '{impact_type_value}'.")
|
|
112
|
+
continue
|
|
113
|
+
|
|
114
|
+
impact_level = ImpactLevel.objects.get(value=value, impact_type=impact_type.id)
|
|
115
|
+
impact_level.name = new_name
|
|
116
|
+
impact_level.description = description
|
|
117
|
+
impact_level.save()
|
|
118
|
+
logger.info(f"Updated ImpactLevel ({value}, {impact_type}) to name '{new_name}'")
|
|
119
|
+
except ImpactLevel.DoesNotExist:
|
|
120
|
+
logger.warning(f"ImpactLevel with value '{value}' and impact_type '{impact_type}' does not exist.")
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class Migration(migrations.Migration):
|
|
124
|
+
|
|
125
|
+
dependencies = [
|
|
126
|
+
("incidents", "0014_update_components_slack_groups"),
|
|
127
|
+
]
|
|
128
|
+
|
|
129
|
+
operations = [
|
|
130
|
+
migrations.AddField(
|
|
131
|
+
model_name="impactlevel",
|
|
132
|
+
name="description",
|
|
133
|
+
field=models.TextField(null=True, blank=True),
|
|
134
|
+
),
|
|
135
|
+
migrations.RunPython(update_impact_level_names),
|
|
136
|
+
]
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Generated by Django 4.2.7 on 2023-12-04 11:09
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import logging
|
|
5
|
+
|
|
6
|
+
from django.db import migrations
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def update_incidents(apps, _schema_editor):
|
|
12
|
+
ImpactLevel = apps.get_model("incidents", "ImpactLevel")
|
|
13
|
+
ImpactType = apps.get_model("incidents", "ImpactType")
|
|
14
|
+
Incident = apps.get_model("incidents", "Incident")
|
|
15
|
+
|
|
16
|
+
business_impact_type = ImpactType.objects.filter(value="business_impact").first()
|
|
17
|
+
if not business_impact_type:
|
|
18
|
+
logger.error("ImpactType 'business_impact' does not exist. Skipping incident update.")
|
|
19
|
+
return
|
|
20
|
+
|
|
21
|
+
md_impact_level = ImpactLevel.objects.filter(value="MD", impact_type=business_impact_type.id).first()
|
|
22
|
+
if not md_impact_level:
|
|
23
|
+
logger.error("ImpactLevel 'MD' for business_impact does not exist. Skipping incident update.")
|
|
24
|
+
return
|
|
25
|
+
|
|
26
|
+
for level_value in ["LT", "LO"]:
|
|
27
|
+
old_impact_level = ImpactLevel.objects.filter(value=level_value, impact_type=business_impact_type.id).first()
|
|
28
|
+
if not old_impact_level:
|
|
29
|
+
logger.error(f"ImpactLevel '{level_value}' for business_impact does not exist. Skipping.")
|
|
30
|
+
continue
|
|
31
|
+
|
|
32
|
+
# Find incidents that have the old impact level through the impacts relationship
|
|
33
|
+
incidents_with_old_level = Incident.objects.filter(impacts=old_impact_level.id)
|
|
34
|
+
updated_count = 0
|
|
35
|
+
|
|
36
|
+
for incident in incidents_with_old_level:
|
|
37
|
+
# Remove the old impact level and add the new one if not already present
|
|
38
|
+
incident.impacts.remove(old_impact_level)
|
|
39
|
+
if not incident.impacts.filter(id=md_impact_level.id).exists():
|
|
40
|
+
incident.impacts.add(md_impact_level)
|
|
41
|
+
updated_count += 1
|
|
42
|
+
|
|
43
|
+
logger.info(f"Updated {updated_count} incidents from impact_level '{level_value}' to 'MD' for business_impact.")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def remove_old_impact_levels(apps, _schema_editor):
|
|
47
|
+
ImpactLevel = apps.get_model("incidents", "ImpactLevel")
|
|
48
|
+
ImpactType = apps.get_model("incidents", "ImpactType")
|
|
49
|
+
Impact = apps.get_model("incidents", "Impact")
|
|
50
|
+
|
|
51
|
+
business_impact_type = ImpactType.objects.filter(value="business_impact").first()
|
|
52
|
+
if not business_impact_type:
|
|
53
|
+
logger.error("ImpactType 'business_impact' does not exist. Skipping impact level removal.")
|
|
54
|
+
return
|
|
55
|
+
|
|
56
|
+
md_impact_level = ImpactLevel.objects.filter(value="MD", impact_type=business_impact_type.id).first()
|
|
57
|
+
if not md_impact_level:
|
|
58
|
+
logger.error("ImpactLevel 'MD' for business_impact does not exist. Cannot update Impact objects.")
|
|
59
|
+
return
|
|
60
|
+
|
|
61
|
+
for level_value in ["LT", "LO"]:
|
|
62
|
+
impact_level = ImpactLevel.objects.filter(value=level_value, impact_type=business_impact_type.id).first()
|
|
63
|
+
if impact_level:
|
|
64
|
+
# Update all Impact objects that reference this impact level
|
|
65
|
+
impacts_to_update = Impact.objects.filter(impact_level=impact_level)
|
|
66
|
+
updated_count = impacts_to_update.update(impact_level=md_impact_level)
|
|
67
|
+
logger.info(f"Updated {updated_count} Impact objects from '{level_value}' to 'MD' for business_impact.")
|
|
68
|
+
|
|
69
|
+
# Now safe to delete the impact level
|
|
70
|
+
impact_level.delete()
|
|
71
|
+
logger.info(f"Removed ImpactLevel '{level_value}' for business_impact.")
|
|
72
|
+
else:
|
|
73
|
+
logger.error(f"ImpactLevel '{level_value}' for business_impact not found.")
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class Migration(migrations.Migration):
|
|
77
|
+
|
|
78
|
+
dependencies = [
|
|
79
|
+
("incidents", "0015_update_impact_level"),
|
|
80
|
+
]
|
|
81
|
+
operations = [
|
|
82
|
+
migrations.RunPython(update_incidents),
|
|
83
|
+
migrations.RunPython(remove_old_impact_levels),
|
|
84
|
+
]
|
|
@@ -50,12 +50,12 @@ class LevelChoices(models.TextChoices):
|
|
|
50
50
|
self.LOWEST: 5,
|
|
51
51
|
self.NONE: 6,
|
|
52
52
|
}
|
|
53
|
-
return priority_mapping.get(self,
|
|
53
|
+
return priority_mapping.get(self, 6) # type: ignore [call-overload]
|
|
54
54
|
|
|
55
55
|
@property
|
|
56
56
|
def emoji(self) -> str:
|
|
57
57
|
"""Send emoji un function of priority."""
|
|
58
|
-
none_emoji = "
|
|
58
|
+
none_emoji = ""
|
|
59
59
|
emoji_mapping = {
|
|
60
60
|
self.HIGHEST: "⏫",
|
|
61
61
|
self.HIGH: "🔼",
|
|
@@ -80,9 +80,13 @@ class ImpactLevel(models.Model):
|
|
|
80
80
|
default="",
|
|
81
81
|
help_text="Description for the impact level for this impact type.",
|
|
82
82
|
)
|
|
83
|
-
value = models.CharField(choices=LevelChoices.choices, max_length=2, default="
|
|
83
|
+
value = models.CharField(choices=LevelChoices.choices, max_length=2, default="NO")
|
|
84
84
|
order = models.PositiveSmallIntegerField(default=10)
|
|
85
|
-
|
|
85
|
+
description = models.TextField(
|
|
86
|
+
blank=True,
|
|
87
|
+
null=True,
|
|
88
|
+
help_text="Detailed multi-line description for this impact level.",
|
|
89
|
+
)
|
|
86
90
|
class Meta(TypedModelMeta):
|
|
87
91
|
constraints = [
|
|
88
92
|
models.UniqueConstraint(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{% extends '../layouts/view_filters.html' %}
|
|
2
2
|
|
|
3
3
|
{% block page_title %}
|
|
4
|
-
|
|
4
|
+
Issue category list <div role="status" class="hx-progress htmx-indicator inline">
|
|
5
5
|
<svg class="inline mr-2 w-6 h-6 text-gray-200 animate-spin dark:text-gray-600 fill-primary" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
6
6
|
<path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/>
|
|
7
7
|
<path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill"/>
|
|
@@ -153,7 +153,12 @@ class OpenModal(SlackModal):
|
|
|
153
153
|
def get_intro_blocks() -> list[Block]:
|
|
154
154
|
blocks: list[Block] = [
|
|
155
155
|
SectionBlock(
|
|
156
|
-
|
|
156
|
+
text=(
|
|
157
|
+
"Hello and thanks for reporting a new incident! :beetle:\n\n"
|
|
158
|
+
"Please report as much information as you can!\n\n"
|
|
159
|
+
"More information about the incident process in this "
|
|
160
|
+
"<https://manomano.atlassian.net/wiki/spaces/TC/pages/3928261283/IMPACT+-+Incident+Management+Platform|documentation>."
|
|
161
|
+
)
|
|
157
162
|
)
|
|
158
163
|
]
|
|
159
164
|
|
|
@@ -8,7 +8,9 @@ from typing import TYPE_CHECKING, Any, Never, cast
|
|
|
8
8
|
from django import forms
|
|
9
9
|
from django.conf import settings
|
|
10
10
|
from django.db.models import Model, QuerySet
|
|
11
|
+
from slack_sdk.models.blocks.basic_components import MarkdownTextObject
|
|
11
12
|
from slack_sdk.models.blocks.blocks import (
|
|
13
|
+
ContextBlock,
|
|
12
14
|
DividerBlock,
|
|
13
15
|
SectionBlock,
|
|
14
16
|
)
|
|
@@ -16,6 +18,7 @@ from slack_sdk.models.views import View
|
|
|
16
18
|
|
|
17
19
|
from firefighter.firefighter.utils import get_in
|
|
18
20
|
from firefighter.incidents.forms.select_impact import SelectImpactForm
|
|
21
|
+
from firefighter.incidents.models.impact import ImpactType
|
|
19
22
|
from firefighter.incidents.models.priority import Priority
|
|
20
23
|
from firefighter.slack.slack_app import SlackApp
|
|
21
24
|
from firefighter.slack.views.modals import modal_open
|
|
@@ -85,13 +88,14 @@ class SelectImpactModal(
|
|
|
85
88
|
initial_form_values_impact[field_name] = None # type: ignore
|
|
86
89
|
blocks = [
|
|
87
90
|
SectionBlock(
|
|
88
|
-
text=f"{SLACK_APP_EMOJI} Define the
|
|
91
|
+
text=f"{SLACK_APP_EMOJI} Define the impact(s) to find the incident priority (<https://manomano.atlassian.net/wiki/spaces/TC/pages/4024500413/Priority+levels|documentation>):"
|
|
89
92
|
),
|
|
90
93
|
*self.get_form_class()(initial=initial_form_values_impact).slack_blocks(
|
|
91
94
|
"section_accessory"
|
|
92
95
|
),
|
|
93
96
|
]
|
|
94
97
|
priority_data = open_incident_context.get("priority")
|
|
98
|
+
|
|
95
99
|
if open_incident_context and priority_data:
|
|
96
100
|
if not isinstance(priority_data, Priority):
|
|
97
101
|
priority = Priority.objects.get(pk=priority_data)
|
|
@@ -101,11 +105,24 @@ class SelectImpactModal(
|
|
|
101
105
|
err_msg = f"Invalid priority data: {priority_data}" # type: ignore[unreachable]
|
|
102
106
|
raise TypeError(err_msg)
|
|
103
107
|
process = ":slack: Slack :jira_new: Jira ticket" if open_incident_context.get("response_type") == "critical" else ":jira_new: Jira ticket"
|
|
108
|
+
|
|
109
|
+
impact_descriptions = self.extract_descriptions(open_incident_context)
|
|
110
|
+
|
|
104
111
|
blocks.extend((
|
|
105
112
|
DividerBlock(),
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
113
|
+
ContextBlock(
|
|
114
|
+
elements=[
|
|
115
|
+
MarkdownTextObject(
|
|
116
|
+
text=(
|
|
117
|
+
f":dart: Selected priority: *{priority} - {priority.description}*\n"
|
|
118
|
+
f"⏱️ SLA: {priority.sla}\n"
|
|
119
|
+
f":gear: Process: {process}\n"
|
|
120
|
+
f":pushpin: Selected impacts:\n"
|
|
121
|
+
f"{impact_descriptions}\n"
|
|
122
|
+
)
|
|
123
|
+
)
|
|
124
|
+
]
|
|
125
|
+
)
|
|
109
126
|
))
|
|
110
127
|
|
|
111
128
|
return View(
|
|
@@ -117,6 +134,20 @@ class SelectImpactModal(
|
|
|
117
134
|
submit="Save impacts",
|
|
118
135
|
)
|
|
119
136
|
|
|
137
|
+
def extract_descriptions(self, open_incident_context: OpeningData) -> str:
|
|
138
|
+
impact_form_data = open_incident_context.get("impact_form_data", {})
|
|
139
|
+
impact_descriptions = ""
|
|
140
|
+
if impact_form_data:
|
|
141
|
+
for value in impact_form_data.values():
|
|
142
|
+
if value.name != "NO" and value.description:
|
|
143
|
+
if hasattr(value, "impact_type_id") and value.impact_type_id:
|
|
144
|
+
impact_type = ImpactType.objects.get(pk=value.impact_type_id)
|
|
145
|
+
if impact_type:
|
|
146
|
+
impact_descriptions += f"\u00A0\u00A0 :exclamation: {impact_type} - {value}\n"
|
|
147
|
+
for line in str(value.description).splitlines():
|
|
148
|
+
impact_descriptions += f"\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0 • {line}\n"
|
|
149
|
+
return impact_descriptions
|
|
150
|
+
|
|
120
151
|
def handle_modal_fn( # type: ignore
|
|
121
152
|
self,
|
|
122
153
|
ack: Ack,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: firefighter-incident
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.8
|
|
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=
|
|
9
|
+
firefighter/_version.py,sha256=SbamvXnLxfCU9pL5KMng4JCEwFYPcZcxEC7yaD9HbZ4,511
|
|
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
|
|
@@ -32,25 +32,25 @@ firefighter/api/views/severities.py,sha256=mdkR4GjZibydC1Dx-Sglm-f35GZxWbjmqStAx
|
|
|
32
32
|
firefighter/components/__init__.py,sha256=Vd_Uk5Uq7Mqp6NOFp5QiniWZAyzmYLqNSFEEw1x7COk,167
|
|
33
33
|
firefighter/components/avatar/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
34
34
|
firefighter/components/avatar/avatar.html,sha256=oleFPTy1qs9X6hZx3iWppBteHummFvSxoNzPOOl5aeA,773
|
|
35
|
-
firefighter/components/avatar/avatar.py,sha256=
|
|
35
|
+
firefighter/components/avatar/avatar.py,sha256=lNRZ7Z-LvqAJ6V9gljsBPNjB_oW1XMVgSGUgmpyP110,879
|
|
36
36
|
firefighter/components/card/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
37
37
|
firefighter/components/card/card.html,sha256=ziahql8X7WiQdprMktzy7sx0gVXNIxqtAsh_Rc5Iy0g,725
|
|
38
|
-
firefighter/components/card/card.py,sha256=
|
|
38
|
+
firefighter/components/card/card.py,sha256=VwPNNkSOmRbwoDEGKKXOo78xpOBc9USV05eOMNbieCM,541
|
|
39
39
|
firefighter/components/export_button/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
40
40
|
firefighter/components/export_button/export_button.html,sha256=XTA9FbDxho8aIqnfTcsDUm7swGWfn2JSw5WndDaThYY,1989
|
|
41
|
-
firefighter/components/export_button/export_button.py,sha256=
|
|
41
|
+
firefighter/components/export_button/export_button.py,sha256=prc-f9Jx8okciSaEZvC_WDfEJDGSw632EcgsvZuBPUU,1759
|
|
42
42
|
firefighter/components/form/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
43
43
|
firefighter/components/form/form.html,sha256=LtW07AxFsR-MI-iGVq0CsUVsUN3af5rS2R4SbAlfI5s,312
|
|
44
|
-
firefighter/components/form/form.py,sha256=
|
|
44
|
+
firefighter/components/form/form.py,sha256=OrvsiOtwfD1DtFk0Cx_I9cMv542vzMAJGZ1S2szMpNM,695
|
|
45
45
|
firefighter/components/form_field/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
46
46
|
firefighter/components/form_field/form_field.html,sha256=k5yyxvETqJSt5jHb8Z2v5o9oJRDLwWBKhISy0j0184Y,450
|
|
47
|
-
firefighter/components/form_field/form_field.py,sha256=
|
|
47
|
+
firefighter/components/form_field/form_field.py,sha256=_mGNF5B820Obhp-7aDDQsnvGDJp7s2jwIRudAhYsC4Y,799
|
|
48
48
|
firefighter/components/messages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
49
49
|
firefighter/components/messages/messages.html,sha256=P0V6Wsz7lTZL0xNPu_5w-J6Dc_aPkP0wqbHjMJ1D4qs,3157
|
|
50
|
-
firefighter/components/messages/messages.py,sha256=
|
|
50
|
+
firefighter/components/messages/messages.py,sha256=9Ra04QApmstH-oLlBiIF8OBJQBwy7kO0iN5-LUfNJZA,564
|
|
51
51
|
firefighter/components/modal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
52
52
|
firefighter/components/modal/modal.html,sha256=PrOtS8eJHvzTHqILlXmjE4KsGVdbubSCexHiPa_I3Yk,2391
|
|
53
|
-
firefighter/components/modal/modal.py,sha256=
|
|
53
|
+
firefighter/components/modal/modal.py,sha256=OCbQojZ5fhivCUUy1rwzDBOrb1jLhbK8faRFKEgPzCI,925
|
|
54
54
|
firefighter/confluence/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
55
55
|
firefighter/confluence/admin.py,sha256=aDXghuuLc7G_TLt-655M31smx-H6vkIgLtEmmNCA3lg,1490
|
|
56
56
|
firefighter/confluence/apps.py,sha256=vKswBwQL7L9e2JQwvRb7xy3myyE_GRldYX78jSY3XCM,406
|
|
@@ -132,7 +132,7 @@ firefighter/incidents/admin.py,sha256=ycKw5kYL55W1n12t39Mkgx9rqfi_iawXw0waQznByf
|
|
|
132
132
|
firefighter/incidents/apps.py,sha256=GySoDZsz-BH-nsIZWTOd0H1hgL9s9il1BEuLC4gKTXs,378
|
|
133
133
|
firefighter/incidents/enums.py,sha256=qRVpRvcCXEZ8xF6FTXmAtZjDxCj06hLDgEZlak6ket4,937
|
|
134
134
|
firefighter/incidents/factories.py,sha256=lfR6qqqBJc5nEMHmTg9D6837VZnDSx4y68lzcciYg6w,3364
|
|
135
|
-
firefighter/incidents/menus.py,sha256=
|
|
135
|
+
firefighter/incidents/menus.py,sha256=rttZBReRACqOMZFng2svvk3gU1Ld84PQCNbBo9AIecE,4129
|
|
136
136
|
firefighter/incidents/signals.py,sha256=hUlPVVKSi9zuL4gz_Sa-HrDleYCASeMqKqA-kkHCaDQ,2128
|
|
137
137
|
firefighter/incidents/tables.py,sha256=SH-ScSw7SkwbdiAIApHn1eYfOuj7CRy__jY9gDadenk,3324
|
|
138
138
|
firefighter/incidents/urls.py,sha256=4QJAIjmyE90_j8HLNExa4UpjM2CgasBOlx_r07ucjiM,2059
|
|
@@ -140,7 +140,7 @@ firefighter/incidents/forms/__init__.py,sha256=OU0r5eZc2A0UJNsL83n8AI5EvwUvg4Yx0
|
|
|
140
140
|
firefighter/incidents/forms/close_incident.py,sha256=syT5Lpr_WXNFT3KGCe1oy-FzOqMt98S7YEzovdnp7To,940
|
|
141
141
|
firefighter/incidents/forms/create_incident.py,sha256=Wpp0qqUJQs5-5BXrS-P5-dGvM5zgr9XqaEEl6tpNZi4,2739
|
|
142
142
|
firefighter/incidents/forms/edit.py,sha256=2rQkiKak-vac-K3cIsqlGv4R5nhI7JLxw3DhFMXbWms,956
|
|
143
|
-
firefighter/incidents/forms/select_impact.py,sha256=
|
|
143
|
+
firefighter/incidents/forms/select_impact.py,sha256=0cnV2DFHuO1In6CgRATjg0zNLd9YN_LbQnPL7Fm9pAU,4631
|
|
144
144
|
firefighter/incidents/forms/update_key_events.py,sha256=1Xmnxe5OgZqLFS2HmMzQm3VGFPQipsdrLgKSwdh-fKc,4441
|
|
145
145
|
firefighter/incidents/forms/update_roles.py,sha256=Q26UPfwAj-8N23RNZLQkvmHGnS1_j_X5KQWjJmPjMKY,3635
|
|
146
146
|
firefighter/incidents/forms/update_status.py,sha256=QCRKfDhSYZhVsJ6oofQxOXGMWMDRQEDnH29y8YnFn_Y,1034
|
|
@@ -152,19 +152,21 @@ firefighter/incidents/migrations/0004_incidentupdate_environment.py,sha256=BoIua
|
|
|
152
152
|
firefighter/incidents/migrations/0005_enable_from_p1_to_p5_priority.py,sha256=sBr3nMOf7qnAg1qHjfPOY79fP08yuvgbUaFkOFIBAiU,863
|
|
153
153
|
firefighter/incidents/migrations/0006_update_group_names.py,sha256=RHWre_VrnBmloFaqfoKA3TQtF8J2k5w1vzTEfGW81SQ,3172
|
|
154
154
|
firefighter/incidents/migrations/0007_update_component_name.py,sha256=Al9k5Xx2_ea4u20MIp2blTErdv7jkGDYCLhGJ3P-gdw,6555
|
|
155
|
-
firefighter/incidents/migrations/0008_impact_level.py,sha256=
|
|
155
|
+
firefighter/incidents/migrations/0008_impact_level.py,sha256=tjSzEMTa1hDB4JFola1Z_Zs-zWV6kzcWmIK8OaU_v7Q,9702
|
|
156
156
|
firefighter/incidents/migrations/0009_update_sla.py,sha256=cLbDmOKrcQOa6lb1kMd-xPJC1w7iDJuEsDTKymEnUMw,849
|
|
157
157
|
firefighter/incidents/migrations/0010_update_components.py,sha256=IwAj3axIXM95DrQcAZ8NBe-3GgL4NPrZqyBMdVqA8Lo,4301
|
|
158
158
|
firefighter/incidents/migrations/0011_update_incidents.py,sha256=tV4MA5ZJcqiRPteOLxJNZuhj7q6ncWXjAklm_9IzLbo,3190
|
|
159
|
-
firefighter/incidents/migrations/0012_alter_impactlevel.py,sha256=
|
|
159
|
+
firefighter/incidents/migrations/0012_alter_impactlevel.py,sha256=krszrYoJ_vkYW5RdrgnT-vIIoCa4HC0SPGUtvZ4lMzs,1136
|
|
160
160
|
firefighter/incidents/migrations/0013_add_missing_component.py,sha256=qVLQEl-riFwYNCbhXM-9-GNCHE-bk9QhbVMKqqOL0Ag,1962
|
|
161
161
|
firefighter/incidents/migrations/0014_update_components_slack_groups.py,sha256=5tiQnrtOpYVUztFdvZ6xTUReuJfpDX0cOvqIvDZpBv0,8700
|
|
162
|
+
firefighter/incidents/migrations/0015_update_impact_level.py,sha256=OQVTVrWvQ1orxqdrqwrhBMjxKY5qzqN2ZRobHc_tGDc,5451
|
|
163
|
+
firefighter/incidents/migrations/0016_update_business_incidents_and_level.py,sha256=O5AL9twmjstSw44ndJ2-Og6dpKreReXVw_brpQb-t0w,3600
|
|
162
164
|
firefighter/incidents/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
163
165
|
firefighter/incidents/models/__init__.py,sha256=dCNP-zRYNNDOZB3JDDWp7vCl084Jh6RgDT_iP57RkOY,862
|
|
164
166
|
firefighter/incidents/models/component.py,sha256=7GyXKNFk1MZns6RUGLpkNw5u6He7H9N1LexzXbG4sBM,7445
|
|
165
167
|
firefighter/incidents/models/environment.py,sha256=51txwua3dCrWZ1iSG3ZA8rbDn9c00pyMAZujl9gwE5c,827
|
|
166
168
|
firefighter/incidents/models/group.py,sha256=MscG3IY5AdyJbmq8h4mMqEvLwmnJLor9rkd6CIycKho,685
|
|
167
|
-
firefighter/incidents/models/impact.py,sha256=
|
|
169
|
+
firefighter/incidents/models/impact.py,sha256=URoMsQBJQnyfaNRpVl1o4A1IllM7dg94sd6tf5Ssr-k,4868
|
|
168
170
|
firefighter/incidents/models/incident.py,sha256=aQUAboXmHH9DO1Nq6AbB4w17dPQqn5iMTwT2r4TeJrA,26129
|
|
169
171
|
firefighter/incidents/models/incident_cost.py,sha256=juwOfJKRaNQpOHkRUCHShDDba0FU98YjRPkU4I0ofAU,1346
|
|
170
172
|
firefighter/incidents/models/incident_cost_type.py,sha256=wm8diry_VySJzIjC9M3Yavv2tYbvJgpN9UDb2gFRuH4,845
|
|
@@ -225,7 +227,7 @@ firefighter/incidents/templates/layouts/partials/table.html,sha256=eZE4kh0nQwGik
|
|
|
225
227
|
firefighter/incidents/templates/layouts/partials/user_card.html,sha256=LgYHSpqC0BAhVENMSmLpow8jlPnh5uRvHzooJlJna6w,802
|
|
226
228
|
firefighter/incidents/templates/layouts/partials/user_tooltip.html,sha256=KkVPpoODXIzrm6iItTg5RQphBGruQw4dFdOgAuGRt1E,562
|
|
227
229
|
firefighter/incidents/templates/pages/component_detail.html,sha256=WLO9zg8zDCUtINOHK9xP5dKd5WaB8UWT6JNjLjYSQKs,5277
|
|
228
|
-
firefighter/incidents/templates/pages/component_list.html,sha256=
|
|
230
|
+
firefighter/incidents/templates/pages/component_list.html,sha256=WbkLGozNbijTk_5iklOS5Hftlc-JHBpkSVL2s1FgUgk,1719
|
|
229
231
|
firefighter/incidents/templates/pages/dashboard.html,sha256=jGfTCTdyLt3fWtX66HVG1bNgpffV4J7jagVgksCGsSE,1743
|
|
230
232
|
firefighter/incidents/templates/pages/docs_metrics.html,sha256=q10CCPwjujuj9_h7Mj4-NgP6BMt4TJ6Z3D20W9qZbaQ,3744
|
|
231
233
|
firefighter/incidents/templates/pages/incident_create.html,sha256=syDS8EqmdcCf6z2dJox5gSPTOsyNdq0jFiDdzVc_vmU,2280
|
|
@@ -381,7 +383,7 @@ firefighter/slack/views/modals/close.py,sha256=ur1SSRWk9NYFfL24gjOqoIiXKquDy6qeE
|
|
|
381
383
|
firefighter/slack/views/modals/downgrade_workflow.py,sha256=S0y0_GYH4q7ewZUr_eA9Ly2c1FQueZzNCTiuIiWYUoY,3109
|
|
382
384
|
firefighter/slack/views/modals/edit.py,sha256=60xav4XG4KGS9KknqsQNCQjl3qQzk7OtmHiEYTQ9pUk,3861
|
|
383
385
|
firefighter/slack/views/modals/key_event_message.py,sha256=ga3-ITZyzJExwzctX-GfgnDqyQaxTfcqpqnOwY2E38M,5620
|
|
384
|
-
firefighter/slack/views/modals/open.py,sha256=
|
|
386
|
+
firefighter/slack/views/modals/open.py,sha256=mAjOkvejCciUP7-QQmVfPKmljuEowNdGybAhwyKlfUI,21548
|
|
385
387
|
firefighter/slack/views/modals/postmortem.py,sha256=AeEtmiam_XgCRxDmltKluNT2VN1gcuCB2VbYeeATVcA,2525
|
|
386
388
|
firefighter/slack/views/modals/select.py,sha256=Y-Ji_ALnzhYkXDBAyi497UL1Xn2vCGqXCtj8eog75Jk,3312
|
|
387
389
|
firefighter/slack/views/modals/send_sos.py,sha256=bP6HgYyDwPrIcTq7n_sQz6UQsxhYbvBDS4HjM0uRccA,4838
|
|
@@ -398,7 +400,7 @@ firefighter/slack/views/modals/base_modal/mixins.py,sha256=c7WYs0aXKXVktEMNSZ8IU
|
|
|
398
400
|
firefighter/slack/views/modals/base_modal/modal_utils.py,sha256=1uHTlLxxeXUQttH3bHaehJwCuI6a-h04s-GzdnVA4sI,2459
|
|
399
401
|
firefighter/slack/views/modals/opening/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
400
402
|
firefighter/slack/views/modals/opening/check_current_incidents.py,sha256=28GN0SXP7rVPa55arX1aI98k45w9568GCRDA73eCHEM,2535
|
|
401
|
-
firefighter/slack/views/modals/opening/select_impact.py,sha256=
|
|
403
|
+
firefighter/slack/views/modals/opening/select_impact.py,sha256=qTggWabR6lgs4OZa7wYEmFlQTbgUka1052n01NNLcsc,9754
|
|
402
404
|
firefighter/slack/views/modals/opening/set_details.py,sha256=i6zQM2FYz3Z6s5AZH7lXgB2e8yjS0rDwgfMBZaiOqIw,5791
|
|
403
405
|
firefighter/slack/views/modals/opening/types.py,sha256=ETpp0DAz5OMI5h7iv62Of7yJCbI-Q4-3kKSS6msPQeY,563
|
|
404
406
|
firefighter/slack/views/modals/opening/details/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -423,7 +425,7 @@ firefighter_tests/test_firefighter/test_firefighter_utils.py,sha256=og79bkErCBQB
|
|
|
423
425
|
firefighter_tests/test_firefighter/test_logging.py,sha256=4HUH73vLDwmOCpMiXwDasMLL7F0kA1B_DxE48mqswSk,878
|
|
424
426
|
firefighter_tests/test_firefighter/test_urls.py,sha256=UMGx4oW98RoL0ceePkIIKEVjbHdFECvQuGNXYAJForQ,4839
|
|
425
427
|
firefighter_tests/test_incidents/test_incident_urls.py,sha256=vQy9f1ewJK3N9cjVQDBnLaZjhtiBv5TzoRiGUdV3u5E,3769
|
|
426
|
-
firefighter_tests/test_incidents/test_forms/test_form_select_impact.py,sha256=
|
|
428
|
+
firefighter_tests/test_incidents/test_forms/test_form_select_impact.py,sha256=DTaPGrJi8mXHfh7mhvDTKYVvDCxqarILauE59UDlwqo,3210
|
|
427
429
|
firefighter_tests/test_incidents/test_forms/test_form_utils.py,sha256=24ATxxAjkLlz7cj_jIQZvuQvtrfieeh4oaIM90yQrlc,2299
|
|
428
430
|
firefighter_tests/test_incidents/test_forms/test_update_key_events.py,sha256=rHRGRU9iFXDdMr_kK3pMB7gyeZuMf7Dyq8bRZkddBC4,1644
|
|
429
431
|
firefighter_tests/test_incidents/test_models/test_incident_model.py,sha256=Kl2dQ0P3qruAaQP5M8WRYJiff-4SpmxpFYHYmA9Xv3k,879
|
|
@@ -444,8 +446,8 @@ firefighter_tests/test_slack/views/modals/test_open.py,sha256=Iatphd7vnrEMrv8ysK
|
|
|
444
446
|
firefighter_tests/test_slack/views/modals/test_send_sos.py,sha256=_rE6jD-gOzcGyhlY0R9GzlGtPx65oOOguJYdENgxtLc,1289
|
|
445
447
|
firefighter_tests/test_slack/views/modals/test_status.py,sha256=oQzPfwdg2tkbo9nfkO1GfS3WydxqSC6vy1AZjZDKT30,2226
|
|
446
448
|
firefighter_tests/test_slack/views/modals/test_update_status.py,sha256=Y8Oa_fraj1vtaGig9Y28_6tOWvMrRPS-wyg3rY-DHBk,39380
|
|
447
|
-
firefighter_incident-0.0.
|
|
448
|
-
firefighter_incident-0.0.
|
|
449
|
-
firefighter_incident-0.0.
|
|
450
|
-
firefighter_incident-0.0.
|
|
451
|
-
firefighter_incident-0.0.
|
|
449
|
+
firefighter_incident-0.0.8.dist-info/METADATA,sha256=PPkrT4PwwSus6I-j9FTlg0w8wiP9fpti41s3BpS7LJM,5487
|
|
450
|
+
firefighter_incident-0.0.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
451
|
+
firefighter_incident-0.0.8.dist-info/entry_points.txt,sha256=c13meJbv7YNmYz7MipMOQwzQ5IeFOPXUBYAJ44XMQsM,61
|
|
452
|
+
firefighter_incident-0.0.8.dist-info/licenses/LICENSE,sha256=krRiGp-a9-1nH1bWpBEdxyTKLhjLmn6DMVVoIb0zF90,1087
|
|
453
|
+
firefighter_incident-0.0.8.dist-info/RECORD,,
|
|
@@ -74,7 +74,7 @@ def test_suggest_priority_from_impact(form_data, expected_priority):
|
|
|
74
74
|
"set_impact_type_customers_impact": "LT",
|
|
75
75
|
"set_impact_type_employees_impact": "LT",
|
|
76
76
|
},
|
|
77
|
-
|
|
77
|
+
6,
|
|
78
78
|
),
|
|
79
79
|
(
|
|
80
80
|
{
|
|
@@ -83,7 +83,7 @@ def test_suggest_priority_from_impact(form_data, expected_priority):
|
|
|
83
83
|
"set_impact_type_customers_impact": "MD",
|
|
84
84
|
"set_impact_type_employees_impact": "LT",
|
|
85
85
|
},
|
|
86
|
-
|
|
86
|
+
6,
|
|
87
87
|
),
|
|
88
88
|
(
|
|
89
89
|
{
|
|
@@ -92,7 +92,7 @@ def test_suggest_priority_from_impact(form_data, expected_priority):
|
|
|
92
92
|
"set_impact_type_customers_impact": "INVALID",
|
|
93
93
|
"set_impact_type_employees_impact": "LT",
|
|
94
94
|
},
|
|
95
|
-
|
|
95
|
+
6,
|
|
96
96
|
),
|
|
97
97
|
],
|
|
98
98
|
)
|
|
File without changes
|
{firefighter_incident-0.0.6.dist-info → firefighter_incident-0.0.8.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{firefighter_incident-0.0.6.dist-info → firefighter_incident-0.0.8.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|