## Changes ### Critical fixes - Fix Switch `isChecked` → `checked` prop in CreateMonitor Globalping toggle - Merge double `getDBSettings()` calls in globalpingService into single `getClientAndLocations()` method to eliminate redundant DB reads per check cycle - Add in-flight lock (Set) to prevent overlapping Globalping checks for the same monitor - Add hostname validation before calling Globalping API to prevent invalid targets ### Dead code removal - Remove unused `locations` field from server Monitor type, Mongoose model, Joi validation, and repository mappers - Remove unused `locations` field from client Monitor type - Remove dead `getLimits()` method from globalpingService - Remove dead `locations` translation keys from en.json - Remove dead `monitorType`, `groupedUpChecks`, `groupedDownChecks` fields from findLocationChecksByMonitorId return value ### Medium/low fixes - Make globalping/locations API fetch conditional on `monitor.globalpingEnabled` in Details page to avoid unnecessary requests - Add useEffect to reset selectedLocationTab when location keys change to prevent out-of-bounds tab index - Add `globalpingEnabled: false` to default case in useMonitorForm - Replace console.log with comment in CreateMonitor onError handler - Add aria-label to Globe icon for accessibility - Add warning log when Globalping buildCheck returns undefined - Fix step numbering in SuperSimpleQueueHelper (was duplicated Step 4) ## Benefits - Eliminates one DB round-trip per monitor check cycle - Prevents race conditions with overlapping Globalping checks - Validates hostnames before external API calls - Removes ~30 lines of dead code across server and client - Improves accessibility with proper aria labels
112 lines
2.7 KiB
TypeScript
112 lines
2.7 KiB
TypeScript
import { useMemo } from "react";
|
|
import { monitorSchema, type MonitorFormData } from "@/Validation/monitor";
|
|
import type { Monitor, MonitorType } from "@/Types/Monitor";
|
|
|
|
interface UseMonitorFormOptions {
|
|
data?: Monitor | null;
|
|
defaultType?: MonitorType;
|
|
}
|
|
|
|
const getBaseDefaults = (data?: Monitor | null) => ({
|
|
name: data?.name || "",
|
|
description: data?.description || "",
|
|
interval: data?.interval || 60000,
|
|
notifications: data?.notifications || [],
|
|
statusWindowSize: data?.statusWindowSize || 5,
|
|
statusWindowThreshold: data?.statusWindowThreshold || 60,
|
|
});
|
|
|
|
export const useMonitorForm = ({
|
|
data = null,
|
|
defaultType = "http",
|
|
}: UseMonitorFormOptions = {}) => {
|
|
return useMemo(() => {
|
|
const type = data?.type || defaultType;
|
|
const base = getBaseDefaults(data);
|
|
|
|
let defaults: MonitorFormData;
|
|
|
|
switch (type) {
|
|
case "http":
|
|
defaults = {
|
|
...base,
|
|
type: "http",
|
|
url: data?.url || "",
|
|
ignoreTlsErrors: data?.ignoreTlsErrors || false,
|
|
useAdvancedMatching: data?.useAdvancedMatching || false,
|
|
matchMethod: data?.matchMethod || "",
|
|
expectedValue: data?.expectedValue || "",
|
|
jsonPath: data?.jsonPath || "",
|
|
globalpingEnabled: data?.globalpingEnabled || false,
|
|
};
|
|
break;
|
|
case "ping":
|
|
defaults = {
|
|
...base,
|
|
type: "ping",
|
|
url: data?.url || "",
|
|
globalpingEnabled: data?.globalpingEnabled || false,
|
|
};
|
|
break;
|
|
case "port":
|
|
defaults = {
|
|
...base,
|
|
type: "port",
|
|
url: data?.url || "",
|
|
port: data?.port || 80,
|
|
};
|
|
break;
|
|
case "docker":
|
|
defaults = {
|
|
...base,
|
|
type: "docker",
|
|
url: data?.url || "",
|
|
};
|
|
break;
|
|
case "game":
|
|
defaults = {
|
|
...base,
|
|
type: "game",
|
|
url: data?.url || "",
|
|
port: data?.port || 27015,
|
|
gameId: data?.gameId || "",
|
|
};
|
|
break;
|
|
case "pagespeed":
|
|
defaults = {
|
|
...base,
|
|
type: "pagespeed",
|
|
url: data?.url || "",
|
|
};
|
|
break;
|
|
case "hardware":
|
|
defaults = {
|
|
...base,
|
|
type: "hardware",
|
|
url: data?.url || "",
|
|
secret: data?.secret || "",
|
|
cpuAlertThreshold: data?.cpuAlertThreshold ?? 100,
|
|
memoryAlertThreshold: data?.memoryAlertThreshold ?? 100,
|
|
diskAlertThreshold: data?.diskAlertThreshold ?? 100,
|
|
tempAlertThreshold: data?.tempAlertThreshold ?? 100,
|
|
selectedDisks: data?.selectedDisks || [],
|
|
};
|
|
break;
|
|
default:
|
|
defaults = {
|
|
...base,
|
|
type: "http",
|
|
url: "",
|
|
ignoreTlsErrors: false,
|
|
useAdvancedMatching: false,
|
|
matchMethod: "",
|
|
expectedValue: "",
|
|
jsonPath: "",
|
|
globalpingEnabled: false,
|
|
};
|
|
}
|
|
|
|
return { schema: monitorSchema, defaults };
|
|
}, [data, defaultType]);
|
|
};
|