fix: sync dev fixes into v2 and improve regression reports (#6821)
Co-authored-by: Homarr Update Contributors <210161987+homarr-update-contributors[bot]@users.noreply.github.com> Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com> Co-authored-by: Releases Homarr <175486441+homarr-releases[bot]@users.noreply.github.com> Co-authored-by: Thomas <thomas@ajnart.fr> Co-authored-by: homarr-releases[bot] <175486441+homarr-releases[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: homarr-update-contributors[bot] <210161987+homarr-update-contributors[bot]@users.noreply.github.com> Co-authored-by: homarr-crowdin[bot] <190541745+homarr-crowdin[bot]@users.noreply.github.com> Co-authored-by: Afonso Jorge Ramos <afonsojorgeramos@gmail.com> Co-authored-by: Danura30082 <danura30082+github@gmail.com> Co-authored-by: Kushie <122986913+kushiemoon-dev@users.noreply.github.com> Closes #6604
This commit is contained in:
1 parent
ff2b589380
commit
f18033ddaa
73 files changed
+25555
-23442
No files matched your search
@@ -9,6 +9,12 @@ describe("normalizeStorageDeviceName", () => {
|
||||
expect(normalizeStorageDeviceName("/dev/sda")).toBe("/dev/sda");
|
||||
});
|
||||
|
||||
test("strips partition suffixes from unprefixed device names (OpenMediaVault)", () => {
|
||||
expect(normalizeStorageDeviceName("sda1")).toBe("sda");
|
||||
expect(normalizeStorageDeviceName("sda")).toBe("sda");
|
||||
expect(normalizeStorageDeviceName("nvme0n1p1")).toBe("nvme0n1");
|
||||
});
|
||||
|
||||
test("preserves Synology-style volume names", () => {
|
||||
expect(normalizeStorageDeviceName("volume_1")).toBe("volume_1");
|
||||
expect(normalizeStorageDeviceName("volume_2")).toBe("volume_2");
|
||||
@@ -139,4 +145,36 @@ describe("matchFileSystemAndSmart", () => {
|
||||
overallStatus: "",
|
||||
});
|
||||
});
|
||||
|
||||
test("joins unprefixed OMV partitions with their base device SMART data", () => {
|
||||
const result = matchFileSystemAndSmart(
|
||||
[
|
||||
{ deviceName: "sda1", used: "3.13 GiB", available: "26853056512", percentage: 12 },
|
||||
{ deviceName: "sdb1", used: "396.24 GiB", available: "1542365618176", percentage: 22 },
|
||||
],
|
||||
[
|
||||
{ deviceName: "sda", temperature: 0, overallStatus: "BAD_STATUS" },
|
||||
{ deviceName: "sdb", temperature: 33, overallStatus: "GOOD" },
|
||||
],
|
||||
);
|
||||
|
||||
expect(result).toEqual([
|
||||
{
|
||||
deviceName: "sda",
|
||||
used: "3.13 GiB",
|
||||
available: "26853056512",
|
||||
percentage: 12,
|
||||
temperature: 0,
|
||||
overallStatus: "BAD_STATUS",
|
||||
},
|
||||
{
|
||||
deviceName: "sdb",
|
||||
used: "396.24 GiB",
|
||||
available: "1542365618176",
|
||||
percentage: 22,
|
||||
temperature: 33,
|
||||
overallStatus: "GOOD",
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -5,10 +5,16 @@ interface StorageVolumeEntry {
|
||||
const partitionSuffixPatterns: ReadonlyArray<{ pattern: RegExp; baseGroupIndex: number }> = [
|
||||
// SCSI/SATA/VirtIO: /dev/sda1 -> /dev/sda
|
||||
{ pattern: /^(\/dev\/(?:sd|vd|hd|xvd)[a-z]+)[0-9]+$/, baseGroupIndex: 1 },
|
||||
// SCSI/SATA/VirtIO without device node prefix: sda1 -> sda (OMV reports unprefixed names)
|
||||
{ pattern: /^((?:sd|vd)[a-z]+)[0-9]+$/, baseGroupIndex: 1 },
|
||||
// NVMe: /dev/nvme0n1p2 -> /dev/nvme0n1
|
||||
{ pattern: /^(\/dev\/nvme[0-9]+n[0-9]+)p[0-9]+$/, baseGroupIndex: 1 },
|
||||
// NVMe without device node prefix: nvme0n1p2 -> nvme0n1
|
||||
{ pattern: /^(nvme[0-9]+n[0-9]+)p[0-9]+$/, baseGroupIndex: 1 },
|
||||
// eMMC: /dev/mmcblk0p1 -> /dev/mmcblk0
|
||||
{ pattern: /^(\/dev\/mmcblk[0-9]+)p[0-9]+$/, baseGroupIndex: 1 },
|
||||
// eMMC without device node prefix: mmcblk0p1 -> mmcblk0
|
||||
{ pattern: /^(mmcblk[0-9]+)p[0-9]+$/, baseGroupIndex: 1 },
|
||||
];
|
||||
|
||||
export const normalizeStorageDeviceName = (deviceName: string): string => {
|
||||
@@ -28,7 +34,7 @@ export const toScopedStorageVolumeValue = (integrationId: string, value: string)
|
||||
return `${integrationId}:${volumeName}`;
|
||||
};
|
||||
|
||||
const storageDeviceNamesMatch = (leftDeviceName: string, rightDeviceName: string): boolean => {
|
||||
export const storageDeviceNamesMatch = (leftDeviceName: string, rightDeviceName: string): boolean => {
|
||||
return (
|
||||
leftDeviceName === rightDeviceName ||
|
||||
normalizeStorageDeviceName(leftDeviceName) === normalizeStorageDeviceName(rightDeviceName)
|
||||
|
||||
@@ -129,7 +129,7 @@ export default function FirewallWidget({
|
||||
}
|
||||
|
||||
return (
|
||||
<ScrollArea h="100%">
|
||||
<ScrollArea h="100%" style={{ minHeight: 0 }}>
|
||||
<Stack gap="xs" p={isAdvanced ? "xs" : 0}>
|
||||
{!isAdvanced && (
|
||||
<Group justify="space-between" w="100%" p="xs">
|
||||
|
||||
@@ -42,7 +42,7 @@ import type { ScopedTranslationFunction } from "@homarr/translation";
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
import { zoomCompensatedSize } from "@homarr/ui";
|
||||
|
||||
import { filterStorageVolumes, normalizeStorageDeviceName } from "../filter-storage-volumes";
|
||||
import { filterStorageVolumes, storageDeviceNamesMatch } from "../filter-storage-volumes";
|
||||
import { WidgetEmptyState } from "../common/empty-state";
|
||||
import { IntegrationErrorIndicator } from "../common/integration-error-indicator";
|
||||
import { getUsableWidgetQueryData, isInitialWidgetQueryPending } from "../common/query-state";
|
||||
@@ -444,12 +444,7 @@ interface SmartData {
|
||||
export const matchFileSystemAndSmart = (fileSystems: FileSystem[], smartData: SmartData[]) => {
|
||||
return fileSystems
|
||||
.map((fileSystem) => {
|
||||
const normalizedFileSystemName = normalizeStorageDeviceName(fileSystem.deviceName);
|
||||
const smartDisk = smartData.find(
|
||||
(smart) =>
|
||||
smart.deviceName === fileSystem.deviceName ||
|
||||
normalizeStorageDeviceName(smart.deviceName) === normalizedFileSystemName,
|
||||
);
|
||||
const smartDisk = smartData.find((smart) => storageDeviceNamesMatch(smart.deviceName, fileSystem.deviceName));
|
||||
|
||||
return {
|
||||
deviceName: smartDisk?.deviceName ?? fileSystem.deviceName,
|
||||
|
||||
@@ -14,7 +14,7 @@ import { IntegrationErrorIndicator } from "../common/integration-error-indicator
|
||||
import { getUsableWidgetQueryData, isInitialWidgetQueryPending } from "../common/query-state";
|
||||
import { WidgetQueryLoadingState } from "../common/query-state-indicator";
|
||||
import type { WidgetComponentProps } from "../definition";
|
||||
import { filterStorageVolumes, normalizeStorageDeviceName } from "../filter-storage-volumes";
|
||||
import { filterStorageVolumes, storageDeviceNamesMatch } from "../filter-storage-volumes";
|
||||
import { NoIntegrationDataError } from "../errors/no-data-integration";
|
||||
|
||||
type DiskDisplayMode = WidgetComponentProps<"systemDisks">["options"]["displayMode"];
|
||||
@@ -255,9 +255,7 @@ export default function SystemResources({
|
||||
integrationId: entry.integrationId,
|
||||
integrationName: entry.integrationName,
|
||||
item,
|
||||
smartItem: smart.find(
|
||||
(candidate) => normalizeStorageDeviceName(candidate.deviceName) === normalizeStorageDeviceName(item.deviceName),
|
||||
),
|
||||
smartItem: smart.find((candidate) => storageDeviceNamesMatch(candidate.deviceName, item.deviceName)),
|
||||
}));
|
||||
});
|
||||
const isAdvanced = displayMode === "advanced";
|
||||
|
||||
Reference in new issue
Block a user