docs: update CLAUDE.md, ROADMAP.md, SESSION-LOG.md
- Registratura v0.4.0 with QuickLook preview description - New task 3.03d: QuickLook + bug fixes (NAS links, overflow, vault filter) - Session log updated with all fixes and new features - attachment-preview.tsx added to key files list
This commit is contained in:
@@ -101,7 +101,7 @@ legacy/ # Original HTML tools for reference
|
|||||||
| 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.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), **detail sheet side panel**, **configurable column visibility** |
|
| 4 | **Registratura** | `/registratura` | 0.4.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, copy-to-clipboard), **detail sheet side panel**, **configurable column visibility**, **QuickLook attachment preview** (images: zoom/pan, PDFs: native viewer, multi-file navigation) |
|
||||||
| 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)** |
|
||||||
@@ -129,6 +129,7 @@ Key files:
|
|||||||
- `services/working-days.ts` — Romanian holidays, `addWorkingDays()`, `isWorkingDay()`
|
- `services/working-days.ts` — Romanian holidays, `addWorkingDays()`, `isWorkingDay()`
|
||||||
- `services/deadline-catalog.ts` — 16 `DeadlineTypeDef` entries
|
- `services/deadline-catalog.ts` — 16 `DeadlineTypeDef` entries
|
||||||
- `services/deadline-service.ts` — `createTrackedDeadline()`, `resolveDeadline()`, `aggregateDeadlines()`
|
- `services/deadline-service.ts` — `createTrackedDeadline()`, `resolveDeadline()`, `aggregateDeadlines()`
|
||||||
|
- `components/attachment-preview.tsx` — QuickLook-style fullscreen preview (images: zoom/pan, PDFs: blob URL iframe, multi-file nav)
|
||||||
- `components/deadline-dashboard.tsx` — Stats + filters + table
|
- `components/deadline-dashboard.tsx` — Stats + filters + table
|
||||||
- `components/deadline-add-dialog.tsx` — 3-step wizard (category → type → date preview)
|
- `components/deadline-add-dialog.tsx` — 3-step wizard (category → type → date preview)
|
||||||
|
|
||||||
|
|||||||
+13
@@ -316,6 +316,19 @@
|
|||||||
- ✅ **Table UX cleanup**: click pe rând deschide detail sheet, acțiuni reduse la View + Edit, Close/Delete mutate în sheet
|
- ✅ **Table UX cleanup**: click pe rând deschide detail sheet, acțiuni reduse la View + Edit, Close/Delete mutate în sheet
|
||||||
- ✅ **Row click navigation**: cursor-pointer pe rânduri, Eye icon + Pencil icon în acțiuni
|
- ✅ **Row click navigation**: cursor-pointer pe rânduri, Eye icon + Pencil icon în acțiuni
|
||||||
|
|
||||||
|
### 3.03d ✅ `[STANDARD]` Registratura — QuickLook Attachment Preview + Bug Fixes (2026-02-28)
|
||||||
|
|
||||||
|
**Implementat:**
|
||||||
|
|
||||||
|
- ✅ **QuickLook-style preview modal** (`attachment-preview.tsx`, ~480 lines): fullscreen dark overlay cu animații
|
||||||
|
- ✅ **Image preview**: zoom with scroll wheel + buttons (25%–500%), pan/drag when zoomed, reset cu tasta 0
|
||||||
|
- ✅ **PDF preview**: native browser PDF viewer via blob URL iframe (scroll, zoom, print built-in)
|
||||||
|
- ✅ **Multi-file navigation**: săgeți stânga/dreapta (keyboard + butoane), thumbnail strip în josul ecranului
|
||||||
|
- ✅ **Actions**: download, print, close (Esc)
|
||||||
|
- ✅ **NAS link fix**: `file:///` URLs blocked by browsers — replaced with copy-to-clipboard + "Copiat!" feedback
|
||||||
|
- ✅ **NAS card overflow fix**: disabled horizontal scroll on Radix ScrollArea viewport, redesigned card to single-row compact
|
||||||
|
- ✅ **Password Vault filter reset**: category/search reset to "all" after add/edit
|
||||||
|
|
||||||
### 3.04 ✅ `[ARCHITECTURE]` Autentificare & Identitate (2026-02-27)
|
### 3.04 ✅ `[ARCHITECTURE]` Autentificare & Identitate (2026-02-27)
|
||||||
|
|
||||||
**Cerințe noi:**
|
**Cerințe noi:**
|
||||||
|
|||||||
+36
-7
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
### Context
|
### Context
|
||||||
|
|
||||||
Continuation of QA improvements. NAS path enhancement: all 4 drives + DNS→IP fallback.
|
Continuation of QA improvements. NAS path enhancement: all 4 drives + DNS→IP fallback. Detail sheet, column visibility, QuickLook attachment preview, multiple bug fixes.
|
||||||
|
|
||||||
### Completed
|
### Completed
|
||||||
|
|
||||||
@@ -21,11 +21,10 @@ Continuation of QA improvements. NAS path enhancement: all 4 drives + DNS→IP f
|
|||||||
- Validation hint updated to show all 4 drive letters
|
- Validation hint updated to show all 4 drive letters
|
||||||
|
|
||||||
- **Registratura — Entry Detail Sheet (Side Panel):**
|
- **Registratura — Entry Detail Sheet (Side Panel):**
|
||||||
- New `registry-entry-detail.tsx` component (~500 lines)
|
- New `registry-entry-detail.tsx` component (~700 lines)
|
||||||
- Side panel (Sheet) slides in from the right on Eye icon click or row click
|
- Side panel (Sheet) slides in from the right on Eye icon click or row click
|
||||||
- Full entry visualization: status badges, document info, parties, dates, thread links, legal deadlines, attachments with inline image preview, NAS path links with IP fallback, external tracking, tags, notes
|
- Full entry visualization: status badges, document info, parties, dates, thread links, legal deadlines, attachments with inline image preview, NAS path links with IP fallback, external tracking, tags, notes
|
||||||
- Action buttons inside sheet: Edită, Închide, Șterge
|
- Action buttons inside sheet: Edită, Închide, Șterge
|
||||||
- Attachment preview: images display inline, files show download button, NAS paths show full UNC + short display + copy + IP fallback
|
|
||||||
|
|
||||||
- **Registratura — Column Visibility Manager:**
|
- **Registratura — Column Visibility Manager:**
|
||||||
- Configurable columns via Settings dropdown in table header
|
- Configurable columns via Settings dropdown in table header
|
||||||
@@ -40,20 +39,50 @@ Continuation of QA improvements. NAS path enhancement: all 4 drives + DNS→IP f
|
|||||||
- Actions reduced from 3 buttons (close/edit/delete) to 2 (view/edit)
|
- Actions reduced from 3 buttons (close/edit/delete) to 2 (view/edit)
|
||||||
- Close and Delete moved into detail sheet
|
- Close and Delete moved into detail sheet
|
||||||
- Column headers have tooltips explaining naming convention
|
- Column headers have tooltips explaining naming convention
|
||||||
- Attachment/thread/deadline indicators compacted in Subject column
|
|
||||||
|
- **Bug Fix: NAS `file:///` links don't open Explorer:**
|
||||||
|
- Root cause: all modern browsers block `file:///` URLs from web pages (hard security restriction)
|
||||||
|
- Solution: click-to-copy-to-clipboard with green "Copiat!" badge feedback (2s timeout)
|
||||||
|
- Applied to both detail sheet and entry form
|
||||||
|
- Removed broken `window.open(toFileUrl(...))` calls
|
||||||
|
- **Learning:** `file:///` cannot be opened from web pages — only clipboard copy works
|
||||||
|
|
||||||
|
- **Bug Fix: NAS attachment card overflows Sheet boundary:**
|
||||||
|
- Root cause: Radix ScrollArea Viewport has `overflow: scroll` on both axes by default
|
||||||
|
- Fix 1: `overflow-x-hidden` on ScrollArea Viewport via CSS selector override
|
||||||
|
- Fix 2: Redesigned NAS card from two-row layout to compact single-row (filename + NAS badge + Copiază button)
|
||||||
|
- Removed `font-mono` on paths (prevents word-break), removed `shortDisplayPath` (replaced with `pathFileName`)
|
||||||
|
|
||||||
|
- **Bug Fix: Password Vault — new entry lands on filtered empty view:**
|
||||||
|
- Root cause: after adding, the module returns to list view but keeps the active category/search filter
|
||||||
|
- Solution: `handleSubmit` now resets `filters.category` to `"all"` and `filters.search` to `""` after save
|
||||||
|
|
||||||
|
- **QuickLook-style Attachment Preview (macOS Quick Look inspired):**
|
||||||
|
- New `attachment-preview.tsx` component (~480 lines)
|
||||||
|
- Fullscreen dark overlay (`z-[100]`, `bg-black/90`, `backdrop-blur-sm`) with smooth animations
|
||||||
|
- **Images**: zoomable (scroll wheel + ±buttons, 25%–500%), pannable when zoomed (grab/grabbing cursor), zoom % display, reset with 0 key
|
||||||
|
- **PDFs**: browser native viewer via blob URL iframe (base64→Blob→createObjectURL), with scroll/zoom/print built-in
|
||||||
|
- **Navigation**: left/right arrows (keyboard + circular buttons), bottom thumbnail strip when multiple
|
||||||
|
- **Actions**: download (createElement('a') + click), print (PDF: hidden iframe, image: new window), close (Esc)
|
||||||
|
- **Fallback**: unsupported types show icon + "Download" button
|
||||||
|
- Preview button (Eye icon) shown for images AND PDFs in detail sheet
|
||||||
|
- Replaced old inline image-only preview with fullscreen modal
|
||||||
|
- React 19 compatible: no `setState` in effects, uses `key` prop for remount-based state reset
|
||||||
|
|
||||||
- **Documentation updated:**
|
- **Documentation updated:**
|
||||||
- CLAUDE.md: Registratura v0.3.0 updated description
|
- CLAUDE.md: Registratura v0.4.0 with QuickLook description
|
||||||
- ROADMAP.md: New task 3.03c with detail sheet + column manager features
|
- ROADMAP.md: New task 3.03d with QuickLook + bug fixes
|
||||||
- SESSION-LOG.md: This session entry
|
- SESSION-LOG.md: This session entry
|
||||||
|
|
||||||
### Files Changed
|
### Files Changed
|
||||||
|
|
||||||
- **New:** `src/modules/registratura/components/registry-entry-detail.tsx`
|
- **New:** `src/modules/registratura/components/registry-entry-detail.tsx`
|
||||||
|
- **New:** `src/modules/registratura/components/attachment-preview.tsx`
|
||||||
- **Modified:** `src/config/nas-paths.ts` (4 drives, IP fallback helpers, shareLabelFor)
|
- **Modified:** `src/config/nas-paths.ts` (4 drives, IP fallback helpers, shareLabelFor)
|
||||||
- **Modified:** `src/modules/registratura/components/registry-table.tsx` (column visibility, tooltips, view button, row click)
|
- **Modified:** `src/modules/registratura/components/registry-table.tsx` (column visibility, tooltips, view button, row click)
|
||||||
- **Modified:** `src/modules/registratura/components/registratura-module.tsx` (detail sheet integration, handleView)
|
- **Modified:** `src/modules/registratura/components/registratura-module.tsx` (detail sheet integration, handleView)
|
||||||
- **Modified:** `src/modules/registratura/components/registry-entry-form.tsx` (IP fallback link, share badge, validation hints)
|
- **Modified:** `src/modules/registratura/components/registry-entry-form.tsx` (NAS link copy-to-clipboard, removed broken file:/// links)
|
||||||
|
- **Modified:** `src/modules/password-vault/components/password-vault-module.tsx` (filter reset after add/edit)
|
||||||
- **Modified:** `CLAUDE.md`, `ROADMAP.md`, `SESSION-LOG.md`
|
- **Modified:** `CLAUDE.md`, `ROADMAP.md`, `SESSION-LOG.md`
|
||||||
|
|
||||||
### Build
|
### Build
|
||||||
|
|||||||
@@ -32,10 +32,7 @@ const ZOOM_STEP = 0.25;
|
|||||||
|
|
||||||
/** Check if a MIME type can be previewed */
|
/** Check if a MIME type can be previewed */
|
||||||
function isPreviewable(type: string): boolean {
|
function isPreviewable(type: string): boolean {
|
||||||
return (
|
return type.startsWith("image/") || type === "application/pdf";
|
||||||
type.startsWith("image/") ||
|
|
||||||
type === "application/pdf"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Filter to only previewable attachments with inline data */
|
/** Filter to only previewable attachments with inline data */
|
||||||
@@ -169,7 +166,12 @@ export function AttachmentPreview({
|
|||||||
if (!isImage || zoom <= 1) return;
|
if (!isImage || zoom <= 1) return;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setIsPanning(true);
|
setIsPanning(true);
|
||||||
panStart.current = { x: e.clientX, y: e.clientY, panX: pan.x, panY: pan.y };
|
panStart.current = {
|
||||||
|
x: e.clientX,
|
||||||
|
y: e.clientY,
|
||||||
|
panX: pan.x,
|
||||||
|
panY: pan.y,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
[isImage, zoom, pan],
|
[isImage, zoom, pan],
|
||||||
);
|
);
|
||||||
@@ -239,7 +241,9 @@ export function AttachmentPreview({
|
|||||||
if (!open || !att) return null;
|
if (!open || !att) return null;
|
||||||
|
|
||||||
const fileExt =
|
const fileExt =
|
||||||
att.name.split(".").pop()?.toUpperCase() ?? att.type.split("/")[1]?.toUpperCase() ?? "FILE";
|
att.name.split(".").pop()?.toUpperCase() ??
|
||||||
|
att.type.split("/")[1]?.toUpperCase() ??
|
||||||
|
"FILE";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 z-[100] flex flex-col bg-black/90 backdrop-blur-sm animate-in fade-in duration-200">
|
<div className="fixed inset-0 z-[100] flex flex-col bg-black/90 backdrop-blur-sm animate-in fade-in duration-200">
|
||||||
@@ -270,7 +274,9 @@ export function AttachmentPreview({
|
|||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon"
|
size="icon"
|
||||||
className="h-8 w-8 text-white/70 hover:text-white hover:bg-white/10"
|
className="h-8 w-8 text-white/70 hover:text-white hover:bg-white/10"
|
||||||
onClick={() => setZoom((z) => Math.max(z - ZOOM_STEP, ZOOM_MIN))}
|
onClick={() =>
|
||||||
|
setZoom((z) => Math.max(z - ZOOM_STEP, ZOOM_MIN))
|
||||||
|
}
|
||||||
title="Micșorează (−)"
|
title="Micșorează (−)"
|
||||||
>
|
>
|
||||||
<Minus className="h-4 w-4" />
|
<Minus className="h-4 w-4" />
|
||||||
@@ -278,7 +284,10 @@ export function AttachmentPreview({
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="px-2 text-xs text-white/70 hover:text-white font-mono min-w-[3.5rem] text-center"
|
className="px-2 text-xs text-white/70 hover:text-white font-mono min-w-[3.5rem] text-center"
|
||||||
onClick={() => { setZoom(1); setPan({ x: 0, y: 0 }); }}
|
onClick={() => {
|
||||||
|
setZoom(1);
|
||||||
|
setPan({ x: 0, y: 0 });
|
||||||
|
}}
|
||||||
title="Resetează zoom (0)"
|
title="Resetează zoom (0)"
|
||||||
>
|
>
|
||||||
{Math.round(zoom * 100)}%
|
{Math.round(zoom * 100)}%
|
||||||
@@ -287,7 +296,9 @@ export function AttachmentPreview({
|
|||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon"
|
size="icon"
|
||||||
className="h-8 w-8 text-white/70 hover:text-white hover:bg-white/10"
|
className="h-8 w-8 text-white/70 hover:text-white hover:bg-white/10"
|
||||||
onClick={() => setZoom((z) => Math.min(z + ZOOM_STEP, ZOOM_MAX))}
|
onClick={() =>
|
||||||
|
setZoom((z) => Math.min(z + ZOOM_STEP, ZOOM_MAX))
|
||||||
|
}
|
||||||
title="Mărește (+)"
|
title="Mărește (+)"
|
||||||
>
|
>
|
||||||
<Plus className="h-4 w-4" />
|
<Plus className="h-4 w-4" />
|
||||||
@@ -347,7 +358,10 @@ export function AttachmentPreview({
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="absolute left-3 top-1/2 -translate-y-1/2 z-10 flex items-center justify-center w-10 h-10 rounded-full bg-black/50 text-white/70 hover:text-white hover:bg-black/70 transition-colors"
|
className="absolute left-3 top-1/2 -translate-y-1/2 z-10 flex items-center justify-center w-10 h-10 rounded-full bg-black/50 text-white/70 hover:text-white hover:bg-black/70 transition-colors"
|
||||||
onClick={(e) => { e.stopPropagation(); goPrev(); }}
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
goPrev();
|
||||||
|
}}
|
||||||
title="Anterior (←)"
|
title="Anterior (←)"
|
||||||
>
|
>
|
||||||
<ChevronLeft className="h-5 w-5" />
|
<ChevronLeft className="h-5 w-5" />
|
||||||
@@ -355,7 +369,10 @@ export function AttachmentPreview({
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="absolute right-3 top-1/2 -translate-y-1/2 z-10 flex items-center justify-center w-10 h-10 rounded-full bg-black/50 text-white/70 hover:text-white hover:bg-black/70 transition-colors"
|
className="absolute right-3 top-1/2 -translate-y-1/2 z-10 flex items-center justify-center w-10 h-10 rounded-full bg-black/50 text-white/70 hover:text-white hover:bg-black/70 transition-colors"
|
||||||
onClick={(e) => { e.stopPropagation(); goNext(); }}
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
goNext();
|
||||||
|
}}
|
||||||
title="Următor (→)"
|
title="Următor (→)"
|
||||||
>
|
>
|
||||||
<ChevronRight className="h-5 w-5" />
|
<ChevronRight className="h-5 w-5" />
|
||||||
|
|||||||
@@ -617,17 +617,16 @@ export function RegistryEntryDetail({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
{/* QuickLook-style attachment preview */}
|
{/* QuickLook-style attachment preview */}
|
||||||
{previewIndex !== null && (
|
{previewIndex !== null && (
|
||||||
<AttachmentPreview
|
<AttachmentPreview
|
||||||
key={previewIndex}
|
key={previewIndex}
|
||||||
attachments={previewableAtts}
|
attachments={previewableAtts}
|
||||||
initialIndex={previewIndex}
|
initialIndex={previewIndex}
|
||||||
open
|
open
|
||||||
onClose={() => setPreviewIndex(null)}
|
onClose={() => setPreviewIndex(null)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</SheetContent>
|
</SheetContent>
|
||||||
</Sheet>
|
</Sheet>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user