Skip to main content
Back to ScopeForged

ScopeForged Documentation

Technical documentation, guides, and feature references for the ScopeForged client portal.

Files & Documents/Enhanced File Management

Enhanced File Management Guide

Last Updated: 2026-01-12 Status: Implemented Plan Reference: 030-enhanced-file-management.md, 057-enhanced-file-management-enhancement.md, 092-enhanced-file-management-improvement.md


Overview

Enhanced File Management extends the basic file sharing system with advanced features including virus scanning, file versioning, bulk operations, file categories, and improved search capabilities. These features provide enterprise-grade file management for the client portal.

Plan 057 Enhancements (2026-01-10):

  • Enhanced virus scanning UI with clear status indicators
  • Rich file preview system (8+ file types)
  • Batch upload with progress tracking
  • Advanced file search and filtering
  • Improved file versioning interface
  • Real-time scan status updates

Plan 092 Enhancements (2026-01-12):

  • Centralized configuration (config/file-management.php)
  • File tagging component with Alpine.js interactivity
  • FileBatchController for comprehensive batch operations
  • StorageAnalyticsService for storage insights
  • Batch routes for download, delete, move, tag, visibility, rescan

Table of Contents

  1. Accessing Features
  2. Features
  3. How to Use
  4. Virus Scanning
  5. File Versioning
  6. Batch Uploads
  7. File Preview
  8. Advanced Search
  9. Bulk Operations
  10. Technical Architecture
  11. Related Features

Accessing Features

Access PointLocationURLRole
Project FilesProject detail/admin/projects/{id} (files section)Admin
File DetailFile row/admin/files/{id}Admin
File VersionsFile detail modal/admin/files/{id}/versionsAdmin
Bulk ActionsFile listCheckbox selection on project pageAdmin

Note: Files are accessed within their project context. There is no standalone file browser - files are managed per-project.

Permissions

ActionAdminClient User
View file versions
Restore versions
Bulk operations
Categorize files
View scan status

Features

Virus Scanning

  • Automatic scan on upload
  • ClamAV integration
  • Quarantine infected files
  • Scan status indicators

File Versioning

  • Automatic version creation on re-upload
  • Version history with timestamps
  • Restore previous versions
  • Compare versions

Bulk Operations

  • Multi-select files
  • Bulk delete
  • Bulk move between projects
  • Bulk visibility change
  • Bulk download (ZIP)

File Categories

  • Predefined categories
  • Custom category creation
  • Category-based filtering
  • Color-coded labels
  • Search by filename
  • Filter by type, date, category
  • Full-text content search (PDF/documents)

File Preview

  • Image preview in modal
  • PDF preview
  • Video preview
  • Audio preview

Batch Uploads

Overview

The batch upload system provides a queue-based upload experience with progress tracking, concurrent uploads, and error handling.

Features

FeatureDescription
Drag & DropDrop multiple files onto the upload zone
Queue ManagementTrack all pending, uploading, and completed files
Concurrent UploadsUp to 3 simultaneous uploads
Progress TrackingReal-time progress bars per file
Retry FailedOne-click retry for failed uploads
Cancel UploadsCancel queued or in-progress uploads

Using Batch Upload

  1. Navigate to project files
  2. Drag files onto the drop zone (or click browse)
  3. Files appear in the upload queue with status
  4. Progress bars show upload completion
  5. Completed files show green checkmark
  6. Failed files show Retry button

Upload Queue States

StateIconDescription
QueuedWaiting to start
Uploading⬆️Currently uploading (shows progress)
CompletedSuccessfully uploaded
FailedUpload failed (can retry)

Configuration

// Maximum concurrent uploads
maxConcurrent: 3

// Maximum file size (100MB)
maxFileSize: 100 * 1024 * 1024

// Allowed file types
allowedTypes: ['image/*', 'application/pdf', 'video/*', ...]

File Preview

Supported File Types

The enhanced preview system supports 8+ file types with rich viewing capabilities:

TypeExtensionsPreview Features
Imagejpg, png, gif, webp, svgZoom, rotate, pan
PDFpdfEmbedded viewer
Videomp4, webm, movNative video player with controls
Audiomp3, wav, oggAudio player with waveform
Codephp, js, ts, py, css, html, jsonSyntax highlighting
Spreadsheetcsv, xlsx, xlsTable preview (first 100 rows)
Texttxt, md, logPlain text viewer
Documentdoc, docxDownload prompt (preview not available)

File Icons

Files display type-specific icons based on extension:

