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

View File

@ -245,8 +245,8 @@ export default Controller.extend({
const searchKey = getSearchKey(args); const searchKey = getSearchKey(args);
ajax("/search", { data: args }) ajax("/search", { data: args })
.then((results) => { .then(async (results) => {
const model = translateResults(results) || {}; const model = (await translateResults(results)) || {};
if (results.grouped_search_result) { if (results.grouped_search_result) {
this.set("q", results.grouped_search_result.term); 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 { replaceFormatter } from "discourse/lib/utilities";
import { replaceTagRenderer } from "discourse/lib/render-tag"; import { replaceTagRenderer } from "discourse/lib/render-tag";
import { setNewCategoryDefaultColors } from "discourse/routes/new-category"; 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 // 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 { class PluginApi {
constructor(version, container) { constructor(version, container) {
@ -1281,6 +1282,21 @@ class PluginApi {
setNewCategoryDefaultColors(backgroundColor, textColor) { setNewCategoryDefaultColors(backgroundColor, textColor) {
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 // 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 Category from "discourse/models/category";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import I18n from "I18n"; import I18n from "I18n";
import { Promise } from "rsvp";
import Post from "discourse/models/post"; import Post from "discourse/models/post";
import Topic from "discourse/models/topic"; import Topic from "discourse/models/topic";
import User from "discourse/models/user"; 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 { userPath } from "discourse/lib/url";
import userSearch from "discourse/lib/user-search"; import userSearch from "discourse/lib/user-search";
const translateResultsCallbacks = [];
export function addSearchResultsCallback(callback) {
translateResultsCallbacks.push(callback);
}
export function translateResults(results, opts) { export function translateResults(results, opts) {
opts = opts || {}; opts = opts || {};
@ -84,9 +91,29 @@ export function translateResults(results, opts) {
}) })
.compact(); .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; const groupedSearchResult = results.grouped_search_result;
if (groupedSearchResult) { 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) { export function searchForTerm(term, opts) {
@ -157,12 +175,9 @@ export function searchForTerm(term, opts) {
}; };
} }
let promise = ajax("/search/query", { data: data }); let ajaxPromise = ajax("/search/query", { data });
const promise = ajaxPromise.then((res) => translateResults(res, opts));
promise.then((results) => { promise.abort = ajaxPromise.abort;
return translateResults(results, opts);
});
return promise; return promise;
} }

View File

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

View File

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

View File

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

View File

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