mirror of https://github.com/zulip/zulip.git
drafts: Add functionality to bulk delete drafts.
Fixes #19360. Co-authored-by: Satyam Bansal <sbansal1999@gmail.com>
This commit is contained in:
parent
e4048de0a9
commit
fed866449d
|
@ -617,6 +617,7 @@ export function launch() {
|
|||
});
|
||||
}
|
||||
update_rendered_drafts(narrow_drafts.length > 0, other_drafts.length > 0);
|
||||
update_bulk_delete_ui();
|
||||
}
|
||||
|
||||
function setup_event_handlers() {
|
||||
|
@ -638,8 +639,37 @@ export function launch() {
|
|||
const $draft_row = $(this).closest(".overlay-message-row");
|
||||
|
||||
remove_draft($draft_row);
|
||||
update_bulk_delete_ui();
|
||||
},
|
||||
);
|
||||
|
||||
$("#drafts_table .overlay_message_controls .draft-selection-checkbox").on("click", (e) => {
|
||||
const is_checked = is_checkbox_icon_checked($(e.target));
|
||||
toggle_checkbox_icon_state($(e.target), !is_checked);
|
||||
update_bulk_delete_ui();
|
||||
});
|
||||
|
||||
$(".select-drafts-button").on("click", (e) => {
|
||||
e.preventDefault();
|
||||
const $unchecked_checkboxes = $(".draft-selection-checkbox").filter(function () {
|
||||
return !is_checkbox_icon_checked($(this));
|
||||
});
|
||||
const check_boxes = $unchecked_checkboxes.length > 0;
|
||||
$(".draft-selection-checkbox").each(function () {
|
||||
toggle_checkbox_icon_state($(this), check_boxes);
|
||||
});
|
||||
update_bulk_delete_ui();
|
||||
});
|
||||
|
||||
$(".delete-selected-drafts-button").on("click", () => {
|
||||
$(".drafts-list")
|
||||
.find(".draft-selection-checkbox.fa-check-square")
|
||||
.closest(".overlay-message-row")
|
||||
.each(function () {
|
||||
remove_draft($(this));
|
||||
});
|
||||
update_bulk_delete_ui();
|
||||
});
|
||||
}
|
||||
|
||||
const drafts = draft_model.get();
|
||||
|
@ -663,6 +693,35 @@ export function launch() {
|
|||
setup_event_handlers();
|
||||
}
|
||||
|
||||
function update_bulk_delete_ui() {
|
||||
const $unchecked_checkboxes = $(".draft-selection-checkbox").filter(function () {
|
||||
return !is_checkbox_icon_checked($(this));
|
||||
});
|
||||
const $checked_checkboxes = $(".draft-selection-checkbox").filter(function () {
|
||||
return is_checkbox_icon_checked($(this));
|
||||
});
|
||||
const $select_drafts_button = $(".select-drafts-button");
|
||||
const $select_state_indicator = $(".select-drafts-button .select-state-indicator");
|
||||
const $delete_selected_drafts_button = $(".delete-selected-drafts-button");
|
||||
|
||||
if ($checked_checkboxes.length > 0) {
|
||||
$delete_selected_drafts_button.prop("disabled", false);
|
||||
if ($unchecked_checkboxes.length === 0) {
|
||||
toggle_checkbox_icon_state($select_state_indicator, true);
|
||||
} else {
|
||||
toggle_checkbox_icon_state($select_state_indicator, false);
|
||||
}
|
||||
} else {
|
||||
if ($unchecked_checkboxes.length > 0) {
|
||||
toggle_checkbox_icon_state($select_state_indicator, false);
|
||||
$delete_selected_drafts_button.prop("disabled", true);
|
||||
} else {
|
||||
$select_drafts_button.hide();
|
||||
$delete_selected_drafts_button.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function open_overlay() {
|
||||
sync_count();
|
||||
overlays.open_overlay({
|
||||
|
@ -675,6 +734,19 @@ function open_overlay() {
|
|||
});
|
||||
}
|
||||
|
||||
function is_checkbox_icon_checked($checkbox) {
|
||||
return $checkbox.hasClass("fa-check-square");
|
||||
}
|
||||
|
||||
function toggle_checkbox_icon_state($checkbox, checked) {
|
||||
$checkbox.parent().attr("aria-checked", checked);
|
||||
if (checked) {
|
||||
$checkbox.removeClass("fa-square-o").addClass("fa-check-square");
|
||||
} else {
|
||||
$checkbox.removeClass("fa-check-square").addClass("fa-square-o");
|
||||
}
|
||||
}
|
||||
|
||||
export function initialize() {
|
||||
remove_old_drafts();
|
||||
|
||||
|
|
|
@ -143,12 +143,45 @@ export function initialize() {
|
|||
// below specify the target directly, elements using those should
|
||||
// not have the tippy-zulip-tooltip class.
|
||||
|
||||
$("body").on("blur", ".message_control_button", (e) => {
|
||||
delegate("body", {
|
||||
target: ".draft-selection-tooltip",
|
||||
delay: LONG_HOVER_DELAY,
|
||||
appendTo: () => document.body,
|
||||
onShow(instance) {
|
||||
let content = $t({defaultMessage: "Select draft"});
|
||||
const $elem = $(instance.reference);
|
||||
if ($($elem).parent().find(".draft-selection-checkbox").hasClass("fa-check-square")) {
|
||||
content = $t({defaultMessage: "Deselect draft"});
|
||||
}
|
||||
instance.setContent(content);
|
||||
return true;
|
||||
},
|
||||
});
|
||||
|
||||
delegate("body", {
|
||||
target: ".delete-selected-drafts-button-container",
|
||||
appendTo: () => document.body,
|
||||
onShow(instance) {
|
||||
let content = $t({defaultMessage: "Delete all selected drafts"});
|
||||
const $elem = $(instance.reference);
|
||||
if ($($elem).find(".delete-selected-drafts-button").is(":disabled")) {
|
||||
content = $t({defaultMessage: "No drafts selected"});
|
||||
}
|
||||
instance.setContent(content);
|
||||
return true;
|
||||
},
|
||||
});
|
||||
|
||||
$("body").on(
|
||||
"blur",
|
||||
".message_control_button, .delete-selected-drafts-button-container",
|
||||
(e) => {
|
||||
// Remove tooltip when user is trying to tab through all the icons.
|
||||
// If user tabs slowly, tooltips are displayed otherwise they are
|
||||
// destroyed before they can be displayed.
|
||||
e.currentTarget?._tippy?.destroy();
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
delegate("body", {
|
||||
target: [
|
||||
|
|
|
@ -879,6 +879,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
.drafts-container .header-body .delete-drafts-group > *:focus {
|
||||
background-color: hsl(228deg 11% 17%);
|
||||
}
|
||||
|
||||
& thead,
|
||||
.drafts-container .drafts-header,
|
||||
.nav > li > a:focus,
|
||||
|
|
|
@ -1,4 +1,60 @@
|
|||
.drafts-container {
|
||||
.header-body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
gap: 5px;
|
||||
|
||||
.removed-drafts {
|
||||
text-align: left;
|
||||
margin-left: 25px;
|
||||
|
||||
@media (width < $lg_min) {
|
||||
text-align: center;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.delete-drafts-group {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
|
||||
.delete-selected-drafts-button {
|
||||
&:focus {
|
||||
background-color: hsl(0deg 0% 93%);
|
||||
}
|
||||
}
|
||||
|
||||
.select-drafts-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
margin-right: 25px;
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
|
||||
&:focus {
|
||||
background-color: hsl(0deg 0% 93%);
|
||||
}
|
||||
}
|
||||
|
||||
.select-state-indicator {
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
@media (width < $lg_min) {
|
||||
margin-top: 5px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (width < $lg_min) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.drafts-list {
|
||||
& h2 {
|
||||
font-size: 1.1em;
|
||||
|
@ -6,4 +62,12 @@
|
|||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.draft-selection-checkbox {
|
||||
margin-top: 5px;
|
||||
/* Required to make sure that the checkbox icon stays inside
|
||||
the grid. Any value greater than 13px (original width of
|
||||
the checkbox icon) will work. */
|
||||
width: 15px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
<div class="overlay_message_controls">
|
||||
<i class="fa fa-pencil fa-lg restore-overlay-message tippy-zulip-tooltip" aria-hidden="true" data-tooltip-template-id="restore-draft-tooltip-template"></i>
|
||||
<i class="fa fa-trash-o fa-lg delete-overlay-message tippy-zulip-tooltip" aria-hidden="true" data-tooltip-template-id="delete-draft-tooltip-template"></i>
|
||||
<div class="draft-selection-tooltip">
|
||||
<i class="fa fa-square-o fa-lg draft-selection-checkbox" aria-hidden="true"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="message_content rendered_markdown restore-overlay-message tippy-zulip-delayed-tooltip" data-tooltip-template-id="restore-draft-tooltip-template">{{rendered_markdown content}}</div>
|
||||
|
|
|
@ -6,11 +6,24 @@
|
|||
<div class="exit">
|
||||
<span class="exit-sign">×</span>
|
||||
</div>
|
||||
<div class="header-body">
|
||||
<div class="removed-drafts">
|
||||
{{t "Drafts are not synced to other devices and browsers." }}
|
||||
<br />
|
||||
{{#tr}}Drafts older than <strong>{draft_lifetime}</strong> days are automatically removed.{{/tr}}
|
||||
</div>
|
||||
<div class="delete-drafts-group">
|
||||
<div class="delete-selected-drafts-button-container">
|
||||
<button class="button small rounded delete-selected-drafts-button" type="button" disabled>
|
||||
<i class="fa fa-trash-o fa-lg" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
<button class="button small rounded select-drafts-button" role="checkbox" aria-checked="false">
|
||||
<span>{{t "Select all drafts" }}</span>
|
||||
<i class="fa fa-square-o fa-lg select-state-indicator" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="drafts-list overlay-messages-list">
|
||||
<div class="no-drafts no-overlay-messages">
|
||||
|
|
|
@ -610,6 +610,7 @@ test("format_drafts", ({override_rewire, mock_template}) => {
|
|||
$(".top_left_drafts").set_find_results(".unread_count", $unread_count);
|
||||
|
||||
$.create("#drafts_table .overlay-message-row", {children: []});
|
||||
$(".draft-selection-checkbox").filter = () => [];
|
||||
drafts.launch();
|
||||
|
||||
$.clear_all_elements();
|
||||
|
@ -625,6 +626,7 @@ test("format_drafts", ({override_rewire, mock_template}) => {
|
|||
|
||||
$(".top_left_drafts").set_find_results(".unread_count", $unread_count);
|
||||
|
||||
$(".draft-selection-checkbox").filter = () => [];
|
||||
drafts.launch();
|
||||
});
|
||||
|
||||
|
@ -770,5 +772,6 @@ test("filter_drafts", ({override_rewire, mock_template}) => {
|
|||
compose_state.private_message_recipient(aaron.email);
|
||||
|
||||
$.create("#drafts_table .overlay-message-row", {children: []});
|
||||
$(".draft-selection-checkbox").filter = () => [];
|
||||
drafts.launch();
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue