1. Overview

The File Repository Module is a comprehensive file management system within the Nimbly audit administration platform. This module provides centralized storage, organization, and [access control](../Settings/Access control/AccessControlOverview.md) for various types of files used across the audit workflow.

1.1 Purpose

  • Centralized file storage and management
  • Version control for audit documents
  • [Access control](../Settings/Access control/AccessControlOverview.md) and [permissions](../Settings/Access control/AccessControlOverview.md) management
  • File categorization and tagging
  • Search and retrieval capabilities

1.2 Key Features

  • File upload and download
  • Folder structure organization
  • File metadata management
  • Search functionality
  • [Access control](../Settings/Access control/AccessControlOverview.md)
  • File preview capabilities
  • Integration with other modules

2. Architecture

The Repository module follows a component-based architecture pattern integrated within the React-Redux ecosystem of the audit-admin application.

graph TD
    A[User] --> B[React Routes]
    B --> C[Repository Page]
    C --> D[Repository Container]
    D --> E[Redux Store]
    E --> F[Redux Saga]
    F --> G[API Services]
    G --> H[Backend API]

    D --> I[Layout Components]
    D --> J[Feature Components]
    D --> K[Modal Components]

    I --> L[Header]
    I --> M[SubHeader]
    I --> N[View Components]

    J --> O[Upload]
    J --> P[Share]
    J --> Q[Search]

    K --> R[File Operations]
    K --> S[Confirmations]

2.1 Module Structure

src/
├── pages/repository/
│   └── RepositoryPage.tsx           # Main page wrapper
├── components/repository/
│   ├── Repository.tsx               # Primary container
│   ├── RepositoryDashboard.tsx      # Storage dashboard
│   ├── layout/                      # Layout components
│   │   ├── RepositoryHeader.tsx     # Top navigation bar
│   │   ├── RepositorySubHeader.tsx  # Search and filters
│   │   ├── RepositoryTitle.tsx      # Breadcrumb navigation
│   │   ├── RepositoryFloatingMenu.tsx # Bulk action menu
│   │   ├── RepositoryTableView.tsx  # List view
│   │   └── RepositoryTileView.tsx   # Grid view
│   ├── component/                   # Feature components
│   │   ├── modal/                   # Modal dialogs
│   │   │   ├── RepositoryModal.tsx  # Modal orchestrator
│   │   │   ├── NewFolderModal.tsx   # Create folder
│   │   │   ├── ShareModal.tsx       # Share files
│   │   │   └── ... (other modals)
│   │   ├── RepositoryFileList.tsx   # File listing
│   │   ├── RepositoryFolderList.tsx # Folder listing
│   │   └── FileThumbnail.tsx        # File preview
│   └── utils/                       # Utility functions
│       ├── useRepository.ts         # CRUD operations
│       ├── useRepositoryUpload.ts   # Upload management
│       ├── useRepositoryDownload.ts # Download handling
│       └── repositoryUtils.ts       # Helper functions
├── reducers/repository/             # Redux state management
│   ├── repository.reducer.ts        # Main reducer
│   ├── repository.action.ts         # Action creators
│   ├── repository.actionTypes.ts    # Action constants
│   └── type.d.ts                    # TypeScript types
├── services/repository/             # API services
│   └── repository.service.ts        # API interactions
└── routes/                          # Route definitions
    └── admin-routes.js              # Admin route config

2.2 Component Architecture Details

2.2.1 Layout Components

The layout components form the structural foundation of the repository interface:

RepositoryHeader

  • Displays current storage usage with visual indicator
  • Provides “Add New” dropdown for file/folder uploads
  • Navigates to storage dashboard on click
  • Integrates with upload hooks for file selection
  • Responsive design for mobile/desktop views

RepositorySubHeader

  • Search input with real-time suggestions
  • View toggle between grid and list layouts
  • Filter button opening filter sidebar
  • Sort dropdown with multiple options
  • Bulk selection controls when in select mode

RepositoryTitle

  • Dynamic breadcrumb navigation
  • Displays current folder hierarchy
  • Click handlers for folder navigation
  • Truncates long paths with ellipsis
  • Shows folder count and size info

2.2.2 Modal System Architecture

The modal system uses a centralized pattern for consistency:

// Modal orchestrator pattern
const RepositoryModal = ({ uploadStates, handleRetry, handleCancel }) => {
	const modals = useSelector(selectModalStates);
 
	return (
		<>
			{modals.isNewFolderModalVisible && <NewFolderModal />}
			{modals.isShareModalVisible && <ShareModal />}
			{modals.isFilePreviewModalVisible && <FilePreviewModal />}
			{/* ... other modals */}
		</>
	);
};

Each modal follows consistent patterns:

  • Redux state for visibility control
  • Props for data passing
  • Callback handlers for actions
  • Loading states during operations
  • Error handling with user feedback

2.2.3 Custom Hooks Deep Dive

useRepository Hook

The core hook managing CRUD operations:

export const useRepository = () => {
	const dispatch = useDispatch();
	const { files, folders, selectedFile } = useSelector(selectRepository);
 
	const createNewFolder = async (name: string) => {
		// Validation
		// API call
		// Optimistic update
		// Error handling
	};
 
	const renameItem = async (id: string, newName: string) => {
		// Similar pattern
	};
 
	const deleteItem = async (id: string) => {
		// Soft delete to trash
	};
 
	const restoreItem = async (id: string) => {
		// Restore from trash
	};
 
	const shareItem = async (id: string, users: string[]) => {
		// Update permissions
	};
 
	return {
		createNewFolder,
		renameItem,
		deleteItem,
		restoreItem,
		shareItem,
		// ... other methods
	};
};

useRepositoryUpload Hook

Manages complex upload workflows:

export const useRepositoryUpload = () => {
	const [uploadQueue, setUploadQueue] = useState<UploadItem[]>([]);
	const [progress, setProgress] = useState<Record<string, number>>({});
 
	const initFileUpload = async (files: FileList) => {
		// Validate files
		// Create upload items
		// Get signed URLs
		// Start uploads
		// Track progress
		// Handle completion
	};
 
	const initFolderUpload = async (folder: any) => {
		// Similar but for folders
		// Recursive file handling
	};
 
	const handleRetry = (itemId: string) => {
		// Retry failed upload
	};
 
	const handleCancel = (itemId: string) => {
		// Cancel ongoing upload
	};
 
	return {
		uploadQueue,
		progress,
		initFileUpload,
		initFolderUpload,
		handleRetry,
		handleCancel,
	};
};

3. Routes and Navigation

3.1 Route Configuration

The Repository module is accessible through the following routes defined in admin-routes.js:

Route PathComponentDescription
/repositoryRepositoryPageMain repository view with default tab
/repository/:tabRepositoryPageRepository with specific tab selected
/repository/folder/:idRepositoryPageView specific folder contents

3.2 Access Control

The repository routes are protected by:

  • Authentication: User must be logged in
  • Feature Flag: Features.FILE_REPOSITORY must be enabled
  • Role: Admin access required

3.3 Navigation Tabs

The repository module supports multiple navigation tabs:

TabEnum ValueDescription
My FilesMY_FILESUser’s personal files and folders
Shared with MeSHARED_WITH_MEFiles shared by other users
RecentRECENTRecently accessed files
StarredSTARREDFiles marked as favorite
TrashTRASHDeleted files (soft delete)
SearchSEARCHSearch results view
Dashboard[DASHBOARD](../Dashboard/DashboardOverview.md)Storage usage dashboard
FolderFOLDERFolder contents view

4. Components

The Repository module consists of various specialized components organized into logical groups:

4.1 Core Components

4.1.1 Repository.tsx

src/components/repository/Repository.tsx

  • Root container component that orchestrates the entire repository module
  • Manages upload states and modal visibility
  • Implements tab-based navigation between different views
  • Integrates with Redux store for state management

4.1.2 RepositoryDashboard.tsx

src/components/repository/RepositoryDashboard.tsx

  • Storage usage dashboard component
  • Displays organization-wide storage consumption
  • Shows breakdown between Repository and LMS storage
  • Implements pagination for user storage list

4.2 Layout Components

ComponentPurpose
RepositoryHeaderMain header with storage indicator and upload actions
RepositorySubHeaderSearch bar, view toggle, filters, and sorting controls
RepositoryTitleDynamic breadcrumb navigation display
RepositoryFloatingMenuContextual actions for selected items
RepositoryTableViewList view layout for files and folders
RepositoryTileViewGrid view layout with thumbnails

4.3 Modal Components

The module uses a centralized modal system managed by RepositoryModal.tsx:

ModalFunctionality
NewFolderModalCreate new folder with name validation
RenameItemModalRename files or folders
ShareModalShare items with other users
FilePreviewModalPreview images and documents
UploadModalFile upload with progress tracking
MoveToTrashModalSoft delete confirmation
DeleteForeverModalPermanent deletion confirmation
RestoreModalRestore items from trash
EmptyTrashModalClear all trash items
StarredModalMark items as favorite

4.4 Feature Components

4.4.1 File Management

  • RepositoryFileList: Displays files grouped by sections with bulk selection
  • FileThumbnail: Individual file representation with icon/preview
  • FileUploadProgress: Real-time upload progress indicator

4.4.2 Folder Management

  • RepositoryFolderList: Folder navigation with hierarchy support
  • FolderThumbnail: Folder representation with nested item count

