Redesign document workspace layout and tighten frontend type config

This commit is contained in:
2026-02-21 10:00:35 -03:00
parent 5dfc2cbd85
commit 04cf830e21
16 changed files with 1373 additions and 109 deletions

View File

@@ -1,6 +1,8 @@
/**
* Reusable modal for confirmations and multi-action prompts.
*/
import type { JSX } from 'react';
interface ActionModalOption {
key: string;
label: string;

View File

@@ -2,6 +2,7 @@
* Card view for displaying document summary, preview, and metadata.
*/
import { useState } from 'react';
import type { JSX } from 'react';
import { Download, FileText, Trash2 } from 'lucide-react';
import type { DmsDocument } from '../types';

View File

@@ -1,6 +1,8 @@
/**
* Grid renderer for document collections.
*/
import type { JSX } from 'react';
import type { DmsDocument } from '../types';
import DocumentCard from './DocumentCard';

View File

@@ -2,6 +2,7 @@
* Embedded document viewer panel for preview, metadata updates, and lifecycle actions.
*/
import { useEffect, useMemo, useState } from 'react';
import type { JSX } from 'react';
import {
contentMarkdownUrl,

View File

@@ -2,6 +2,7 @@
* Path editor with suggestion dropdown for scalable logical-path selection.
*/
import { useMemo, useState } from 'react';
import type { JSX } from 'react';
/**
* Defines properties for the reusable path input component.

View File

@@ -2,6 +2,7 @@
* Processing log timeline panel for upload, OCR, summarization, routing, and indexing events.
*/
import { useEffect, useMemo, useRef, useState } from 'react';
import type { JSX } from 'react';
import type { ProcessingLogEntry } from '../types';

View File

@@ -1,6 +1,8 @@
/**
* Compact search and filter controls for document discovery.
*/
import type { JSX } from 'react';
interface SearchFiltersBarProps {
searchText: string;
onSearchTextChange: (value: string) => void;
@@ -24,7 +26,7 @@ interface SearchFiltersBarProps {
}
/**
* Renders dense search, filter, and quick reset controls.
* Renders two-row document discovery controls with a dedicated search/action row.
*/
export default function SearchFiltersBar({
searchText,
@@ -49,59 +51,63 @@ export default function SearchFiltersBar({
}: SearchFiltersBarProps): JSX.Element {
return (
<div className="search-filters-bar">
<input
value={searchText}
onChange={(event) => onSearchTextChange(event.target.value)}
placeholder="Search across name, text, path, tags"
onKeyDown={(event) => {
if (event.key === 'Enter') {
event.preventDefault();
onSearchSubmit();
}
}}
/>
<select value={tagFilter} onChange={(event) => onTagFilterChange(event.target.value)}>
<option value="">All Tags</option>
{knownTags.map((tag) => (
<option key={tag} value={tag}>
{tag}
</option>
))}
</select>
<select value={typeFilter} onChange={(event) => onTypeFilterChange(event.target.value)}>
<option value="">All Types</option>
{knownTypes.map((typeValue) => (
<option key={typeValue} value={typeValue}>
{typeValue}
</option>
))}
</select>
<select value={pathFilter} onChange={(event) => onPathFilterChange(event.target.value)}>
<option value="">All Paths</option>
{knownPaths.map((path) => (
<option key={path} value={path}>
{path}
</option>
))}
</select>
<input
type="date"
value={processedFrom}
onChange={(event) => onProcessedFromChange(event.target.value)}
title="Processed from"
/>
<input
type="date"
value={processedTo}
onChange={(event) => onProcessedToChange(event.target.value)}
title="Processed to"
/>
<button type="button" onClick={onSearchSubmit} disabled={isLoading}>
Search
</button>
<button type="button" className="secondary-action" onClick={onReset} disabled={!hasActiveSearch || isLoading}>
Reset
</button>
<div className="search-filters-primary-row">
<input
value={searchText}
onChange={(event) => onSearchTextChange(event.target.value)}
placeholder="Search across name, text, path, tags"
onKeyDown={(event) => {
if (event.key === 'Enter') {
event.preventDefault();
onSearchSubmit();
}
}}
/>
<button type="button" onClick={onSearchSubmit} disabled={isLoading}>
Search
</button>
<button type="button" className="secondary-action" onClick={onReset} disabled={!hasActiveSearch || isLoading}>
Reset
</button>
</div>
<div className="search-filters-secondary-row">
<select value={tagFilter} onChange={(event) => onTagFilterChange(event.target.value)}>
<option value="">All Tags</option>
{knownTags.map((tag) => (
<option key={tag} value={tag}>
{tag}
</option>
))}
</select>
<select value={typeFilter} onChange={(event) => onTypeFilterChange(event.target.value)}>
<option value="">All Types</option>
{knownTypes.map((typeValue) => (
<option key={typeValue} value={typeValue}>
{typeValue}
</option>
))}
</select>
<select value={pathFilter} onChange={(event) => onPathFilterChange(event.target.value)}>
<option value="">All Paths</option>
{knownPaths.map((path) => (
<option key={path} value={path}>
{path}
</option>
))}
</select>
<input
type="date"
value={processedFrom}
onChange={(event) => onProcessedFromChange(event.target.value)}
title="Processed from"
/>
<input
type="date"
value={processedTo}
onChange={(event) => onProcessedToChange(event.target.value)}
title="Processed to"
/>
</div>
</div>
);
}

View File

@@ -2,6 +2,7 @@
* Dedicated settings screen for providers, task model bindings, and catalog controls.
*/
import { useCallback, useEffect, useMemo, useState } from 'react';
import type { JSX } from 'react';
import PathInput from './PathInput';
import TagInput from './TagInput';

View File

@@ -2,7 +2,7 @@
* Tag editor with suggestion dropdown and keyboard-friendly chip interactions.
*/
import { useMemo, useState } from 'react';
import type { KeyboardEvent } from 'react';
import type { JSX, KeyboardEvent } from 'react';
/**
* Defines properties for the reusable tag input component.

View File

@@ -2,7 +2,7 @@
* Upload surface that supports global drag-and-drop and file/folder picking.
*/
import { useEffect, useMemo, useRef, useState } from 'react';
import type { ChangeEvent } from 'react';
import type { JSX, ChangeEvent } from 'react';
/**
* Defines callback signature for queued file uploads.