FEATURE: Support tag and replace in watched words in test modal (#13100)
The modal showed only the matches, without the replacement or tags.
This commit is contained in:
parent
0df6b0bc47
commit
f700f3ef00
|
@ -1,10 +1,20 @@
|
|||
import Component from "@ember/component";
|
||||
import I18n from "I18n";
|
||||
import { equal } from "@ember/object/computed";
|
||||
import bootbox from "bootbox";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import I18n from "I18n";
|
||||
|
||||
export default Component.extend({
|
||||
classNames: ["watched-word"],
|
||||
|
||||
isReplace: equal("actionKey", "replace"),
|
||||
isTag: equal("actionKey", "tag"),
|
||||
|
||||
@discourseComputed("word.replacement")
|
||||
tags(replacement) {
|
||||
return replacement.split(",");
|
||||
},
|
||||
|
||||
click() {
|
||||
this.word
|
||||
.destroy()
|
||||
|
|
|
@ -1,14 +1,48 @@
|
|||
import Controller from "@ember/controller";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { equal } from "@ember/object/computed";
|
||||
|
||||
export default Controller.extend(ModalFunctionality, {
|
||||
@discourseComputed("value", "model.compiledRegularExpression")
|
||||
matches(value, regexpString) {
|
||||
isReplace: equal("model.nameKey", "replace"),
|
||||
isTag: equal("model.nameKey", "tag"),
|
||||
|
||||
@discourseComputed(
|
||||
"value",
|
||||
"model.compiledRegularExpression",
|
||||
"model.words",
|
||||
"isReplace",
|
||||
"isTag"
|
||||
)
|
||||
matches(value, regexpString, words, isReplace, isTag) {
|
||||
if (!value || !regexpString) {
|
||||
return;
|
||||
}
|
||||
let censorRegexp = new RegExp(regexpString, "ig");
|
||||
return value.match(censorRegexp);
|
||||
|
||||
const regexp = new RegExp(regexpString, "ig");
|
||||
const matches = value.match(regexp) || [];
|
||||
|
||||
if (isReplace) {
|
||||
return matches.map((match) => ({
|
||||
match,
|
||||
replacement: words.find((word) =>
|
||||
new RegExp(word.regexp, "ig").test(match)
|
||||
).replacement,
|
||||
}));
|
||||
} else if (isTag) {
|
||||
return matches.map((match) => {
|
||||
const tags = new Set();
|
||||
|
||||
words.forEach((word) => {
|
||||
if (new RegExp(word.regexp, "ig").test(match)) {
|
||||
word.replacement.split(",").forEach((tag) => tags.add(tag));
|
||||
}
|
||||
});
|
||||
|
||||
return { match, tags: Array.from(tags) };
|
||||
});
|
||||
}
|
||||
|
||||
return matches;
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1 +1,9 @@
|
|||
{{d-icon "times"}} {{word.word}} {{#if word.replacement}}→ <span class="replacement">{{word.replacement}}</span>{{/if}}
|
||||
{{d-icon "times"}} {{word.word}}
|
||||
{{#if isReplace}}
|
||||
→ <span class="replacement">{{word.replacement}}</span>
|
||||
{{else if isTag}}
|
||||
→
|
||||
{{#each tags as |tag|}}
|
||||
<span class="tag">{{tag}}</span>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
{{#if canReplace}}
|
||||
<div class="watched-word-input">
|
||||
<label for="watched-replacement">{{i18n "admin.watched_words.form.replacement_label"}}</label>
|
||||
{{text-field id="watched-replacement" value=replacement disabled=formSubmitted class="watched-word-input-replace" autocorrect="off" autocapitalize="off" placeholderKey="admin.watched_words.form.replacement_placeholder"}}
|
||||
{{text-field id="watched-replacement" value=replacement disabled=formSubmitted class="watched-word-input-field" autocorrect="off" autocapitalize="off" placeholderKey="admin.watched_words.form.replacement_placeholder"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if canTag}}
|
||||
<div class="watched-word-input">
|
||||
<label for="watched-tag">{{i18n "admin.watched_words.form.tag_label"}}</label>
|
||||
{{text-field id="watched-tag" value=replacement disabled=formSubmitted class="watched-word-input" autocorrect="off" autocapitalize="off" placeholderKey="admin.watched_words.form.tag_placeholder"}}
|
||||
{{text-field id="watched-tag" value=replacement disabled=formSubmitted class="watched-word-input-field" autocorrect="off" autocapitalize="off" placeholderKey="admin.watched_words.form.tag_placeholder"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
|
|
|
@ -5,9 +5,29 @@
|
|||
<p>
|
||||
{{i18n "admin.watched_words.test.found_matches"}}
|
||||
<ul>
|
||||
{{#if isReplace}}
|
||||
{{#each matches as |match|}}
|
||||
<li>
|
||||
<span class="match">{{match.match}}</span>
|
||||
→
|
||||
<span class="replacement">{{match.replacement}}</span>
|
||||
</li>
|
||||
{{/each}}
|
||||
{{else if isTag}}
|
||||
{{#each matches as |match|}}
|
||||
<li>
|
||||
<span class="match">{{match.match}}</span>
|
||||
→
|
||||
{{#each match.tags as |tag|}}
|
||||
<span class="tag">{{tag}}</span>
|
||||
{{/each}}
|
||||
</li>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
{{#each matches as |match|}}
|
||||
<li>{{match}}</li>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
</ul>
|
||||
</p>
|
||||
{{else}}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
{{watched-word-uploader uploading=uploading actionKey=actionNameKey done=(action "uploadComplete")}}
|
||||
|
||||
{{d-button
|
||||
class="watched-word-test"
|
||||
label="admin.watched_words.test.button_label"
|
||||
icon="far-eye"
|
||||
action=(action "test")}}
|
||||
|
@ -37,7 +38,7 @@
|
|||
{{#if showWordsList}}
|
||||
<div class="watched-words-list">
|
||||
{{#each filteredContent as |word| }}
|
||||
<div class="watched-word-box">{{admin-watched-word word=word action=(action "recordRemoved")}}</div>
|
||||
<div class="watched-word-box">{{admin-watched-word actionKey=actionNameKey word=word action=(action "recordRemoved")}}</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
|
|
@ -83,4 +83,20 @@ acceptance("Admin - Watched Words", function (needs) {
|
|||
|
||||
assert.equal(queryAll(".watched-words-list .watched-word").length, 2);
|
||||
});
|
||||
|
||||
test("test modal - replace", async function (assert) {
|
||||
await visit("/admin/customize/watched_words/action/replace");
|
||||
await click(".watched-word-test");
|
||||
await fillIn(".modal-body textarea", "Hi there!");
|
||||
assert.equal(find(".modal-body li .match").text(), "Hi");
|
||||
assert.equal(find(".modal-body li .replacement").text(), "hello");
|
||||
});
|
||||
|
||||
test("test modal - tag", async function (assert) {
|
||||
await visit("/admin/customize/watched_words/action/tag");
|
||||
await click(".watched-word-test");
|
||||
await fillIn(".modal-body textarea", "Hello world!");
|
||||
assert.equal(find(".modal-body li .match").text(), "Hello");
|
||||
assert.equal(find(".modal-body li .tag").text(), "greeting");
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,14 +1,35 @@
|
|||
export default {
|
||||
"/admin/customize/watched_words.json": {
|
||||
actions: ["block", "censor", "require_approval", "flag"],
|
||||
actions: ["block", "censor", "require_approval", "flag", "replace", "tag"],
|
||||
words: [
|
||||
{ id: 1, word: "liquorice", action: "block" },
|
||||
{ id: 2, word: "anise", action: "block" },
|
||||
{ id: 3, word: "pyramid", action: "flag" },
|
||||
{ id: 4, word: "scheme", action: "flag" },
|
||||
{ id: 5, word: "coupon", action: "require_approval" },
|
||||
{ id: 6, word: '<img src="x">', action: "block" }
|
||||
{ id: 6, word: '<img src="x">', action: "block" },
|
||||
{
|
||||
id: 7,
|
||||
word: "hi",
|
||||
regexp: "hi",
|
||||
replacement: "hello",
|
||||
action: "replace",
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
word: "hello",
|
||||
regexp: "hello",
|
||||
replacement: "greeting",
|
||||
action: "tag",
|
||||
},
|
||||
],
|
||||
compiled_regular_expressions: {}
|
||||
}
|
||||
compiled_regular_expressions: {
|
||||
block: '(?:\\W|^)(liquorice|anise|<img\\ src="x">)(?=\\W|$)',
|
||||
censor: null,
|
||||
require_approval: "(?:\\W|^)(coupon)(?=\\W|$)",
|
||||
flag: "(?:\\W|^)(pyramid|scheme)(?=\\W|$)",
|
||||
replace: "(?:\\W|^)(hi)(?=\\W|$)",
|
||||
tag: "(?:\\W|^)(hello)(?=\\W|$)",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -330,9 +330,20 @@ table.screened-ip-addresses {
|
|||
width: 250px;
|
||||
margin-bottom: 1em;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.watched-word-box,
|
||||
.watched-words-test-modal {
|
||||
.replacement {
|
||||
white-space: pre;
|
||||
background-color: var(--tertiary-low);
|
||||
background: var(--tertiary-low);
|
||||
}
|
||||
|
||||
.tag {
|
||||
background: var(--primary-low);
|
||||
font-size: $font-down-1;
|
||||
margin-right: 0.1em;
|
||||
padding: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -385,9 +396,6 @@ table.screened-ip-addresses {
|
|||
input.watched-word-input-field {
|
||||
min-width: 300px;
|
||||
}
|
||||
input.watched-word-input-replace {
|
||||
min-width: 260px;
|
||||
}
|
||||
}
|
||||
|
||||
// Search logs
|
||||
|
|
|
@ -1,7 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class WatchedWordSerializer < ApplicationSerializer
|
||||
attributes :id, :word, :replacement, :action
|
||||
attributes :id, :word, :regexp, :replacement, :action
|
||||
|
||||
def regexp
|
||||
WordWatcher.word_to_regexp(word)
|
||||
end
|
||||
|
||||
def include_regexp?
|
||||
WatchedWord.has_replacement?(action)
|
||||
end
|
||||
|
||||
def action
|
||||
WatchedWord.actions[object.action]
|
||||
|
|
|
@ -4728,7 +4728,7 @@ en:
|
|||
upload_successful: "Upload successful. Words have been added."
|
||||
test:
|
||||
button_label: "Test"
|
||||
modal_title: "Test '%{action}' Watched Words"
|
||||
modal_title: "Test %{action} Watched Words"
|
||||
description: "Enter text below to check for matches with watched words"
|
||||
found_matches: "Found matches:"
|
||||
no_matches: "No matches found"
|
||||
|
|
Loading…
Reference in New Issue