feat: add app actions (#322)

* feat: add app actions

* fix: broken lockfile

* fix: app should only load when one is selected and server data not fail when no app found

* fix: add missing dependency

* fix: format issue
This commit is contained in:
Meier Lukas
2024-04-09 21:51:00 +02:00
committed by GitHub
parent e6e6e4e7d6
commit 8988880439
6 changed files with 37 additions and 6 deletions

View File

@@ -5,7 +5,7 @@ import useDeepCompareEffect from "use-deep-compare-effect";
import type { SpotlightActionData, SpotlightActionGroup } from "./type"; import type { SpotlightActionData, SpotlightActionGroup } from "./type";
const defaultGroups = ["all", "web", "action"] as const; const defaultGroups = ["all", "web", "action"] as const;
const reversedDefaultGroups = [...defaultGroups].reverse(); const reversedDefaultGroups = [...defaultGroups].reverse() as string[];
const actionsAtom = atom<Record<string, readonly SpotlightActionData[]>>({}); const actionsAtom = atom<Record<string, readonly SpotlightActionData[]>>({});
export const actionsAtomRead = atom((get) => export const actionsAtomRead = atom((get) =>
Object.values(get(actionsAtom)).flatMap((item) => item), Object.values(get(actionsAtom)).flatMap((item) => item),

View File

@@ -219,6 +219,7 @@ export default {
all: "All", all: "All",
web: "Web", web: "Web",
action: "Actions", action: "Actions",
app: "Apps",
}, },
}, },
userAvatar: { userAvatar: {

View File

@@ -39,6 +39,7 @@
"@homarr/form": "workspace:^0.1.0", "@homarr/form": "workspace:^0.1.0",
"@homarr/modals": "workspace:^0.1.0", "@homarr/modals": "workspace:^0.1.0",
"@homarr/notifications": "workspace:^0.1.0", "@homarr/notifications": "workspace:^0.1.0",
"@homarr/spotlight": "workspace:^0.1.0",
"@homarr/redis": "workspace:^0.1.0", "@homarr/redis": "workspace:^0.1.0",
"@homarr/translation": "workspace:^0.1.0", "@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0", "@homarr/ui": "workspace:^0.1.0",

View File

@@ -3,6 +3,7 @@
import type { PropsWithChildren } from "react"; import type { PropsWithChildren } from "react";
import { clientApi } from "@homarr/api/client"; import { clientApi } from "@homarr/api/client";
import { useRegisterSpotlightActions } from "@homarr/spotlight";
import { useScopedI18n } from "@homarr/translation/client"; import { useScopedI18n } from "@homarr/translation/client";
import { import {
Center, Center,
@@ -26,6 +27,7 @@ export default function AppWidget({
height, height,
}: WidgetComponentProps<"app">) { }: WidgetComponentProps<"app">) {
const t = useScopedI18n("widget.app"); const t = useScopedI18n("widget.app");
const isQueryEnabled = Boolean(options.appId);
const { const {
data: app, data: app,
isPending, isPending,
@@ -37,14 +39,34 @@ export default function AppWidget({
{ {
initialData: initialData:
// We need to check if the id's match because otherwise the same initialData for a changed id will be used // We need to check if the id's match because otherwise the same initialData for a changed id will be used
serverData?.app.id === options.appId ? serverData?.app : undefined, serverData?.app?.id === options.appId ? serverData?.app : undefined,
refetchOnMount: false, refetchOnMount: false,
refetchOnWindowFocus: false, refetchOnWindowFocus: false,
refetchOnReconnect: false, refetchOnReconnect: false,
enabled: isQueryEnabled,
}, },
); );
if (isPending) { useRegisterSpotlightActions(
`app-${options.appId}`,
app?.href
? [
{
id: `app-${options.appId}`,
title: app?.name,
description: app?.description ?? "",
icon: app?.iconUrl,
group: "app",
type: "link",
href: app?.href,
openInNewTab: options.openInNewTab,
},
]
: [],
[app, options.appId, options.openInNewTab],
);
if (isPending && isQueryEnabled) {
return ( return (
<Center h="100%"> <Center h="100%">
<Loader /> <Loader />
@@ -52,7 +74,7 @@ export default function AppWidget({
); );
} }
if (isError) { if (isError || !isQueryEnabled) {
return ( return (
<Tooltip.Floating label={t("error.notFound.tooltip")}> <Tooltip.Floating label={t("error.notFound.tooltip")}>
<Stack gap="xs" align="center" justify="center" h="100%" w="100%"> <Stack gap="xs" align="center" justify="center" h="100%" w="100%">

View File

@@ -5,6 +5,10 @@ import { api } from "@homarr/api/server";
import type { WidgetProps } from "../definition"; import type { WidgetProps } from "../definition";
export default async function getServerData({ options }: WidgetProps<"app">) { export default async function getServerData({ options }: WidgetProps<"app">) {
const app = await api.app.byId({ id: options.appId }); try {
return { app }; const app = await api.app.byId({ id: options.appId });
return { app };
} catch (error) {
return { app: null };
}
} }

3
pnpm-lock.yaml generated
View File

@@ -804,6 +804,9 @@ importers:
'@homarr/redis': '@homarr/redis':
specifier: workspace:^0.1.0 specifier: workspace:^0.1.0
version: link:../redis version: link:../redis
'@homarr/spotlight':
specifier: workspace:^0.1.0
version: link:../spotlight
'@homarr/translation': '@homarr/translation':
specifier: workspace:^0.1.0 specifier: workspace:^0.1.0
version: link:../translation version: link:../translation