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:
@@ -96,22 +96,22 @@ legacy/ # Original HTML tools for reference
|
|||||||
|
|
||||||
## Implemented Modules (14/14 — zero placeholders)
|
## Implemented Modules (14/14 — zero placeholders)
|
||||||
|
|
||||||
| # | Module | Route | Version | Key Features |
|
| # | Module | Route | Version | Key Features |
|
||||||
| --- | ---------------------- | --------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| --- | ---------------------- | --------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| 1 | **Dashboard** | `/` | 0.1.0 | KPI cards (6), activity feed (last 20), module grid, external tools |
|
| 1 | **Dashboard** | `/` | 0.1.0 | KPI cards (6), activity feed (last 20), module grid, external tools |
|
||||||
| 2 | **Email Signature** | `/email-signature` | 0.1.0 | Multi-company branding, address toggle (BTG/US/SDT), live preview, zoom/copy/download |
|
| 2 | **Email Signature** | `/email-signature` | 0.1.0 | Multi-company branding, address toggle (BTG/US/SDT), live preview, zoom/copy/download |
|
||||||
| 3 | **Word XML Generator** | `/word-xml` | 0.1.0 | Category-based XML gen, simple/advanced mode, ZIP export |
|
| 3 | **Word XML Generator** | `/word-xml` | 0.1.0 | Category-based XML gen, simple/advanced mode, ZIP export |
|
||||||
| 4 | **Registratura** | `/registratura` | 0.2.0 | CRUD registry, dynamic doc types, bidirectional Address Book, threads, backdating, **legal deadline tracking**, recipient registration, document expiry |
|
| 4 | **Registratura** | `/registratura` | 0.3.0 | CRUD registry, dynamic doc types, bidirectional Address Book, threads, backdating, **legal deadline tracking**, recipient registration, document expiry, **NAS network path attachments** (A/O/P/T drives, hostname+IP fallback) |
|
||||||
| 5 | **Tag Manager** | `/tag-manager` | 0.2.0 | CRUD tags, category/scope/color, US/SDT seeds, mandatory categories, **ManicTime bidirectional sync** |
|
| 5 | **Tag Manager** | `/tag-manager` | 0.2.0 | CRUD tags, category/scope/color, US/SDT seeds, mandatory categories, **ManicTime bidirectional sync** |
|
||||||
| 6 | **IT Inventory** | `/it-inventory` | 0.2.0 | Dynamic equipment types, rented status (purple pulse), **42U rack visualization**, type/status/company filters |
|
| 6 | **IT Inventory** | `/it-inventory` | 0.2.0 | Dynamic equipment types, rented status (purple pulse), **42U rack visualization**, type/status/company filters |
|
||||||
| 7 | **Address Book** | `/address-book` | 0.1.0 | CRUD contacts, card grid, vCard export, Registratura reverse lookup, **dynamic types (creatable)** |
|
| 7 | **Address Book** | `/address-book` | 0.1.0 | CRUD contacts, card grid, vCard export, Registratura reverse lookup, **dynamic types (creatable)** |
|
||||||
| 8 | **Password Vault** | `/password-vault` | 0.3.0 | CRUD credentials, 9 categorii cu iconițe, **WiFi QR code real**, context-aware form, strength meter, company scope, **AES-256-GCM encryption** |
|
| 8 | **Password Vault** | `/password-vault` | 0.3.0 | CRUD credentials, 9 categorii cu iconițe, **WiFi QR code real**, context-aware form, strength meter, company scope, **AES-256-GCM encryption** |
|
||||||
| 9 | **Mini Utilities** | `/mini-utilities` | 0.1.0 | Text case, char counter, percentage, area converter, U→R, artifact cleaner, MDLPA, PDF reducer, OCR |
|
| 9 | **Mini Utilities** | `/mini-utilities` | 0.1.0 | Text case, char counter, percentage, area converter, U→R, artifact cleaner, MDLPA, PDF reducer, OCR |
|
||||||
| 10 | **Prompt Generator** | `/prompt-generator` | 0.2.0 | Template-driven prompt builder, **18 templates** (14 text + 4 image), search bar, target type filter |
|
| 10 | **Prompt Generator** | `/prompt-generator` | 0.2.0 | Template-driven prompt builder, **18 templates** (14 text + 4 image), search bar, target type filter |
|
||||||
| 11 | **Digital Signatures** | `/digital-signatures` | 0.1.0 | CRUD assets, drag-and-drop file upload, tag chips |
|
| 11 | **Digital Signatures** | `/digital-signatures` | 0.1.0 | CRUD assets, drag-and-drop file upload, tag chips |
|
||||||
| 12 | **Word Templates** | `/word-templates` | 0.1.0 | Template library, 8 categories, version tracking, .docx placeholder auto-detection |
|
| 12 | **Word Templates** | `/word-templates` | 0.1.0 | Template library, 8 categories, version tracking, .docx placeholder auto-detection |
|
||||||
| 13 | **AI Chat** | `/ai-chat` | 0.2.0 | Multi-provider (OpenAI/Claude/Ollama/demo), **project linking via Tag Manager**, provider status badge |
|
| 13 | **AI Chat** | `/ai-chat` | 0.2.0 | Multi-provider (OpenAI/Claude/Ollama/demo), **project linking via Tag Manager**, provider status badge |
|
||||||
| 14 | **Hot Desk** | `/hot-desk` | 0.1.0 | 4 desks, week-ahead calendar, room layout (window+door), reserve/cancel |
|
| 14 | **Hot Desk** | `/hot-desk` | 0.1.0 | 4 desks, week-ahead calendar, room layout (window+door), reserve/cancel |
|
||||||
|
|
||||||
### Registratura — Legal Deadline Tracking (Termene Legale)
|
### Registratura — Legal Deadline Tracking (Termene Legale)
|
||||||
|
|
||||||
@@ -245,15 +245,16 @@ src/modules/<name>/
|
|||||||
|
|
||||||
## Current Integrations
|
## Current Integrations
|
||||||
|
|
||||||
| Feature | Status | Notes |
|
| Feature | Status | Notes |
|
||||||
| -------------------- | ---------------------- | --------------------------------------------------------------- |
|
| -------------------- | ---------------------- | ------------------------------------------------------------------------------------------ |
|
||||||
| **Authentik SSO** | ✅ Active | NextAuth v4 + OIDC, group→role/company mapping |
|
| **Authentik SSO** | ✅ Active | NextAuth v4 + OIDC, group→role/company mapping |
|
||||||
| **PostgreSQL** | ✅ Active | Prisma ORM, `KeyValueStore` model, `/api/storage` route |
|
| **PostgreSQL** | ✅ Active | Prisma ORM, `KeyValueStore` model, `/api/storage` route |
|
||||||
| **MinIO** | Client configured | 10.10.10.166:9002, bucket `tools`, adapter pending |
|
| **MinIO** | Client configured | 10.10.10.166:9002, bucket `tools`, adapter pending |
|
||||||
| **AI Chat API** | ✅ Multi-provider | `/api/ai-chat` — OpenAI/Claude/Ollama/demo; needs API key env |
|
| **AI Chat API** | ✅ Multi-provider | `/api/ai-chat` — OpenAI/Claude/Ollama/demo; needs API key env |
|
||||||
| **Vault Encryption** | ✅ Active | AES-256-GCM server-side, `/api/vault`, ENCRYPTION_SECRET env |
|
| **Vault Encryption** | ✅ Active | AES-256-GCM server-side, `/api/vault`, ENCRYPTION_SECRET env |
|
||||||
| **ManicTime Sync** | ✅ Implemented | `/api/manictime` — bidirectional Tags.txt sync, needs SMB mount |
|
| **ManicTime Sync** | ✅ Implemented | `/api/manictime` — bidirectional Tags.txt sync, needs SMB mount |
|
||||||
| **N8N automations** | Webhook URL configured | For notifications, backups, workflows |
|
| **NAS Paths** | ✅ Active | `\\newamun` (10.10.10.10), drives A/O/P/T, hostname+IP fallback, `src/config/nas-paths.ts` |
|
||||||
|
| **N8N automations** | Webhook URL configured | For notifications, backups, workflows |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+14
-1
@@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
| # | Module | Version | Status | Remaining Gaps | Future Enhancements |
|
| # | Module | Version | Status | Remaining Gaps | Future Enhancements |
|
||||||
| --- | ------------------ | ------- | -------- | ---------------------------------------- | ------------------------------------------------- |
|
| --- | ------------------ | ------- | -------- | ---------------------------------------- | ------------------------------------------------- |
|
||||||
| 1 | Registratura | 0.2.0 | COMPLETE | — | Workflow automation, email integration, OCR |
|
| 1 | Registratura | 0.3.0 | COMPLETE | — | Workflow automation, email integration, OCR |
|
||||||
| 2 | Email Signature | 0.1.0 | COMPLETE | US/SDT addresses may need update | AD sync, branding packs, promo banners |
|
| 2 | Email Signature | 0.1.0 | COMPLETE | US/SDT addresses may need update | AD sync, branding packs, promo banners |
|
||||||
| 3 | Word XML | 0.1.0 | COMPLETE | — | Schema validator, visual mapper |
|
| 3 | Word XML | 0.1.0 | COMPLETE | — | Schema validator, visual mapper |
|
||||||
| 4 | Digital Signatures | 0.1.0 | COMPLETE | — | Permission layers, document insertion |
|
| 4 | Digital Signatures | 0.1.0 | COMPLETE | — | Permission layers, document insertion |
|
||||||
@@ -291,6 +291,19 @@
|
|||||||
|
|
||||||
- ⏳ **Generare Raport/Declarație:** Necesită integrare cross-module Registratura ↔ Word Templates
|
- ⏳ **Generare Raport/Declarație:** Necesită integrare cross-module Registratura ↔ Word Templates
|
||||||
|
|
||||||
|
### 3.03b ✅ `[STANDARD]` Registratura — NAS Network Path Attachments (2026-02-28)
|
||||||
|
|
||||||
|
**Implementat:**
|
||||||
|
|
||||||
|
- ✅ **NAS config** (`src/config/nas-paths.ts`): 4 drive mappings (A:\=Arhiva, O:\=Organizare, P:\=Proiecte, T:\=Transfer)
|
||||||
|
- ✅ **Hostname + IP fallback**: toate funcțiile au variante `...ByIp()` — `toUncPathByIp()`, `toFileUrlByIp()` — pentru când DNS nu rezolvă `newamun`
|
||||||
|
- ✅ **Link NAS button** în secțiunea atașamente: input inline cu validare, preview cale scurtă
|
||||||
|
- ✅ **Visual distinct**: border albastru, HardDrive icon, badge cu numele share-ului (Proiecte/Arhiva/etc.)
|
||||||
|
- ✅ **Click deschide Explorer** via `file:///` URL, buton "IP" fallback pe hover
|
||||||
|
- ✅ **Copy path** button pe hover
|
||||||
|
- ✅ **Drive letter → UNC** normalization automată (P:\ → \\newamun\Proiecte)
|
||||||
|
- ✅ **`shareLabelFor()`** helper returns human-readable share name
|
||||||
|
|
||||||
### 3.04 ✅ `[ARCHITECTURE]` Autentificare & Identitate (2026-02-27)
|
### 3.04 ✅ `[ARCHITECTURE]` Autentificare & Identitate (2026-02-27)
|
||||||
|
|
||||||
**Cerințe noi:**
|
**Cerințe noi:**
|
||||||
|
|||||||
@@ -4,6 +4,40 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Session — 2026-02-28c (GitHub Copilot - Claude Opus 4.6)
|
||||||
|
|
||||||
|
### Context
|
||||||
|
|
||||||
|
Continuation of QA improvements. NAS path enhancement: all 4 drives + DNS→IP fallback.
|
||||||
|
|
||||||
|
### Completed
|
||||||
|
|
||||||
|
- **NAS Network Path Attachments (enhanced):**
|
||||||
|
- 4 drive mappings: A:\=Arhiva, O:\=Organizare, P:\=Proiecte, T:\=Transfer
|
||||||
|
- `NAS_HOST` / `NAS_IP` constants used consistently across all UNC templates
|
||||||
|
- New helpers: `toUncPathByIp()`, `toFileUrlByIp()`, `shareLabelFor()`
|
||||||
|
- IP fallback: every network attachment shows an "IP" button on hover that opens via `\\10.10.10.10\...` when DNS fails
|
||||||
|
- Badge now shows share label (Proiecte/Arhiva/Organizare/Transfer) instead of generic "NAS"
|
||||||
|
- Validation hint updated to show all 4 drive letters
|
||||||
|
|
||||||
|
- **Documentation updated:**
|
||||||
|
- CLAUDE.md: Registratura v0.3.0, NAS drives in module table, NAS row in integrations table
|
||||||
|
- ROADMAP.md: Registratura version bump, new task 3.03b with full feature list
|
||||||
|
- SESSION-LOG.md: This session entry
|
||||||
|
|
||||||
|
### Files Changed
|
||||||
|
|
||||||
|
- **Modified:** `src/config/nas-paths.ts` (4 drives, IP fallback helpers, shareLabelFor)
|
||||||
|
- **Modified:** `src/modules/registratura/components/registry-entry-form.tsx` (IP fallback link, share badge, validation hints)
|
||||||
|
- **Modified:** `CLAUDE.md`, `ROADMAP.md`, `SESSION-LOG.md`
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
- `npx next build` — zero errors
|
||||||
|
- Pushed to main → Portainer auto-deploy
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Session — 2026-02-28b (GitHub Copilot - Claude Opus 4.6)
|
## Session — 2026-02-28b (GitHub Copilot - Claude Opus 4.6)
|
||||||
|
|
||||||
### Context
|
### Context
|
||||||
|
|||||||
+52
-12
@@ -4,6 +4,10 @@
|
|||||||
* The office NAS (\\newamun / 10.10.10.10) exposes several shares.
|
* The office NAS (\\newamun / 10.10.10.10) exposes several shares.
|
||||||
* Windows maps these to drive letters. This config lets us normalise
|
* Windows maps these to drive letters. This config lets us normalise
|
||||||
* user-pasted paths to UNC and back, and build clickable `file:///` links.
|
* 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 {
|
export interface NasDriveMapping {
|
||||||
@@ -15,17 +19,18 @@ export interface NasDriveMapping {
|
|||||||
label: string;
|
label: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** All known drive-letter → UNC mappings */
|
/** NAS hostname / IP */
|
||||||
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 */
|
|
||||||
export const NAS_HOST = "newamun";
|
export const NAS_HOST = "newamun";
|
||||||
export const NAS_IP = "10.10.10.10";
|
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 ──
|
// ── helpers ──
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,7 +39,7 @@ export const NAS_IP = "10.10.10.10";
|
|||||||
*/
|
*/
|
||||||
export function isNetworkPath(input: string): boolean {
|
export function isNetworkPath(input: string): boolean {
|
||||||
const trimmed = input.trim();
|
const trimmed = input.trim();
|
||||||
// UNC path
|
// UNC path (hostname or IP)
|
||||||
if (trimmed.startsWith("\\\\")) return true;
|
if (trimmed.startsWith("\\\\")) return true;
|
||||||
// Mapped drive letter that we recognise
|
// Mapped drive letter that we recognise
|
||||||
const match = trimmed.match(/^([A-Z]):\\/i);
|
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.
|
* If already UNC or unrecognised → returns the original trimmed.
|
||||||
*/
|
*/
|
||||||
export function toUncPath(input: string): string {
|
export function toUncPath(input: string): string {
|
||||||
@@ -62,13 +67,36 @@ export function toUncPath(input: string): string {
|
|||||||
return trimmed;
|
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.
|
* 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 {
|
export function toFileUrl(input: string): string {
|
||||||
const unc = toUncPath(input);
|
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, "/");
|
const slashed = unc.replace(/\\/g, "/");
|
||||||
return `file:///${slashed}`;
|
return `file:///${slashed}`;
|
||||||
}
|
}
|
||||||
@@ -96,3 +124,15 @@ export function shortDisplayPath(input: string): string {
|
|||||||
const last2 = parts.slice(-2).join("\\");
|
const last2 = parts.slice(-2).join("\\");
|
||||||
return `${share}\\…\\${last2}`;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -34,8 +34,10 @@ import {
|
|||||||
isNetworkPath,
|
isNetworkPath,
|
||||||
toUncPath,
|
toUncPath,
|
||||||
toFileUrl,
|
toFileUrl,
|
||||||
|
toFileUrlByIp,
|
||||||
pathFileName,
|
pathFileName,
|
||||||
shortDisplayPath,
|
shortDisplayPath,
|
||||||
|
shareLabelFor,
|
||||||
} from "@/config/nas-paths";
|
} from "@/config/nas-paths";
|
||||||
import { Input } from "@/shared/components/ui/input";
|
import { Input } from "@/shared/components/ui/input";
|
||||||
import { Label } from "@/shared/components/ui/label";
|
import { Label } from "@/shared/components/ui/label";
|
||||||
@@ -1223,7 +1225,7 @@ export function RegistryEntryForm({
|
|||||||
<div className="mt-2 rounded-md border border-blue-200 bg-blue-50/50 dark:border-blue-800 dark:bg-blue-950/30 p-3 space-y-2">
|
<div className="mt-2 rounded-md border border-blue-200 bg-blue-50/50 dark:border-blue-800 dark:bg-blue-950/30 p-3 space-y-2">
|
||||||
<Label className="text-xs flex items-center gap-1">
|
<Label className="text-xs flex items-center gap-1">
|
||||||
<HardDrive className="h-3 w-3" />
|
<HardDrive className="h-3 w-3" />
|
||||||
Cale fișier pe NAS (\\newamun sau P:\\...)
|
Cale fișier pe NAS (A:\ O:\ P:\ T:\ sau \\newamun\\...)
|
||||||
</Label>
|
</Label>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<Input
|
<Input
|
||||||
@@ -1254,7 +1256,8 @@ export function RegistryEntryForm({
|
|||||||
)}
|
)}
|
||||||
{networkPathInput.trim() && !isNetworkPath(networkPathInput) && (
|
{networkPathInput.trim() && !isNetworkPath(networkPathInput) && (
|
||||||
<p className="text-[10px] text-amber-600 dark:text-amber-400">
|
<p className="text-[10px] text-amber-600 dark:text-amber-400">
|
||||||
Calea nu pare a fi pe NAS. Introdu o cale de tip P:\\... sau \\newamun\\...
|
Calea nu pare a fi pe NAS. Introdu o cale de tip A:\ O:\ P:\ T:\
|
||||||
|
sau \\newamun\\...
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -1275,7 +1278,6 @@ export function RegistryEntryForm({
|
|||||||
className="flex-1 min-w-0 flex items-center gap-1 text-blue-700 dark:text-blue-300 hover:underline cursor-pointer"
|
className="flex-1 min-w-0 flex items-center gap-1 text-blue-700 dark:text-blue-300 hover:underline cursor-pointer"
|
||||||
title={`Deschide în Explorer: ${att.networkPath}`}
|
title={`Deschide în Explorer: ${att.networkPath}`}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
// file:/// links might be blocked by browser; copy path as fallback
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
window.open(toFileUrl(att.networkPath!), "_blank");
|
window.open(toFileUrl(att.networkPath!), "_blank");
|
||||||
}}
|
}}
|
||||||
@@ -1285,11 +1287,23 @@ export function RegistryEntryForm({
|
|||||||
{shortDisplayPath(att.networkPath)}
|
{shortDisplayPath(att.networkPath)}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
|
{/* IP fallback link — visible on hover when DNS fails */}
|
||||||
|
<a
|
||||||
|
href={toFileUrlByIp(att.networkPath)}
|
||||||
|
className="opacity-0 group-hover:opacity-100 transition-opacity text-[10px] text-blue-400 hover:text-blue-600 dark:hover:text-blue-200 shrink-0"
|
||||||
|
title={`Fallback IP: ${toFileUrlByIp(att.networkPath!)}`}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
window.open(toFileUrlByIp(att.networkPath!), "_blank");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
IP
|
||||||
|
</a>
|
||||||
<Badge
|
<Badge
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="text-[10px] border-blue-300 dark:border-blue-700 text-blue-600 dark:text-blue-400 shrink-0"
|
className="text-[10px] border-blue-300 dark:border-blue-700 text-blue-600 dark:text-blue-400 shrink-0"
|
||||||
>
|
>
|
||||||
NAS
|
{shareLabelFor(att.networkPath) ?? "NAS"}
|
||||||
</Badge>
|
</Badge>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
|||||||
Reference in New Issue
Block a user