mirror of https://github.com/zulip/zulip.git
ts: Covert `dialog_widget.js` to typescript.
Created `WidgetConfig` type which has all the parameter that can be passed launch(). Except html_heading, html_body, and on_click all other fields are optional. Therefore, removed checking of undefined mandatory fields as it will be done by typescript. Co-authored-by: Hardik Dharmani <Ddharmani99@gmail.com>
This commit is contained in:
parent
fcbc6dcae4
commit
ebc07c0dd7
|
@ -139,7 +139,7 @@ js_rules = RuleList(
|
||||||
"web/src/portico",
|
"web/src/portico",
|
||||||
"web/src/lightbox.js",
|
"web/src/lightbox.js",
|
||||||
"web/src/ui_report.ts",
|
"web/src/ui_report.ts",
|
||||||
"web/src/dialog_widget.js",
|
"web/src/dialog_widget.ts",
|
||||||
"web/tests/",
|
"web/tests/",
|
||||||
},
|
},
|
||||||
"description": "Setting HTML content with jQuery .html() can lead to XSS security bugs. Consider .text() or using rendered_foo as a variable name if content comes from Handlebars and thus is already sanitized.",
|
"description": "Setting HTML content with jQuery .html() can lead to XSS security bugs. Consider .text() or using rendered_foo as a variable name if content comes from Handlebars and thus is already sanitized.",
|
||||||
|
|
|
@ -78,7 +78,7 @@ EXEMPT_FILES = make_set(
|
||||||
"web/src/debug.ts",
|
"web/src/debug.ts",
|
||||||
"web/src/deprecated_feature_notice.js",
|
"web/src/deprecated_feature_notice.js",
|
||||||
"web/src/desktop_integration.js",
|
"web/src/desktop_integration.js",
|
||||||
"web/src/dialog_widget.js",
|
"web/src/dialog_widget.ts",
|
||||||
"web/src/drafts.js",
|
"web/src/drafts.js",
|
||||||
"web/src/dropdown_list_widget.js",
|
"web/src/dropdown_list_widget.js",
|
||||||
"web/src/echo.js",
|
"web/src/echo.js",
|
||||||
|
|
|
@ -112,6 +112,9 @@ function call(args) {
|
||||||
return $.ajax(args);
|
return $.ajax(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: When this file is converted to TypeScript, deduplicate the
|
||||||
|
// AjaxRequest type defined in dialog_widget.js.
|
||||||
|
|
||||||
export function get(options) {
|
export function get(options) {
|
||||||
const args = {type: "GET", dataType: "json", ...options};
|
const args = {type: "GET", dataType: "json", ...options};
|
||||||
return call(args);
|
return call(args);
|
||||||
|
|
|
@ -2,7 +2,6 @@ import $ from "jquery";
|
||||||
|
|
||||||
import render_dialog_widget from "../templates/dialog_widget.hbs";
|
import render_dialog_widget from "../templates/dialog_widget.hbs";
|
||||||
|
|
||||||
import * as blueslip from "./blueslip";
|
|
||||||
import {$t_html} from "./i18n";
|
import {$t_html} from "./i18n";
|
||||||
import * as loading from "./loading";
|
import * as loading from "./loading";
|
||||||
import * as overlays from "./overlays";
|
import * as overlays from "./overlays";
|
||||||
|
@ -42,7 +41,47 @@ import * as ui_report from "./ui_report";
|
||||||
* to DOM, it can do so by passing a post_render hook.
|
* to DOM, it can do so by passing a post_render hook.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export function hide_dialog_spinner() {
|
type WidgetConfig = {
|
||||||
|
html_heading: string;
|
||||||
|
html_body: string;
|
||||||
|
on_click: (e: unknown) => void;
|
||||||
|
html_submit_button?: string;
|
||||||
|
close_on_submit?: boolean;
|
||||||
|
focus_submit_on_open?: boolean;
|
||||||
|
help_link?: string;
|
||||||
|
id?: string;
|
||||||
|
single_footer_button?: boolean;
|
||||||
|
form_id?: string;
|
||||||
|
validate_input?: (e: unknown) => boolean;
|
||||||
|
on_show?: () => void;
|
||||||
|
on_shown?: () => void;
|
||||||
|
on_hide?: () => void;
|
||||||
|
on_hidden?: () => void;
|
||||||
|
post_render?: () => void;
|
||||||
|
loading_spinner?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: This type should probably be exported from channel.ts once
|
||||||
|
// that's converted to TypeScript.
|
||||||
|
type AjaxRequest = ({
|
||||||
|
url,
|
||||||
|
data = {},
|
||||||
|
success,
|
||||||
|
error,
|
||||||
|
}: {
|
||||||
|
url: string;
|
||||||
|
data?: Record<string, never>;
|
||||||
|
success(response_data?: string): void;
|
||||||
|
error(xhr?: JQuery.jqXHR): void;
|
||||||
|
}) => void;
|
||||||
|
|
||||||
|
type RequestOpts = {
|
||||||
|
failure_msg_html?: string;
|
||||||
|
success_continuation?: (response_data?: string) => void;
|
||||||
|
error_continuation?: (xhr?: JQuery.jqXHR) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function hide_dialog_spinner(): void {
|
||||||
$(".dialog_submit_button span").show();
|
$(".dialog_submit_button span").show();
|
||||||
$("#dialog_widget_modal .modal__btn").prop("disabled", false);
|
$("#dialog_widget_modal .modal__btn").prop("disabled", false);
|
||||||
|
|
||||||
|
@ -50,7 +89,7 @@ export function hide_dialog_spinner() {
|
||||||
loading.destroy_indicator($spinner);
|
loading.destroy_indicator($spinner);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function show_dialog_spinner() {
|
export function show_dialog_spinner(): void {
|
||||||
$(".dialog_submit_button span").hide();
|
$(".dialog_submit_button span").hide();
|
||||||
// Disable both the buttons.
|
// Disable both the buttons.
|
||||||
$("#dialog_widget_modal .modal__btn").prop("disabled", true);
|
$("#dialog_widget_modal .modal__btn").prop("disabled", true);
|
||||||
|
@ -65,19 +104,18 @@ export function show_dialog_spinner() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Supports a callback to be called once the modal finishes closing.
|
// Supports a callback to be called once the modal finishes closing.
|
||||||
export function close_modal(on_hidden_callback) {
|
export function close_modal(on_hidden_callback?: () => void): void {
|
||||||
overlays.close_modal("dialog_widget_modal", {on_hidden: on_hidden_callback});
|
overlays.close_modal("dialog_widget_modal", {on_hidden: on_hidden_callback});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function launch(conf) {
|
export function launch(conf: WidgetConfig): void {
|
||||||
const mandatory_fields = [
|
// Mandatory fields:
|
||||||
|
// * html_heading
|
||||||
|
// * html_body
|
||||||
|
// * on_click
|
||||||
// The html_ fields should be safe HTML. If callers
|
// The html_ fields should be safe HTML. If callers
|
||||||
// interpolate user data into strings, they should use
|
// interpolate user data into strings, they should use
|
||||||
// templates.
|
// templates.
|
||||||
"html_heading",
|
|
||||||
"html_body",
|
|
||||||
"on_click",
|
|
||||||
];
|
|
||||||
|
|
||||||
// Optional parameters:
|
// Optional parameters:
|
||||||
// * html_submit_button: Submit button text.
|
// * html_submit_button: Submit button text.
|
||||||
|
@ -93,12 +131,8 @@ export function launch(conf) {
|
||||||
// * on_hide: Callback to run when the modal is triggered to hide.
|
// * on_hide: Callback to run when the modal is triggered to hide.
|
||||||
// * on_hidden: Callback to run when the modal is hidden.
|
// * on_hidden: Callback to run when the modal is hidden.
|
||||||
// * post_render: Callback to run after the modal body is added to DOM.
|
// * post_render: Callback to run after the modal body is added to DOM.
|
||||||
|
// * loading_spinner: Whether to show a loading spinner inside the
|
||||||
for (const f of mandatory_fields) {
|
// submit button when clicked.
|
||||||
if (conf[f] === undefined) {
|
|
||||||
blueslip.error("programmer omitted " + f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const html_submit_button = conf.html_submit_button || $t_html({defaultMessage: "Save changes"});
|
const html_submit_button = conf.html_submit_button || $t_html({defaultMessage: "Save changes"});
|
||||||
const html = render_dialog_widget({
|
const html = render_dialog_widget({
|
||||||
|
@ -156,26 +190,26 @@ export function launch(conf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function submit_api_request(
|
export function submit_api_request(
|
||||||
request_method,
|
request_method: AjaxRequest,
|
||||||
url,
|
url: string,
|
||||||
data = {},
|
data = {},
|
||||||
{
|
{
|
||||||
failure_msg_html = $t_html({defaultMessage: "Failed"}),
|
failure_msg_html = $t_html({defaultMessage: "Failed"}),
|
||||||
success_continuation,
|
success_continuation,
|
||||||
error_continuation,
|
error_continuation,
|
||||||
} = {},
|
}: RequestOpts = {},
|
||||||
) {
|
): void {
|
||||||
show_dialog_spinner();
|
show_dialog_spinner();
|
||||||
request_method({
|
request_method({
|
||||||
url,
|
url,
|
||||||
data,
|
data,
|
||||||
success(response_data) {
|
success(response_data?: string) {
|
||||||
close_modal();
|
close_modal();
|
||||||
if (success_continuation !== undefined) {
|
if (success_continuation !== undefined) {
|
||||||
success_continuation(response_data);
|
success_continuation(response_data);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error(xhr) {
|
error(xhr?: JQuery.jqXHR) {
|
||||||
ui_report.error(failure_msg_html, xhr, $("#dialog_error"));
|
ui_report.error(failure_msg_html, xhr, $("#dialog_error"));
|
||||||
hide_dialog_spinner();
|
hide_dialog_spinner();
|
||||||
if (error_continuation !== undefined) {
|
if (error_continuation !== undefined) {
|
Loading…
Reference in New Issue