Skip to content

Commit

Permalink
linkifiers: Support dragging and reordering linkifiers.
Browse files Browse the repository at this point in the history
This also removes sorting on the pattern and the URL template, because
it does not make sense anymore as we make linkifiers draggable.

Fixes zulip#23716
  • Loading branch information
PIG208 committed Aug 10, 2023
1 parent 15c8444 commit 71e7a4a
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 25 deletions.
38 changes: 38 additions & 0 deletions help/add-a-custom-linkifier.md
Expand Up @@ -100,6 +100,10 @@ variety of situations. Linkifier patterns are regular expressions, using the
[re2](https://github.com/google/re2/wiki/Syntax) regular expression
engine.

The linkifiers are ordered as they are displayed in the settings. When the
regular expressions have an overlapping match, only the earliest one will be used
to generate the link. You can reorder the linkifiers by dragging and dropping.

Linkifiers use [RFC 6570](https://www.rfc-editor.org/rfc/rfc6570.html) compliant
URL templates to describe how links should be generated. These templates support
several expression types. The default expression type (`{var}`) will URL-encode
Expand Down Expand Up @@ -155,3 +159,37 @@ This example pattern allows linking to Google searches.
This pattern uses the `{?var}` expression type. With the default expression
type (`{q}`), there would be no way to only include the `?` in the URL
if the optional `q` is present.

### Overlapping patterns

These example patterns link to arbitrary repositories in either
the organization `zulip-testing` or `zulip`. `zulip` is only used
when the repo name is not `lorem`.

{start_tabs}

* Linkifier #1
* Pattern: `lorem#(?P<id>[0-9]+)`
* URL template: `https://github.com/zulip-testing/lorem/pull/{id}`

* Linkifier #2
* Pattern: `(?P<repo>[a-zA-Z0-9_-]+)#(?P<id>[0-9]+)`
* URL template: `https://github.com/zulip/{repo}/pull/{id}`

* Example matching linkifier #1 and #2
* Original text: `lorem#123`
* Automatically links to: `https://github.com/zulip-testing/lorem/pull/123`

* Example matching linkifier #2 only
* Original text: `zulip-flutter#123`
* Automatically links to: `https://github.com/zulip/zulip-flutter/pull/123`

{end_tabs}

!!! tip ""

This set of patterns have overlapping regular expressions. Note that
`(?P<repo>[a-zA-Z0-9_-]+)#(?P<id>[0-9]+)` would match `lorem#123` too.
Linkifier #1 gets prioritized over linkifier #2 because it is
ordered before the linkifier #2. This order can be customized by
dragging and dropping the linkifiers.
44 changes: 22 additions & 22 deletions web/src/settings_linkifiers.js
@@ -1,4 +1,5 @@
import $ from "jquery";
import {Sortable} from "sortablejs";

import render_confirm_delete_linkifier from "../templates/confirm_dialog/confirm_delete_linkifier.hbs";
import render_admin_linkifier_edit_form from "../templates/settings/admin_linkifier_edit_form.hbs";
Expand Down Expand Up @@ -28,23 +29,6 @@ export function maybe_disable_widgets() {
}
}

function compare_values(x, y) {
if (x > y) {
return 1;
} else if (x === y) {
return 0;
}
return -1;
}

function sort_pattern(a, b) {
return compare_values(a.pattern, b.pattern);
}

function sort_url(a, b) {
return compare_values(a.url_template, b.url_template);
}

function open_linkifier_edit_form(linkifier_id) {
const linkifiers_list = page_params.realm_linkifiers;
const linkifier = linkifiers_list.find((linkifier) => linkifier.id === linkifier_id);
Expand Down Expand Up @@ -108,6 +92,19 @@ function open_linkifier_edit_form(linkifier_id) {
});
}

function update_linkifiers_order() {
const order = [];
$(".linkifier_row").each(function () {
order.push(Number.parseInt($(this).attr("data-linkifier-id"), 10));
});
settings_ui.do_settings_change(
channel.patch,
"/json/realm/linkifiers",
{ordered_linkifier_ids: JSON.stringify(order)},
$("#linkifier-field-status").expectOne(),
);
}

function handle_linkifier_api_error(xhr, pattern_status, template_status, linkifier_status) {
// The endpoint uses the Django ValidationError system for error
// handling, which returns somewhat complicated error
Expand Down Expand Up @@ -159,13 +156,16 @@ export function populate_linkifiers(linkifiers_data) {
},
},
$parent_container: $("#linkifier-settings").expectOne(),
init_sort: sort_pattern,
sort_fields: {
pattern: sort_pattern,
url: sort_url,
},
$simplebar_container: $("#linkifier-settings .progressive-table-wrapper"),
});

if (page_params.is_admin) {
Sortable.create($linkifiers_table[0], {
onUpdate: update_linkifiers_order,
filter: "input",
preventOnFilter: false,
});
}
}

export function set_up() {
Expand Down
1 change: 1 addition & 0 deletions web/styles/settings.css
Expand Up @@ -726,6 +726,7 @@ input[type="checkbox"] {

.admin_profile_fields_table,
.edit_profile_field_choices_container,
.admin_linkifiers_table,
.profile_field_choices_table {
.movable-row {
cursor: move;
Expand Down
6 changes: 5 additions & 1 deletion web/templates/settings/admin_linkifier_list.hbs
@@ -1,6 +1,10 @@
{{#with linkifier}}
<tr class="linkifier_row">
<tr class="linkifier_row{{#if ../can_modify}} movable-row{{/if}}" data-linkifier-id="{{id}}">
<td>
{{#if ../can_modify}}
<i class="fa fa-ellipsis-v" aria-hidden="true"></i>
<i class="fa fa-ellipsis-v" aria-hidden="true"></i>
{{/if}}
<span class="linkifier_pattern">{{pattern}}</span>
</td>
<td>
Expand Down
9 changes: 7 additions & 2 deletions web/templates/settings/linkifier_settings_admin.hbs
Expand Up @@ -21,6 +21,11 @@
{{t "URL template" }}: <span class="rendered_markdown"><code>https://github.com/zulip/zulip/issues/{id}</code></span>
</li>
</ul>
<p>
{{t "The linkifiers are ordered as they are displayed below. When the
regular expressions have an overlapping match, only the earliest one will be used
to generate the link. You can reorder the linkifiers by dragging and dropping." }}
</p>
<p>
{{#tr}}
For more examples, see the <z-link>help center documentation</z-link>
Expand Down Expand Up @@ -65,8 +70,8 @@
<div class="progressive-table-wrapper" data-simplebar>
<table class="table table-condensed table-striped wrapped-table admin_linkifiers_table">
<thead class="table-sticky-headers">
<th class="active" data-sort="pattern">{{t "Pattern" }}</th>
<th data-sort="url">{{t "URL template" }}</th>
<th>{{t "Pattern" }}</th>
<th>{{t "URL template" }}</th>
{{#if is_admin}}
<th class="actions">{{t "Actions" }}</th>
{{/if}}
Expand Down

0 comments on commit 71e7a4a

Please sign in to comment.