4.4.3 View Components

  • RepositoryViewContainer: Switches between table and tile views
  • RepositoryViewByDays: Groups items by date (Today, Yesterday, etc.)
  • RepositorySearchSection: Displays search results with highlighting

5. API Endpoints

The Repository module interacts with the backend through a RESTful API. All endpoints are prefixed with the base URL configured in baseURL.ts.

5.1 Base Configuration

FILE_REPO_API_URL = apiURLAlt + '/file-repo';

5.2 Repository Service APIs

MethodEndpointFunctionDescription
GET/file-repofetchRepository()Fetch paginated repository items with filters
GET/file-repo/foldersfetchRepositoryFolderList()Get all folders for navigation
GET/file-repo/searchsearchRepository()Search files and folders
POST/file-repocreateRepositoryItem()Create new file or folder
PUT/file-repoupdateRepositoryItem()Update item properties (rename, star, etc.)
GET/file-repo/signedUploadURLgetRepositorySignedUrl()Get signed URL for file upload
POST/file-repo/downloaddownloadRepositoryItem()Download single or multiple items
GET/file-repo/user/allfetchRepositoryStorageDetails()Get user storage usage details
POST/file-repo/usercreateRepositoryUser()Initialize user repository

5.3 Organization Usage APIs

MethodEndpointFunctionDescription
GET/file-repo/tracker/:organizationIDfetchRepositoryOrganizationUsageRequest()Get organization storage usage

5.4 Query Parameters

5.4.1 Fetch Repository Items

  • list: Type of items to fetch (myFiles, sharedWithMe, recent, starred, trash)
  • parentID: Folder ID for nested navigation
  • page: Page number for pagination
  • limit: Items per page
  • sortBy: Sort field (name, lastModifiedDate, size)
  • sortType: Sort direction (asc, desc)
  • qFileType: Filter by file types
  • qUser: Filter by shared users
  • qStartDate: Filter by date range start
  • qEndDate: Filter by date range end

5.4.2 Search Parameters

  • search: Search query string
  • Additional filter parameters as above

5.5 Request/Response Types

The API uses TypeScript interfaces from @nimbly-technologies/nimbly-common:

interface CreateRepositoryItemRequest {
	name: string;
	type: 'file' | 'folder';
	parentID?: string;
	entityInfo: Record<string, any>;
	metadata?: {
		size?: number;
		mimeType?: string;
		lastModified?: Date;
	};
}
 
interface GetRepositoryItemsResponse {
	id: string;
	name: string;
	type: string;
	kind: Kind; // FILE or FOLDER
	size: number;
	lastModifiedDate: Date;
	createdDate: Date;
	owner: {
		id: string;
		name: string;
		email: string;
	};
	sharedWith: string[];
	starred: boolean;
	parentID: string | null;
	path: string;
	downloadURL?: string;
	thumbnailURL?: string;
	metadata: Record<string, any>;
}
 
interface PaginatedRepositoryItems {
	docs: GetRepositoryItemsResponse[];
	totalDocs: number;
	page: number;
	limit: number;
	totalPages: number;
	hasNextPage: boolean;
	hasPrevPage: boolean;
}
 
interface UpdateRepositoryItemRequest {
	operation: RepositoryItemOperations;
	entityIDs: string[];
	data?: {
		name?: string;
		starred?: boolean;
		sharedWith?: string[];
		parentID?: string;
	};
}

5.6 API Error Handling

The API implements comprehensive error handling:

interface APIError {
	status: number;
	message: string;
	code: string;
	details?: any;
}
 
// Common error codes
enum RepositoryErrorCodes {
	STORAGE_LIMIT_EXCEEDED = 'STORAGE_LIMIT_EXCEEDED',
	FILE_TOO_LARGE = 'FILE_TOO_LARGE',
	INVALID_FILE_TYPE = 'INVALID_FILE_TYPE',
	PERMISSION_DENIED = 'PERMISSION_DENIED',
	ITEM_NOT_FOUND = 'ITEM_NOT_FOUND',
	DUPLICATE_NAME = 'DUPLICATE_NAME',
}

5.7 API Rate Limiting

The repository API implements rate limiting:

  • Upload endpoints: 100 requests per minute
  • Read endpoints: 1000 requests per minute
  • Search endpoints: 200 requests per minute
  • Batch operations: 50 requests per minute

Headers returned:

  • X-RateLimit-Limit: Maximum requests allowed
  • X-RateLimit-Remaining: Requests remaining
  • X-RateLimit-Reset: Reset timestamp

6. Data Flow

The Repository module follows a unidirectional data flow pattern using Redux for state management:

