Phase: 1 - MVP Priority: High Status: Complete Edition: Community Edition (Read-Only)
A functional web interface for viewing Laserfiche table data. Built with React and Material-UI, provides intuitive browsing, search, and export capabilities.
Note: The Community Edition is read-only. For write operations (Create, Edit, Delete, CSV Import), see LFDataView Managed.
- User logs in (Feature 01)
- Lands on table list page
- Sees all accessible tables
- Clicks on a table to view data
- User clicks on a table
- Table detail page loads
- Sees rows in table/grid format
- Can paginate through data
- Sees total row count
- Sees loading indicator while fetching
- Server-side search: Use search bar for exact match queries
- Client-side filters: Use column filters for partial matching on displayed rows
- Both are case-insensitive
- User clicks "Download CSV"
- Currently filtered/displayed rows are exported
- CSV file downloads with table name and date
src/
├── pages/
│ ├── TablesPage.tsx # List of tables
│ ├── TableDetailPage.tsx # Table rows + search/filter/export
│ ├── LoginPage.tsx # (Feature 01)
│ └── CallbackPage.tsx # (Feature 01)
│
├── components/
│ ├── Layout.tsx # App shell (header, nav, footer)
│ └── ... # Shared components
│
├── hooks/
│ └── useAuth.ts # (Feature 01)
│
└── services/
└── api.ts # API client
- Header: "LFDataView"
- Table grid showing:
- Table name
- Display name (if available)
- Click to view data
- Loading spinner while fetching
- Error message if fetch fails
- Header: Table name with total row count
- Action buttons:
- "Refresh" (reload data)
- "Download CSV" (exports filtered data)
- Help button (usage instructions)
- Search bar:
- Column selector dropdown
- Search input field
- Search and Clear buttons
- Data grid:
- Columns: Dynamic based on table schema
_keycolumn is hidden (internal system field)- Column filters below each header for partial matching
- Rows: Table data
- Pagination controls
- Loading indicator
- Error message display
The search bar queries Laserfiche directly:
- Exact match: Searches for exact values (case-insensitive)
- Column selector: Search a specific column or all columns
- OR mode: When searching all columns, any match counts
Filter fields below each column header:
- Partial matching: Typing "smith" matches "Smith", "Smithson", "Blacksmith"
- Case-insensitive: Matches regardless of case
- AND logic: All filters must match
- Only affects displayed rows: Works on current page data
The "Download CSV" button exports the currently displayed data:
- Exports filtered data: Only rows matching the current filters
- Excludes
_key: Internal system field is not exported - Proper CSV formatting: Values are properly escaped
- Filename format:
{tableName}_{date}.csv - Disabled when empty: Button disabled when no rows to export
Explains search and filter usage with a note about Community Edition being read-only.
| Route | Component | Description |
|---|---|---|
/ |
TablesPage | List of tables (default after login) |
/login |
LoginPage | Login page (Feature 01) |
/auth/callback |
CallbackPage | OAuth callback (Feature 01) |
/tables/:tableName |
TableDetailPage | Table data viewing |
Uses React Query (@tanstack/react-query) for server state:
// Fetch tables
const { data: tables, isLoading, error } = useQuery({
queryKey: ['tables'],
queryFn: fetchTables
});
// Fetch table rows with filters
const { data: rows } = useQuery({
queryKey: ['tableRows', tableName, page, filters],
queryFn: () => fetchTableRows(tableName, limit, offset, filters)
});
// Fetch row count
const { data: count } = useQuery({
queryKey: ['tableRowCount', tableName],
queryFn: () => fetchTableRowCount(tableName)
});- Network errors: "Failed to connect. Please check your internet connection."
- 401 Unauthorized: Redirect to login
- 403 Forbidden: "You don't have permission to access this resource."
- 404 Not Found: "Table not found."
- 500 Server Error: "Something went wrong. Please try again later."
Built with Material-UI (MUI) for:
- Consistent design system
- Pre-built accessible components
- Responsive layout
- Dark mode support (future)