IconFile Types
document-textpdf, doc, docx
photojpg, png, gif, webp
filmmp4, webm, mov
musical-notemp3, wav, ogg
code-bracketphp, js, py, css, html
table-cellscsv, xlsx, xls
documenttxt, md, log

Preview Modal Features

  • Navigation: Previous/Next buttons for multiple files
  • Actions: Download, share, and close buttons
  • Keyboard: Escape to close, arrow keys to navigate
  • Responsive: Full-screen on mobile devices

Using File Preview

  1. Click on any file in the file list
  2. Preview modal opens with appropriate viewer
  3. Use controls based on file type:
    • Images: Zoom (+/-), rotate, fit to window
    • Videos: Play, pause, seek, volume, fullscreen
    • Audio: Play, pause, seek, volume
    • Code: Scroll with syntax highlighting
  4. Navigate between files with arrow buttons
  5. Click Download to save file
  6. Click X or press Escape to close

Search Capabilities

The FileSearchService provides comprehensive file filtering:

FilterOptionsDescription
Text SearchAny textSearch filename, description, tags
File Typeimages, documents, videos, audio, archives, codeFilter by category
Date Rangetoday, yesterday, this_week, this_month, etc.Filter by upload date
Size Rangesmall, medium, large, xlargeFilter by file size
Scan Statusclean, pending, infected, errorFilter by virus scan status
Visibilitypublic, privateFilter by client visibility
ProjectProject IDFilter by specific project
UploaderUser IDFilter by who uploaded
TagsTag namesFilter by assigned tags

Date Presets

PresetDescription
todayUploaded today
yesterdayUploaded yesterday
this_weekUploaded this week
last_weekUploaded last week
this_monthUploaded this month
last_monthUploaded last month
this_yearUploaded this year

Size Ranges

RangeSize
smallUnder 1 MB
medium1 MB - 10 MB
large10 MB - 100 MB
xlargeOver 100 MB
  1. Navigate to Admin → Files
  2. Use the search box for text search
  3. Click filter dropdowns to narrow results:
    • Type: Select file category
    • Date: Choose date preset or custom range
    • Size: Select size range
    • Status: Filter by scan status
  4. Active filters appear as removable chips
  5. Click Clear all to reset filters
  6. Results update in real-time

Search API Usage

use App\Services\Files\FileSearchService;

$service = app(FileSearchService::class);

$results = $service->search([
    'query' => 'invoice',
    'types' => 'documents',
    'date_preset' => 'this_month',
    'size_range' => 'small',
    'scan_status' => 'clean',
]);

// Get available filter options
$fileTypes = $service->getAvailableFileTypes();
$sizeRanges = $service->getAvailableSizeRanges();
$datePresets = $service->getAvailableDatePresets();

How to Use

Viewing File Versions

  1. Navigate to project files
  2. Click on a file row to open detail modal
  3. Click "Version History" tab
  4. View all previous versions with:
    • Version number
    • Upload date
    • Uploader name
    • File size

Restoring a Previous Version

  1. Open file version history
  2. Find desired version
  3. Click "Restore" button
  4. Confirm restoration
  5. Current file becomes new version
  6. Selected version becomes current

Uploading a New Version

  1. Navigate to project files
  2. Find existing file
  3. Click "Upload New Version"
  4. Select new file
  5. Previous file saved as version
  6. New file becomes current

Using Bulk Operations

  1. Navigate to file list
  2. Check boxes next to files
  3. Select action from toolbar:
    • Delete Selected: Remove all selected files
    • Change Visibility: Toggle client visibility
    • Move To: Move to different project
    • Download ZIP: Download all as archive
  4. Confirm action

Categorizing Files

  1. Navigate to project files
  2. Click file to open modal
  3. Click "Category" dropdown
  4. Select category:
    • Contracts
    • Deliverables
    • Reference
    • Drafts
    • Final
    • Custom...
  5. Category label appears on file

Searching Files

  1. Navigate to Admin → Files
  2. Use search box for filename
  3. Use filters sidebar:
    • File type (Images, Documents, etc.)
    • Date range
    • Category
    • Project
    • Uploader
  4. Results update dynamically

Virus Scanning

How It Works

  1. File uploaded to temporary storage
  2. ClamAV daemon scans file
  3. Clean files moved to permanent storage
  4. Infected files quarantined
  5. User notified of scan result

Scan Statuses

StatusIconDescription
PendingAwaiting scan
CleanNo threats found
InfectedThreat detected
Error⚠️Scan failed

Configuration