sequenceDiagram
    participant User
    participant Component
    participant Hook
    participant Redux
    participant API
    participant Backend

    User->>Component: Interaction (click, type)
    Component->>Hook: Call custom hook
    Hook->>Redux: Dispatch action
    Redux->>Redux: Update state
    Hook->>API: API call (if async)
    API->>Backend: HTTP request
    Backend-->>API: Response
    API-->>Hook: Process data
    Hook->>Redux: Dispatch success/error
    Redux-->>Component: State update
    Component-->>User: UI update

6.1 State Management Architecture

The Repository module implements a sophisticated state management system using Redux:

6.1.1 Redux Architecture

graph TB
    A[Components] --> B[Actions]
    B --> C[Reducers]
    C --> D[Store]
    D --> E[Selectors]
    E --> A

    B --> F[Middleware]
    F --> G[API Calls]
    G --> H[Backend]
    H --> I[Response]
    I --> B

6.2 State Slices

6.2.1 Main Repository State

Managed by repository.reducer.ts:

const initialState: RepositoryState = {
	// UI State
	isLoading: false,
	isLoadingNextPage: false,
	isLoadingSearch: false,
	error: '',
 
	// View Settings
	activeTab: RepositoryTabEnum.MY_FILES,
	viewType: LmsViewType.TILE,
	gridSize: 6,
 
	// Data
	files: [],
	folders: [],
	fileSections: {}, // Files grouped by date
 
	// Selection
	selectedFile: null,
	selectedFileIds: new Set(),
	selectedFolderIds: new Set(),
	totalSelectedItems: 0,
	totalSelectedFilesSize: 0,
 
	// Navigation
	folderHierarchy: [],
 
	// Search & Filters
	searchQuery: '',
	filters: {
		qFileType: [],
		qUser: [],
		qLocation: '',
		qStartDate: null,
		qEndDate: null,
	},
 
	// Pagination
	page: 1,
	limit: 24,
	totalPages: 0,
	totalDocs: 0,
 
	// Modal States
	isFilePreviewModalVisible: false,
	isNewFolderModalVisible: false,
	// ... other modals
};

6.2.2 Repository Folder List State

Manages available folders for navigation:

interface RepositoryFolderListState {
	isLoading: boolean;
	error: string;
	folders: RepositoryFolderList[];
}

6.2.3 User Storage Usage State

Tracks per-user storage consumption:

interface RepositoryUserUsageState {
	isLoading: boolean;
	docs: UserStorageDoc[];
	page: number;
	limit: number;
	totalDocs: number;
	sortBy: RepositoryUserUsageSortBy;
	sortType: 'asc' | 'desc';
}

6.2.4 Organization Usage State

Monitors organization-wide storage:

interface RepositoryOrganizationUsageState {
	isLoading: boolean;
	totalUsedStorageGB: number;
	totalOrganizationUsedStorageGB: number;
	allocationPerEntity: {
		REPOSITORY: number;
		LMS: number;
	};
}

6.3 Action Patterns

Actions follow a consistent naming convention:

// Synchronous actions
export const setActiveRepositoryTab = createAction('repository/SET_ACTIVE_TAB')<RepositoryTabEnum>();
export const setRepositoryFiles = createAction('repository/SET_FILES')<GetRepositoryItemsResponse[]>();
 
// Async actions (with request/success/failure)
export const fetchRepositoryRequest = createAction('repository/FETCH_REQUEST')();
export const fetchRepositorySuccess = createAction('repository/FETCH_SUCCESS')<PaginatedRepositoryItems>();
export const fetchRepositoryFailure = createAction('repository/FETCH_FAILURE')<string>();

6.4 Selector Patterns

Selectors provide derived state and memoization:

// Basic selectors
const selectRepository = (state: RootState) => state.repository;
const selectActiveTab = (state: RootState) => state.repository.activeTab;
 
// Computed selectors
const selectVisibleItems = createSelector([selectFiles, selectFolders, selectActiveTab], (files, folders, tab) => {
	// Logic to compute visible items based on tab
});
 
// Parameterized selectors
const selectFileById = (fileId: string) => createSelector([selectFiles], (files) => files.find((f) => f.id === fileId));

6.5 Middleware Integration

The module uses custom middleware for:

  1. API Call Management
  • Automatic token attachment
  • Error handling
  • Loading state management
  1. State Persistence
  • Selected view preferences
  • Filter settings
  • Sort preferences
  1. Analytics Tracking
  • File operations
  • Usage patterns
  • Error events

10.9 Performance Optimizations

  1. Normalized State
  • Files stored flat, not nested
  • Relationships via IDs
  • Efficient updates
  1. Memoized Selectors
  • Reselect library usage
  • Computed values cached
  • Re-render optimization
  1. Lazy Loading
  • Pagination for large datasets
  • Virtual scrolling for lists
  • On-demand data fetching
  1. Optimistic Updates
  • Immediate UI feedback
  • Background synchronization
  • Rollback on failure

7. State Management

