DEV: Add plugin API to extend search results (#12966)

This commit is contained in:
Dan Ungureanu 2021-06-15 08:32:41 +03:00 committed by GitHub
parent 9190e4390f
commit ff4fb9c771
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 67 additions and 30 deletions

View File

@ -20,7 +20,7 @@ export default DiscourseRoute.extend({
search_type: params.searchType,
term: params.term,
},
}).then((json) => {
}).then(async (json) => {
// Add zero values for missing dates
if (json.term.data.length > 0) {
const startDate =
@ -31,7 +31,9 @@ export default DiscourseRoute.extend({
json.term.data = fillMissingDates(json.term.data, startDate, endDate);
}
if (json.term.search_result) {
json.term.search_result = translateResults(json.term.search_result);
json.term.search_result = await translateResults(
json.term.search_result
);
}
const model = EmberObject.create({ type: "search_log_term" });

View File

@ -245,8 +245,8 @@ export default Controller.extend({
const searchKey = getSearchKey(args);
ajax("/search", { data: args })
.then((results) => {
const model = translateResults(results) || {};
.then(async (results) => {
const model = (await translateResults(results)) || {};
if (results.grouped_search_result) {
this.set("q", results.grouped_search_result.term);

View File

@ -72,9 +72,10 @@ import { registerTopicFooterButton } from "discourse/lib/register-topic-footer-b
import { replaceFormatter } from "discourse/lib/utilities";
import { replaceTagRenderer } from "discourse/lib/render-tag";
import { setNewCategoryDefaultColors } from "discourse/routes/new-category";
import { addSearchResultsCallback } from "discourse/lib/search";
// If you add any methods to the API ensure you bump up this number
const PLUGIN_API_VERSION = "0.11.4";
const PLUGIN_API_VERSION = "0.11.5";
class PluginApi {
constructor(version, container) {
@ -1281,6 +1282,21 @@ class PluginApi {
setNewCategoryDefaultColors(backgroundColor, textColor) {
setNewCategoryDefaultColors(backgroundColor, textColor);
}
/**
* Add a callback to modify search results before displaying them.
*
* ```
* api.addSearchResultsCallback((results) => {
* results.topics.push(Topic.create({ ... }));
* return results;
* });
* ```
*
*/
addSearchResultsCallback(callback) {
addSearchResultsCallback(callback);
}
}
// from http://stackoverflow.com/questions/6832596/how-to-compare-software-version-number-using-js-only-number

View File

@ -1,6 +1,7 @@
import Category from "discourse/models/category";
import EmberObject from "@ember/object";
import I18n from "I18n";
import { Promise } from "rsvp";
import Post from "discourse/models/post";
import Topic from "discourse/models/topic";
import User from "discourse/models/user";
@ -15,6 +16,12 @@ import { search as searchCategoryTag } from "discourse/lib/category-tag-search";
import { userPath } from "discourse/lib/url";
import userSearch from "discourse/lib/user-search";
const translateResultsCallbacks = [];
export function addSearchResultsCallback(callback) {
translateResultsCallbacks.push(callback);
}
export function translateResults(results, opts) {
opts = opts || {};
@ -84,9 +91,29 @@ export function translateResults(results, opts) {
})
.compact();
results.resultTypes = [];
return translateResultsCallbacks
.reduce(
(promise, callback) => promise.then((r) => callback(r)),
Promise.resolve(results)
)
.then((results_) => {
translateGroupedSearchResults(results_, opts);
// TODO: consider refactoring front end to take a better structure
if (
!results_.topics.length &&
!results_.posts.length &&
!results_.users.length &&
!results_.categories.length
) {
return null;
}
return EmberObject.create(results_);
});
}
function translateGroupedSearchResults(results, opts) {
results.resultTypes = [];
const groupedSearchResult = results.grouped_search_result;
if (groupedSearchResult) {
[
@ -121,15 +148,6 @@ export function translateResults(results, opts) {
}
});
}
const noResults = !!(
!results.topics.length &&
!results.posts.length &&
!results.users.length &&
!results.categories.length
);
return noResults ? null : EmberObject.create(results);
}
export function searchForTerm(term, opts) {
@ -157,12 +175,9 @@ export function searchForTerm(term, opts) {
};
}
let promise = ajax("/search/query", { data: data });
promise.then((results) => {
return translateResults(results, opts);
});
let ajaxPromise = ajax("/search/query", { data });
const promise = ajaxPromise.then((res) => translateResults(res, opts));
promise.abort = ajaxPromise.abort;
return promise;
}

View File

@ -52,11 +52,11 @@ export default DiscourseRoute.extend({
} else {
return null;
}
}).then((results) => {
}).then(async (results) => {
const grouped_search_result = results
? results.grouped_search_result
: {};
const model = (results && translateResults(results)) || {
const model = (results && (await translateResults(results))) || {
grouped_search_result,
};
setTransient("lastSearch", { searchKey, model }, 5);

View File

@ -55,12 +55,12 @@ const SearchHelper = {
fullSearchUrl,
});
this._activeSearch
.then((content) => {
.then((results) => {
// we ensure the current search term is the one used
// when starting the query
if (term === searchData.term) {
searchData.noResults = content.resultTypes.length === 0;
searchData.results = content;
if (results && term === searchData.term) {
searchData.noResults = results.resultTypes.length === 0;
searchData.results = results;
if (searchContext && searchContext.type === "topic") {
widget.appEvents.trigger("post-stream:refresh", { force: true });

View File

@ -6,7 +6,7 @@ import {
import I18n from "I18n";
module("Unit | Utility | search", function () {
test("unescapesEmojisInBlurbs", function (assert) {
test("unescapesEmojisInBlurbs", async function (assert) {
const source = {
posts: [
{
@ -28,7 +28,7 @@ module("Unit | Utility | search", function () {
grouped_search_result: false,
};
const results = translateResults(source);
const results = await translateResults(source);
const blurb = results.posts[0].get("blurb");
assert.ok(blurb.indexOf("thinking.png"));

View File

@ -21,6 +21,10 @@ class SearchPostSerializer < BasicPostSerializer
options[:result].blurb(object)
end
def include_blurb?
options[:result].present?
end
def include_cooked?
false
end