mirror of
https://github.com/jlengrand/bugsink.git
synced 2026-03-10 08:01:17 +00:00
@@ -353,6 +353,10 @@ class IssueStateManager(object):
|
||||
kind=TurningPointKind.UNMUTED, metadata=json.dumps(unmute_metadata))
|
||||
triggering_event.never_evict = True # .save() will be called by the caller of this function
|
||||
|
||||
@staticmethod
|
||||
def delete(issue):
|
||||
issue.delete_deferred()
|
||||
|
||||
@staticmethod
|
||||
def get_unmute_thresholds(issue):
|
||||
unmute_vbcs = [
|
||||
@@ -471,6 +475,11 @@ class IssueQuerysetStateManager(object):
|
||||
for issue in issue_qs:
|
||||
IssueStateManager.unmute(issue, triggering_event)
|
||||
|
||||
@staticmethod
|
||||
def delete(issue_qs):
|
||||
for issue in issue_qs:
|
||||
issue.delete_deferred()
|
||||
|
||||
|
||||
class TurningPointKind(models.IntegerChoices):
|
||||
# The language of the kinds reflects a historic view of the system, e.g. "first seen" as opposed to "new issue"; an
|
||||
|
||||
@@ -7,6 +7,23 @@
|
||||
|
||||
{% block content %}
|
||||
|
||||
<!-- Delete Confirmation Modal -->
|
||||
<div id="deleteModal" class="hidden fixed inset-0 bg-slate-600 bg-opacity-50 overflow-y-auto h-full w-full z-50 flex items-center justify-center">
|
||||
<div class="relative p-6 border border-slate-300 w-96 shadow-lg rounded-md bg-white">
|
||||
<div class="text-center m-4">
|
||||
<h3 class="text-2xl font-semibold text-slate-800 mt-3 mb-4">Delete Issues</h3>
|
||||
<div class="mt-4 mb-6">
|
||||
<p class="text-slate-700">
|
||||
Deleting an Issue is a permanent action and cannot be undone. It's typically better to resolve or mute an issue instead of deleting it, as this allows you to keep track of past issues and their resolutions.
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex items-center justify-center space-x-4 mb-4">
|
||||
<button id="cancelDelete" class="text-cyan-500 font-bold">Cancel</button>
|
||||
<button id="confirmDelete" type="submit" class="font-bold py-2 px-4 rounded bg-red-500 text-white border-2 border-red-600 hover:bg-red-600 active:ring">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="m-4">
|
||||
@@ -35,7 +52,7 @@
|
||||
|
||||
<div>
|
||||
|
||||
<form action="." method="post">
|
||||
<form action="." method="post" id="issueForm">
|
||||
{% csrf_token %}
|
||||
|
||||
<table class="w-full">
|
||||
@@ -122,8 +139,18 @@
|
||||
<button disabled class="font-bold text-slate-300 border-slate-300 pl-4 pr-4 pb-2 pt-2 border-r-2 border-b-2 border-t-2 rounded-e-md" name="action" value="unmute">Unmute</button>
|
||||
{% endif %}
|
||||
|
||||
<div class="dropdown">
|
||||
<button disabled {# disabled b/c clicking the dropdown does nothing - we have hover for that #} class="font-bold text-slate-500 fill-slate-500 border-slate-300 ml-2 pl-4 pr-4 pb-2 pt-2 border-2 hover:bg-slate-200 active:ring rounded-md">...</button>
|
||||
|
||||
<div class="dropdown-content-right flex-col">
|
||||
<button type="button" onclick="showDeleteConfirmation()" class="block self-stretch font-bold text-red-500 border-slate-300 pl-4 pr-4 pb-2 pt-2 border-l-2 border-r-2 border-b-2 bg-white hover:bg-red-50 active:ring text-left whitespace-nowrap">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endspaceless %}
|
||||
|
||||
|
||||
|
||||
{# NOTE: "reopen" is not available in the UI as per the notes in issue_detail #}
|
||||
{# only for resolved/muted items <button class="font-bold text-slate-500 border-slate-300 pl-4 pr-4 pb-2 pt-2 ml-1 border-2 hover:bg-slate-200 active:ring rounded-md">Reopen</button> #}
|
||||
|
||||
@@ -281,5 +308,36 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
|
||||
<script>
|
||||
const deleteButton = document.getElementById('');
|
||||
const confirmationBox = document.getElementById('deleteModal');
|
||||
const confirmDelete = document.getElementById('confirmDelete');
|
||||
const cancelDelete = document.getElementById('cancelDelete');
|
||||
const form = document.getElementById('issueForm');
|
||||
|
||||
let actionInput = null;
|
||||
|
||||
function showDeleteConfirmation() {
|
||||
confirmationBox.style.display = 'flex';
|
||||
}
|
||||
|
||||
cancelDelete.addEventListener('click', () => {
|
||||
confirmationBox.style.display = 'none';
|
||||
});
|
||||
|
||||
confirmDelete.addEventListener('click', () => {
|
||||
// Add hidden input only for this submission
|
||||
if (!actionInput) {
|
||||
actionInput = document.createElement('input');
|
||||
actionInput.type = 'hidden';
|
||||
actionInput.name = 'action';
|
||||
actionInput.value = 'delete';
|
||||
form.appendChild(actionInput);
|
||||
}
|
||||
form.submit();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="{% static 'js/issue_list.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -128,6 +128,10 @@ def _is_valid_action(action, issue):
|
||||
"""We take the 'strict' approach of complaining even when the action is simply a no-op, because you're already in
|
||||
the desired state."""
|
||||
|
||||
if action == "delete":
|
||||
# any type of issue can be deleted
|
||||
return True
|
||||
|
||||
if issue.is_resolved:
|
||||
# any action is illegal on resolved issues (as per our current UI)
|
||||
return False
|
||||
@@ -153,6 +157,10 @@ def _is_valid_action(action, issue):
|
||||
def _q_for_invalid_for_action(action):
|
||||
"""returns a Q obj of issues for which the action is not valid."""
|
||||
|
||||
if action == "delete":
|
||||
# delete is always valid, so we don't want any issues to be returned, https://stackoverflow.com/a/39001190
|
||||
return Q(pk__in=[])
|
||||
|
||||
illegal_conditions = Q(is_resolved=True) # any action is illegal on resolved issues (as per our current UI)
|
||||
|
||||
if action.startswith("resolved_release:"):
|
||||
@@ -169,7 +177,10 @@ def _q_for_invalid_for_action(action):
|
||||
|
||||
|
||||
def _make_history(issue_or_qs, action, user):
|
||||
if action == "resolve":
|
||||
if action == "delete":
|
||||
return # we're about to delete the issue, so no history is needed (nor possible)
|
||||
|
||||
elif action == "resolve":
|
||||
kind = TurningPointKind.RESOLVED
|
||||
elif action.startswith("resolved"):
|
||||
kind = TurningPointKind.RESOLVED
|
||||
@@ -252,6 +263,8 @@ def _apply_action(manager, issue_or_qs, action, user):
|
||||
}]))
|
||||
elif action == "unmute":
|
||||
manager.unmute(issue_or_qs)
|
||||
elif action == "delete":
|
||||
manager.delete(issue_or_qs)
|
||||
|
||||
|
||||
def issue_list(request, project_pk, state_filter="open"):
|
||||
|
||||
2
theme/static/css/dist/styles.css
vendored
2
theme/static/css/dist/styles.css
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user