Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NEW] add a modal dialog to warn the user about sending an email without a body #868

Merged
merged 1 commit into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions modules/core/site.css
Original file line number Diff line number Diff line change
Expand Up @@ -329,4 +329,105 @@ div.unseen, .unseen .subject { font-weight: 700; }
}
.drag_target {
background-color: #888 !important;
}

.cypht-modal {
display: block;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
}

.cypht-modal-bg {
background-color: rgba(0,0,0,0.4);
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
}

.cypht-modal-content {
background-color: #fefefe;
margin: 15% auto;
padding: 20px;
border: 1px solid #888;
width: 50%;
display: flex;
flex-direction: column;
gap: 20px;
position: relative;
}

.cypht-modal-content-close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
align-self: flex-end;
position: absolute;
}

.cypht-modal-content-close:hover,
.cypht-modal-content-close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}

.cypht-modal-header {
font-size: 1.5rem;
font-weight: 600;
}

.cypht-modal-footer {
display: flex;
justify-content: flex-end;
gap: 10px;
}

.cypht-modal-footer button {
padding: 10px 20px;
cursor: pointer;
}

.cypht-modal-content-close:hover,
.cypht-modal-content-close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}

.cypht-modal-header {
font-size: 1.5rem;
font-weight: 600;
}

.cypht-modal-footer {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
gap: 10px;
}

.cypht-modal-footer button {
padding: 10px 20px;
cursor: pointer;
height: max-content;
width: max-content;
}

.mobile .cypht-modal-content {
width: 75%;
}

.mobile .cypht-modal-footer {
justify-content: flex-start;
}

.mobile .cypht-modal-footer button {
padding: 5px 10px;
}
46 changes: 46 additions & 0 deletions modules/core/site.js
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,52 @@ var Hm_Ajax_Request = function() { return {
}
}};

/**
* Show a modal dialog with a title, content and buttons.
*/
const Hm_Modals = {
/**
* show the modal
* @param {string | HTMLElement} title title of the modal
* @param {string | HTMLElement} content content of the modal
* @param {Array<string>} btnsTexts buttons texts
* @param {Array<Function>} btnsCbs array of callbacks for each button @default Hm_Modals.hide()
*/
show: function (title = '', content = '', btnsTexts = [], btnsCbs = []) {
const modal = `
<div id="cypht-modal" class="cypht-modal">
<div class="cypht-modal-bg"></div>
<div class="cypht-modal-content">
<span class="cypht-modal-content-close">&times;</span>
<div class="cypht-modal-header">
${title}
</div>

<div class="cypht-modal-body">
${content}
</div>

<div class="cypht-modal-footer">
${btnsTexts.map((text, index) => `<button class="cypht-modal-btn-${index + 1}">${text}</button>`).join('')}
</div>
</div>
</div>
`;
document.querySelector('body').insertAdjacentHTML('beforeend', modal);

btnsTexts.forEach((_, index) => {
document.querySelector(`.cypht-modal-btn-${index + 1}`).addEventListener('click', btnsCbs[index] || this.hide);
});

document.querySelector('.cypht-modal-content-close').addEventListener('click', this.hide);
document.querySelector('.cypht-modal-bg').addEventListener('click', this.hide);
},

hide: () => {
document.querySelector('#cypht-modal').remove();
}
}

