Dashboards/search: improve openapi spec (#111575)

Co-authored-by: Clarity-89 <homes89@ukr.net>
This commit is contained in:
Ryan McKinley
2025-09-25 11:08:47 +00:00
committed by GitHub
co-authored by Clarity-89
parent 9d682ce774
commit 7b1413ec54
5 changed files with 125 additions and 37 deletions
+57 -20
View File
@@ -85,6 +85,15 @@ func (s *SearchHandler) GetAPIRoutes(defs map[string]common.OpenAPIDefinition) *
Schema: spec.StringProperty(),
},
},
{
ParameterProps: spec3.ParameterProps{
Name: "type",
In: "query",
Description: "search dashboards or folders. When empty, this will search both",
Required: false,
Schema: spec.StringProperty().WithEnum("folder", "dashboard"),
},
},
{
ParameterProps: spec3.ParameterProps{
Name: "folder",
@@ -94,6 +103,24 @@ func (s *SearchHandler) GetAPIRoutes(defs map[string]common.OpenAPIDefinition) *
Schema: spec.StringProperty(),
},
},
{
ParameterProps: spec3.ParameterProps{
Name: "facet",
In: "query",
Description: "count distinct terms for selected fields",
Required: false,
Schema: spec.ArrayProperty(spec.StringProperty()),
},
},
{
ParameterProps: spec3.ParameterProps{
Name: "tags",
In: "query",
Description: "tag query filter",
Required: false,
Schema: spec.ArrayProperty(spec.StringProperty()),
},
},
{
ParameterProps: spec3.ParameterProps{
Name: "sort",
@@ -124,6 +151,24 @@ func (s *SearchHandler) GetAPIRoutes(defs map[string]common.OpenAPIDefinition) *
Schema: spec.StringProperty(),
},
},
{
ParameterProps: spec3.ParameterProps{
Name: "limit",
In: "query",
Description: "number of results to return",
Required: false,
Schema: spec.Int64Property(),
},
},
{
ParameterProps: spec3.ParameterProps{
Name: "explain",
In: "query",
Description: "add debugging info that may help explain why the result matched",
Required: false,
Schema: spec.BoolProperty(),
},
},
},
Responses: &spec3.Responses{
ResponsesProps: spec3.ResponsesProps{
@@ -257,33 +302,25 @@ func (s *SearchHandler) DoSearch(w http.ResponseWriter, r *http.Request) {
}
searchRequest.Fields = fields
types := queryParams["type"]
var federate *resourcepb.ResourceKey
switch len(types) {
case 0:
// When no type specified, search for dashboards
// Search dashboards or folders (or both)
switch queryParams.Get("type") {
case "folder":
searchRequest.Options.Key, err = asResourceKey(user.GetNamespace(), folders.RESOURCE)
case "dashboard":
searchRequest.Options.Key, err = asResourceKey(user.GetNamespace(), dashboardv0alpha1.DASHBOARD_RESOURCE)
// Currently a search query is across folders and dashboards
if err == nil {
federate, err = asResourceKey(user.GetNamespace(), folders.RESOURCE)
}
case 1:
searchRequest.Options.Key, err = asResourceKey(user.GetNamespace(), types[0])
case 2:
searchRequest.Options.Key, err = asResourceKey(user.GetNamespace(), types[0])
if err == nil {
federate, err = asResourceKey(user.GetNamespace(), types[1])
}
default:
err = apierrors.NewBadRequest("too many type requests")
searchRequest.Options.Key, err = asResourceKey(user.GetNamespace(), dashboardv0alpha1.DASHBOARD_RESOURCE)
if err == nil {
federate, _ := asResourceKey(user.GetNamespace(), folders.RESOURCE)
if federate != nil {
searchRequest.Federated = []*resourcepb.ResourceKey{federate}
}
}
}
if err != nil {
errhttp.Write(ctx, err, w)
return
}
if federate != nil {
searchRequest.Federated = []*resourcepb.ResourceKey{federate}
}
// Add sorting
if queryParams.Has("sort") {
@@ -1770,6 +1770,18 @@
"type": "string"
}
},
{
"name": "type",
"in": "query",
"description": "search dashboards or folders. When empty, this will search both",
"schema": {
"type": "string",
"enum": [
"folder",
"dashboard"
]
}
},
{
"name": "folder",
"in": "query",
@@ -1778,6 +1790,28 @@
"type": "string"
}
},
{
"name": "facet",
"in": "query",
"description": "count distinct terms for selected fields",
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
},
{
"name": "tags",
"in": "query",
"description": "tag query filter",
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
},
{
"name": "sort",
"in": "query",
@@ -1798,6 +1832,23 @@
"value": "title"
}
}
},
{
"name": "limit",
"in": "query",
"description": "number of results to return",
"schema": {
"type": "integer",
"format": "int64"
}
},
{
"name": "explain",
"in": "query",
"description": "add debugging info that may help explain why the result matched",
"schema": {
"type": "boolean"
}
}
],
"responses": {
@@ -11,8 +11,13 @@ const injectedRtkApi = api
url: `/search`,
params: {
query: queryArg.query,
type: queryArg['type'],
folder: queryArg.folder,
facet: queryArg.facet,
tags: queryArg.tags,
sort: queryArg.sort,
limit: queryArg.limit,
explain: queryArg.explain,
},
}),
providesTags: ['Search'],
@@ -46,8 +51,18 @@ export type GetSearchApiResponse = /** status 200 undefined */ {
export type GetSearchApiArg = {
/** user query string */
query?: string;
/** search dashboards or folders. When empty, this will search both */
type?: 'folder' | 'dashboard';
/** search/list within a folder (not recursive) */
folder?: string;
/** count distinct terms for selected fields */
facet?: string[];
/** tag query filter */
tags?: string[];
/** sortable field */
sort?: string;
/** number of results to return */
limit?: number;
/** add debugging info that may help explain why the result matched */
explain?: boolean;
};
@@ -1,25 +1,10 @@
import { generatedAPI, GetSearchApiArg } from './endpoints.gen';
type OverrideGetSearchRequestOptions = GetSearchApiArg & {
type: string;
};
import { generatedAPI } from './endpoints.gen';
export const dashboardAPIv0alpha1 = generatedAPI.enhanceEndpoints({
addTagTypes: ['Folder', 'Dashboard'],
endpoints: {
getSearch: (endpointDefinition) => {
const originalQuery = endpointDefinition.query;
endpointDefinition.providesTags = ['Search', 'Folder', 'Dashboard'];
if (originalQuery) {
// TODO: Remove once API spec is updated with `type`
endpointDefinition.query = (requestOptions: OverrideGetSearchRequestOptions) => ({
...originalQuery(requestOptions),
params: {
...requestOptions,
type: requestOptions.type,
},
});
}
},
},
});
@@ -86,7 +86,7 @@ export function useFoldersQueryAppPlatform({
return;
}
const args = { folder: finalParentUid, type: 'folder' };
const args = { folder: finalParentUid, type: 'folder' } as const;
// Make a request
const subscription = dispatch(dashboardAPIv0alpha1.endpoints.getSearch.initiate(args));