Require node names and preserve disk monitoring defaults

This commit is contained in:
rcourtman 2025-10-25 15:28:02 +00:00
parent a279e6720e
commit cb37d0de01

View file

@ -26,6 +26,25 @@ interface NodeModalProps {
securityStatus?: Partial<SecurityStatus>;
}
const deriveNameFromHost = (host: string): string => {
let value = host.trim();
if (!value) {
return '';
}
try {
const url = value.includes('://') ? new URL(value) : new URL(`https://${value}`);
value = url.hostname || value;
} catch {
value = value.replace(/^https?:\/\//, '');
}
value = value.replace(/\/.*$/, '').replace(/^\[(.*)\]$/, '$1');
value = value.replace(/\s+/g, '-');
return value;
};
export const NodeModal: Component<NodeModalProps> = (props) => {
const [testResult, setTestResult] = createSignal<{
status: string;
@ -136,7 +155,7 @@ export const NodeModal: Component<NodeModalProps> = (props) => {
verifySSL: node.verifySSL ?? true,
monitorPhysicalDisks:
node.type === 'pve'
? (node as NodeConfig & { monitorPhysicalDisks?: boolean }).monitorPhysicalDisks ?? false
? (node as NodeConfig & { monitorPhysicalDisks?: boolean }).monitorPhysicalDisks ?? true
: false,
monitorMailStats: pmgConfig?.monitorMailStats ?? true,
monitorQueues: pmgConfig?.monitorQueues ?? true,
@ -150,10 +169,20 @@ export const NodeModal: Component<NodeModalProps> = (props) => {
e.preventDefault();
const data = formData();
const normalizedName = data.name.trim() || deriveNameFromHost(data.host);
if (!normalizedName) {
showError('Node name is required');
return;
}
if (normalizedName !== data.name) {
setFormData((prev) => ({ ...prev, name: normalizedName }));
}
// Prepare data based on auth type
const nodeData: Partial<NodeConfig> = {
type: props.nodeType,
name: data.name || '', // Will be auto-generated by backend if empty
name: normalizedName,
host: data.host,
fingerprint: data.fingerprint,
verifySSL: data.verifySSL,
@ -202,10 +231,24 @@ export const NodeModal: Component<NodeModalProps> = (props) => {
};
const updateField = (field: string, value: string | boolean) => {
setFormData((prev) => ({ ...prev, [field]: value }));
if (field === 'host') {
if (field === 'host' && typeof value === 'string') {
setFormData((prev) => {
const next = { ...prev, host: value };
const derivedName = deriveNameFromHost(value);
const previousDerivedName = deriveNameFromHost(prev.host || '');
const shouldAutoUpdate =
!prev.name.trim() || (previousDerivedName && prev.name === previousDerivedName);
if (derivedName && shouldAutoUpdate) {
next.name = derivedName;
}
return next;
});
setQuickSetupCommand('');
return;
}
setFormData((prev) => ({ ...prev, [field]: value }));
if (field === 'setupMode' && value !== 'auto') {
setQuickSetupCommand('');
}
@ -213,6 +256,11 @@ export const NodeModal: Component<NodeModalProps> = (props) => {
const handleTestConnection = async () => {
const data = formData();
const normalizedName = data.name.trim() || deriveNameFromHost(data.host);
if (!data.name.trim() && normalizedName) {
setFormData((prev) => ({ ...prev, name: normalizedName }));
}
// If editing an existing node and no new credentials provided, use stored credentials
if (props.editingNode) {
@ -267,7 +315,7 @@ export const NodeModal: Component<NodeModalProps> = (props) => {
// Prepare test data
const testData: Partial<NodeConfig> = {
type: props.nodeType,
name: data.name || '', // Will be auto-generated by backend if empty
name: normalizedName || '',
host: data.host,
fingerprint: data.fingerprint,
verifySSL: data.verifySSL,
@ -369,15 +417,19 @@ export const NodeModal: Component<NodeModalProps> = (props) => {
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
<div class={formField}>
<label class={labelClass('flex items-center gap-2')}>
Node Name <span class="text-xs text-gray-500">(optional)</span>
Node Name <span class="text-red-500">*</span>
</label>
<input
type="text"
value={formData().name}
onInput={(e) => updateField('name', e.currentTarget.value)}
placeholder="Will auto-detect from hostname"
placeholder="Pulse uses this label across dashboards"
required
class={controlClass()}
/>
<p class={formHelpText}>
Required and must be unique. We can auto-fill it from the Host URL if you leave it blank.
</p>
</div>
<div class={formField}>