feat: add improved search (#1051)

* feat: add improved search

* wip: add support for sorting, rename use-options to use-query-options, add use-options for local usage, add pages search group

* feat: add help links from manage layout to help search mode

* feat: add additional search engines

* feat: add group search details

* refactor: improve users search group type

* feat: add apps search group, add disabled search interaction

* feat: add integrations and boards for search

* wip: hook issue with react

* fix: hook issue regarding actions and interactions

* chore: address pull request feedback

* fix: format issues

* feat: add additional global actions to search

* chore: remove unused code

* fix: search engine short key

* fix: typecheck issues

* fix: deepsource issues

* fix: eslint issue

* fix: lint issues

* fix: unordered dependencies

* chore: address pull request feedback
This commit is contained in:
Meier Lukas
2024-09-20 16:51:42 +02:00
committed by GitHub
parent 0c44af2f67
commit ce1ef3cbe7
64 changed files with 1985 additions and 628 deletions

View File

@@ -0,0 +1,56 @@
import type { MaybePromise } from "@homarr/common/types";
import type { TranslationObject } from "@homarr/translation";
import type { CreateChildrenOptionsProps } from "./children";
const createSearchInteraction = <TType extends string>(type: TType) => ({
optionsType: <TOption extends Record<string, unknown>>() => ({ type, _inferOptions: {} as TOption }),
});
// This is used to define search interactions with their options
const searchInteractions = [
createSearchInteraction("link").optionsType<{ href: string; newTab?: boolean }>(),
createSearchInteraction("javaScript").optionsType<{ onSelect: () => MaybePromise<void> }>(),
createSearchInteraction("mode").optionsType<{ mode: keyof TranslationObject["search"]["mode"] }>(),
createSearchInteraction("children").optionsType<{
// eslint-disable-next-line @typescript-eslint/no-explicit-any
useActions: CreateChildrenOptionsProps<any>["useActions"];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
detailComponent: CreateChildrenOptionsProps<any>["detailComponent"];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
option: any;
}>(),
] as const;
// Union of all search interactions types
export type SearchInteraction = (typeof searchInteractions)[number]["type"];
// Infer the options for the specified search interaction
export type inferSearchInteractionOptions<TInteraction extends SearchInteraction> = Extract<
(typeof searchInteractions)[number],
{ type: TInteraction }
>["_inferOptions"];
// Infer the search interaction definition (type + options) for the specified search interaction
export type inferSearchInteractionDefinition<TInteraction extends SearchInteraction> = {
[interactionKey in TInteraction]: { type: interactionKey } & inferSearchInteractionOptions<interactionKey>;
}[TInteraction];
// Type used for helper functions to define basic search interactions
type SearchInteractions = {
[optionKey in SearchInteraction]: <TOption extends Record<string, unknown>>(
callback: (option: TOption, query: string) => inferSearchInteractionOptions<optionKey>,
) => (option: TOption, query: string) => inferSearchInteractionDefinition<optionKey>;
};
// Helper functions to define basic search interactions
export const interaction = searchInteractions.reduce((acc, interaction) => {
return {
...acc,
[interaction.type]: <TOption extends Record<string, unknown>>(
callback: (option: TOption, query: string) => inferSearchInteractionOptions<SearchInteraction>,
) => {
return (option: TOption, query: string) => ({ type: interaction.type, ...callback(option, query) });
},
};
}, {} as SearchInteractions);