From 89888804393720c10aab9f03f33d54d039d32a2b Mon Sep 17 00:00:00 2001 From: Meier Lukas Date: Tue, 9 Apr 2024 21:51:00 +0200 Subject: [PATCH] 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 --- packages/spotlight/src/data-store.ts | 2 +- packages/translation/src/lang/en.ts | 1 + packages/widgets/package.json | 1 + packages/widgets/src/app/component.tsx | 28 +++++++++++++++++++++++--- packages/widgets/src/app/serverData.ts | 8 ++++++-- pnpm-lock.yaml | 3 +++ 6 files changed, 37 insertions(+), 6 deletions(-) diff --git a/packages/spotlight/src/data-store.ts b/packages/spotlight/src/data-store.ts index 31bcf1cba..f217ae2ee 100644 --- a/packages/spotlight/src/data-store.ts +++ b/packages/spotlight/src/data-store.ts @@ -5,7 +5,7 @@ import useDeepCompareEffect from "use-deep-compare-effect"; import type { SpotlightActionData, SpotlightActionGroup } from "./type"; const defaultGroups = ["all", "web", "action"] as const; -const reversedDefaultGroups = [...defaultGroups].reverse(); +const reversedDefaultGroups = [...defaultGroups].reverse() as string[]; const actionsAtom = atom>({}); export const actionsAtomRead = atom((get) => Object.values(get(actionsAtom)).flatMap((item) => item), diff --git a/packages/translation/src/lang/en.ts b/packages/translation/src/lang/en.ts index fadbef39a..316192669 100644 --- a/packages/translation/src/lang/en.ts +++ b/packages/translation/src/lang/en.ts @@ -219,6 +219,7 @@ export default { all: "All", web: "Web", action: "Actions", + app: "Apps", }, }, userAvatar: { diff --git a/packages/widgets/package.json b/packages/widgets/package.json index 4c0d03753..03be539b0 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -39,6 +39,7 @@ "@homarr/form": "workspace:^0.1.0", "@homarr/modals": "workspace:^0.1.0", "@homarr/notifications": "workspace:^0.1.0", + "@homarr/spotlight": "workspace:^0.1.0", "@homarr/redis": "workspace:^0.1.0", "@homarr/translation": "workspace:^0.1.0", "@homarr/ui": "workspace:^0.1.0", diff --git a/packages/widgets/src/app/component.tsx b/packages/widgets/src/app/component.tsx index 4e5b6a51c..df69f8e6a 100644 --- a/packages/widgets/src/app/component.tsx +++ b/packages/widgets/src/app/component.tsx @@ -3,6 +3,7 @@ import type { PropsWithChildren } from "react"; import { clientApi } from "@homarr/api/client"; +import { useRegisterSpotlightActions } from "@homarr/spotlight"; import { useScopedI18n } from "@homarr/translation/client"; import { Center, @@ -26,6 +27,7 @@ export default function AppWidget({ height, }: WidgetComponentProps<"app">) { const t = useScopedI18n("widget.app"); + const isQueryEnabled = Boolean(options.appId); const { data: app, isPending, @@ -37,14 +39,34 @@ export default function AppWidget({ { initialData: // 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, refetchOnWindowFocus: 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 (
@@ -52,7 +74,7 @@ export default function AppWidget({ ); } - if (isError) { + if (isError || !isQueryEnabled) { return ( diff --git a/packages/widgets/src/app/serverData.ts b/packages/widgets/src/app/serverData.ts index b21097779..3783692e2 100644 --- a/packages/widgets/src/app/serverData.ts +++ b/packages/widgets/src/app/serverData.ts @@ -5,6 +5,10 @@ import { api } from "@homarr/api/server"; import type { WidgetProps } from "../definition"; export default async function getServerData({ options }: WidgetProps<"app">) { - const app = await api.app.byId({ id: options.appId }); - return { app }; + try { + const app = await api.app.byId({ id: options.appId }); + return { app }; + } catch (error) { + return { app: null }; + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6272bcf6b..e9b37d158 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -804,6 +804,9 @@ importers: '@homarr/redis': specifier: workspace:^0.1.0 version: link:../redis + '@homarr/spotlight': + specifier: workspace:^0.1.0 + version: link:../spotlight '@homarr/translation': specifier: workspace:^0.1.0 version: link:../translation