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"}}

{{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"