fix: default node display to canonical name

This commit is contained in:
rcourtman
2025-10-03 19:48:11 +00:00
parent b87e5acaca
commit f9cf1293f0
+48 -5
View File
@@ -1,19 +1,62 @@
import type { Node } from '@/types/api';
type DisplayableNode = Pick<Node, 'name'> & Partial<Pick<Node, 'displayName' | 'instance'>>;
type DisplayableNode = Pick<Node, 'name'> &
Partial<Pick<Node, 'displayName' | 'instance' | 'host'>>;
const sanitize = (value: string): string => value.trim().toLowerCase().replace(/[^a-z0-9]/g, '');
const escapeRegExp = (value: string): string => value.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\$&');
const extractHostname = (value: string): string => {
if (!value) return '';
const trimmed = value.trim();
const withoutProtocol = trimmed.replace(/^[a-z]+:\/\//i, '');
const [hostPart] = withoutProtocol.split('/');
return hostPart.replace(/:\d+$/, '');
};
export function getNodeDisplayName<T extends DisplayableNode>(node: T): string {
const nameRaw = typeof node.name === 'string' ? node.name.trim() : '';
if (nameRaw) return nameRaw;
const display = typeof node.displayName === 'string' ? node.displayName.trim() : '';
if (display) return display;
const hostRaw = typeof node.host === 'string' ? node.host.trim() : '';
const hostname = extractHostname(hostRaw);
if (hostname) return hostname;
const instance = typeof node.instance === 'string' ? node.instance.trim() : '';
if (instance) return instance;
return node.name;
return '';
}
export function hasAlternateDisplayName<T extends DisplayableNode>(node: T): boolean {
const display = typeof node.displayName === 'string' ? node.displayName.trim() : '';
if (!display) return false;
return display.toLowerCase() !== node.name.trim().toLowerCase();
const displayRaw = typeof node.displayName === 'string' ? node.displayName.trim() : '';
if (!displayRaw) return false;
const nameRaw = typeof node.name === 'string' ? node.name.trim() : '';
if (!nameRaw) return false;
const displayLower = displayRaw.toLowerCase();
const nameLower = nameRaw.toLowerCase();
if (displayLower === nameLower) return false;
// Normalize values so cosmetic punctuation/domains do not trigger duplicates in the UI
const sanitizedDisplay = sanitize(displayRaw);
const sanitizedName = sanitize(nameRaw);
if (sanitizedDisplay === sanitizedName) return false;
// Catch cases where the raw display text already embeds the node name (e.g. "Friendly (node)")
const namePattern = new RegExp(`\\b${escapeRegExp(nameLower)}\\b`, 'i');
if (namePattern.test(displayLower)) return false;
const [firstLabel = ''] = displayLower.split('.');
const sanitizedFirstLabel = sanitize(firstLabel);
if (sanitizedFirstLabel === sanitizedName) return false;
return true;
}