mirror of
https://github.com/ajnart/homarr.git
synced 2026-02-27 17:00:54 +01:00
refactor: revert assignment of oldmarr widget mapping (#1780)
This commit is contained in:
@@ -11,3 +11,8 @@ export type RemoveReadonly<T> = {
|
||||
};
|
||||
|
||||
export type MaybeArray<T> = T | T[];
|
||||
export type Inverse<T extends Invertible> = {
|
||||
[Key in keyof T as T[Key]]: Key;
|
||||
};
|
||||
|
||||
type Invertible = Record<PropertyKey, PropertyKey>;
|
||||
|
||||
@@ -55,7 +55,7 @@ export const insertItemsAsync = async (
|
||||
xOffset: screenSizeShape.location.x,
|
||||
yOffset: screenSizeShape.location.y,
|
||||
kind,
|
||||
options: SuperJSON.stringify(mapOptions(kind, widget.properties, appsMap)),
|
||||
options: SuperJSON.stringify(mapOptions(widget.type, widget.properties, appsMap)),
|
||||
});
|
||||
|
||||
logger.debug(`Inserted widget id=${widget.id} sectionId=${sectionId}`);
|
||||
|
||||
@@ -83,7 +83,11 @@ export const mapWidget = (
|
||||
yOffset: shapeForSize.location.y,
|
||||
kind,
|
||||
options: SuperJSON.stringify(
|
||||
mapOptions(kind, widget.properties, new Map([...appsMap.entries()].map(([key, value]) => [key, value.id]))),
|
||||
mapOptions(
|
||||
widget.type,
|
||||
widget.properties,
|
||||
new Map([...appsMap.entries()].map(([key, value]) => [key, value.id])),
|
||||
),
|
||||
),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { objectEntries } from "@homarr/common";
|
||||
import type { Inverse } from "@homarr/common/types";
|
||||
import type { WidgetKind } from "@homarr/definitions";
|
||||
|
||||
import type { OldmarrBookmarkDefinition } from "./bookmark";
|
||||
@@ -49,32 +50,32 @@ export type OldmarrWidgetDefinitions =
|
||||
| OldmarrMediaTranscodingDefinition;
|
||||
|
||||
export const widgetKindMapping = {
|
||||
app: null, // In oldmarr apps were not widgets
|
||||
clock: "date",
|
||||
date: "clock",
|
||||
calendar: "calendar",
|
||||
downloads: "torrents-status",
|
||||
"torrents-status": "downloads",
|
||||
weather: "weather",
|
||||
rssFeed: "rss",
|
||||
video: "video-stream",
|
||||
rss: "rssFeed",
|
||||
"video-stream": "video",
|
||||
iframe: "iframe",
|
||||
mediaServer: "media-server",
|
||||
dnsHoleSummary: "dns-hole-summary",
|
||||
dnsHoleControls: "dns-hole-controls",
|
||||
"media-server": "mediaServer",
|
||||
"dns-hole-summary": "dnsHoleSummary",
|
||||
"dns-hole-controls": "dnsHoleControls",
|
||||
notebook: "notebook",
|
||||
"smartHome-entityState": "smart-home/entity-state",
|
||||
"smartHome-executeAutomation": "smart-home/trigger-automation",
|
||||
"mediaRequests-requestList": "media-requests-list",
|
||||
"mediaRequests-requestStats": "media-requests-stats",
|
||||
indexerManager: "indexer-manager",
|
||||
bookmarks: "bookmark",
|
||||
healthMonitoring: "health-monitoring",
|
||||
mediaTranscoding: "media-transcoding",
|
||||
} satisfies Record<WidgetKind, OldmarrWidgetDefinitions["id"] | null>;
|
||||
// Use null for widgets that did not exist in oldmarr
|
||||
// TODO: revert assignment so that only old widgets are needed in the object,
|
||||
// this can be done ones all widgets are implemented
|
||||
"smart-home/entity-state": "smartHome-entityState",
|
||||
"smart-home/trigger-automation": "smartHome-executeAutomation",
|
||||
"media-requests-list": "mediaRequests-requestList",
|
||||
"media-requests-stats": "mediaRequests-requestStats",
|
||||
"indexer-manager": "indexerManager",
|
||||
bookmark: "bookmarks",
|
||||
"health-monitoring": "healthMonitoring",
|
||||
dashdot: "healthMonitoring",
|
||||
"media-transcoding": "mediaTranscoding",
|
||||
dlspeed: null,
|
||||
usenet: "downloads",
|
||||
} satisfies Record<OldmarrWidgetDefinitions["id"], WidgetKind | null>;
|
||||
|
||||
export type WidgetMapping = typeof widgetKindMapping;
|
||||
export type InversedWidgetMapping = Inverse<Omit<typeof widgetKindMapping, "dlspeed">>;
|
||||
|
||||
export const mapKind = (kind: OldmarrWidgetDefinitions["id"]): WidgetKind | undefined =>
|
||||
objectEntries(widgetKindMapping).find(([_, value]) => value === kind)?.[0];
|
||||
export const mapKind = (kind: OldmarrWidgetDefinitions["id"]): keyof InversedWidgetMapping | null =>
|
||||
objectEntries(widgetKindMapping).find(([key]) => key === kind)?.[1] ?? null;
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { objectEntries } from "@homarr/common";
|
||||
import type { WidgetKind } from "@homarr/definitions";
|
||||
import { logger } from "@homarr/log";
|
||||
|
||||
import type { WidgetComponentProps } from "../../../widgets/src/definition";
|
||||
import type { OldmarrWidgetDefinitions, WidgetMapping } from "./definitions";
|
||||
import { mapKind } from "./definitions";
|
||||
import type { InversedWidgetMapping, OldmarrWidgetDefinitions, WidgetMapping } from "./definitions";
|
||||
|
||||
// This type enforces, that for all widget mappings there is a corresponding option mapping,
|
||||
// each option of newmarr can be mapped from the value of the oldmarr options
|
||||
type OptionMapping = {
|
||||
[WidgetKey in keyof WidgetMapping]: WidgetMapping[WidgetKey] extends null
|
||||
[WidgetKey in keyof InversedWidgetMapping]: InversedWidgetMapping[WidgetKey] extends null
|
||||
? null
|
||||
: {
|
||||
[OptionsKey in keyof WidgetComponentProps<WidgetKey>["options"]]: (
|
||||
oldOptions: Extract<OldmarrWidgetDefinitions, { id: WidgetMapping[WidgetKey] }>["options"],
|
||||
oldOptions: Extract<OldmarrWidgetDefinitions, { id: InversedWidgetMapping[WidgetKey] }>["options"],
|
||||
appsMap: Map<string, string>,
|
||||
) => WidgetComponentProps<WidgetKey>["options"][OptionsKey] | undefined;
|
||||
};
|
||||
@@ -55,12 +55,16 @@ const optionMapping: OptionMapping = {
|
||||
useCustomTimezone: () => true,
|
||||
},
|
||||
downloads: {
|
||||
activeTorrentThreshold: (oldOptions) => oldOptions.speedLimitOfActiveTorrents,
|
||||
applyFilterToRatio: (oldOptions) => oldOptions.displayRatioWithFilter,
|
||||
categoryFilter: (oldOptions) => oldOptions.labelFilter,
|
||||
filterIsWhitelist: (oldOptions) => oldOptions.labelFilterIsWhitelist,
|
||||
enableRowSorting: (oldOptions) => oldOptions.rowSorting,
|
||||
showCompletedTorrent: (oldOptions) => oldOptions.displayCompletedTorrents,
|
||||
activeTorrentThreshold: (oldOptions) =>
|
||||
"speedLimitOfActiveTorrents" in oldOptions ? oldOptions.speedLimitOfActiveTorrents : undefined,
|
||||
applyFilterToRatio: (oldOptions) =>
|
||||
"displayRatioWithFilter" in oldOptions ? oldOptions.displayRatioWithFilter : undefined,
|
||||
categoryFilter: (oldOptions) => ("labelFilter" in oldOptions ? oldOptions.labelFilter : undefined),
|
||||
filterIsWhitelist: (oldOptions) =>
|
||||
"labelFilterIsWhitelist" in oldOptions ? oldOptions.labelFilterIsWhitelist : undefined,
|
||||
enableRowSorting: (oldOptions) => ("rowSorting" in oldOptions ? oldOptions.rowSorting : undefined),
|
||||
showCompletedTorrent: (oldOptions) =>
|
||||
"displayCompletedTorrents" in oldOptions ? oldOptions.displayCompletedTorrents : undefined,
|
||||
columns: () => ["integration", "name", "progress", "time", "actions"],
|
||||
defaultSort: () => "type",
|
||||
descendingDefaultSort: () => false,
|
||||
@@ -124,45 +128,54 @@ const optionMapping: OptionMapping = {
|
||||
openIndexerSiteInNewTab: (oldOptions) => oldOptions.openIndexerSiteInNewTab,
|
||||
},
|
||||
healthMonitoring: {
|
||||
cpu: (oldOptions) => oldOptions.cpu,
|
||||
memory: (oldOptions) => oldOptions.memory,
|
||||
fahrenheit: (oldOptions) => oldOptions.fahrenheit,
|
||||
fileSystem: (oldOptions) => oldOptions.fileSystem,
|
||||
cpu: (oldOptions) =>
|
||||
"cpu" in oldOptions
|
||||
? oldOptions.cpu
|
||||
: oldOptions.graphsOrder.some((graph) => graph.key === "cpu" && graph.subValues.enabled),
|
||||
memory: (oldOptions) =>
|
||||
"memory" in oldOptions
|
||||
? oldOptions.memory
|
||||
: oldOptions.graphsOrder.some((graph) => graph.key === "ram" && graph.subValues.enabled),
|
||||
fahrenheit: (oldOptions) => ("fahrenheit" in oldOptions ? oldOptions.fahrenheit : undefined),
|
||||
fileSystem: (oldOptions) =>
|
||||
"fileSystem" in oldOptions
|
||||
? oldOptions.fileSystem
|
||||
: oldOptions.graphsOrder.some((graph) => graph.key === "storage" && graph.subValues.enabled),
|
||||
},
|
||||
mediaTranscoding: {
|
||||
defaultView: (oldOptions) => oldOptions.defaultView,
|
||||
queuePageSize: (oldOptions) => oldOptions.queuePageSize,
|
||||
},
|
||||
app: null,
|
||||
};
|
||||
|
||||
/**
|
||||
* Maps the oldmarr options to the newmarr options
|
||||
* @param kind item kind to map
|
||||
* @param type old widget type
|
||||
* @param oldOptions oldmarr options for this item
|
||||
* @param appsMap map of old app ids to new app ids
|
||||
* @returns newmarr options for this item or null if the item did not exist in oldmarr
|
||||
*/
|
||||
export const mapOptions = <K extends WidgetKind>(
|
||||
kind: K,
|
||||
oldOptions: Extract<OldmarrWidgetDefinitions, { id: WidgetMapping[K] }>["options"],
|
||||
export const mapOptions = <K extends OldmarrWidgetDefinitions["id"]>(
|
||||
type: K,
|
||||
oldOptions: Extract<OldmarrWidgetDefinitions, { id: K }>["options"],
|
||||
appsMap: Map<string, string>,
|
||||
) => {
|
||||
logger.debug(`Mapping old homarr options for widget kind=${kind} options=${JSON.stringify(oldOptions)}`);
|
||||
if (optionMapping[kind] === null) {
|
||||
logger.debug(`Mapping old homarr options for widget type=${type} options=${JSON.stringify(oldOptions)}`);
|
||||
const kind = mapKind(type);
|
||||
if (!kind) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const mapping = optionMapping[kind];
|
||||
return objectEntries(mapping).reduce(
|
||||
(acc, [key, value]) => {
|
||||
const newValue = value(oldOptions as never, appsMap);
|
||||
logger.debug(`Mapping old homarr option kind=${kind} key=${key as string} newValue=${newValue as string}`);
|
||||
(acc, [key, value]: [string, (oldOptions: Record<string, unknown>, appsMap: Map<string, string>) => unknown]) => {
|
||||
const newValue = value(oldOptions, appsMap);
|
||||
logger.debug(`Mapping old homarr option kind=${kind} key=${key} newValue=${newValue as string}`);
|
||||
if (newValue !== undefined) {
|
||||
acc[key as string] = newValue;
|
||||
acc[key] = newValue;
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, unknown>,
|
||||
) as WidgetComponentProps<K>["options"];
|
||||
) as WidgetComponentProps<Exclude<WidgetMapping[K], null>>["options"];
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user