The Repository module utilizes Redux for centralized state management with clear separation of concerns:

7.1 Action Types Organization

Actions are organized into logical groups:

// UI Actions
'repository/SET_LOADING';
'repository/SET_ERROR';
'repository/TOGGLE_MODAL';
'repository/SET_VIEW_TYPE';
 
// Data Actions
'repository/SET_FILES';
'repository/SET_FOLDERS';
'repository/SET_FILE_SECTIONS';
'repository/UPDATE_ITEM';
 
// Navigation Actions
'repository/SET_ACTIVE_TAB';
'repository/SET_FOLDER_HIERARCHY';
'repository/SET_PAGE';
 
// Selection Actions
'repository/SELECT_FILE';
'repository/SELECT_MULTIPLE';
'repository/CLEAR_SELECTION';

7.2 State Update Patterns

7.2.1 Direct State Updates

Used for synchronous operations like UI state changes:

case 'repository/SET_ACTIVE_TAB':
  return {
    ...state,
    activeTab: action.payload,
    page: 1, // Reset pagination
    selectedFileIds: new Set(), // Clear selection
  };

7.2.2 Immutable Updates

For complex data structures:

case 'repository/UPDATE_FILE_SECTION':
  return {
    ...state,
    fileSections: {
      ...state.fileSections,
      [action.payload.date]: action.payload.files
    }
  };

7.3 Side Effects Management

The module handles side effects through custom hooks that abstract async operations:

  1. Data Fetching
  • Managed by useRepositoryData hook
  • Handles loading states automatically
  • Implements caching and invalidation
  1. File Operations
  • useRepository hook for CRUD operations
  • Optimistic updates for better UX
  • Error handling with rollback
  1. Upload Management
  • useRepositoryUpload for file uploads
  • Progress tracking
  • Batch upload support

7.4 State Persistence

Certain state properties are persisted across sessions:

const persistedState = {
	viewType: LmsViewType.TILE,
	sortBy: RepositorySortByOptionsEnum.LAST_MODIFIED,
	sortType: 'desc',
	gridSize: 6,
};

7.5 Performance Considerations

  1. Normalized Data Structure
  • Files and folders stored separately
  • References by ID for relationships
  • Efficient lookups and updates
  • Index-based access patterns
  1. Selective Re-renders
  • Component connections minimized
  • Use of React.memo for expensive components
  • Granular subscriptions to state slices
  • Memoized selectors with reselect
  1. Batch Updates
  • Multiple state changes batched
  • Reduces re-render cycles
  • Improves performance for bulk operations
  • Debounced API calls

7.6 Redux Middleware Configuration

The repository module uses custom middleware:

// API Middleware
const apiMiddleware = (store) => (next) => (action) => {
	if (action.meta?.api) {
		// Attach auth token
		// Handle loading states
		// Process errors
		// Log analytics
	}
	return next(action);
};
 
// Analytics Middleware
const analyticsMiddleware = (store) => (next) => (action) => {
	if (action.meta?.track) {
		analytics.track(action.type, {
			...action.payload,
			timestamp: Date.now(),
		});
	}
	return next(action);
};
 
// Persistence Middleware
const persistenceMiddleware = (store) => (next) => (action) => {
	const result = next(action);
	if (PERSISTED_ACTIONS.includes(action.type)) {
		localStorage.setItem(
			'repository_prefs',
			JSON.stringify({
				viewType: store.getState().repository.viewType,
				sortBy: store.getState().repository.sortBy,
				sortType: store.getState().repository.sortType,
			}),
		);
	}
	return result;
};

7.7 State Synchronization

The module implements state synchronization across tabs:

// Broadcast channel for cross-tab communication
const channel = new BroadcastChannel('repository_sync');
 
// Listen for changes
channel.addEventListener('message', (event) => {
	if (event.data.type === 'STATE_UPDATE') {
		store.dispatch(syncState(event.data.payload));
	}
});
 
// Broadcast changes
const broadcastMiddleware = (store) => (next) => (action) => {
	const result = next(action);
	if (BROADCAST_ACTIONS.includes(action.type)) {
		channel.postMessage({
			type: 'STATE_UPDATE',
			payload: store.getState().repository,
		});
	}
	return result;
};

8. Dependencies

The Repository module leverages various external libraries and internal packages to provide its functionality:

8.1 Core Dependencies

PackageVersionPurpose
react16.13.1Core React library
react-redux7.2.0Redux React bindings
redux4.0.5State management
typesafe-actions5.1.0Type-safe Redux actions
@loadable/component5.14.1Lazy loading for route splitting

8.2 UI & Styling

