Files
homarr/packages/widgets/src/umami/index.ts
T

101 lines
3.7 KiB
TypeScript

import { IconChartBar, IconServerOff } from "@tabler/icons-react";
import { z } from "zod/v4";
import { createWidgetDefinition, matchesWidgetRuntimeQuery } from "../definition";
import { optionsBuilder } from "../options";
export const timeFrameValues = ["today", "24h", "7d", "30d", "month", "lastMonth"] as const;
export const { definition, componentLoader } = createWidgetDefinition("umami", {
icon: IconChartBar,
supportsAdvancedFocus: true,
queryKeys: [
[["widget", "umami", "getVisitorStats"]],
[["widget", "umami", "getActiveVisitors"]],
[["widget", "umami", "getMultiEventTimeSeries"]],
[["widget", "umami", "getTopPages"]],
[["widget", "umami", "getTopReferrers"]],
],
queryMatcher: matchesWidgetRuntimeQuery,
refetchInterval: null,
supportedIntegrations: ["umami"],
integrationsRequired: true,
maxIntegrations: 1,
createOptions() {
return optionsBuilder.from(
(factory) => ({
websiteId: factory.umamiWebsite(),
timeFrame: factory.select({
options: timeFrameValues.map((value) => ({
value,
label: (t) => t(`widget.umami.option.timeFrame.option.${value}`),
})),
defaultValue: "24h",
withDescription: true,
}),
viewMode: factory.select({
options: [
{ value: "chart", label: (t) => t("widget.umami.option.viewMode.option.chart") },
{ value: "events", label: (t) => t("widget.umami.option.viewMode.option.events") },
{ value: "topPages", label: (t) => t("widget.umami.option.viewMode.option.topPages") },
{ value: "topReferrers", label: (t) => t("widget.umami.option.viewMode.option.topReferrers") },
] as const,
defaultValue: "chart",
withDescription: true,
}),
chartType: factory.select({
options: [
{ value: "bar", label: (t) => t("widget.umami.option.chartType.option.bar") },
{ value: "sparkline", label: (t) => t("widget.umami.option.chartType.option.sparkline") },
] as const,
defaultValue: "bar",
withDescription: true,
}),
chartStyle: factory.select({
options: [
{ value: "grouped", label: (t) => t("widget.umami.option.chartStyle.option.grouped") },
{ value: "overlay", label: (t) => t("widget.umami.option.chartStyle.option.overlay") },
] as const,
defaultValue: "grouped",
withDescription: true,
}),
eventName: factory.umamiEventName(),
eventNames: factory.umamiEventNames(),
topCount: factory.number({
validate: z.number().int().min(1).max(500),
defaultValue: 5,
step: 1,
withDescription: true,
}),
}),
{
viewMode: {
shouldHide: (options) => !options.websiteId,
},
chartType: {
shouldHide: (options) =>
!options.websiteId || (options.viewMode !== "chart" && options.viewMode !== "events"),
},
chartStyle: {
shouldHide: (options) => options.viewMode !== "chart" || !options.eventName || options.chartType !== "bar",
},
eventName: {
shouldHide: (options) => !options.websiteId || options.viewMode !== "chart",
},
eventNames: {
shouldHide: (options) => !options.websiteId || options.viewMode !== "events",
},
topCount: {
shouldHide: (options) => !options.websiteId || options.viewMode === "chart" || options.viewMode === "events",
},
},
);
},
errors: {
INTERNAL_SERVER_ERROR: {
icon: IconServerOff,
message: (t) => t("widget.umami.error.internalServerError"),
},
},
}).withDynamicImport(() => import("./component"));