REFACTOR: reworks all the search-advanced-options panel (#10661)

REFACTOR: reworks all the search-advanced-options panel (#10661)

  • REFACTOR: reworks all the search-advanced-options panel

This commit includes the following changes:

  • prevents any mutation of external (to the component) values
  • get rid of observers
  • uses @action
  • minor UI tweaks
  • dropped the unecessary debounce
  • drops all the legacy code for badges/groups which is not being used
  • replaces user-selector by user-chooser and improves multi-select to not show search if maximum has been reached

Most importantly this refactor should fix multiple bugs due to _update() being called multiple times if searchTerm was empty and other various bugs where some changes in searchTerm was not applied to the sidebar.

diff --git a/app/assets/javascripts/discourse/app/components/search-advanced-options.js b/app/assets/javascripts/discourse/app/components/search-advanced-options.js
index 375177a..37bf5c2 100644
--- a/app/assets/javascripts/discourse/app/components/search-advanced-options.js
+++ b/app/assets/javascripts/discourse/app/components/search-advanced-options.js
@@ -1,19 +1,13 @@
 import I18n from "I18n";
-import { debounce, scheduleOnce } from "@ember/runloop";
 import Component from "@ember/component";
-import { observes } from "discourse-common/utils/decorators";
+import { action } from "@ember/object";
 import { escapeExpression } from "discourse/lib/utilities";
-import Group from "discourse/models/group";
-import Badge from "discourse/models/badge";
 import Category from "discourse/models/category";
-import { INPUT_DELAY } from "discourse-common/config/environment";
 
 const REGEXP_BLOCKS = /(([^" \t\n\x0B\f\r]+)?(("[^"]+")?))/g;
 
 const REGEXP_USERNAME_PREFIX = /^(user:|@)/gi;
 const REGEXP_CATEGORY_PREFIX = /^(category:|#)/gi;
-const REGEXP_GROUP_PREFIX = /^group:/gi;
-const REGEXP_BADGE_PREFIX = /^badge:/gi;
 const REGEXP_TAGS_PREFIX = /^(tags?:|#(?=[a-z0-9\-]+::tag))/gi;
 const REGEXP_IN_PREFIX = /^(in|with):/gi;
 const REGEXP_STATUS_PREFIX = /^status:/gi;
@@ -77,30 +71,17 @@ function addAdvancedSearchOptions(options) {
 
 export default Component.extend({
   classNames: ["search-advanced-options"],
+  category: null,
 
   init() {
     this._super(...arguments);
 
-    this._init();
-
-    scheduleOnce("afterRender", this, this._update);
-  },
-
-  @observes("searchTerm")
-  _updateOptions() {
-    this._update();
-    debounce(this, this._update, INPUT_DELAY);
-  },
-
-  _init() {
     this.setProperties({
       searchedTerms: {
-        username: "",
-        category: "",
-        group: [],
-        badge: [],
-        tags: [],
-        in: "",
+        username: null,
+        category: null,
+        tags: null,
+        in: null,
         special: {
           in: {
             title: false,
@@ -110,11 +91,11 @@ export default Component.extend({
           },
           all_tags: false,
         },
-        status: "",
-        min_post_count: "",
+        status: null,
+        min_post_count: null,
         time: {
           when: "before",
-          days: "",
+          days: null,
         },
       },
       inOptions: this.currentUser
@@ -125,16 +106,11 @@ export default Component.extend({
     });
   },
 
-  _update() {
-    if (!this.searchTerm) {
-      this._init();
-      return;
-    }
+  didReceiveAttrs() {
+    this._super(...arguments);
 
     this.setSearchedTermValue("searchedTerms.username", REGEXP_USERNAME_PREFIX);
     this.setSearchedTermValueForCategory();
-    this.setSearchedTermValueForGroup();
-    this.setSearchedTermValueForBadge();
     this.setSearchedTermValueForTags();
 
     let regExpInMatch = this.inOptions.map((option) => option.value).join("|");
@@ -216,14 +192,14 @@ export default Component.extend({
     const match = this.filterBlocks(matchRegEx);
 
     let val = this.get(key);
-
     if (match.length !== 0) {
       const userInput = match[0].replace(replaceRegEx, "");
-      if (val !== userInput) {
+
+      if (val !== userInput && userInput.length) {
         this.set(key, userInput);
       }
     } else if (val && val.length !== 0) {
-      this.set(key, "");
+      this.set(key, null);
     }
   },
 
@@ -239,11 +215,6 @@ export default Component.extend({
     }
   },
 
-  setCategory(category) {
-    this.set("searchedTerms.category", category);
-    this.set("category", category);
-  },
-
   setSearchedTermValueForCategory() {
     const match = this.filterBlocks(REGEXP_CATEGORY_PREFIX);
     if (match.length !== 0) {
@@ -259,61 +230,28 @@ export default Component.extend({
         if (
           (!existingInput && userInput) ||
           (existingInput && userInput && existingInput.id !== userInput.id)
-        )
-          this.setCategory(userInput);
+        ) {
+          this.set("searchedTerms.category", userInput);
+        }
       } else if (isNaN(subcategories)) {
         const userInput = Category.findSingleBySlug(subcategories[0]);
         if (
           (!existingInput && userInput) ||
           (existingInput && userInput && existingInput.id !== userInput.id)
-        )
-          this.setCategory(userInput);
+        ) {
+          this.set("searchedTerms.category", userInput);
+        }
       } else {
         const userInput = Category.findById(subcategories[0]);
         if (
           (!existingInput && userInput) ||
           (existingInput && userInput && existingInput.id !== userInput.id)
-        )
-          this.setCategory(userInput);
+        ) {
+          this.set("searchedTerms.category", userInput);
+        }
       }
-    } else this.set("searchedTerms.category", "");
-  },
-
-  setSearchedTermValueForGroup() {
-    const match = this.filterBlocks(REGEXP_GROUP_PREFIX);
-    const group = this.get("searchedTerms.group");
-
-    if (match.length !== 0) {
-      const existingInput = Array.isArray(group) ? group[0] : group;
-      const userInput = match[0].replace(REGEXP_GROUP_PREFIX, "");
-
-      if (existingInput !== userInput) {
-        this.set(
-          "searchedTerms.group",
-          userInput.length !== 0 ? [userInput] : []
-        );
-      }
-    } else if (group.length !== 0) {
-      this.set("searchedTerms.group", []);
-    }
-  },
-
-  setSearchedTermValueForBadge() {
-    const match = this.filterBlocks(REGEXP_BADGE_PREFIX);
-    const badge = this.get("searchedTerms.badge");
-
-    if (match.length !== 0) {
-      const existingInput = Array.isArray(badge) ? badge[0] : badge;
-      const userInput = match[0].replace(REGEXP_BADGE_PREFIX, "");
-
-      if (existingInput !== userInput) {
-        this.set(
-          "searchedTerms.badge",
-          userInput.length !== 0 ? [userInput] : []
-        );
-      }
-    } else if (badge.length !== 0) {
-      this.set("searchedTerms.badge", []);
+    } else {
+      this.set("searchedTerms.category", null);
     }
   },
 
@@ -322,21 +260,24 @@ export default Component.extend({
 
     const match = this.filterBlocks(REGEXP_TAGS_PREFIX);
     const tags = this.get("searchedTerms.tags");
-    const contain_all_tags = this.get("searchedTerms.special.all_tags");
+    if (match.length) {
+      this.set("searchedTerms.special.all_tags", match[0].includes("+"));
+    }
+    const containAllTags = this.get("searchedTerms.special.all_tags");
 
     if (match.length !== 0) {
-      const join_char = contain_all_tags ? "+" : ",";
-      const existingInput = Array.isArray(tags) ? tags.join(join_char) : tags;
+      const joinChar = containAllTags ? "+" : ",";
+      const existingInput = Array.isArray(tags) ? tags.join(joinChar) : tags;
       const userInput = match[0].replace(REGEXP_TAGS_REPLACE, "");
 
       if (existingInput !== userInput) {
         this.set(
           "searchedTerms.tags",
-          userInput.length !== 0 ? userInput.split(join_char) : []
+          userInput.length !== 0 ? userInput.split(joinChar) : null
         );
       }
-    } else if (tags.length !== 0) {
-      this.set("searchedTerms.tags", []);
+    } else if (!tags) {
+      this.set("searchedTerms.tags", null);
     }
   },
 
@@ -360,32 +301,141 @@ export default Component.extend({
 
       this.setProperties(properties);
     } else {
-      this.set("searchedTerms.time.days", "");
+      this.set("searchedTerms.time.when", "before");
+      this.set("searchedTerms.time.days", null);
     }
   },
 
-  @observes("searchedTerms.username")
-  updateSearchTermForUsername() {
-    const match = this.filterBlocks(REGEXP_USERNAME_PREFIX);
-    const userFilter = this.get("searchedTerms.username");
+  updateInRegex(regex, filter) {
+    const match = this.filterBlocks(regex);
+    const inFilter = this.get("searchedTerms.special.in." + filter);
     let searchTerm = this.searchTerm || "";
 

[... diff too long, it was truncated ...]

GitHub sha: 324aa3eb

This commit appears in #10661 which was approved by ZogStriP and eviltrout. It was merged by jjaffeux.