# .env
CLAMAV_ENABLED=true
CLAMAV_SOCKET=/var/run/clamav/clamd.ctl
QUARANTINE_PATH=storage/app/quarantine

Viewing Quarantined Files

  1. Navigate to Admin → Files → Quarantined
  2. View list of infected files
  3. Options:
    • Delete permanently
    • Whitelist (if false positive)
    • View scan details

File Versioning

Version Creation

Versions are created when:

  • Same filename uploaded to same project
  • "Upload New Version" used
  • File restored from version

Version Retention

SettingDefaultDescription
Max versions10Per file
Retention period90 daysBefore cleanup
Include in backupYesAll versions

Version Storage

// Version stored at
storage/app/project_files/versions/{file_id}/{version}.{ext}

Bulk Operations

Available Operations

OperationDescription
DeleteRemove selected files permanently
Make VisibleSet client visibility to true
Make HiddenSet client visibility to false
MoveMove to different project
DownloadPackage as ZIP and download
CategorizeApply category to all

Bulk Download

  1. Select files (max 100)
  2. Click "Download as ZIP"
  3. ZIP generated in background
  4. Download link provided
  5. ZIP available for 1 hour

Technical Architecture

Models

FileVersion Model: app/Models/FileVersion.php

class FileVersion extends Model
{
    protected $fillable = [
        'project_file_id',
        'version_number',
        'filename',
        'path',
        'size',
        'uploaded_by',
    ];
}

FileCategory Model: app/Models/FileCategory.php

class FileCategory extends Model
{
    protected $fillable = [
        'name',
        'color',
        'icon',
        'is_system',
    ];
}

Updated ProjectFile Model

// Additional fields
protected $fillable = [
    // ... existing fields
    'category_id',
    'scan_status',
    'scanned_at',
    'threat_name',
    'content_hash',
];

protected $casts = [
    // ... existing casts
    'scanned_at' => 'datetime',
];

// Relationships
public function versions(): HasMany
{
    return $this->hasMany(FileVersion::class)->orderByDesc('version_number');
}

public function category(): BelongsTo
{
    return $this->belongsTo(FileCategory::class);
}

Services

FileVersionService: app/Services/FileVersionService.php

  • Creates new versions
  • Restores versions
  • Cleans old versions

VirusScanService: app/Services/VirusScanService.php

  • Scans uploaded files
  • Quarantines threats
  • Reports results

BulkFileService: app/Services/BulkFileService.php

  • Processes bulk operations
  • Generates ZIP archives

Routes

// Version routes
Route::get('files/{file}/versions', [FileVersionController::class, 'index']);
Route::post('files/{file}/versions', [FileVersionController::class, 'store']);
Route::post('files/{file}/versions/{version}/restore', [FileVersionController::class, 'restore']);
Route::delete('files/{file}/versions/{version}', [FileVersionController::class, 'destroy']);

// Bulk routes (legacy)
Route::post('files/bulk/delete', [BulkFileController::class, 'delete']);
Route::post('files/bulk/visibility', [BulkFileController::class, 'visibility']);
Route::post('files/bulk/move', [BulkFileController::class, 'move']);
Route::post('files/bulk/download', [BulkFileController::class, 'download']);
Route::post('files/bulk/categorize', [BulkFileController::class, 'categorize']);

// Batch routes (new - Plan 092)
Route::prefix('files/batch')->name('files.batch.')->group(function () {
    Route::post('download', [FileBatchController::class, 'download'])->name('download');
    Route::post('delete', [FileBatchController::class, 'delete'])->name('delete');
    Route::post('move', [FileBatchController::class, 'move'])->name('move');
    Route::post('tag', [FileBatchController::class, 'tag'])->name('tag');
    Route::post('untag', [FileBatchController::class, 'untag'])->name('untag');
    Route::post('visibility', [FileBatchController::class, 'visibility'])->name('visibility');
    Route::post('rescan', [FileBatchController::class, 'rescan'])->name('rescan');
});

// Scan routes
Route::get('files/{file}/scan-status', [FileScanController::class, 'status']);
Route::post('files/{file}/rescan', [FileScanController::class, 'rescan']);

Storage Analytics

The StorageAnalyticsService provides comprehensive storage insights:

use App\Services\StorageAnalyticsService;

$analytics = app(StorageAnalyticsService::class);

// Get overall storage overview
$overview = $analytics->getOverview();
// Returns: total_size, total_files, average_file_size, total_versions

// Get storage by client
$byClient = $analytics->getByClient(10); // Top 10 clients
// Returns: name, size, files, projects for each client

