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 Component from "@ember/component";
|
||||||
import I18n from "I18n";
|
import { equal } from "@ember/object/computed";
|
||||||
import bootbox from "bootbox";
|
import bootbox from "bootbox";
|
||||||
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
|
import I18n from "I18n";
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
classNames: ["watched-word"],
|
classNames: ["watched-word"],
|
||||||
|
|
||||||
|
isReplace: equal("actionKey", "replace"),
|
||||||
|
isTag: equal("actionKey", "tag"),
|
||||||
|
|
||||||
|
@discourseComputed("word.replacement")
|
||||||
|
tags(replacement) {
|
||||||
|
return replacement.split(",");
|
||||||
|
},
|
||||||
|
|
||||||
click() {
|
click() {
|
||||||
this.word
|
this.word
|
||||||
.destroy()
|
.destroy()
|
||||||
|
|
|
@ -1,14 +1,48 @@
|
||||||
import Controller from "@ember/controller";
|
import Controller from "@ember/controller";
|
||||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
|
import { equal } from "@ember/object/computed";
|
||||||
|
|
||||||
export default Controller.extend(ModalFunctionality, {
|
export default Controller.extend(ModalFunctionality, {
|
||||||
@discourseComputed("value", "model.compiledRegularExpression")
|
isReplace: equal("model.nameKey", "replace"),
|
||||||
matches(value, regexpString) {
|
isTag: equal("model.nameKey", "tag"),
|
||||||
|
|
||||||
|
@discourseComputed(
|
||||||
|
"value",
|
||||||
|
"model.compiledRegularExpression",
|
||||||
|
"model.words",
|
||||||
|
"isReplace",
|
||||||
|
"isTag"
|
||||||
|
)
|
||||||
|
matches(value, regexpString, words, isReplace, isTag) {
|
||||||
if (!value || !regexpString) {
|
if (!value || !regexpString) {
|
||||||
return;
|
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}}
|
{{#if canReplace}}
|
||||||
<div class="watched-word-input">
|
<div class="watched-word-input">
|
||||||
<label for="watched-replacement">{{i18n "admin.watched_words.form.replacement_label"}}</label>
|
<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>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if canTag}}
|
{{#if canTag}}
|
||||||
<div class="watched-word-input">
|
<div class="watched-word-input">
|
||||||
<label for="watched-tag">{{i18n "admin.watched_words.form.tag_label"}}</label>
|
<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>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,29 @@
|
||||||
<p>
|
<p>
|
||||||
{{i18n "admin.watched_words.test.found_matches"}}
|
{{i18n "admin.watched_words.test.found_matches"}}
|
||||||
<ul>
|
<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|}}
|
{{#each matches as |match|}}
|
||||||
<li>{{match}}</li>
|
<li>{{match}}</li>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
{{/if}}
|
||||||
</ul>
|
</ul>
|
||||||
</p>
|
</p>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
{{watched-word-uploader uploading=uploading actionKey=actionNameKey done=(action "uploadComplete")}}
|
{{watched-word-uploader uploading=uploading actionKey=actionNameKey done=(action "uploadComplete")}}
|
||||||
|
|
||||||
{{d-button
|
{{d-button
|
||||||
|
class="watched-word-test"
|
||||||
label="admin.watched_words.test.button_label"
|
label="admin.watched_words.test.button_label"
|
||||||
icon="far-eye"
|
icon="far-eye"
|
||||||
action=(action "test")}}
|
action=(action "test")}}
|
||||||
|
@ -37,7 +38,7 @@
|
||||||
{{#if showWordsList}}
|
{{#if showWordsList}}
|
||||||
<div class="watched-words-list">
|
<div class="watched-words-list">
|
||||||
{{#each filteredContent as |word| }}
|
{{#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}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -83,4 +83,20 @@ acceptance("Admin - Watched Words", function (needs) {
|
||||||
|
|
||||||
assert.equal(queryAll(".watched-words-list .watched-word").length, 2);
|
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 {
|
export default {
|
||||||
"/admin/customize/watched_words.json": {
|
"/admin/customize/watched_words.json": {
|
||||||
actions: ["block", "censor", "require_approval", "flag"],
|
actions: ["block", "censor", "require_approval", "flag", "replace", "tag"],
|
||||||
words: [
|
words: [
|
||||||
{ id: 1, word: "liquorice", action: "block" },
|
{ id: 1, word: "liquorice", action: "block" },
|
||||||
{ id: 2, word: "anise", action: "block" },
|
{ id: 2, word: "anise", action: "block" },
|
||||||
{ id: 3, word: "pyramid", action: "flag" },
|
{ id: 3, word: "pyramid", action: "flag" },
|
||||||
{ id: 4, word: "scheme", action: "flag" },
|
{ id: 4, word: "scheme", action: "flag" },
|
||||||
{ id: 5, word: "coupon", action: "require_approval" },
|
{ 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;
|
width: 250px;
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.watched-word-box,
|
||||||
|
.watched-words-test-modal {
|
||||||
.replacement {
|
.replacement {
|
||||||
white-space: pre;
|
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 {
|
input.watched-word-input-field {
|
||||||
min-width: 300px;
|
min-width: 300px;
|
||||||
}
|
}
|
||||||
input.watched-word-input-replace {
|
|
||||||
min-width: 260px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search logs
|
// Search logs
|
||||||
|
|
|
@ -1,7 +1,15 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class WatchedWordSerializer < ApplicationSerializer
|
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
|
def action
|
||||||
WatchedWord.actions[object.action]
|
WatchedWord.actions[object.action]
|
||||||
|
|
|
@ -4728,7 +4728,7 @@ en:
|
||||||
upload_successful: "Upload successful. Words have been added."
|
upload_successful: "Upload successful. Words have been added."
|
||||||
test:
|
test:
|
||||||
button_label: "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"
|
description: "Enter text below to check for matches with watched words"
|
||||||
found_matches: "Found matches:"
|
found_matches: "Found matches:"
|
||||||
no_matches: "No matches found"
|
no_matches: "No matches found"
|
||||||
|
|
Loading…
Reference in New Issue