Repository: zulip/zulip

Issue:
Organization linkifiers should be editable in place
It would be nice if linkifications were editable, rather than requiring deletion and re-creation. But I understand it would be harder to check for duplicate regex that way.


Discussion:
Hello @zulip/server-markdown, @zulip/server-settings members, this issue was labeled with the "area: markdown", "area: settings (admin/org)" labels, so you may want to check it out!

<!-- areaLabelAddition -->
This seems like a reasonable UI to add, though probably not super high priority, just because folks tend to edit these only once when setting up an organization.
So, there are three functions in file zerver/views/realm_filters.py. For listing, creating and deleting. And I think a function for editing filter needs to be created. Should I do so and hit PR?
@zulipbot claim

Welcome to Zulip, @ruchit2801! We just sent you an invite to collaborate on this repository at https://github.com/zulip/zulip/invitations. Please accept this invite in order to claim this issue and begin a fun, rewarding experience contributing to Zulip!

Here's some tips to get you off to a good start:
* Join me on the [Zulip developers' server](https://chat.zulip.org), to get help, chat about this issue, and meet the other developers.
* Sign the [Dropbox Contributor License Agreement](https://opensource.dropbox.com/cla/), so that Zulip can use your code.
* [Unwatch this repository](https://help.github.com/articles/unwatching-repositories/), so that you don't get 100 emails a day.

As you work on this issue, you'll also want to refer to the [Zulip code contribution guide](https://zulip.readthedocs.io/en/latest/contributing/index.html), as well as the rest of the developer documentation on that site.

See you on the other side (that is, the pull request side)!
That's correct, we need to extend the API for this.
@zulipbot abandon


Resolving patch:
diff --git a/tools/linter_lib/custom_check.py b/tools/linter_lib/custom_check.py
--- a/tools/linter_lib/custom_check.py
+++ b/tools/linter_lib/custom_check.py
@@ -745,6 +745,10 @@
             "pattern": '{{t "[^"]+ " }}',
             "description": "Translatable strings should not have trailing spaces.",
         },
+        {
+            "pattern": r'"{{t "',
+            "description": "Invalid quoting for HTML element with translated string.",
+        },
     ],
 )
 


Test patch:
diff --git a/frontend_tests/puppeteer_tests/realm-linkifier.ts b/frontend_tests/puppeteer_tests/realm-linkifier.ts
--- a/frontend_tests/puppeteer_tests/realm-linkifier.ts
+++ b/frontend_tests/puppeteer_tests/realm-linkifier.ts
@@ -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);