mirror of
https://github.com/zulip/zulip.git
synced 2025-10-23 04:52:12 +00:00
linkifiers: Add frontend support to edit linkifier.
A modal is added to edit the realm linkifier which supports ui_report error. Puppeteer tests to verify linkifier update and an invalid test to verify that linkifier error messages are reported on the modal are added as well.
This commit is contained in:
@@ -35,11 +35,11 @@ async function test_add_linkifier(page: Page): Promise<void> {
|
||||
}
|
||||
|
||||
async function test_delete_linkifier(page: Page): Promise<void> {
|
||||
await page.click(".linkifier_row button");
|
||||
await page.click(".linkifier_row .delete");
|
||||
await page.waitForSelector(".linkifier_row", {hidden: true});
|
||||
}
|
||||
|
||||
async function test_invalid_linkifier_pattern(page: Page): Promise<void> {
|
||||
async function test_add_invalid_linkifier_pattern(page: Page): Promise<void> {
|
||||
await page.waitForSelector(".admin-linkifier-form", {visible: true});
|
||||
await common.fill_form(page, "form.admin-linkifier-form", {
|
||||
pattern: "a$",
|
||||
@@ -54,14 +54,94 @@ async function test_invalid_linkifier_pattern(page: Page): Promise<void> {
|
||||
);
|
||||
}
|
||||
|
||||
async function test_edit_linkifier(page: Page): Promise<void> {
|
||||
await page.click(".linkifier_row .edit");
|
||||
await page.waitForFunction(() => document.activeElement === $("#linkifier-edit-form-modal")[0]);
|
||||
await common.fill_form(page, "form.linkifier-edit-form", {
|
||||
pattern: "(?P<num>[0-9a-f]{40})",
|
||||
url_format_string: "https://trac.example.com/commit/%(num)s",
|
||||
});
|
||||
await page.click(".submit-linkifier-info-change");
|
||||
|
||||
await page.waitForSelector("#linkifier-edit-form-modal", {hidden: true});
|
||||
await page.waitForFunction(() => $(".edit-linkifier-status").text().trim() === "Saved");
|
||||
await page.waitForSelector(".linkifier_row", {visible: true});
|
||||
assert.strictEqual(
|
||||
await common.get_text_from_selector(page, ".linkifier_row span.linkifier_pattern"),
|
||||
"(?P<num>[0-9a-f]{40})",
|
||||
);
|
||||
assert.strictEqual(
|
||||
await common.get_text_from_selector(
|
||||
page,
|
||||
".linkifier_row span.linkifier_url_format_string",
|
||||
),
|
||||
"https://trac.example.com/commit/%(num)s",
|
||||
);
|
||||
}
|
||||
|
||||
async function test_edit_invalid_linkifier(page: Page): Promise<void> {
|
||||
await page.click(".linkifier_row .edit");
|
||||
await page.waitForFunction(() => document.activeElement === $("#linkifier-edit-form-modal")[0]);
|
||||
await common.fill_form(page, "form.linkifier-edit-form", {
|
||||
pattern: "####",
|
||||
url_format_string: "####",
|
||||
});
|
||||
await page.click(".submit-linkifier-info-change");
|
||||
|
||||
const edit_linkifier_pattern_status_selector = "div#edit-linkifier-pattern-status";
|
||||
await page.waitForSelector(edit_linkifier_pattern_status_selector, {visible: true});
|
||||
const edit_linkifier_pattern_status = await common.get_text_from_selector(
|
||||
page,
|
||||
edit_linkifier_pattern_status_selector,
|
||||
);
|
||||
assert.strictEqual(
|
||||
edit_linkifier_pattern_status,
|
||||
"Failed: Invalid linkifier pattern. Valid characters are [ a-zA-Z_#=/:+!-].",
|
||||
);
|
||||
|
||||
const edit_linkifier_format_status_selector = "div#edit-linkifier-format-status";
|
||||
await page.waitForSelector(edit_linkifier_format_status_selector, {visible: true});
|
||||
const edit_linkifier_format_status = await common.get_text_from_selector(
|
||||
page,
|
||||
edit_linkifier_format_status_selector,
|
||||
);
|
||||
assert.strictEqual(
|
||||
edit_linkifier_format_status,
|
||||
"Failed: Enter a valid URL.,Invalid URL format string.",
|
||||
);
|
||||
|
||||
await page.click(".cancel-linkifier-info-change");
|
||||
await page.waitForSelector("#linkifier-edit-form-modal", {hidden: true});
|
||||
|
||||
await page.waitForFunction(
|
||||
() =>
|
||||
$(".edit-linkifier-status").text().trim() ===
|
||||
"Save failed: Invalid linkifier pattern. Valid characters are [ a-zA-Z_#=/:+!-].",
|
||||
);
|
||||
await page.waitForSelector(".linkifier_row", {visible: true});
|
||||
assert.strictEqual(
|
||||
await common.get_text_from_selector(page, ".linkifier_row span.linkifier_pattern"),
|
||||
"(?P<num>[0-9a-f]{40})",
|
||||
);
|
||||
assert.strictEqual(
|
||||
await common.get_text_from_selector(
|
||||
page,
|
||||
".linkifier_row span.linkifier_url_format_string",
|
||||
),
|
||||
"https://trac.example.com/commit/%(num)s",
|
||||
);
|
||||
}
|
||||
|
||||
async function linkifier_test(page: Page): Promise<void> {
|
||||
await common.log_in(page);
|
||||
await common.manage_organization(page);
|
||||
await page.click("li[data-section='linkifier-settings']");
|
||||
|
||||
await test_add_linkifier(page);
|
||||
await test_edit_linkifier(page);
|
||||
await test_edit_invalid_linkifier(page);
|
||||
await test_add_invalid_linkifier_pattern(page);
|
||||
await test_delete_linkifier(page);
|
||||
await test_invalid_linkifier_pattern(page);
|
||||
}
|
||||
|
||||
common.run_test(linkifier_test);
|
||||
|
@@ -1,11 +1,14 @@
|
||||
import $ from "jquery";
|
||||
|
||||
import render_admin_linkifier_edit_form from "../templates/settings/admin_linkifier_edit_form.hbs";
|
||||
import render_admin_linkifier_list from "../templates/settings/admin_linkifier_list.hbs";
|
||||
|
||||
import * as channel from "./channel";
|
||||
import {$t_html} from "./i18n";
|
||||
import * as ListWidget from "./list_widget";
|
||||
import * as overlays from "./overlays";
|
||||
import {page_params} from "./page_params";
|
||||
import * as settings_ui from "./settings_ui";
|
||||
import * as ui from "./ui";
|
||||
import * as ui_report from "./ui_report";
|
||||
|
||||
@@ -40,6 +43,22 @@ function sort_url(a, b) {
|
||||
return compare_values(a.url_format, b.url_format);
|
||||
}
|
||||
|
||||
function open_linkifier_edit_form(linkifier_id) {
|
||||
const linkifiers_list = page_params.realm_linkifiers;
|
||||
const linkifier = linkifiers_list.find((linkifier) => linkifier.id === linkifier_id);
|
||||
const edit_form_html = render_admin_linkifier_edit_form({
|
||||
linkifier_id,
|
||||
pattern: linkifier.pattern,
|
||||
url_format_string: linkifier.url_format,
|
||||
});
|
||||
const $edit_form_div = $(edit_form_html);
|
||||
const modal_container = $("#linkifier-edit-form-modal-container");
|
||||
modal_container.empty().append($edit_form_div);
|
||||
overlays.open_modal("#linkifier-edit-form-modal");
|
||||
|
||||
return $edit_form_div;
|
||||
}
|
||||
|
||||
function handle_linkifier_api_error(xhr, pattern_status, format_status, linkifier_status) {
|
||||
// The endpoint uses the Django ValidationError system for error
|
||||
// handling, which returns somewhat complicated error
|
||||
@@ -127,6 +146,58 @@ export function build_page() {
|
||||
});
|
||||
});
|
||||
|
||||
$(".admin_linkifiers_table").on("click", ".edit", function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const btn = $(this);
|
||||
const linkifier_id = Number.parseInt(btn.attr("data-linkifier-id"), 10);
|
||||
const modal = open_linkifier_edit_form(linkifier_id);
|
||||
|
||||
modal.find(".submit-linkifier-info-change").on("click", (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const change_linkifier_button = $(".submit-linkifier-info-change");
|
||||
change_linkifier_button.prop("disabled", true);
|
||||
|
||||
const url = "/json/realm/filters/" + encodeURIComponent(linkifier_id);
|
||||
const pattern = modal.find("#edit-linkifier-pattern").val().trim();
|
||||
const url_format_string = modal.find("#edit-linkifier-url-format-string").val().trim();
|
||||
const data = {pattern, url_format_string};
|
||||
const pattern_status = modal.find("#edit-linkifier-pattern-status").expectOne();
|
||||
const format_status = modal.find("#edit-linkifier-format-status").expectOne();
|
||||
const linkifier_status = modal.find(".edit-linkifier-status").expectOne();
|
||||
const opts = {
|
||||
success_continuation() {
|
||||
change_linkifier_button.prop("disabled", false);
|
||||
overlays.close_modal("#linkifier-edit-form-modal");
|
||||
},
|
||||
error_continuation(xhr) {
|
||||
change_linkifier_button.prop("disabled", false);
|
||||
const response_text = JSON.parse(xhr.responseText);
|
||||
if (response_text.errors !== undefined) {
|
||||
handle_linkifier_api_error(
|
||||
xhr,
|
||||
pattern_status,
|
||||
format_status,
|
||||
linkifier_status,
|
||||
);
|
||||
} else {
|
||||
// This must be `Linkifier not found` error.
|
||||
ui_report.error($t_html({defaultMessage: "Failed"}), xhr, linkifier_status);
|
||||
}
|
||||
},
|
||||
};
|
||||
settings_ui.do_settings_change(
|
||||
channel.patch,
|
||||
url,
|
||||
data,
|
||||
$("#linkifier-field-status"),
|
||||
opts,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
$(".organization form.admin-linkifier-form")
|
||||
.off("submit")
|
||||
.on("submit", function (e) {
|
||||
|
@@ -1927,3 +1927,15 @@ body:not(.night-mode) #settings_page .custom_user_field .datepicker {
|
||||
max-height: unset;
|
||||
}
|
||||
}
|
||||
|
||||
.linkifier-edit-form {
|
||||
#edit-linkifier-pattern,
|
||||
#edit-linkifier-url-format-string {
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
#edit-linkifier-pattern-status,
|
||||
#edit-linkifier-format-status {
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
27
static/templates/settings/admin_linkifier_edit_form.hbs
Normal file
27
static/templates/settings/admin_linkifier_edit_form.hbs
Normal file
@@ -0,0 +1,27 @@
|
||||
<div id="linkifier-edit-form-modal" class="modal modal-bg hide fade" tabindex="-1" role="dialog" aria-labelledby="linkifier-edit-form-modal-label" aria-hidden="true">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="{{t 'Close' }}"><span aria-hidden="true">×</span></button>
|
||||
<h3 id="linkifier-edit-form-modal-label">{{t "Edit linkifiers" }}</h3>
|
||||
<div class="alert-notification edit-linkifier-status"></div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="edit-linkifier-form">
|
||||
<form class="form-horizontal linkifier-edit-form">
|
||||
<div class="input-group name_change_container">
|
||||
<label for="edit-linkifier-pattern" >{{t "Pattern" }}</label>
|
||||
<input type="text" autocomplete="off" id="edit-linkifier-pattern" name="pattern" placeholder="#(?P<id>[0-9]+)" value="{{ pattern }}" />
|
||||
<div class="alert" id="edit-linkifier-pattern-status"></div>
|
||||
</div>
|
||||
<div class="input-group name_change_container">
|
||||
<label for="edit-linkifier-url-format-string" >{{t "URL format string" }}</label>
|
||||
<input type="text" autocomplete="off" id="edit-linkifier-url-format-string" name="url_format_string" placeholder="https://github.com/zulip/zulip/issues/%(id)s" value="{{ url_format_string }}" />
|
||||
<div class="alert" id="edit-linkifier-format-status"></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="button rounded sea-green submit-linkifier-info-change">{{t "Save changes" }}</button>
|
||||
<button type="button" class="button rounded cancel-linkifier-info-change" data-dismiss="modal">{{t "Cancel" }}</button>
|
||||
</div>
|
||||
</div>
|
@@ -8,6 +8,9 @@
|
||||
</td>
|
||||
{{#if ../can_modify}}
|
||||
<td class="no-select actions">
|
||||
<button class="button small edit btn-warning" data-linkifier-id="{{id}}" title="{{t 'Edit' }}" aria-label="{{t 'Edit' }}">
|
||||
<i class="fa fa-pencil"></i>
|
||||
</button>
|
||||
<button class="button small delete btn-danger" data-linkifier-id="{{id}}" title="{{t 'Delete' }}" aria-label="{{t 'Delete' }}">
|
||||
<i class="fa fa-trash-o"></i>
|
||||
</button>
|
||||
|
@@ -5,3 +5,4 @@
|
||||
{{> resend_invite_modal }}
|
||||
|
||||
<div id="user-info-form-modal-container"></div>
|
||||
<div id="linkifier-edit-form-modal-container"></div>
|
||||
|
@@ -66,6 +66,7 @@
|
||||
{{/if}}
|
||||
|
||||
<input type="text" class="search" placeholder="{{t 'Filter linkifiers' }}" aria-label="{{t 'Filter linkifiers' }}"/>
|
||||
<div class="alert-notification edit-linkifier-status" id="linkifier-field-status"></div>
|
||||
<div class="progressive-table-wrapper" data-simplebar>
|
||||
<table class="table table-condensed table-striped wrapped-table admin_linkifiers_table">
|
||||
<thead class="table-sticky-headers">
|
||||
|
Reference in New Issue
Block a user