PackagePurpose
styled-componentsCSS-in-JS styling solution
react-iconsIcon library (MdOutlineCloud, FiHardDrive)
@radix-ui/**UI primitive components
react-toastifyToast notifications

8.3 Utility Libraries

PackagePurpose
lodashUtility functions (cloneDeep, debounce)
dayjsDate manipulation and formatting
uuidUnique ID generation for uploads
query-stringURL query parameter handling
copy-to-clipboardClipboard operations

8.4 Internal Packages

8.4.1 @nimbly-technologies/nimbly-common (v1.95.3)

Provides shared types and utilities:

Types & Interfaces:

  • GetRepositoryItemsResponse
  • PaginatedRepositoryItems
  • CreateRepositoryItemRequest
  • UpdateRepositoryItemRequest
  • AttachmentGalleryResponse
  • FilterAttachmentsResult

Enumerators:

  • RepositoryListEnum - Tab navigation types
  • RepositorySortByOptionsEnum - Sorting options
  • RepositoryItemOperations - CRUD operations
  • Kind - File/Folder types

Utilities:

  • MIME type mappings
  • File type detection
  • Common validation functions

8.5 Integration Points

The module integrates with:

  • Firebase Auth - Token-based API authentication
  • Cloud Storage - File upload/download via signed URLs
  • Redux DevTools - Development debugging
  • React Router - Navigation and routing
  • i18next - Internationalization support

9. User Flows

The Repository module supports various user workflows for file management:

9.1 File Upload Flow

graph LR
    A[User clicks Upload] --> B{Select Type}
    B -->|Files| C[File Picker]
    B -->|Folder| D[Folder Picker]
    C --> E[Validate Files]
    D --> F[Validate Folder]
    E --> G[Get Signed URLs]
    F --> G
    G --> H[Upload to Cloud]
    H --> I[Create DB Entry]
    I --> J[Update UI]
    J --> K[Show Success]

Steps:

  1. User clicks “Add New” button in header
  2. Selects between file or folder upload
  3. System validates selection (size limits, file types)
  4. Requests signed URLs from backend
  5. Uploads files directly to cloud storage
  6. Creates repository entries in database
  7. Updates local state optimistically
  8. Shows upload progress and completion

9.2 File Search Flow

stateDiagram-v2
    [*] --> Idle
    Idle --> Typing: User types
    Typing --> Debouncing: Wait 300ms
    Debouncing --> Searching: Trigger search
    Searching --> DisplayResults: Results found
    Searching --> NoResults: No matches
    DisplayResults --> [*]
    NoResults --> [*]

Features:

  • Real-time search with debouncing
  • Search across file names, folders, and metadata
  • Highlights matching terms
  • Groups results by category

9.3 File Sharing Flow

sequenceDiagram
    participant U as User
    participant M as ShareModal
    participant A as API
    participant R as Recipients

    U->>M: Select files & click Share
    M->>U: Show user selector
    U->>M: Select recipients
    M->>A: Update permissions
    A->>R: Send notifications
    A-->>M: Confirm shared
    M-->>U: Show success

Process:

  1. User selects files/folders to share
  2. Opens share modal
  3. Searches and selects recipients
  4. Sets permission levels
  5. System updates access control
  6. Recipients receive notification
  7. Files appear in “Shared with Me”

9.4 Folder Navigation Flow

graph TD
    A[Root Folder] --> B{User Action}
    B -->|Click Folder| C[Enter Folder]
    B -->|Breadcrumb| D[Navigate Up]
    C --> E[Load Contents]
    D --> F[Load Parent]
    E --> G[Update URL]
    F --> G
    G --> H[Update View]

Navigation Features:

  • Click folders to navigate down
  • Use breadcrumbs to navigate up
  • URL updates reflect current location
  • Back/forward browser buttons work
  • Folder hierarchy maintained in state

9.5 Bulk Operations Flow

graph LR
    A[Select Mode] --> B[Choose Items]
    B --> C{Action}
    C -->|Download| D[Zip & Download]
    C -->|Delete| E[Move to Trash]
    C -->|Share| F[Bulk Share]
    C -->|Move| G[Select Destination]
    D --> H[Complete]
    E --> H
    F --> H
    G --> I[Move Items]
    I --> H

Bulk Actions:

  • Select multiple items via checkboxes
  • Floating action menu appears
  • Supports download, delete, share, move
  • Progress tracking for large operations
  • Undo capability for some actions

9.6 File Preview Flow

stateDiagram-v2
    [*] --> Thumbnail: File displayed
    Thumbnail --> Preview: User clicks
    Preview --> Loading: Fetch file
    Loading --> Display: Show content
    Display --> Actions: User interacts
    Actions --> Download: Download file
    Actions --> Share: Share file
    Actions --> Close: Close preview
    Close --> [*]

Preview Capabilities:

  • Images: Full resolution view
  • Documents: Embedded viewer
  • Videos: Inline player
  • Other files: Download prompt
  • Navigation between files in preview

9.7 Storage Management Flow

graph TD
    A[Dashboard Tab] --> B[Load Usage Data]
    B --> C[Organization Stats]
    B --> D[User List]
    C --> E[Show Breakdown]
    D --> F[Paginated Table]
    E --> G[Repository vs LMS]
    F --> H[Sort by Usage]

Dashboard Features:

  • Organization storage overview
  • Per-user usage breakdown
  • Storage type distribution
  • Sort users by consumption
  • Export usage reports

10. Technical Implementation

This section covers key technical implementation details and patterns used in the Repository module:

10.1 File Upload Implementation

The file upload process uses signed URLs for secure direct uploads to cloud storage:

// 1. Get signed URL
const signedUrl = await getRepositorySignedUrl(queryParams);
 
// 2. Upload file directly
await fetch(signedUrl, {
	method: 'PUT',
	body: file,
	headers: {
		'Content-Type': file.type,
	},
});
 
// 3. Create repository entry
await createRepositoryItem({
	entityInfo: { [fileName]: fileMetadata },
	parentID: currentFolderId,
});

10.2 Folder Structure Management

Folders are managed hierarchically with efficient navigation:

interface FolderHierarchy {
	id: string;
	name: string;
	path: string;
	parentID: string | null;
}
 
// Navigation maintains breadcrumb trail
const navigateToFolder = (folderId: string) => {
	const hierarchy = buildHierarchy(folderId);
	dispatch(setFolderHierarchy(hierarchy));
	history.push(`/repository/folder/${folderId}`);
};

10.3 Search Implementation

Search functionality uses debouncing and intelligent result grouping:

const useSearch = () => {
	const [query, setQuery] = useState('');
	const debouncedQuery = useDebounce(query, 300);
 
	useEffect(() => {
		if (debouncedQuery) {
			searchRepository({
				search: debouncedQuery,
				...filters,
			});
		}
	}, [debouncedQuery]);
};

10.4 File Type Detection

The module uses MIME types and extensions for file type identification:

const getFileType = (file: File): RepositoryFileType => {
	const mimeType = file.type;
	const extension = file.name.split('.').pop()?.toLowerCase();
 
	if (mimeType.startsWith('image/')) return RepositoryFileType.IMAGE;
	if (mimeType.startsWith('video/')) return RepositoryFileType.VIDEO;
	if (DOCUMENT_EXTENSIONS.includes(extension)) return RepositoryFileType.DOCUMENT;
 
	return RepositoryFileType.OTHER;
};

10.5 Permission Management

File permissions are managed at the item level:

interface ItemPermissions {
	canView: boolean;
	canEdit: boolean;
	canDelete: boolean;
	canShare: boolean;
	sharedWith: string[]; // User IDs
}

10.6 Error Handling Patterns

Comprehensive error handling with user-friendly messages:

try {
	await updateRepositoryItem(payload);
	toast.success('File updated successfully');
} catch (error) {
	console.error('Update failed:', error);
	toast.error(getErrorMessage(error));
	// Rollback optimistic update
	dispatch(revertUpdate(itemId));
}

10.7 Caching Strategy

The module implements intelligent caching:

  1. API Response Caching
  • Cache folder lists for navigation
  • Cache file metadata for quick access
  • Invalidate on modifications
  1. Preview Caching
  • Cache generated thumbnails
  • Lazy load preview images
  • Memory management for large files

10.8 Security Considerations

  1. Authentication
  • Firebase token validation
  • Automatic token refresh
  • Secure API endpoints
  1. Authorization
  • Feature flag validation
  • Role-based access control
  • Per-item permissions
  1. Data Validation
  • File type restrictions
  • Size limitations
  • Name sanitization

10.9 Performance Optimizations

  1. Lazy Loading

    const RepositoryPage = loadable(() => import('./pages/repository/RepositoryPage'));
  2. Virtual Scrolling

  • For large file lists
  • Renders only visible items
  • Smooth scroll performance
  1. Batch Operations
    const batchDelete = async (itemIds: string[]) => {
    	const chunks = chunk(itemIds, 50); // Process in chunks
    	await Promise.all(chunks.map(deleteChunk));
    };

10.10 Testing Strategies

  1. Unit Tests
  • Redux reducers
  • Utility functions
  • API services
  1. Integration Tests
  • Component interactions
  • API communication
  • State management
  1. E2E Tests
  • File upload flows
  • Search functionality
  • Permission validation

10.11 Monitoring and Analytics

The module tracks key metrics:

// Track file operations
analytics.track('file_uploaded', {
	fileType: file.type,
	fileSize: file.size,
	uploadDuration: duration,
});
 
// Monitor performance
performance.mark('repository_load_start');
// ... load data
performance.mark('repository_load_end');
performance.measure('repository_load', 'repository_load_start', 'repository_load_end');

Planned improvements for the module:

  1. Advanced Features
  • Version control for files
  • Collaborative editing
  • Advanced search filters
  • File tagging system
  1. Performance
  • Service worker caching
  • Progressive web app features
  • Optimized bundle splitting
  1. Integration
  • Third-party storage providers
  • External collaboration tools
  • Advanced analytics dashboard

11. Integration Patterns

11.1 Integration with Other Modules

The Repository module integrates seamlessly with other parts of the application:

11.1.1 Issues Module Integration

Files can be attached to issues for documentation:

// Issue attachment flow
const attachFileToIssue = async (issueId: string, fileId: string) => {
	// Get file from repository
	const file = await getRepositoryItem(fileId);
 
	// Create attachment reference
	await createIssueAttachment({
		issueId,
		fileId,
		fileName: file.name,
		fileSize: file.size,
		uploadedBy: currentUser.id,
	});
};

11.1.2 Reports Module Integration

Reports can reference repository files:

// Report file inclusion
const includeFileInReport = (reportId: string, fileIds: string[]) => {
	return updateReport(reportId, {
		attachments: fileIds,
		lastModified: new Date(),
	});
};

Shared image handling between modules:

// Shared image viewer
const openImagePreview = (imageId: string, source: 'repository' | 'gallery') => {
	dispatch(
		openPreviewModal({
			imageId,
			source,
			navigation: source === 'repository' ? getRepositoryNavigation() : getGalleryNavigation(),
		}),
	);
};

11.2 Event-Driven Architecture

The module uses events for loose coupling:

// Event emitter for repository events
class RepositoryEventEmitter extends EventEmitter {
	emitFileUploaded(file: GetRepositoryItemsResponse) {
		this.emit('file:uploaded', file);
	}
 
	emitFileDeleted(fileId: string) {
		this.emit('file:deleted', fileId);
	}
 
	emitStorageUpdated(usage: StorageUsage) {
		this.emit('storage:updated', usage);
	}
}
 
// Other modules can listen
repositoryEvents.on('file:uploaded', (file) => {
	// Update related data
	// Send notifications
	// Trigger workflows
});

12. Troubleshooting Guide

12.1 Common Issues and Solutions

  1. Upload Failures
  • Check network connectivity
  • Verify storage quota
  • Validate file size limits
  • Check file type restrictions
  1. Performance Issues
  • Enable React DevTools Profiler
  • Check for unnecessary re-renders
  • Verify API response times
  • Monitor bundle size
  1. State Inconsistencies
  • Check Redux DevTools
  • Verify action dispatching
  • Look for race conditions
  • Check middleware order

12.2 Debug Utilities

// Debug logger for development
const debugLog = (action: string, data: any) => {
	if (process.env.NODE_ENV === 'development') {
		console.group(`[Repository] ${action}`);
		console.log('Data:', data);
		console.log('State:', store.getState().repository);
		console.groupEnd();
	}
};
 
// Performance monitor
const measurePerformance = (operation: string, fn: () => void) => {
	const start = performance.now();
	fn();
	const end = performance.now();
	console.log(`${operation} took ${end - start}ms`);
};

13. Summary

The File Repository Module is a comprehensive file management solution within the Nimbly audit administration platform. It provides:

13.1 Key Capabilities

  • Centralized Storage: Single source of truth for all audit-related files
  • Hierarchical Organization: Folder-based structure with breadcrumb navigation
  • Advanced Search: Full-text search across file names and metadata
  • [Access Control](../Settings/Access control/AccessControlOverview.md): Feature flag protection and user-based [permissions](../Settings/Access control/AccessControlOverview.md)
  • Storage Management: Organization and user-level quota tracking
  • Multiple Views: Tile and table layouts with customizable sorting
  • [Bulk Operationss](../Bulk Operation/BulkOperationOverview.md): Efficient handling of multiple file operations

13.2 Technical Highlights

  • React-Redux Architecture: Clean separation of concerns with predictable state management
  • TypeScript: Full type safety across components and APIs
  • Performance Optimized: Lazy loading, memoization, and virtual scrolling
  • Cloud Integration: Direct uploads to cloud storage with signed URLs
  • Responsive Design: Mobile-friendly interface with adaptive layouts

13.3 Module Statistics

  • Components: 40+ specialized React components
  • Custom Hooks: 15+ reusable hooks for business logic
  • API Endpoints: 10+ RESTful endpoints
  • State Slices: 4 Redux reducers for different aspects
  • File Types: Support for images, videos, documents, and more

The module exemplifies modern web development practices with a focus on user experience, performance, and maintainability. It serves as a critical component in the Nimbly ecosystem, enabling efficient file management for audit workflows.

For questions or contributions, please refer to the GitHub repository.