// Get storage by file type
$byType = $analytics->getByType();
// Returns: type, mime_category, size, count, icon

// Get storage growth trend
$trend = $analytics->getGrowthTrend(6); // Last 6 months
// Returns: month, size, count, cumulative_size

// Get storage by project
$byProject = $analytics->getByProject(10);

// Get scan statistics
$scanStats = $analytics->getScanStats();
// Returns: total_scanned, clean, infected, pending, clean_percentage

// Clear analytics cache
$analytics->clearCache();

Database Tables

Table: file_versions

ColumnTypeDescription
idbigintPrimary key
project_file_idbigintParent file
version_numberintegerVersion (1, 2, 3...)
filenamestringVersion filename
pathstringStorage path
sizebigintFile size
uploaded_bybigintUser who uploaded
created_attimestampVersion date

Table: file_categories

ColumnTypeDescription
idbigintPrimary key
namestringCategory name
colorstringHex color code
iconstringIcon name
is_systembooleanSystem category

Jobs

ScanFileJob: Queued virus scan

ScanFileJob::dispatch($file);

GenerateZipJob: Queued ZIP creation

GenerateZipJob::dispatch($files, $user);

Configuration

Central Configuration File

All file management settings are centralized in config/file-management.php:

// config/file-management.php
return [
    'tagging' => [
        'enabled' => env('FILE_TAGGING_ENABLED', true),
        'max_tags_per_file' => env('FILE_MAX_TAGS', 10),
        'default_colors' => ['#3B82F6', '#10B981', '#F59E0B', ...],
    ],

    'batch' => [
        'enabled' => env('FILE_BATCH_ENABLED', true),
        'max_files' => env('FILE_BATCH_MAX_FILES', 100),
        'max_download_size' => env('FILE_BATCH_MAX_DOWNLOAD_SIZE', 524288000), // 500MB
        'operations' => [
            'download' => true,
            'delete' => true,
            'move' => true,
            'tag' => true,
            'visibility' => true,
            'rescan' => true,
        ],
    ],

    'analytics' => [
        'enabled' => env('STORAGE_ANALYTICS_ENABLED', true),
        'cache_ttl' => env('STORAGE_ANALYTICS_CACHE_TTL', 900), // 15 minutes
    ],

    'quotas' => [
        'enabled' => env('STORAGE_QUOTAS_ENABLED', false),
        'default_client_quota' => env('STORAGE_DEFAULT_CLIENT_QUOTA', 5368709120), // 5GB
    ],

    'scanning' => [
        'show_status_badge' => env('FILE_SHOW_SCAN_STATUS', true),
        'block_infected_downloads' => env('FILE_BLOCK_INFECTED', true),
    ],

    'preview' => [
        'enabled' => env('FILE_PREVIEW_ENABLED', true),
        'max_size' => env('FILE_PREVIEW_MAX_SIZE', 52428800), // 50MB
    ],
];

File Categories

Default categories are seeded:

// database/seeders/FileCategorySeeder.php
$categories = [
    ['name' => 'Contracts', 'color' => '#3B82F6', 'icon' => 'document-text'],
    ['name' => 'Deliverables', 'color' => '#10B981', 'icon' => 'check-circle'],
    ['name' => 'Reference', 'color' => '#6366F1', 'icon' => 'book-open'],
    ['name' => 'Drafts', 'color' => '#F59E0B', 'icon' => 'pencil'],
    ['name' => 'Final', 'color' => '#059669', 'icon' => 'badge-check'],
];

Dependencies

FeatureRelationship
File SharingBase file system
Background JobsAsync scanning and ZIP

Complementary Features

FeatureDescription
Activity LoggingLogs all file operations
NotificationsScan result notifications
Admin ToolsFile management utilities

Best Practices

For Administrators

  1. Enable virus scanning in production
  2. Review quarantined files regularly
  3. Set version limits to manage storage
  4. Use categories for organization
  5. Run bulk cleanup periodically

For Developers

  1. Queue virus scans for performance
  2. Use transactions for bulk operations
  3. Clean up versions with scheduled job
  4. Index file content for search

Troubleshooting

IssueSolution
Scan stuck on pendingCheck ClamAV daemon running
Version not creatingCheck max version limit
Bulk download failsCheck file count limit (100)
Category not savingVerify category exists

ClamAV Issues

# Check ClamAV status
sudo systemctl status clamav-daemon

# Test scan manually
clamscan /path/to/file

# Update virus definitions
sudo freshclam

See Also