From f700f3ef009d7a149cddb706b78c807b1469d2a9 Mon Sep 17 00:00:00 2001
From: Bianca Nenciu
Date: Fri, 21 May 2021 17:50:24 +0300
Subject: [PATCH] FEATURE: Support tag and replace in watched words in test
modal (#13100)
The modal showed only the matches, without the replacement or tags.
---
.../addon/components/admin-watched-word.js | 12 +++++-
.../modals/admin-watched-word-test.js | 42 +++++++++++++++++--
.../components/admin-watched-word.hbs | 10 ++++-
.../components/watched-word-form.hbs | 4 +-
.../modal/admin-watched-word-test.hbs | 26 ++++++++++--
.../addon/templates/watched-words-action.hbs | 3 +-
.../acceptance/admin-watched-words-test.js | 16 +++++++
.../tests/fixtures/watched-words-fixtures.js | 29 +++++++++++--
.../stylesheets/common/admin/staff_logs.scss | 16 +++++--
app/serializers/watched_word_serializer.rb | 10 ++++-
config/locales/client.en.yml | 2 +-
11 files changed, 148 insertions(+), 22 deletions(-)
diff --git a/app/assets/javascripts/admin/addon/components/admin-watched-word.js b/app/assets/javascripts/admin/addon/components/admin-watched-word.js
index fb24a6f388f..1dcee049eb7 100644
--- a/app/assets/javascripts/admin/addon/components/admin-watched-word.js
+++ b/app/assets/javascripts/admin/addon/components/admin-watched-word.js
@@ -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()
diff --git a/app/assets/javascripts/admin/addon/controllers/modals/admin-watched-word-test.js b/app/assets/javascripts/admin/addon/controllers/modals/admin-watched-word-test.js
index 215cc08a6d9..3dfbd278b56 100644
--- a/app/assets/javascripts/admin/addon/controllers/modals/admin-watched-word-test.js
+++ b/app/assets/javascripts/admin/addon/controllers/modals/admin-watched-word-test.js
@@ -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;
},
});
diff --git a/app/assets/javascripts/admin/addon/templates/components/admin-watched-word.hbs b/app/assets/javascripts/admin/addon/templates/components/admin-watched-word.hbs
index cc034965108..26f8a9ebbda 100644
--- a/app/assets/javascripts/admin/addon/templates/components/admin-watched-word.hbs
+++ b/app/assets/javascripts/admin/addon/templates/components/admin-watched-word.hbs
@@ -1 +1,9 @@
-{{d-icon "times"}} {{word.word}} {{#if word.replacement}}→ {{word.replacement}}{{/if}}
+{{d-icon "times"}} {{word.word}}
+{{#if isReplace}}
+ → {{word.replacement}}
+{{else if isTag}}
+ →
+ {{#each tags as |tag|}}
+ {{tag}}
+ {{/each}}
+{{/if}}
diff --git a/app/assets/javascripts/admin/addon/templates/components/watched-word-form.hbs b/app/assets/javascripts/admin/addon/templates/components/watched-word-form.hbs
index dbc7c8603f5..8d10aeb14da 100644
--- a/app/assets/javascripts/admin/addon/templates/components/watched-word-form.hbs
+++ b/app/assets/javascripts/admin/addon/templates/components/watched-word-form.hbs
@@ -6,14 +6,14 @@
{{#if canReplace}}
- {{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"}}
{{/if}}
{{#if canTag}}
- {{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"}}
{{/if}}
diff --git a/app/assets/javascripts/admin/addon/templates/modal/admin-watched-word-test.hbs b/app/assets/javascripts/admin/addon/templates/modal/admin-watched-word-test.hbs
index ef56567cdd6..2b2361bb35b 100644
--- a/app/assets/javascripts/admin/addon/templates/modal/admin-watched-word-test.hbs
+++ b/app/assets/javascripts/admin/addon/templates/modal/admin-watched-word-test.hbs
@@ -5,9 +5,29 @@
{{i18n "admin.watched_words.test.found_matches"}}
- {{#each matches as |match|}}
- - {{match}}
- {{/each}}
+ {{#if isReplace}}
+ {{#each matches as |match|}}
+ -
+ {{match.match}}
+ →
+ {{match.replacement}}
+
+ {{/each}}
+ {{else if isTag}}
+ {{#each matches as |match|}}
+ -
+ {{match.match}}
+ →
+ {{#each match.tags as |tag|}}
+ {{tag}}
+ {{/each}}
+
+ {{/each}}
+ {{else}}
+ {{#each matches as |match|}}
+ - {{match}}
+ {{/each}}
+ {{/if}}
{{else}}
diff --git a/app/assets/javascripts/admin/addon/templates/watched-words-action.hbs b/app/assets/javascripts/admin/addon/templates/watched-words-action.hbs
index d17ce9e300f..e6b9c772240 100644
--- a/app/assets/javascripts/admin/addon/templates/watched-words-action.hbs
+++ b/app/assets/javascripts/admin/addon/templates/watched-words-action.hbs
@@ -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}}
{{#each filteredContent as |word| }}
-
{{admin-watched-word word=word action=(action "recordRemoved")}}
+
{{admin-watched-word actionKey=actionNameKey word=word action=(action "recordRemoved")}}
{{/each}}
{{/if}}
diff --git a/app/assets/javascripts/discourse/tests/acceptance/admin-watched-words-test.js b/app/assets/javascripts/discourse/tests/acceptance/admin-watched-words-test.js
index 1a3162e242a..4094f6ba079 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/admin-watched-words-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/admin-watched-words-test.js
@@ -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");
+ });
});
diff --git a/app/assets/javascripts/discourse/tests/fixtures/watched-words-fixtures.js b/app/assets/javascripts/discourse/tests/fixtures/watched-words-fixtures.js
index 8fca803089e..8a6ead382b6 100644
--- a/app/assets/javascripts/discourse/tests/fixtures/watched-words-fixtures.js
+++ b/app/assets/javascripts/discourse/tests/fixtures/watched-words-fixtures.js
@@ -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: '', action: "block" }
+ { id: 6, word: '', 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|)(?=\\W|$)',
+ censor: null,
+ require_approval: "(?:\\W|^)(coupon)(?=\\W|$)",
+ flag: "(?:\\W|^)(pyramid|scheme)(?=\\W|$)",
+ replace: "(?:\\W|^)(hi)(?=\\W|$)",
+ tag: "(?:\\W|^)(hello)(?=\\W|$)",
+ },
+ },
};
diff --git a/app/assets/stylesheets/common/admin/staff_logs.scss b/app/assets/stylesheets/common/admin/staff_logs.scss
index 4c9c9958470..8b5c1e37cc6 100644
--- a/app/assets/stylesheets/common/admin/staff_logs.scss
+++ b/app/assets/stylesheets/common/admin/staff_logs.scss
@@ -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
diff --git a/app/serializers/watched_word_serializer.rb b/app/serializers/watched_word_serializer.rb
index 0a73b4a2a32..6cc7972f0c9 100644
--- a/app/serializers/watched_word_serializer.rb
+++ b/app/serializers/watched_word_serializer.rb
@@ -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]
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index ba78980f2c8..5d6f24931d7 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -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"