feat(widgets): consolidate integration metadata + shared response caching (#6691)
This commit is contained in:
1 parent
7d1d9062ed
commit
8d8dec5749
206 files changed
+3893
-1946
No files matched your search
@@ -8,7 +8,7 @@ describe("buildSortedIntegrations", () => {
|
||||
it("keeps every real integration available during onboarding", () => {
|
||||
const kinds = buildSortedIntegrations({ onboarding: true }).map((integration) => integration.kind);
|
||||
|
||||
expect(kinds).toHaveLength(integrationKinds.length - 1);
|
||||
expect(kinds).toHaveLength(integrationKinds.filter((kind) => kind !== "mock").length);
|
||||
expect(kinds).not.toContain("mock");
|
||||
});
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import type { IntegrationKind, WidgetKind } from "@homarr/definitions";
|
||||
import {
|
||||
featuredIntegrations,
|
||||
getIntegrationName,
|
||||
getIntegrationOnboardingMetadata,
|
||||
getWidgetKindsForIntegration,
|
||||
hiddenFromOnboarding,
|
||||
integrationDefs,
|
||||
integrationKinds,
|
||||
} from "@homarr/definitions";
|
||||
@@ -56,7 +55,7 @@ export const buildSortedIntegrations = (
|
||||
integrationKinds
|
||||
.filter((kind) => {
|
||||
if (options.allowedKinds && !options.allowedKinds.includes(kind)) return false;
|
||||
if (options.onboarding && hiddenFromOnboarding.has(kind)) return false;
|
||||
if (options.onboarding && getIntegrationOnboardingMetadata(kind).hidden) return false;
|
||||
if (!options.enableMockIntegration && kind === "mock") return false;
|
||||
return true;
|
||||
})
|
||||
@@ -67,11 +66,11 @@ export const buildSortedIntegrations = (
|
||||
widgets: getWidgetKindsForIntegration(kind),
|
||||
}))
|
||||
.toSorted((left, right) => {
|
||||
const leftIndex = featuredIntegrations.indexOf(left.kind);
|
||||
const rightIndex = featuredIntegrations.indexOf(right.kind);
|
||||
if (leftIndex !== -1 && rightIndex !== -1) return leftIndex - rightIndex;
|
||||
if (leftIndex !== -1) return -1;
|
||||
if (rightIndex !== -1) return 1;
|
||||
const leftFeaturedOrder = getIntegrationOnboardingMetadata(left.kind).featuredOrder;
|
||||
const rightFeaturedOrder = getIntegrationOnboardingMetadata(right.kind).featuredOrder;
|
||||
if (leftFeaturedOrder !== null && rightFeaturedOrder !== null) return leftFeaturedOrder - rightFeaturedOrder;
|
||||
if (leftFeaturedOrder !== null) return -1;
|
||||
if (rightFeaturedOrder !== null) return 1;
|
||||
return right.widgets.length - left.widgets.length || left.name.localeCompare(right.name);
|
||||
});
|
||||
|
||||
|
||||
@@ -2,45 +2,7 @@
|
||||
|
||||
import { useMemo, useState } from "react";
|
||||
import { Badge, Center, Group, Input, ScrollArea, SimpleGrid, Stack, Text } from "@mantine/core";
|
||||
import {
|
||||
IconAd,
|
||||
IconApps,
|
||||
IconBinaryTree,
|
||||
IconBookmark,
|
||||
IconBrandDocker,
|
||||
IconBrandMinecraft,
|
||||
IconBrowser,
|
||||
IconBuildingBank,
|
||||
IconBusStop,
|
||||
IconCalendar,
|
||||
IconChartBar,
|
||||
IconClock,
|
||||
IconClockPlay,
|
||||
IconCloud,
|
||||
IconDeviceCctv,
|
||||
IconDeviceGamepad,
|
||||
IconDownload,
|
||||
IconGraphFilled,
|
||||
IconHeartRateMonitor,
|
||||
IconHourglass,
|
||||
IconMessage,
|
||||
IconMovie,
|
||||
IconNotes,
|
||||
IconPuzzle,
|
||||
IconReportSearch,
|
||||
IconRobot,
|
||||
IconRocket,
|
||||
IconRss,
|
||||
IconSearch,
|
||||
IconServer2,
|
||||
IconTicket,
|
||||
IconTopologyFull,
|
||||
IconTransform,
|
||||
IconVideo,
|
||||
IconWall,
|
||||
IconWind,
|
||||
IconZoomQuestion,
|
||||
} from "@tabler/icons-react";
|
||||
import { IconSearch } from "@tabler/icons-react";
|
||||
|
||||
import { getWidgetName } from "@homarr/definitions";
|
||||
import type { IntegrationKind, WidgetKind } from "@homarr/definitions";
|
||||
@@ -49,6 +11,7 @@ import { useI18n } from "@homarr/translation/client";
|
||||
import { IntegrationAvatar } from "../components/integration-avatar";
|
||||
import { SelectableCard } from "../components/selectable-card";
|
||||
import { selectGridCols } from "../select-grid-layout";
|
||||
import { widgetCatalogIcons } from "../widget-icons";
|
||||
import { buildSortedIntegrations, filterIntegrations } from "./integration-grid-shared";
|
||||
import type { IntegrationGridItem } from "./integration-grid-shared";
|
||||
|
||||
@@ -155,48 +118,6 @@ const IntegrationCard = ({
|
||||
);
|
||||
};
|
||||
|
||||
const widgetIconsMap: Partial<Record<WidgetKind, typeof IconPuzzle>> = {
|
||||
clock: IconClock,
|
||||
weather: IconCloud,
|
||||
airQuality: IconWind,
|
||||
countdown: IconHourglass,
|
||||
timer: IconClockPlay,
|
||||
app: IconApps,
|
||||
assistant: IconRobot,
|
||||
iframe: IconBrowser,
|
||||
video: IconDeviceCctv,
|
||||
notebook: IconNotes,
|
||||
anchorNote: IconNotes,
|
||||
dnsHoleSummary: IconAd,
|
||||
dnsHoleControls: IconDeviceGamepad,
|
||||
"smartHome-entityState": IconBinaryTree,
|
||||
"smartHome-executeAutomation": IconBinaryTree,
|
||||
stockPrice: IconBuildingBank,
|
||||
mediaServer: IconVideo,
|
||||
calendar: IconCalendar,
|
||||
downloads: IconDownload,
|
||||
"mediaRequests-requestList": IconZoomQuestion,
|
||||
"mediaRequests-requestStats": IconChartBar,
|
||||
mediaTranscoding: IconTransform,
|
||||
mediaMissing: IconMovie,
|
||||
minecraftServerStatus: IconBrandMinecraft,
|
||||
networkControllerSummary: IconTopologyFull,
|
||||
networkControllerStatus: IconTopologyFull,
|
||||
rssFeed: IconRss,
|
||||
bookmarks: IconBookmark,
|
||||
indexerManager: IconReportSearch,
|
||||
healthMonitoring: IconHeartRateMonitor,
|
||||
releases: IconRocket,
|
||||
mediaReleases: IconTicket,
|
||||
dockerContainers: IconBrandDocker,
|
||||
firewall: IconWall,
|
||||
notifications: IconMessage,
|
||||
systemResources: IconGraphFilled,
|
||||
coolify: IconCloud,
|
||||
systemDisks: IconServer2,
|
||||
timetable: IconBusStop,
|
||||
};
|
||||
|
||||
const IntegrationTiedWidgets = ({ widgets, limit }: { widgets: WidgetKind[]; limit?: number }) => {
|
||||
const t = useI18n();
|
||||
if (widgets.length === 0) {
|
||||
@@ -213,7 +134,7 @@ const IntegrationTiedWidgets = ({ widgets, limit }: { widgets: WidgetKind[]; lim
|
||||
return (
|
||||
<Group gap={4} wrap="wrap">
|
||||
{items.map((widgetKind) => {
|
||||
const WidgetIcon = widgetIconsMap[widgetKind] ?? IconPuzzle;
|
||||
const WidgetIcon = widgetCatalogIcons[widgetKind];
|
||||
return (
|
||||
<Badge
|
||||
key={widgetKind}
|
||||
|
||||
Reference in new issue
Block a user