/* user notification manager */
var Hm_Notices = {
hide_id: false,
Expand Down
4 changes: 3 additions & 1 deletion modules/smtp/hm-mime-message.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ function process_attachments() {

/* output mime message */
function get_mime_msg() {
$this->prep_message_body();
if (!empty($this->body)) {
$this->prep_message_body();
}
$res = '';
$headers = '';
foreach ($this->headers as $name => $val) {
Expand Down
6 changes: 3 additions & 3 deletions modules/smtp/modules.php
Original file line number Diff line number Diff line change
Expand Up @@ -646,12 +646,12 @@ function get_mime_type($filename)
class Hm_Handler_process_compose_form_submit extends Hm_Handler_Module {
public function process() {
/* not sending */
if (!array_key_exists('smtp_send', $this->request->post)) {
if (!array_key_exists("compose_smtp_id", $this->request->post)) {
return;
}

/* missing field */
list($success, $form) = $this->process_form(array('compose_to', 'compose_subject', 'compose_smtp_id', 'draft_id', 'post_archive', 'next_email_post'));
list($success, $form) = $this->process_form(array('compose_to', 'compose_subject', 'compose_body', 'compose_smtp_id', 'draft_id', 'post_archive', 'next_email_post'));
if (!$success) {
Hm_Msgs::add('ERRRequired field missing');
return;
Expand Down Expand Up @@ -1074,7 +1074,7 @@ protected function output() {
'" /><div id="cc_contacts"></div></div><div class="compose_container" ><div class="bubbles bubble_dropdown"></div><input autocomplete="off" value="'.$this->html_safe($bcc).
'" name="compose_bcc" class="compose_bcc" type="text" placeholder="'.$this->trans('Bcc').'" />'.
'<div id="bcc_contacts"></div></div></div><input value="'.$this->html_safe($subject).
'" required name="compose_subject" class="compose_subject" type="text" placeholder="'.
'" name="compose_subject" class="compose_subject" type="text" placeholder="'.
$this->trans('Subject').'" /><textarea id="compose_body" name="compose_body" class="compose_body">'.
$this->html_safe($body).'</textarea>';
if ($html == 2) {
Expand Down
1 change: 0 additions & 1 deletion modules/smtp/site.css
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,3 @@
.bubble_dropdown-content ul li span, .bubble_dropdown-content ul li a {display: flex; align-items: center; padding: 8px 4px;text-decoration: none;color: #333;}
.bubble_dropdown-content ul li span:hover, .bubble_dropdown-content ul li a:hover { background-color: #f1f1f1;cursor: pointer;}
.bubble_dropdown-content ul li img { width: 16px;height: 16px;margin-right: 8px;}

92 changes: 79 additions & 13 deletions modules/smtp/site.js
Original file line number Diff line number Diff line change
Expand Up @@ -406,20 +406,86 @@ $(function() {
$('.delete_draft').on("click", function() { smtp_delete_draft($(this).data('id')); });
$('.smtp_save').on("click", function() { save_compose_state(false, true); });
$('.smtp_send_archive').on("click", function() { send_archive(false, true); });
$('.compose_form').on('submit', function() {
var msg_uid = hm_msg_uid();
var detail = Hm_Utils.parse_folder_path(hm_list_path(), 'imap');
var class_name = 'imap_'+detail.server_id+'_'+msg_uid+'_'+detail.folder;
var key = 'imap_'+Hm_Utils.get_url_page_number()+'_'+hm_list_path();
var next_message = Hm_Message_List.prev_next_links(key, class_name)[1];
if (next_message) {
$('.compose_next_email_data').val(next_message);
$('.compose_form').on('submit', function(e) {
e.preventDefault();
const body = $('.compose_body').val().trim();
const subject = $('.compose_subject').val().trim();

let modalContentHeadline = '';
let dontWanValueInStorage = '';

// If the subject is empty, we should warn the user
if (!subject) {
dontWanValueInStorage = 'dont_warn_empty_subject';
modalContentHeadline = "<p>Your subject is empty</p>";
}

// If the body is empty, we should warn the user
if (!body) {
dontWanValueInStorage = 'dont_warn_empty_body';
modalContentHeadline = "<p>Your body is empty!</p>";
}

// if both the subject and the body are empty, we should warn the user
if (!body && !subject) {
dontWanValueInStorage = 'dont_warn_empty_subject_body';
modalContentHeadline = "<p>Your subject and body are empty!</p>";
}

// If the user has disabled the warning, we should send the message
if (Boolean(Hm_Utils.get_from_local_storage(dontWanValueInStorage))) {
return handleSendAnyway();
}
// Otherwise, we should show the modal if we have a headline
if (modalContentHeadline) {
return showModal();
}

// Subject and body are not empty, we can send the message
handleSendAnyway();

/*
========================================
Functions declarations
========================================
*/
function showModal() {
const modalContent = modalContentHeadline + `
<p>Are you sure you want to send this message?</p>
`;
const modalButtons = [
"Cancel sending",
"Send anyway",
"Send anyway and don't warn me in the future",
];
Hm_Modals.show('Warning', modalContent, modalButtons, [Hm_Modals.hide, handleSendAnyway, handleSendAnywayAndDontWarnMe]);
}

function handleSendAnyway() {
e.target.submit();
handleFiles();
};

function handleSendAnywayAndDontWarnMe() {
Hm_Utils.save_to_local_storage(dontWanValueInStorage, true);
handleSendAnyway();
};

function handleFiles() {
var msg_uid = hm_msg_uid();
var detail = Hm_Utils.parse_folder_path(hm_list_path(), 'imap');
var class_name = 'imap_' + detail.server_id + '_' + msg_uid + '_' + detail.folder;
var key = 'imap_' + Hm_Utils.get_url_page_number() + '_' + hm_list_path();
var next_message = Hm_Message_List.prev_next_links(key, class_name)[1];
if (next_message) {
$('.compose_next_email_data').val(next_message);
}
var uploaded_files = $("input[name='uploaded_files[]']").map(function () { return $(this).val(); }).get();
$('#send_uploaded_files').val(uploaded_files);
Hm_Ajax.show_loading_icon(); $('.smtp_send').addClass('disabled_input');
$('.smtp_send_archive').addClass('disabled_input');
$('.smtp_send').on("click", function () { return false; });
}
var uploaded_files = $("input[name='uploaded_files[]']").map(function(){return $(this).val();}).get();
$('#send_uploaded_files').val(uploaded_files);
Hm_Ajax.show_loading_icon(); $('.smtp_send').addClass('disabled_input');
$('.smtp_send_archive').addClass('disabled_input');
$('.smtp_send').on("click", function() { return false; });
});
if ($('.compose_cc').val() || $('.compose_bcc').val()) {
toggle_recip_flds();
Expand Down