Require node names and preserve disk monitoring defaults
This commit is contained in:
parent
a279e6720e
commit
cb37d0de01
1 changed files with 59 additions and 7 deletions
|
|
@ -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}>
|
||||
|
|
|
|||
Loading…
Reference in a new issue