Skip to content

Commit

Permalink
Add warning when all sources are selected for deletion
Browse files Browse the repository at this point in the history
  • Loading branch information
zenmonkeykstop committed Nov 14, 2024
1 parent 5ddbedc commit 08de3bd
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 13 deletions.
5 changes: 4 additions & 1 deletion client/securedrop_client/gui/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,10 @@ def __init__(

# DeleteSource Dialog can accept more than one source (bulk delete),
# but when triggered from this menu, only applies to one source
self._confirmation_dialog = confirmation_dialog([self.source])
self._confirmation_dialog = confirmation_dialog(
[self.source],
self.controller.get_source_count(),
)
self._confirmation_dialog.accepted.connect(
lambda: self.controller.delete_sources([self.source])
)
Expand Down
36 changes: 25 additions & 11 deletions client/securedrop_client/gui/source/delete/dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,31 +31,44 @@
class DeleteSourceDialog(ModalDialog):
"""Used to confirm deletion of source accounts."""

def __init__(self, sources: list[Source]) -> None:
def __init__(self, sources: list[Source], source_total: int) -> None:
super().__init__(show_header=False, dangerous=True)
self.sources = sources
self.source_total = source_total

# If the dialog is constructed with no sources, show a warning; otherwise,
# confirm the number and designation of the sources to be deleted
num_sources = len(sources)
if num_sources == 0:
self._show_warning_nothing_selected()
else:
continue_text = ngettext(
"YES, DELETE ENTIRE SOURCE ACCOUNT",
"YES, DELETE {number} SOURCE ACCOUNTS",
num_sources,
).format(number=num_sources)

self.body.setText(self.make_body_text(self.sources))
if num_sources < source_total:
continue_text = ngettext(
"YES, DELETE ENTIRE SOURCE ACCOUNT",
"YES, DELETE {number} SOURCE ACCOUNTS",
num_sources,
).format(number=num_sources)
else:
continue_text = ngettext(
"YES, DELETE ENTIRE SOURCE ACCOUNT",
"YES, DELETE ALL {number} SOURCE ACCOUNTS",
num_sources,
).format(number=num_sources)

self.body.setText(self.make_body_text(self.sources, self.source_total))
self.continue_button.setText(continue_text)
self.cancel_button.setDefault(True)
self.cancel_button.setFocus()
self.confirmation_label.setText(_("Are you sure this is what you want?"))
self.adjustSize()

def make_body_text(self, sources: list[Source]) -> str:
message_tuple = (
def make_body_text(self, sources: list[Source], source_total) -> str:
if len(sources) == source_total:
all_sources_text = ("<p><b>", _("Notice: All sources have been selected!"), "</p></b>")
else:
all_sources_text = ()

message_text = (
"<p>",
_("Delete entire account for: {source_or_sources}?"),
"</p>",
Expand All @@ -74,7 +87,8 @@ def make_body_text(self, sources: list[Source]) -> str:
"<p>&nbsp;</p>",
)

return "".join(message_tuple).format(
full_text = all_sources_text + message_text
return "".join(full_text).format(
source_or_sources=f"<b>{self._get_source_names_truncated(sources, MAX_DEL_DISP)}</b>"
)

Expand Down
3 changes: 2 additions & 1 deletion client/securedrop_client/gui/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -553,8 +553,9 @@ def on_action_triggered(self) -> None:
# The current source selection is continuously received by the controller
# as the user selects and deselects; here we retrieve the selection
targets = self.controller.get_selected_sources()
source_count = self.controller.get_source_count()
if targets is not None:
dialog = DeleteSourceDialog(targets)
dialog = DeleteSourceDialog(targets, source_count)
self._last_dialog = dialog # FIXME: workaround for #2273
dialog.accepted.connect(lambda: self.controller.delete_sources(targets))
dialog.open()
Expand Down
7 changes: 7 additions & 0 deletions client/securedrop_client/logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -1215,3 +1215,10 @@ def on_receive_selected_sources(self, sources: list[db.Source]) -> None:

def get_selected_sources(self) -> list[db.Source] | None:
return self._selected_sources

def get_source_count(self) -> int:
"""
Return total sourcces in local storage.
"""
sources = list(storage.get_local_sources(self.session))
return len(sources)

0 comments on commit 08de3bd

Please sign in to comment.