feat(registratura): all 4 NAS drives (A/O/P/T) + hostnameIP fallback
- nas-paths.ts: A:\=Arhiva, O:\=Organizare, P:\=Proiecte, T:\=Transfer - toUncPathByIp() / toFileUrlByIp() helpers for DNS failure fallback - shareLabelFor() returns human-readable share name for badges - UI: 'IP' fallback link on hover, badge shows share label - Validation hints updated to show all 4 drive letters - Docs updated: CLAUDE.md, ROADMAP.md, SESSION-LOG.md
This commit is contained in:
+52
-12
@@ -4,6 +4,10 @@
|
||||
* The office NAS (\\newamun / 10.10.10.10) exposes several shares.
|
||||
* Windows maps these to drive letters. This config lets us normalise
|
||||
* user-pasted paths to UNC and back, and build clickable `file:///` links.
|
||||
*
|
||||
* Fallback strategy: hostname → IP.
|
||||
* If DNS fails to resolve `newamun`, every helper has an `...ByIp()` variant
|
||||
* that substitutes the hostname with the raw IP address.
|
||||
*/
|
||||
|
||||
export interface NasDriveMapping {
|
||||
@@ -15,17 +19,18 @@ export interface NasDriveMapping {
|
||||
label: string;
|
||||
}
|
||||
|
||||
/** All known drive-letter → UNC mappings */
|
||||
export const NAS_DRIVE_MAPPINGS: NasDriveMapping[] = [
|
||||
{ drive: "P", unc: "\\\\newamun\\Proiecte", label: "Proiecte" },
|
||||
// Add more as needed:
|
||||
// { drive: "S", unc: "\\\\newamun\\Shared", label: "Shared" },
|
||||
];
|
||||
|
||||
/** NAS hostname / IP — used for display only */
|
||||
/** NAS hostname / IP */
|
||||
export const NAS_HOST = "newamun";
|
||||
export const NAS_IP = "10.10.10.10";
|
||||
|
||||
/** All known drive-letter → UNC mappings */
|
||||
export const NAS_DRIVE_MAPPINGS: NasDriveMapping[] = [
|
||||
{ drive: "A", unc: `\\\\${NAS_HOST}\\Arhiva`, label: "Arhiva" },
|
||||
{ drive: "O", unc: `\\\\${NAS_HOST}\\Organizare`, label: "Organizare" },
|
||||
{ drive: "P", unc: `\\\\${NAS_HOST}\\Proiecte`, label: "Proiecte" },
|
||||
{ drive: "T", unc: `\\\\${NAS_HOST}\\Transfer`, label: "Transfer" },
|
||||
];
|
||||
|
||||
// ── helpers ──
|
||||
|
||||
/**
|
||||
@@ -34,7 +39,7 @@ export const NAS_IP = "10.10.10.10";
|
||||
*/
|
||||
export function isNetworkPath(input: string): boolean {
|
||||
const trimmed = input.trim();
|
||||
// UNC path
|
||||
// UNC path (hostname or IP)
|
||||
if (trimmed.startsWith("\\\\")) return true;
|
||||
// Mapped drive letter that we recognise
|
||||
const match = trimmed.match(/^([A-Z]):\\/i);
|
||||
@@ -46,7 +51,7 @@ export function isNetworkPath(input: string): boolean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalise to UNC path (replace drive letter with \\newamun\Share).
|
||||
* Normalise to UNC path using hostname (replace drive letter with \\newamun\Share).
|
||||
* If already UNC or unrecognised → returns the original trimmed.
|
||||
*/
|
||||
export function toUncPath(input: string): string {
|
||||
@@ -62,13 +67,36 @@ export function toUncPath(input: string): string {
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Swap hostname → IP in a UNC path.
|
||||
* `\\newamun\Proiecte\file.pdf` → `\\10.10.10.10\Proiecte\file.pdf`
|
||||
* Already-IP or unrecognised paths are returned unchanged.
|
||||
*/
|
||||
export function toUncPathByIp(input: string): string {
|
||||
const unc = toUncPath(input);
|
||||
const hostPrefix = `\\\\${NAS_HOST}\\`;
|
||||
if (unc.toLowerCase().startsWith(hostPrefix.toLowerCase())) {
|
||||
return `\\\\${NAS_IP}\\${unc.slice(hostPrefix.length)}`;
|
||||
}
|
||||
return unc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a clickable `file:///` URL from a UNC or drive-letter path.
|
||||
* Windows Explorer opens this natively.
|
||||
* Uses hostname by default.
|
||||
*/
|
||||
export function toFileUrl(input: string): string {
|
||||
const unc = toUncPath(input);
|
||||
// file:///\\server\share\path → file://///server/share/path
|
||||
const slashed = unc.replace(/\\/g, "/");
|
||||
return `file:///${slashed}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a clickable `file:///` URL using the IP fallback.
|
||||
* Use when DNS fails to resolve hostname.
|
||||
*/
|
||||
export function toFileUrlByIp(input: string): string {
|
||||
const unc = toUncPathByIp(input);
|
||||
const slashed = unc.replace(/\\/g, "/");
|
||||
return `file:///${slashed}`;
|
||||
}
|
||||
@@ -96,3 +124,15 @@ export function shortDisplayPath(input: string): string {
|
||||
const last2 = parts.slice(-2).join("\\");
|
||||
return `${share}\\…\\${last2}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the human-readable label of the share a path belongs to.
|
||||
* e.g. `P:\095\file.pdf` → `Proiecte`
|
||||
*/
|
||||
export function shareLabelFor(input: string): string | undefined {
|
||||
const unc = toUncPath(input).toLowerCase();
|
||||
for (const m of NAS_DRIVE_MAPPINGS) {
|
||||
if (unc.startsWith(m.unc.toLowerCase())) return m.label;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user