fix(homepage): merge service groups by name to stop manual entries being dropped #14

Merged
finn.markwitz merged 1 commits from fix/homepage-duplicate-service-groups into main 2026-09-21 15:30:00 +02:00
+78 -64
View File
@@ -12,79 +12,93 @@ let
manualServices = import ./manual-services.nix; manualServices = import ./manual-services.nix;
manualWidgets = import ./manual-widgets.nix; manualWidgets = import ./manual-widgets.nix;
groupedServices = groupedServices = lib.foldl' (
lib.foldl' acc: entry:
( acc
acc: entry: // {
acc ${entry.group} = (acc.${entry.group} or [ ]) ++ [ entry ];
// {
${entry.group} = (acc.${entry.group} or [ ]) ++ [ entry ];
}
)
{ }
config.my.homepage.services;
homepageServices = lib.mapAttrsToList (
group: entries:
{
${group} = map (
entry:
let
service = builtins.removeAttrs entry [
"group"
"name"
];
in
{
${entry.name} = lib.filterAttrs (_: value: value != null) service;
}
) entries;
} }
) groupedServices; ) { } config.my.homepage.services;
homepageServices = lib.mapAttrsToList (group: entries: {
${group} = map (
entry:
let
service = builtins.removeAttrs entry [
"group"
"name"
];
in
{
${entry.name} = lib.filterAttrs (_: value: value != null) service;
}
) entries;
}) groupedServices;
# homepage-dashboard keeps only the first services.yaml list entry with a
# given group name (first match wins), so module-contributed and manual
# groups sharing a name (e.g. "Services") must be merged here rather than
# simply concatenated, or the later ones are silently dropped.
mergeGroups =
lists:
let
merged = lib.foldl' (
acc: groupAttrs:
let
groupName = builtins.head (builtins.attrNames groupAttrs);
in
acc // { ${groupName} = (acc.${groupName} or [ ]) ++ groupAttrs.${groupName}; }
) { } lists;
in
lib.mapAttrsToList (name: entries: { ${name} = entries; }) merged;
in in
{ {
options.my.homepage.services = with lib; mkOption { options.my.homepage.services =
type = types.listOf ( with lib;
types.submodule { mkOption {
options = { type = types.listOf (
group = mkOption { types.submodule {
type = types.str; options = {
description = "Homepage service group"; group = mkOption {
}; type = types.str;
description = "Homepage service group";
};
name = mkOption { name = mkOption {
type = types.str; type = types.str;
description = "Homepage service name"; description = "Homepage service name";
}; };
description = mkOption { description = mkOption {
type = types.str; type = types.str;
description = "Homepage service description"; description = "Homepage service description";
}; };
href = mkOption { href = mkOption {
type = types.str; type = types.str;
description = "Homepage service URL"; description = "Homepage service URL";
}; };
icon = mkOption { icon = mkOption {
type = types.nullOr types.str; type = types.nullOr types.str;
default = null; default = null;
description = "Optional Homepage service icon"; description = "Optional Homepage service icon";
};
}; };
}; }
} );
); default = [ ];
default = [ ]; description = "Merged homepage service metadata contributed by repo modules.";
description = "Merged homepage service metadata contributed by repo modules."; };
};
options.my.homepage.widgets = with lib; mkOption { options.my.homepage.widgets =
type = types.listOf types.attrs; with lib;
default = [ ]; mkOption {
description = "Widget definitions passed directly to services.homepage-dashboard.widgets. Each entry is an attrset like { resources = { cpu = true; memory = true; }; }."; type = types.listOf types.attrs;
}; default = [ ];
description = "Widget definitions passed directly to services.homepage-dashboard.widgets. Each entry is an attrset like { resources = { cpu = true; memory = true; }; }.";
};
options.my.profiles.homepage = with lib; { options.my.profiles.homepage = with lib; {
enable = mkEnableOption "getHomepage.dev Dashboard"; enable = mkEnableOption "getHomepage.dev Dashboard";
@@ -98,7 +112,7 @@ in
listenPort = dashboardPort; listenPort = dashboardPort;
allowedHosts = "${dashboardHost}:${toString dashboardPort},192.168.178.65:${toString dashboardPort},localhost:${toString dashboardPort},127.0.0.1:${toString dashboardPort},jupiter:${toString dashboardPort},jupiter.solar.internal:${toString dashboardPort}"; allowedHosts = "${dashboardHost}:${toString dashboardPort},192.168.178.65:${toString dashboardPort},localhost:${toString dashboardPort},127.0.0.1:${toString dashboardPort},jupiter:${toString dashboardPort},jupiter.solar.internal:${toString dashboardPort}";
bookmarks = import ./bookmarks.nix; bookmarks = import ./bookmarks.nix;
services = homepageServices ++ manualServices; services = mergeGroups (homepageServices ++ manualServices);
widgets = config.my.homepage.widgets ++ manualWidgets; widgets = config.my.homepage.widgets ++ manualWidgets;
}; };