173 lines
5.6 KiB
TypeScript
173 lines
5.6 KiB
TypeScript
import { Group, Text, useMantineColorScheme } from "@mantine/core";
|
|
import {
|
|
IconCategoryPlus,
|
|
IconFileImport,
|
|
IconLanguage,
|
|
IconMailForward,
|
|
IconMoon,
|
|
IconPackage,
|
|
IconPlug,
|
|
IconSun,
|
|
IconUserPlus,
|
|
IconUsersGroup,
|
|
} from "@tabler/icons-react";
|
|
|
|
import { useSession } from "@homarr/auth/client";
|
|
import { useModalAction } from "@homarr/modals";
|
|
import { AddBoardModal, AddGroupModal, ImportBoardModal, InviteCreateModal } from "@homarr/modals-collection";
|
|
import { useScopedI18n } from "@homarr/translation/client";
|
|
import type { TablerIcon } from "@homarr/ui";
|
|
|
|
import { createGroup } from "../../lib/group";
|
|
import type { inferSearchInteractionDefinition, SearchInteraction } from "../../lib/interaction";
|
|
import { interaction } from "../../lib/interaction";
|
|
import type { SearchMode } from "../../lib/mode";
|
|
import { languageChildrenOptions } from "./children/language";
|
|
import { newIntegrationChildrenOptions } from "./children/new-integration";
|
|
|
|
// This has to be type so it can be interpreted as Record<string, unknown>.
|
|
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
|
type Command<TSearchInteraction extends SearchInteraction = SearchInteraction> = {
|
|
commandKey: string;
|
|
icon: TablerIcon;
|
|
name: string;
|
|
useInteraction: (
|
|
_c: Command<TSearchInteraction>,
|
|
query: string,
|
|
) => inferSearchInteractionDefinition<TSearchInteraction>;
|
|
};
|
|
|
|
export const commandMode = {
|
|
modeKey: "command",
|
|
character: ">",
|
|
groups: [
|
|
createGroup<Command>({
|
|
keyPath: "commandKey",
|
|
title: "Global commands",
|
|
useInteraction: (option, query) => option.useInteraction(option, query),
|
|
Component: ({ icon: Icon, name }) => (
|
|
<Group px="md" py="sm">
|
|
<Icon stroke={1.5} />
|
|
<Text>{name}</Text>
|
|
</Group>
|
|
),
|
|
filter(query, option) {
|
|
return option.name.toLowerCase().includes(query.toLowerCase());
|
|
},
|
|
useOptions() {
|
|
const tOption = useScopedI18n("search.mode.command.group.globalCommand.option");
|
|
const { colorScheme } = useMantineColorScheme();
|
|
const { data: session } = useSession();
|
|
|
|
const commands: (Command & { hidden?: boolean })[] = [
|
|
{
|
|
commandKey: "colorScheme",
|
|
icon: colorScheme === "dark" ? IconSun : IconMoon,
|
|
name: tOption(`colorScheme.${colorScheme === "dark" ? "light" : "dark"}`),
|
|
useInteraction: () => {
|
|
const { toggleColorScheme } = useMantineColorScheme();
|
|
|
|
return {
|
|
type: "javaScript",
|
|
onSelect: toggleColorScheme,
|
|
};
|
|
},
|
|
},
|
|
{
|
|
commandKey: "language",
|
|
icon: IconLanguage,
|
|
name: tOption("language.label"),
|
|
useInteraction: interaction.children(languageChildrenOptions),
|
|
},
|
|
{
|
|
commandKey: "newBoard",
|
|
icon: IconCategoryPlus,
|
|
name: tOption("newBoard.label"),
|
|
useInteraction() {
|
|
const { openModal } = useModalAction(AddBoardModal);
|
|
|
|
return {
|
|
type: "javaScript",
|
|
onSelect() {
|
|
openModal(undefined);
|
|
},
|
|
};
|
|
},
|
|
hidden: !session?.user.permissions.includes("board-create"),
|
|
},
|
|
{
|
|
commandKey: "importBoard",
|
|
icon: IconFileImport,
|
|
name: tOption("importBoard.label"),
|
|
useInteraction() {
|
|
const { openModal } = useModalAction(ImportBoardModal);
|
|
|
|
return {
|
|
type: "javaScript",
|
|
onSelect() {
|
|
openModal(undefined);
|
|
},
|
|
};
|
|
},
|
|
hidden: !session?.user.permissions.includes("board-create"),
|
|
},
|
|
{
|
|
commandKey: "newApp",
|
|
icon: IconPackage,
|
|
name: tOption("newApp.label"),
|
|
useInteraction: interaction.link(() => ({ href: "/manage/apps/new" })),
|
|
},
|
|
{
|
|
commandKey: "newIntegration",
|
|
icon: IconPlug,
|
|
name: tOption("newIntegration.label"),
|
|
useInteraction: interaction.children(newIntegrationChildrenOptions),
|
|
hidden: !session?.user.permissions.includes("integration-create"),
|
|
},
|
|
{
|
|
commandKey: "newUser",
|
|
icon: IconUserPlus,
|
|
name: tOption("newUser.label"),
|
|
useInteraction: interaction.link(() => ({ href: "/manage/users/new" })),
|
|
hidden: !session?.user.permissions.includes("admin"),
|
|
},
|
|
{
|
|
commandKey: "newInvite",
|
|
icon: IconMailForward,
|
|
name: tOption("newInvite.label"),
|
|
useInteraction() {
|
|
const { openModal } = useModalAction(InviteCreateModal);
|
|
|
|
return {
|
|
type: "javaScript",
|
|
onSelect() {
|
|
openModal(undefined);
|
|
},
|
|
};
|
|
},
|
|
hidden: !session?.user.permissions.includes("admin"),
|
|
},
|
|
{
|
|
commandKey: "newGroup",
|
|
icon: IconUsersGroup,
|
|
name: tOption("newGroup.label"),
|
|
useInteraction() {
|
|
const { openModal } = useModalAction(AddGroupModal);
|
|
|
|
return {
|
|
type: "javaScript",
|
|
onSelect() {
|
|
openModal(undefined);
|
|
},
|
|
};
|
|
},
|
|
hidden: !session?.user.permissions.includes("admin"),
|
|
},
|
|
];
|
|
|
|
return commands.filter((command) => !command.hidden);
|
|
},
|
|
}),
|
|
],
|
|
} satisfies SearchMode;
|