2021-07-05 19:15:37 +02:00
|
|
|
import $ from "jquery";
|
|
|
|
|
|
|
|
import render_dialog_widget from "../templates/dialog_widget.hbs";
|
|
|
|
|
|
|
|
import * as blueslip from "./blueslip";
|
2021-07-07 19:35:50 +02:00
|
|
|
import {$t_html} from "./i18n";
|
2021-07-16 08:45:23 +02:00
|
|
|
import * as loading from "./loading";
|
2021-07-05 19:15:37 +02:00
|
|
|
import * as overlays from "./overlays";
|
2022-04-28 17:52:03 +02:00
|
|
|
import * as ui_report from "./ui_report";
|
2021-07-05 19:15:37 +02:00
|
|
|
|
|
|
|
/*
|
2021-07-04 08:47:08 +02:00
|
|
|
* Look for confirm_dialog in settings_user_groups
|
|
|
|
* to see an example of how to use this widget. It's
|
|
|
|
* pretty simple to use!
|
|
|
|
*
|
|
|
|
* Some things to note:
|
|
|
|
* 1) We create DOM on the fly, and we remove
|
|
|
|
* the DOM once it's closed.
|
|
|
|
*
|
|
|
|
* 2) We attach the DOM for the modal to the body element
|
|
|
|
* to avoid interference from other elements.
|
|
|
|
*
|
|
|
|
* 3) For settings, we have a click handler in settings.js
|
|
|
|
* that will close the dialog via overlays.close_active_modal.
|
|
|
|
*
|
|
|
|
* 4) We assume that since this is a modal, you will
|
|
|
|
* only ever have one confirm dialog active at any
|
|
|
|
* time.
|
|
|
|
*
|
|
|
|
* 5) If a modal wants a loading spinner, it should pass loading_spinner: true.
|
|
|
|
* This will show a loading spinner when the yes button is clicked.
|
|
|
|
* The caller is responsible for calling hide_confirm_dialog_spinner()
|
|
|
|
* to hide the spinner in both success and error handlers.
|
|
|
|
*
|
|
|
|
* 6) If loading_spinner is used, don't hide it on `success`. This modal has a fade out
|
|
|
|
* animation. This causes the `Confirm` button to be shown for a split second if the
|
|
|
|
* spinner is hidden.
|
|
|
|
* Just close the modal. This will remove the whole modal from the DOM without
|
|
|
|
* needing to remove the spinner.
|
|
|
|
*
|
|
|
|
* 7) If a caller needs to run code after the modal body is added
|
|
|
|
* to DOM, it can do so by passing a post_render hook.
|
|
|
|
*/
|
2021-07-05 19:15:37 +02:00
|
|
|
|
|
|
|
export function hide_dialog_spinner() {
|
|
|
|
$(".dialog_submit_button span").show();
|
2021-07-04 08:47:08 +02:00
|
|
|
$("#dialog_widget_modal .modal__btn").prop("disabled", false);
|
|
|
|
|
2022-01-25 11:36:19 +01:00
|
|
|
const $spinner = $("#dialog_widget_modal .modal__spinner");
|
|
|
|
loading.destroy_indicator($spinner);
|
2021-07-05 19:15:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export function show_dialog_spinner() {
|
|
|
|
$(".dialog_submit_button span").hide();
|
2021-07-04 08:47:08 +02:00
|
|
|
// Disable both the buttons.
|
|
|
|
$("#dialog_widget_modal .modal__btn").prop("disabled", true);
|
|
|
|
|
2022-01-25 11:36:19 +01:00
|
|
|
const $spinner = $("#dialog_widget_modal .modal__spinner");
|
|
|
|
loading.make_indicator($spinner);
|
2021-07-05 19:15:37 +02:00
|
|
|
}
|
|
|
|
|
2022-01-27 08:05:35 +01:00
|
|
|
// Supports a callback to be called once the modal finishes closing.
|
|
|
|
export function close_modal(on_hidden_callback) {
|
2022-07-23 00:15:37 +02:00
|
|
|
overlays.close_modal("dialog_widget_modal", {on_hidden: on_hidden_callback});
|
2021-07-27 18:48:19 +02:00
|
|
|
}
|
|
|
|
|
2021-07-05 19:15:37 +02:00
|
|
|
export function launch(conf) {
|
2021-07-07 19:35:50 +02:00
|
|
|
const mandatory_fields = [
|
|
|
|
// The html_ fields should be safe HTML. If callers
|
2021-07-05 19:15:37 +02:00
|
|
|
// interpolate user data into strings, they should use
|
|
|
|
// templates.
|
|
|
|
"html_heading",
|
|
|
|
"html_body",
|
|
|
|
"on_click",
|
|
|
|
];
|
|
|
|
|
2021-07-14 22:07:03 +02:00
|
|
|
// Optional parameters:
|
|
|
|
// * html_submit_button: Submit button text.
|
|
|
|
// * close_on_submit: Whether to close modal on clicking submit.
|
|
|
|
// * focus_submit_on_open: Whether to focus submit button on open.
|
|
|
|
// * help_link: A help link in the heading area.
|
2021-07-21 13:43:29 +02:00
|
|
|
// * id: Custom id to the container element to modify styles.
|
2021-07-18 14:20:59 +02:00
|
|
|
// * single_footer_button: If true, don't include the "Cancel" button.
|
2021-11-21 16:03:10 +01:00
|
|
|
// * form_id: Id of the form element in the modal if it exists.
|
2021-11-29 18:42:33 +01:00
|
|
|
// * validate_input: Function to validate the input of the modal.
|
2021-11-21 15:28:46 +01:00
|
|
|
// * on_show: Callback to run when the modal is triggered to show.
|
|
|
|
// * on_shown: Callback to run when the modal is shown.
|
|
|
|
// * on_hide: Callback to run when the modal is triggered to hide.
|
|
|
|
// * on_hidden: Callback to run when the modal is hidden.
|
2022-03-07 17:21:30 +01:00
|
|
|
// * post_render: Callback to run after the modal body is added to DOM.
|
2021-07-14 22:07:03 +02:00
|
|
|
|
2021-07-07 19:35:50 +02:00
|
|
|
for (const f of mandatory_fields) {
|
2021-07-05 19:15:37 +02:00
|
|
|
if (conf[f] === undefined) {
|
|
|
|
blueslip.error("programmer omitted " + f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Close any existing modals--on settings screens you can
|
|
|
|
// have multiple buttons that need confirmation.
|
|
|
|
if (overlays.is_modal_open()) {
|
2021-07-27 18:48:19 +02:00
|
|
|
close_modal();
|
2021-07-05 19:15:37 +02:00
|
|
|
}
|
|
|
|
|
2021-07-14 22:07:03 +02:00
|
|
|
const html_submit_button = conf.html_submit_button || $t_html({defaultMessage: "Save changes"});
|
2021-07-04 08:47:08 +02:00
|
|
|
const html = render_dialog_widget({
|
2021-07-14 22:21:06 +02:00
|
|
|
heading_text: conf.html_heading,
|
|
|
|
link: conf.help_link,
|
|
|
|
html_submit_button,
|
|
|
|
html_body: conf.html_body,
|
2021-07-21 13:43:29 +02:00
|
|
|
id: conf.id,
|
2021-07-18 14:20:59 +02:00
|
|
|
single_footer_button: conf.single_footer_button,
|
2021-07-14 22:21:06 +02:00
|
|
|
});
|
2022-01-25 11:36:19 +01:00
|
|
|
const $dialog = $(html);
|
|
|
|
$("body").append($dialog);
|
2021-07-05 19:15:37 +02:00
|
|
|
|
|
|
|
if (conf.post_render !== undefined) {
|
|
|
|
conf.post_render();
|
|
|
|
}
|
|
|
|
|
2022-01-25 11:36:19 +01:00
|
|
|
const $submit_button = $dialog.find(".dialog_submit_button");
|
2021-11-27 15:26:09 +01:00
|
|
|
const $send_email_checkbox = $dialog.find(".send_email");
|
|
|
|
const $email_field = $dialog.find(".email_field");
|
|
|
|
|
|
|
|
$email_field.hide();
|
2021-11-21 16:03:10 +01:00
|
|
|
|
|
|
|
// This is used to link the submit button with the form, if present, in the modal.
|
|
|
|
// This makes it so that submitting this form by pressing Enter on an input element
|
|
|
|
// triggers a click on the submit button.
|
|
|
|
if (conf.form_id) {
|
2022-01-25 11:36:19 +01:00
|
|
|
$submit_button.attr("form", conf.form_id);
|
2021-11-21 16:03:10 +01:00
|
|
|
}
|
|
|
|
|
2021-07-05 19:15:37 +02:00
|
|
|
// Set up handlers.
|
2022-01-25 11:36:19 +01:00
|
|
|
$submit_button.on("click", (e) => {
|
2021-11-29 18:42:33 +01:00
|
|
|
if (conf.validate_input && !conf.validate_input(e)) {
|
|
|
|
return;
|
|
|
|
}
|
2021-07-05 19:15:37 +02:00
|
|
|
if (conf.loading_spinner) {
|
|
|
|
show_dialog_spinner();
|
2021-07-14 22:07:03 +02:00
|
|
|
} else if (conf.close_on_submit) {
|
2021-07-27 18:48:19 +02:00
|
|
|
close_modal();
|
2021-07-05 19:15:37 +02:00
|
|
|
}
|
2021-11-24 15:52:32 +01:00
|
|
|
$("#dialog_error").hide();
|
2021-07-17 14:23:43 +02:00
|
|
|
conf.on_click(e);
|
2021-07-05 19:15:37 +02:00
|
|
|
});
|
|
|
|
|
2021-11-27 15:26:09 +01:00
|
|
|
$($send_email_checkbox).on("change", () => {
|
|
|
|
if ($($send_email_checkbox).is(":checked")) {
|
|
|
|
$email_field.show();
|
|
|
|
} else {
|
|
|
|
$email_field.hide();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-07-04 08:47:08 +02:00
|
|
|
overlays.open_modal("dialog_widget_modal", {
|
|
|
|
autoremove: true,
|
2021-11-21 15:28:46 +01:00
|
|
|
on_show: () => {
|
|
|
|
if (conf.focus_submit_on_open) {
|
2022-01-25 11:36:19 +01:00
|
|
|
$submit_button.trigger("focus");
|
2021-11-21 15:28:46 +01:00
|
|
|
}
|
|
|
|
if (conf.on_show) {
|
|
|
|
conf.on_show();
|
|
|
|
}
|
2021-07-04 08:47:08 +02:00
|
|
|
},
|
2021-11-21 15:28:46 +01:00
|
|
|
on_hide: conf?.on_hide,
|
|
|
|
on_shown: conf?.on_shown,
|
|
|
|
on_hidden: conf?.on_hidden,
|
2021-07-05 19:15:37 +02:00
|
|
|
});
|
|
|
|
}
|
2022-04-28 17:52:03 +02:00
|
|
|
|
|
|
|
export function submit_api_request(
|
|
|
|
request_method,
|
|
|
|
url,
|
|
|
|
data = {},
|
|
|
|
{
|
|
|
|
failure_msg_html = $t_html({defaultMessage: "Failed"}),
|
|
|
|
success_continuation,
|
|
|
|
error_continuation,
|
|
|
|
} = {},
|
|
|
|
) {
|
|
|
|
show_dialog_spinner();
|
|
|
|
request_method({
|
|
|
|
url,
|
|
|
|
data,
|
|
|
|
success(reponse_data) {
|
|
|
|
close_modal();
|
|
|
|
if (success_continuation !== undefined) {
|
|
|
|
success_continuation(reponse_data);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
error(xhr) {
|
|
|
|
ui_report.error(failure_msg_html, xhr, $("#dialog_error"));
|
|
|
|
hide_dialog_spinner();
|
|
|
|
if (error_continuation !== undefined) {
|
|
|
|
error_continuation(xhr);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|