From d1085b34530393efd7aed4e477e46594c02cb682 Mon Sep 17 00:00:00 2001 From: Aiman Fakhrullah Mantasan Date: Fri, 30 May 2025 21:08:11 +0800 Subject: [PATCH] Created Settings Page, Standardize Design, Updated Documentation --- CHANGELOG.md | 204 +++++ README.md | 257 +++++- components/RsInput.vue | 115 +++ components/RsSelect.vue | 143 +++ components/RsTextarea.vue | 105 +++ .../dms/dialogs/DMSAccessRequestDialog.vue | 40 +- components/dms/dialogs/DMSUploadDialog.vue | 812 +++++++++--------- components/dms/search/DMSAdvancedSearch.vue | 543 ++++++++++++ docs/Technical_Guide.md | 431 +++++++--- docs/User_Guide.md | 207 ++++- middleware/dashboard.js | 2 +- middleware/main.js | 13 +- navigation/index.js | 15 - pages/devtool/code-playground/index.js | 6 + pages/dms/design-system.vue | 277 ++++++ pages/dms/document-properties.vue | 364 -------- pages/dms/index.vue | 4 - pages/dms/my-documents.vue | 371 -------- pages/dms/settings.vue | 676 +++++++++++++++ pages/dms/upload-document.vue | 444 ---------- pages/index.vue | 14 +- pages/login/index.vue | 2 +- stores/dms.js | 415 ++++++++- 23 files changed, 3660 insertions(+), 1800 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 components/RsInput.vue create mode 100644 components/RsSelect.vue create mode 100644 components/RsTextarea.vue create mode 100644 components/dms/search/DMSAdvancedSearch.vue create mode 100644 pages/dms/design-system.vue delete mode 100644 pages/dms/document-properties.vue delete mode 100644 pages/dms/my-documents.vue create mode 100644 pages/dms/settings.vue delete mode 100644 pages/dms/upload-document.vue diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..1248267 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,204 @@ +# Changelog + +All notable changes to the Electronic Document Management System (EDMS) project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [2.0.0] - 2024-01-15 + +### 🎨 **Major Design System Overhaul** + +#### Added +- **New Standardized Components** + - `RsInput.vue`: Comprehensive input component with validation, sizing, and error states + - `RsSelect.vue`: Dropdown/select component with single/multiple selection support + - `RsTextarea.vue`: Textarea component with configurable resize and validation + - Design system documentation page at `/dms/design-system` + - Interactive component playground with live examples + - Component usage guidelines and best practices + +- **Enhanced Design System Features** + - Consistent prop structure across all Rs components (`modelValue`, `label`, `error`, `disabled`, `size`) + - Universal dark mode support via CSS variables + - Accessibility features with proper ARIA attributes + - Standardized sizing system (sm, md, lg) + - Error state handling with validation messaging + - Real-time validation and form state management + +#### Changed +- **Settings Architecture Simplification** + - Reduced from 10 to 5 core settings categories: + - 🔐 User & Access Management + - 📁 Document & Folder Settings + - 📝 Metadata & Tagging + - 📤 Upload & Storage Settings + - 📅 System Settings + - Removed categories: Search & Indexing, Integration Settings, Audit & Compliance, Workflow & Automation, UI & Branding + - Streamlined settings structure for better usability and maintenance + +- **Component Standardization** + - `DMSAccessRequestDialog.vue`: Replaced manual button styling with `RsButton` components + - Settings page: Updated key form inputs to use `RsInput`, `RsSelect`, `RsTextarea` + - Standardized modal footer patterns across all dialogs + - Consistent form validation and error handling + +- **Enhanced Component Registration** + - Added new Rs components to global component registry + - Updated export system in `pages/devtool/code-playground/index.js` + - Improved component discovery and usage + +#### Improved +- **Form Consistency** + - Unified form styling across all components + - Consistent error handling and validation states + - Standardized label and placeholder patterns + - Improved accessibility with proper form associations + +- **User Experience** + - Better visual consistency across the application + - Improved dark mode support and theme switching + - Enhanced form validation with real-time feedback + - Standardized interaction patterns + +### 📖 **Documentation Updates** + +#### Added +- **Comprehensive Design System Documentation** + - Interactive component playground at `/dms/design-system` + - Component API documentation with props and examples + - Usage guidelines and best practices + - Color system and typography scale documentation + - Accessibility standards and compliance information + +- **Enhanced Technical Guide** + - Complete design system section with component specifications + - Form component usage examples and API reference + - Color system documentation with CSS variable reference + - Typography and spacing scale definitions + - Integration patterns and best practices + +#### Updated +- **User Guide Enhancements** + - Added comprehensive Settings Administration section + - Documented simplified 5-category settings structure + - Detailed explanation of each settings category + - Best practices for settings management + - Troubleshooting guide for settings issues + +- **README Overhaul** + - Complete project overview with features and technology stack + - Design system highlights and component examples + - Comprehensive setup and installation instructions + - Development guidelines and contribution standards + - Security features and support information + +### 🔧 **Technical Improvements** + +#### Enhanced +- **CSS Architecture** + - Improved CSS variable system for theming + - Standardized component styling patterns + - Better organization of style files + - Enhanced dark mode support + +- **Form Handling** + - Consistent v-model patterns across components + - Improved validation and error state management + - Better form component composition + - Enhanced accessibility features + +- **State Management** + - Improved settings state management + - Better validation and error handling + - Enhanced form state synchronization + +### 🚨 **Breaking Changes** +- Settings API structure changed due to category reduction +- Some component prop names standardized (may affect custom implementations) +- Manual form styling replaced with Rs components (update required for custom forms) + +### 💻 **Development Experience** + +#### Improved +- **Component Development** + - Standardized component patterns for easier development + - Better TypeScript support for component props + - Improved component documentation and examples + - Enhanced development guidelines + +- **Design Consistency** + - Clear design system guidelines + - Standardized component usage patterns + - Better visual consistency across the application + - Improved maintainability + +#### Added +- **Development Tools** + - Interactive design system playground + - Component examples and usage guidelines + - Development best practices documentation + - Contributing guidelines for design system + +### 📱 **User Interface** + +#### Enhanced +- **Visual Consistency** + - Unified button styles and interactions + - Consistent form field appearance + - Standardized modal and dialog layouts + - Improved color scheme and theming + +- **Accessibility** + - Better keyboard navigation support + - Improved screen reader compatibility + - Consistent focus states and indicators + - WCAG 2.1 compliance improvements + +- **Responsive Design** + - Better mobile form interactions + - Improved tablet layout handling + - Consistent breakpoint management + - Enhanced touch interaction support + +### 🔄 **Migration Guide** + +#### For Developers +1. **Update Form Components**: Replace manual form styling with Rs components +2. **Settings Integration**: Update any settings-related code for new 5-category structure +3. **Component Usage**: Follow new Rs component patterns for consistency +4. **Styling Updates**: Remove manual Tailwind classes in favor of Rs components + +#### For Users +1. **Settings Location**: Settings now organized in 5 streamlined categories +2. **Interface Changes**: Improved form interactions and validation +3. **New Features**: Access to design system documentation and examples + +### 🎯 **Future Roadmap** +- Additional Rs components (date picker, multi-select, autocomplete) +- Enhanced animation system for micro-interactions +- Expanded accessibility features and testing +- Advanced form validation and error handling +- Component testing and documentation automation + +--- + +## [1.0.0] - 2023-12-01 + +### Initial Release +- Electronic Document Management System with hierarchical organization +- User authentication and role-based access control +- Document upload, preview, and management capabilities +- Basic settings and configuration system +- Initial UI components and styling + +--- + +**Legend:** +- 🎨 Design System +- 📖 Documentation +- 🔧 Technical +- 🚨 Breaking Changes +- 💻 Development Experience +- 📱 User Interface +- 🔄 Migration +- 🎯 Roadmap \ No newline at end of file diff --git a/README.md b/README.md index 7f452fe..611f1c7 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,256 @@ -# Nuxt 3 Minimal Starter +# Electronic Document Management System (EDMS) -Look at the [nuxt 3 documentation](https://v3.nuxtjs.org) to learn more. +A modern, web-based document management system built with Nuxt.js 3 and Vue.js 3, featuring a comprehensive design system and hierarchical document organization. -## Setup +## 🚀 Features -Make sure to install the dependencies: +### Core Functionality +- **Hierarchical Organization**: Cabinet → Drawer → Folder → Subfolder structure +- **Advanced Document Management**: Upload, version control, metadata management +- **Role-Based Access Control**: Granular permissions with access request workflows +- **Multi-format Document Viewer**: Built-in viewer for PDF, images, Office documents +- **Advanced Search**: Full-text search with metadata and tag filtering +- **Responsive Design**: Works seamlessly across desktop, tablet, and mobile +### Design System +- **Standardized Components**: Complete "Rs" component library (RsButton, RsInput, RsSelect, etc.) +- **Consistent Styling**: Unified design patterns with dark/light mode support +- **Accessibility**: WCAG-compliant components with proper ARIA attributes +- **Interactive Documentation**: Design system playground at `/dms/design-system` + +### Administration +- **Streamlined Settings**: 5 core configuration categories + - 🔐 User & Access Management + - 📁 Document & Folder Settings + - 📝 Metadata & Tagging + - 📤 Upload & Storage Settings + - 📅 System Settings +- **Import/Export**: Configuration backup and transfer capabilities +- **Real-time Validation**: Form validation with dependency checking + +## 🛠️ Technology Stack + +### Frontend +- **Nuxt.js 3**: Universal Vue.js framework with SSR/SPA support +- **Vue.js 3**: Progressive framework with Composition API +- **TailwindCSS**: Utility-first CSS framework with custom component system +- **Pinia**: Modern state management with persistence +- **FormKit**: Advanced form handling with custom theming + +### Backend +- **Prisma ORM**: Type-safe database client with migrations +- **MySQL/PostgreSQL**: Relational database with comprehensive schema +- **File System Integration**: Secure file storage and management +- **JWT Authentication**: Token-based authentication with RBAC + +### Development Tools +- **TypeScript**: Type safety and enhanced development experience +- **ESLint**: Code linting with Vue.js specific rules +- **Vite**: Lightning-fast build tool and HMR + +## 📋 Setup + +### Requirements +- Node.js 18+ and npm/yarn/pnpm +- MySQL 8+ or PostgreSQL 13+ +- Modern web browser with JavaScript enabled + +### Installation + +1. **Clone Repository** ```bash -# yarn -yarn install - -# npm -npm install - -# pnpm -pnpm install --shamefully-hoist +git clone https://github.com/your-repo/edms.git +cd edms ``` -## Development Server +2. **Install Dependencies** +```bash +# Using npm +npm install -Start the development server on http://localhost:3000 +# Using yarn +yarn install +# Using pnpm +pnpm install +``` + +3. **Environment Configuration** +Create `.env` file: +```env +# Database +DATABASE_URL="mysql://username:password@localhost:3306/edms_db" + +# Authentication +JWT_SECRET="your-jwt-secret-key-min-256-bits" +SESSION_SECRET="your-session-secret-key" + +# File Storage +UPLOAD_PATH="/var/uploads/edms" +MAX_FILE_SIZE="104857600" # 100MB +ALLOWED_FILE_TYPES="pdf,doc,docx,xls,xlsx,ppt,pptx,txt,jpg,jpeg,png" + +# Application +NUXT_SECRET_KEY="your-nuxt-app-secret" +BASE_URL="http://localhost:3000" +``` + +4. **Database Setup** +```bash +# Generate Prisma client +npx prisma generate + +# Run migrations +npx prisma db push + +# Seed data (optional) +npx prisma db seed +``` + +5. **Development Server** ```bash npm run dev ``` -## Production +Access the application at `http://localhost:3000` -Build the application for production: +## 🎨 Design System + +### Component Library +The EDMS uses a standardized component library with the "Rs" prefix: + +#### Form Components +- **RsInput**: Standardized input fields with validation +- **RsSelect**: Dropdown/select with options support +- **RsTextarea**: Multi-line text input with resize controls +- **RsButton**: Buttons with multiple variants and sizes + +#### UI Components +- **RsCard**: Container component with header/body/footer +- **RsModal**: Modal dialogs with standardized structure +- **RsTable**: Data tables with sorting and filtering +- **RsDropdown**: Dropdown menus and navigation + +### Usage Examples + +```vue + + + + + + Save Changes + + + + + + + + +``` + +### Design Principles +- **🎯 Consistency**: Unified patterns across all components +- **🔧 Modularity**: Reusable and composable components +- **🌙 Dark Mode**: Universal theme support +- **📱 Responsive**: Mobile-first approach +- **♿ Accessibility**: WCAG-compliant with keyboard navigation + +## 📖 Documentation + +### Available Guides +- **[Technical Guide](docs/Technical_Guide.md)**: Comprehensive technical documentation +- **[User Guide](docs/User_Guide.md)**: End-user instructions and features +- **[Site Settings](docs/SITE_SETTINGS.md)**: Configuration and customization guide + +### Interactive Documentation +- **Design System**: Visit `/dms/design-system` for component examples +- **API Documentation**: Available in development mode +- **Component Playground**: Test components with live examples + +## 🔧 Development + +### Project Structure +``` +edms/ +├── components/ # Vue components +│ ├── dms/ # DMS-specific components +│ │ ├── dialogs/ # Modal dialogs +│ │ ├── explorer/ # Document browser +│ │ ├── search/ # Search functionality +│ │ └── viewers/ # Document preview +│ └── Rs*.vue # Design system components +├── pages/ # File-based routing +│ ├── dms/ # DMS pages +│ └── devtool/ # Admin tools +├── stores/ # Pinia state management +├── server/ # API routes and middleware +├── prisma/ # Database schema and migrations +├── assets/ # Stylesheets and assets +└── docs/ # Documentation +``` + +### Building for Production ```bash +# Build application npm run build -``` -Locally preview production build: - -```bash +# Preview production build npm run preview + +# Generate static site (if applicable) +npm run generate ``` -Checkout the [deployment documentation](https://v3.nuxtjs.org/guide/deploy/presets) for more information. -# corradAF +## 🔐 Security Features -This is the base project for corradAF. +- **Role-Based Access Control**: Granular permission system +- **Document-level Security**: Individual document access controls +- **Access Request Workflow**: Approval system for restricted documents +- **Audit Trail**: Comprehensive activity logging +- **File Type Validation**: Security through file type restrictions +- **Session Management**: Secure token-based authentication + +## 🤝 Contributing + +1. Fork the repository +2. Create a feature branch (`git checkout -b feature/amazing-feature`) +3. Follow the design system guidelines +4. Use standardized components (Rs library) +5. Add tests for new functionality +6. Commit changes (`git commit -m 'Add amazing feature'`) +7. Push to branch (`git push origin feature/amazing-feature`) +8. Open a Pull Request + +### Development Guidelines +- Use Rs components instead of custom styling +- Follow semantic variant naming (primary, secondary, danger) +- Test in both light and dark modes +- Maintain accessibility standards +- Document new features in user/technical guides + +## 📄 License + +This project is part of the corradAF base project. See the license file for details. + +## 🆘 Support + +- **Technical Issues**: Check the [Technical Guide](docs/Technical_Guide.md) +- **User Questions**: Refer to the [User Guide](docs/User_Guide.md) +- **Component Usage**: Visit `/dms/design-system` for examples +- **Bug Reports**: Create an issue with detailed reproduction steps + +--- + +Built with ❤️ using Nuxt.js 3, Vue.js 3, and modern web technologies. diff --git a/components/RsInput.vue b/components/RsInput.vue new file mode 100644 index 0000000..f6e0b98 --- /dev/null +++ b/components/RsInput.vue @@ -0,0 +1,115 @@ + + + + + \ No newline at end of file diff --git a/components/RsSelect.vue b/components/RsSelect.vue new file mode 100644 index 0000000..045b3e1 --- /dev/null +++ b/components/RsSelect.vue @@ -0,0 +1,143 @@ + + + + + \ No newline at end of file diff --git a/components/RsTextarea.vue b/components/RsTextarea.vue new file mode 100644 index 0000000..04ae223 --- /dev/null +++ b/components/RsTextarea.vue @@ -0,0 +1,105 @@ + + + + + \ No newline at end of file diff --git a/components/dms/dialogs/DMSAccessRequestDialog.vue b/components/dms/dialogs/DMSAccessRequestDialog.vue index a45cc8a..69435e2 100644 --- a/components/dms/dialogs/DMSAccessRequestDialog.vue +++ b/components/dms/dialogs/DMSAccessRequestDialog.vue @@ -175,29 +175,24 @@ const submitRequest = async () => {
- - + :options="durationOptions" + label="Access Duration" + :required="false" + />
- - + :rows="4" + :required="true" + resize="none" + />
@@ -209,24 +204,25 @@ const submitRequest = async () => { diff --git a/components/dms/dialogs/DMSUploadDialog.vue b/components/dms/dialogs/DMSUploadDialog.vue index 62e22ea..98bf1e3 100644 --- a/components/dms/dialogs/DMSUploadDialog.vue +++ b/components/dms/dialogs/DMSUploadDialog.vue @@ -1,5 +1,6 @@ \ No newline at end of file diff --git a/components/dms/search/DMSAdvancedSearch.vue b/components/dms/search/DMSAdvancedSearch.vue new file mode 100644 index 0000000..d7a35cf --- /dev/null +++ b/components/dms/search/DMSAdvancedSearch.vue @@ -0,0 +1,543 @@ + + + + + \ No newline at end of file diff --git a/docs/Technical_Guide.md b/docs/Technical_Guide.md index 31ed5a0..b1e491b 100644 --- a/docs/Technical_Guide.md +++ b/docs/Technical_Guide.md @@ -427,153 +427,302 @@ edms/ - **RsButton.vue**: Standardized button component with variants - **RsCard.vue**: Container component with consistent styling - **RsModal.vue**: Modal dialog base component +- **RsInput.vue**: Standardized input field component +- **RsSelect.vue**: Standardized dropdown/select component +- **RsTextarea.vue**: Standardized textarea component - **RsTable.vue**: Data table with sorting and filtering - **RsDropdown.vue**: Dropdown menu component -### State Management (Pinia) +## Design System -#### DMS Store (`stores/dms.js`) -```javascript -export const useDmsStore = defineStore('dms', { - state: () => ({ - // Navigation state - currentPath: '/', - pathHistory: [], - currentItems: [], - selectedItem: null, - - // UI state - treeExpanded: {}, - searchQuery: '', - viewMode: 'list', // list, grid, details - sortOrder: 'asc', - sortField: 'name', - activeTab: 'all', // all, public, private, personal - - // Loading states - isLoading: false, - isUploading: false, - uploadProgress: 0, - - // Dialog states - showUploadDialog: false, - showAccessRequestDialog: false, - accessRequestItem: null - }), - - actions: { - // Navigation actions - async navigateTo(path) { - this.isLoading = true - try { - this.pathHistory.push(this.currentPath) - this.currentPath = path - await this.loadItems() - } finally { - this.isLoading = false - } - }, - - async loadItems() { - const response = await $fetch('/api/dms/items', { - query: { - path: this.currentPath, - search: this.searchQuery, - tab: this.activeTab - } - }) - this.currentItems = response.items - }, - - // File operations - async uploadFile(file, metadata) { - this.isUploading = true - try { - const formData = new FormData() - formData.append('file', file) - formData.append('metadata', JSON.stringify(metadata)) - formData.append('path', this.currentPath) - - const response = await $fetch('/api/dms/upload', { - method: 'POST', - body: formData, - onUploadProgress: (progress) => { - this.uploadProgress = Math.round((progress.loaded / progress.total) * 100) - } - }) - - await this.loadItems() - return response - } finally { - this.isUploading = false - this.uploadProgress = 0 - } - }, - - async requestAccess(item, requestData) { - return await $fetch('/api/dms/access-request', { - method: 'POST', - body: { - documentId: item.id, - requestedLevel: requestData.accessType, - duration: requestData.duration, - justification: requestData.justification - } - }) - }, - - async searchDocuments(query) { - this.searchQuery = query - await this.loadItems() - } - }, - - getters: { - filteredItems: (state) => { - let items = state.currentItems - - // Apply tab filter - if (state.activeTab !== 'all') { - items = items.filter(item => item.accessType === state.activeTab) - } - - // Apply search filter - if (state.searchQuery) { - items = items.filter(item => - item.name.toLowerCase().includes(state.searchQuery.toLowerCase()) || - item.description?.toLowerCase().includes(state.searchQuery.toLowerCase()) - ) - } - - // Apply sorting - items.sort((a, b) => { - const aVal = a[state.sortField] - const bVal = b[state.sortField] - const modifier = state.sortOrder === 'asc' ? 1 : -1 - return aVal < bVal ? -modifier : aVal > bVal ? modifier : 0 - }) - - return items - }, - - currentBreadcrumbs: (state) => { - const parts = state.currentPath.split('/').filter(Boolean) - return parts.map((part, index) => ({ - name: part, - path: '/' + parts.slice(0, index + 1).join('/') - })) - }, - - canNavigateBack: (state) => state.pathHistory.length > 0 - }, - - persist: { - storage: persistedState.localStorage, - pick: ['treeExpanded', 'viewMode', 'sortOrder', 'sortField'] - } -}) +### Overview +The EDMS implements a comprehensive design system built on a standardized component library with the "Rs" prefix (Reusable System). This ensures consistency, maintainability, and accessibility across the entire application. + +### Design Principles +- **🎯 Consistency**: All components follow unified design patterns and naming conventions +- **🔧 Modularity**: Components are reusable and composable for complex interfaces +- **🌙 Dark Mode**: Universal support for both light and dark themes via CSS variables +- **📱 Responsive**: Mobile-first approach with adaptive layouts +- **♿ Accessibility**: WCAG-compliant with proper ARIA attributes and keyboard navigation + +### Component Library + +#### Form Components + +##### RsInput.vue +```vue + ``` +**Props:** +- `modelValue`: String/Number - Input value +- `label`: String - Field label +- `placeholder`: String - Placeholder text +- `type`: String - Input type (text, email, password, etc.) +- `required`: Boolean - Required field indicator +- `error`: String - Error message +- `size`: String - Size variant (sm, md, lg) +- `disabled`: Boolean - Disabled state + +##### RsSelect.vue +```vue + +``` + +**Props:** +- `modelValue`: String/Number/Array - Selected value(s) +- `options`: Array - Options list (objects with value/label or simple strings) +- `label`: String - Field label +- `placeholder`: String - Placeholder text +- `multiple`: Boolean - Multiple selection support +- `required`: Boolean - Required field indicator +- `error`: String - Error message +- `disabled`: Boolean - Disabled state + +##### RsTextarea.vue +```vue + +``` + +**Props:** +- `modelValue`: String - Textarea content +- `label`: String - Field label +- `placeholder`: String - Placeholder text +- `rows`: Number - Number of visible rows +- `resize`: String - Resize behavior (none, both, horizontal, vertical) +- `required`: Boolean - Required field indicator +- `error`: String - Error message +- `disabled`: Boolean - Disabled state + +#### UI Components + +##### RsButton.vue +```vue + + Button Text + +``` + +**Variants:** +- `primary`: Blue primary button +- `secondary`: Gray secondary button +- `info`: Blue info button +- `success`: Green success button +- `warning`: Yellow warning button +- `danger`: Red danger button +- `primary-outline`: Outlined primary button +- `secondary-outline`: Outlined secondary button +- `primary-text`: Text-only primary button + +**Sizes:** +- `sm`: Small button (padding: 0.25rem 0.75rem) +- `md`: Medium button (padding: 0.5rem 1rem) +- `lg`: Large button (padding: 0.75rem 1.25rem) + +##### RsCard.vue +```vue + + + + + +``` + +##### RsModal.vue +```vue + + + + + +``` + +**Sizes:** +- `sm`: 300px width +- `md`: 500px width +- `lg`: 800px width +- `xl`: 1000px width +- `full`: Full screen width + +### Color System + +The design system uses CSS custom properties for consistent theming: + +```css +:root { + /* Primary Colors */ + --color-primary: 59 130 246; /* Blue */ + --color-secondary: 100 116 139; /* Gray */ + --color-info: 14 165 233; /* Sky Blue */ + --color-success: 34 197 94; /* Green */ + --color-warning: 251 191 36; /* Yellow */ + --color-danger: 239 68 68; /* Red */ + + /* Background Colors */ + --bg-1: 248 250 252; /* Light Gray */ + --bg-2: 255 255 255; /* White */ + + /* Text Colors */ + --text-color: 15 23 42; /* Slate 900 */ + --text-muted: 100 116 139; /* Slate 500 */ + + /* Border Colors */ + --border-color: 226 232 240; /* Slate 200 */ + --fk-border-color: 209 213 219; /* Gray 300 */ +} +``` + +### Typography Scale + +```css +/* Font Sizes */ +.text-xs { font-size: 0.75rem; } /* 12px */ +.text-sm { font-size: 0.875rem; } /* 14px */ +.text-base { font-size: 1rem; } /* 16px */ +.text-lg { font-size: 1.125rem; } /* 18px */ +.text-xl { font-size: 1.25rem; } /* 20px */ +.text-2xl { font-size: 1.5rem; } /* 24px */ +.text-3xl { font-size: 1.875rem; } /* 30px */ + +/* Font Weights */ +.font-light { font-weight: 300; } +.font-normal { font-weight: 400; } +.font-medium { font-weight: 500; } +.font-semibold { font-weight: 600; } +.font-bold { font-weight: 700; } +``` + +### Spacing Scale + +```css +/* Spacing (padding/margin) */ +.p-1 { padding: 0.25rem; } /* 4px */ +.p-2 { padding: 0.5rem; } /* 8px */ +.p-3 { padding: 0.75rem; } /* 12px */ +.p-4 { padding: 1rem; } /* 16px */ +.p-6 { padding: 1.5rem; } /* 24px */ +.p-8 { padding: 2rem; } /* 32px */ +``` + +### Usage Guidelines + +#### ✅ Best Practices +1. **Always use Rs components** for UI elements instead of custom styling +2. **Use semantic variants** (primary, secondary, danger) rather than color names +3. **Follow consistent spacing** using the predefined scale +4. **Use CSS variables** for colors instead of hardcoded values +5. **Test in both themes** (light and dark mode) +6. **Maintain accessibility** with proper labels and ARIA attributes + +#### ❌ Anti-patterns +1. **Don't use manual Tailwind classes** for buttons (e.g., `px-4 py-2 bg-blue-500`) +2. **Don't create custom input styling** without extending Rs components +3. **Don't hardcode colors** or spacing values +4. **Don't mix different component styling approaches** +5. **Don't forget dark mode** support in custom components + +### FormKit Integration + +The design system integrates with FormKit for advanced form handling: + +```javascript +// FormKit theme configuration +export default { + global: { + label: "formkit-label-global", + outer: "formkit-outer-global", + wrapper: "formkit-wrapper-global", + }, + button: { + wrapper: "formkit-wrapper-button", + input: "formkit-input-button", + }, + text: { + label: "formkit-outer-text", + inner: "formkit-inner-text", + input: "formkit-input-text", + } +} +``` + +### Component Registration + +All Rs components are globally registered via the component index: + +```javascript +// pages/devtool/code-playground/index.js +export { + RsAlert, + RsBadge, + RsButton, + RsCard, + RsInput, + RsModal, + RsSelect, + RsTextarea, + RsTable, + // ... other components +}; +``` + +### Design System Documentation + +Access the interactive design system documentation at `/dms/design-system` to: +- View all components with live examples +- Test different variants and states +- Copy code snippets for implementation +- Understand usage guidelines and best practices + +### Future Enhancements + +Planned design system improvements: +- **Animation Library**: Consistent micro-interactions and transitions +- **Icon System**: Standardized icon library with consistent sizing +- **Layout Components**: Grid and flexbox utilities +- **Advanced Form Components**: Date pickers, multi-select, autocomplete +- **Data Visualization**: Chart and graph components +- **Notification System**: Toast and alert components + ## API & Data Management ### Server API Routes diff --git a/docs/User_Guide.md b/docs/User_Guide.md index a7afbb0..466eb36 100644 --- a/docs/User_Guide.md +++ b/docs/User_Guide.md @@ -10,7 +10,8 @@ 7. [Search and Filtering](#search-and-filtering) 8. [Document Viewer](#document-viewer) 9. [My Documents](#my-documents) -10. [Troubleshooting](#troubleshooting) +10. [Settings Administration](#settings-administration) +11. [Troubleshooting](#troubleshooting) ## Introduction @@ -290,6 +291,210 @@ View comprehensive information about your document usage: - Document categories and type distribution - Most accessed documents and usage patterns +## Settings Administration + +### Overview +The EDMS Settings module provides administrators with comprehensive control over system configuration and behavior. Access to settings is restricted to users with administrative privileges and affects system-wide operations. + +### Accessing Settings +1. Navigate to **DMS** → **Settings** from the main navigation menu +2. Select a settings category from the left sidebar navigation +3. Configure settings within each category using standardized form components +4. Save changes to apply configurations across the system + +### Settings Categories + +The EDMS settings are organized into 5 core categories for streamlined administration: + +#### 🔐 User & Access Management +Configure user permissions, roles, and authentication settings: + +**User Roles & Permissions** +- Define user roles (Admin, Editor, Viewer, Uploader) +- Set granular permissions for each role: + - View Documents: Read-only access to document content + - Edit Documents: Modify document metadata and properties + - Delete Documents: Remove documents with audit trail + - Download Documents: Save documents for offline access + - Share Documents: Generate sharing links and manage access +- Manage user groups by department or project +- Enable Role-Based Access Control (RBAC) system-wide + +**Authentication Settings** +- Single Sign-On (SSO) integration with external providers +- Multi-Factor Authentication (MFA) enforcement +- LDAP/Active Directory integration for enterprise environments +- Session timeout configuration (1-24 hours) +- Password policies and security requirements + +#### 📁 Document & Folder Settings +Configure document organization and structure: + +**Folder Hierarchy** +- Set maximum folder depth (1-10 levels) +- Choose default folder structure templates: + - Standard: General-purpose organization + - Project-based: Project-focused hierarchy + - Department-based: Organizational structure alignment + - Custom: User-defined structure +- Configure folder creation permissions and restrictions + +**Document Naming Conventions** +- Enable automatic document name generation +- Define mandatory metadata fields for document creation +- Set naming patterns using variables: + - `{department}`: Document department/owner + - `{title}`: Document title or name + - `{date}`: Creation or upload date + - `{project}`: Project code or identifier + - `{category}`: Document category/type + +**Document Retention & Version Control** +- Enable document retention policies with configurable retention periods +- Set automatic archiving before deletion +- Configure version control system: + - Maximum versions to retain (1-50) + - Automatic versioning on document updates + - Version history tracking and comparison tools + +#### 📝 Metadata & Tagging +Configure document metadata and classification: + +**Custom Metadata Fields** +Define custom fields for enhanced document organization: +- Field types: Text, Dropdown, Date, Number, Multi-select +- Required field enforcement for document uploads +- Department-specific metadata schemas +- Dynamic field validation and formatting rules + +**Predefined Metadata Fields** +- Department: Organizational unit assignment +- Priority: Document importance level (Low, Medium, High, Critical) +- Project Code: Project or initiative identifier +- Review Date: Scheduled review or expiration date + +**Tagging System** +- Configure predefined tags: urgent, confidential, public, draft, final +- Enable user-generated tags for flexible categorization +- Tag suggestion system for consistent tagging +- Auto-classification based on: + - Keyword recognition in document content + - Department-based classification rules + - File type and format analysis + +#### 📤 Upload & Storage Settings +Configure file upload restrictions and storage management: + +**File Type Management** +- **Allowed File Types**: Specify permitted file formats + - Default: pdf, doc, docx, xls, xlsx, ppt, pptx, txt, jpg, png + - Configurable list for organizational requirements +- **Blocked File Types**: Prevent potentially harmful files + - Default: exe, bat, cmd (executable files) + - Customizable blacklist for security compliance + +**File Size & Storage Quotas** +- Maximum file size per upload (typically 100MB) +- User storage quotas (default: 5GB per user) +- Group storage quotas (default: 50GB per group) +- Project storage quotas (default: 100GB per project) +- System-wide storage monitoring and alerts + +**Storage Configuration** +- Storage type selection (Local, AWS S3, Azure, Google Cloud) +- Storage path configuration for file organization +- Backup settings and automated backup scheduling +- Compression settings for storage optimization + +#### 📅 System Settings +Configure global system behavior and preferences: + +**General System Configuration** +- **System Timezone**: Set default timezone for timestamps + - Options: Asia/Kuala_Lumpur, UTC, America/New_York, Europe/London + - Affects document timestamps, scheduling, and user interface +- **Backup Schedule**: Configure automated system backups + - Options: Hourly, Daily, Weekly, Monthly + - Affects data protection and recovery capabilities +- **Log Level**: Set system logging verbosity + - Options: Debug, Info, Warning, Error + - Affects troubleshooting and system monitoring + +**System Monitoring & Maintenance** +- **Maintenance Mode**: Enable system-wide maintenance mode + - Displays maintenance message to users + - Restricts access during system updates +- **Automatic Updates**: Configure automatic system updates + - Security patches and feature updates + - Scheduled during low-usage periods +- **System Monitoring**: Enable performance monitoring + - Track system performance metrics + - Monitor user activity and system health + - Generate usage reports and analytics + +### Settings Management Features + +#### Import/Export Configuration +- **Export Settings**: Save current configuration as JSON file + - Backup settings before major changes + - Transfer settings between environments + - Documentation and compliance purposes +- **Import Settings**: Load configuration from JSON file + - Restore previous configurations + - Deploy settings across multiple systems + - Standardize configurations across environments + +#### Reset to Defaults +- **Category Reset**: Reset individual setting categories to default values +- **System Reset**: Reset entire system configuration to factory defaults +- **Selective Reset**: Choose specific settings to reset while preserving others + +#### Settings Validation +- **Real-time Validation**: Form validation prevents invalid configurations +- **Dependency Checking**: Settings are validated for interdependencies +- **Conflict Resolution**: System identifies and resolves setting conflicts +- **Preview Mode**: Test settings before applying system-wide + +### Best Practices for Settings Management + +#### Security Considerations +- Regularly review user permissions and access levels +- Enable MFA for administrative accounts +- Use strong session timeout values for security +- Regularly audit user roles and group memberships + +#### Storage Management +- Monitor storage quotas and usage patterns +- Implement retention policies for compliance +- Regular backup verification and testing +- Plan for storage scaling based on usage growth + +#### System Performance +- Monitor log levels to balance debugging needs with performance +- Schedule maintenance during off-peak hours +- Regular cleanup of temporary files and old versions +- Performance monitoring for system optimization + +#### Documentation & Compliance +- Document all configuration changes with justification +- Maintain change logs for audit purposes +- Regular export of settings for backup and documentation +- Review settings for compliance with organizational policies + +### Troubleshooting Settings Issues + +#### Common Settings Problems +- **Permission Conflicts**: Resolve conflicting role assignments +- **Upload Failures**: Check file type restrictions and size limits +- **Authentication Issues**: Verify SSO and authentication settings +- **Storage Problems**: Monitor quotas and storage allocation + +#### Settings Recovery +- Use exported settings files to restore configurations +- Reset specific categories if issues persist +- Contact system administrator for complex configuration issues +- Review audit logs for recent configuration changes + ## Troubleshooting ### Common Issues and Solutions diff --git a/middleware/dashboard.js b/middleware/dashboard.js index 08091f2..38525b5 100644 --- a/middleware/dashboard.js +++ b/middleware/dashboard.js @@ -7,5 +7,5 @@ export default defineNuxtRouteMiddleware(async (to, from) => { // If user is not logged in, redirect to logout page if (validateUser.value.statusCode === 401) return true; - return navigateTo("/dashboard"); + return navigateTo("/dms"); }); diff --git a/middleware/main.js b/middleware/main.js index b70e2fa..e9f1665 100644 --- a/middleware/main.js +++ b/middleware/main.js @@ -1,3 +1,14 @@ -export default defineNuxtRouteMiddleware((to, from) => { +export default defineNuxtRouteMiddleware(async (to, from) => { + // Check if user is authenticated + const { data: validateUser } = await useFetch("/api/auth/validate", { + method: "GET", + }); + + // If user is authenticated, redirect to DMS + if (validateUser.value.statusCode === 200) { + return navigateTo("/dms"); + } + + // If user is not authenticated, redirect to login return navigateTo("/login"); }); \ No newline at end of file diff --git a/navigation/index.js b/navigation/index.js index 307749d..a0c5a55 100644 --- a/navigation/index.js +++ b/navigation/index.js @@ -1,19 +1,4 @@ export default [ - { - "header": "Utama", - "description": "", - "child": [ - { - "title": "Dashboard", - "path": "/dashboard", - "icon": "ic:outline-dashboard", - "child": [], - "meta": {} - }, - - ], - "meta": {} - }, { "header": "DMS", "description": "Document Management System", diff --git a/pages/devtool/code-playground/index.js b/pages/devtool/code-playground/index.js index fc98745..c03c820 100644 --- a/pages/devtool/code-playground/index.js +++ b/pages/devtool/code-playground/index.js @@ -8,11 +8,14 @@ import RsCollapseItem from "../../../components/RsCollapseItem.vue"; import RsDropdown from "../../../components/RsDropdown.vue"; import RsDropdownItem from "../../../components/RsDropdownItem.vue"; import RsFieldset from "../../../components/RsFieldset.vue"; +import RsInput from "../../../components/RsInput.vue"; import RsModal from "../../../components/RsModal.vue"; import RsProgressBar from "../../../components/RsProgressBar.vue"; +import RsSelect from "../../../components/RsSelect.vue"; import RsTab from "../../../components/RsTab.vue"; import RsTabItem from "../../../components/RsTabItem.vue"; import RsTable from "../../../components/RsTable.vue"; +import RsTextarea from "../../../components/RsTextarea.vue"; import RsWizard from "../../../components/RsWizard.vue"; export { @@ -26,10 +29,13 @@ export { RsDropdown, RsDropdownItem, RsFieldset, + RsInput, RsModal, RsProgressBar, + RsSelect, RsTab, RsTabItem, RsTable, + RsTextarea, RsWizard, }; diff --git a/pages/dms/design-system.vue b/pages/dms/design-system.vue new file mode 100644 index 0000000..48bca0c --- /dev/null +++ b/pages/dms/design-system.vue @@ -0,0 +1,277 @@ + + + + + \ No newline at end of file diff --git a/pages/dms/document-properties.vue b/pages/dms/document-properties.vue deleted file mode 100644 index 84a43dc..0000000 --- a/pages/dms/document-properties.vue +++ /dev/null @@ -1,364 +0,0 @@ - - - - - \ No newline at end of file diff --git a/pages/dms/index.vue b/pages/dms/index.vue index a95416c..2b9a359 100644 --- a/pages/dms/index.vue +++ b/pages/dms/index.vue @@ -10,10 +10,6 @@ definePageMeta({ middleware: ["auth"], requiresAuth: true, breadcrumb: [ - { - name: "Dashboard", - path: "/dashboard", - }, { name: "DMS", path: "/dms", diff --git a/pages/dms/my-documents.vue b/pages/dms/my-documents.vue deleted file mode 100644 index a7b25f4..0000000 --- a/pages/dms/my-documents.vue +++ /dev/null @@ -1,371 +0,0 @@ - - - - - \ No newline at end of file diff --git a/pages/dms/settings.vue b/pages/dms/settings.vue new file mode 100644 index 0000000..713252f --- /dev/null +++ b/pages/dms/settings.vue @@ -0,0 +1,676 @@ + + + + + \ No newline at end of file diff --git a/pages/dms/upload-document.vue b/pages/dms/upload-document.vue deleted file mode 100644 index ecd62ca..0000000 --- a/pages/dms/upload-document.vue +++ /dev/null @@ -1,444 +0,0 @@ - - - - - \ No newline at end of file diff --git a/pages/index.vue b/pages/index.vue index 0cf6a06..9a94be2 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -1,10 +1,18 @@ diff --git a/pages/login/index.vue b/pages/login/index.vue index d7090d5..3b74607 100644 --- a/pages/login/index.vue +++ b/pages/login/index.vue @@ -60,7 +60,7 @@ const login = async () => { showConfirmButton: false, }); - window.location.href = "/dashboard"; + window.location.href = "/dms"; } else { $swal.fire({ title: "Error!", diff --git a/stores/dms.js b/stores/dms.js index 20c382b..51e30d1 100644 --- a/stores/dms.js +++ b/stores/dms.js @@ -334,7 +334,111 @@ export const useDmsStore = defineStore('dms', { showFileViewer: false, viewerDocument: null, searchQuery: '', - searchResults: [] + searchResults: [], + + // Settings integration + systemSettings: { + upload: { + allowedFileTypes: ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'jpg', 'png'], + blockedFileTypes: ['exe', 'bat', 'cmd'], + maxFileSize: 100 * 1024 * 1024, // 100MB in bytes + quotas: { + perUser: 5000 * 1024 * 1024, // 5GB + perGroup: 50000 * 1024 * 1024, // 50GB + perProject: 100000 * 1024 * 1024 // 100GB + } + }, + metadata: { + customFields: [ + { name: 'Department', type: 'dropdown', required: true, options: ['HR', 'Finance', 'IT', 'Legal'] }, + { name: 'Priority', type: 'select', required: false, options: ['Low', 'Medium', 'High', 'Critical'] }, + { name: 'Project Code', type: 'text', required: true }, + { name: 'Review Date', type: 'date', required: false } + ], + predefinedTags: ['urgent', 'confidential', 'public', 'draft', 'final'], + userGeneratedTags: true, + tagSuggestions: true + }, + documents: { + versionControl: { + enabled: true, + maxVersions: 10, + autoVersioning: true + }, + namingConventions: { + autoGenerate: true, + pattern: '{department}_{title}_{date}' + } + }, + access: { + rbacEnabled: true, + permissions: { + view: true, + edit: true, + delete: false, + download: true, + share: true + } + } + }, + + // Enhanced user permissions with detailed tracking + userQuotas: { + used: 1500 * 1024 * 1024, // 1.5GB used + limit: 5000 * 1024 * 1024, // 5GB limit + documents: 450, + maxDocuments: 1000 + }, + + // Document metadata templates + metadataTemplates: { + standard: { + title: '', + description: '', + department: '', + author: '', + tags: [], + priority: 'Medium', + reviewDate: null, + projectCode: '' + }, + contract: { + title: '', + description: '', + department: 'Legal', + contractType: '', + vendor: '', + startDate: null, + endDate: null, + value: '', + tags: ['contract'], + priority: 'High' + }, + report: { + title: '', + description: '', + department: '', + reportType: '', + period: '', + author: '', + tags: ['report'], + priority: 'Medium' + } + }, + + // Version tracking + documentVersions: {}, + + // Enhanced search with metadata + advancedSearchFilters: { + fileType: [], + department: [], + tags: [], + dateRange: { start: null, end: null }, + author: [], + priority: [], + hasVersions: false + } }), getters: { @@ -486,6 +590,315 @@ export const useDmsStore = defineStore('dms', { this.viewerDocument = null; }, + // Enhanced file validation based on settings + validateFile(file) { + const errors = []; + const settings = this.systemSettings.upload; + + // Check file type + const fileExtension = file.name.split('.').pop().toLowerCase(); + if (!settings.allowedFileTypes.includes(fileExtension)) { + errors.push(`File type .${fileExtension} is not allowed`); + } + + if (settings.blockedFileTypes.includes(fileExtension)) { + errors.push(`File type .${fileExtension} is blocked`); + } + + // Check file size + if (file.size > settings.maxFileSize) { + const maxSizeMB = settings.maxFileSize / (1024 * 1024); + errors.push(`File size exceeds limit of ${maxSizeMB}MB`); + } + + // Check user quota + if (this.userQuotas.used + file.size > this.userQuotas.limit) { + errors.push('Upload would exceed your storage quota'); + } + + return { + isValid: errors.length === 0, + errors + }; + }, + + // Enhanced metadata validation + validateMetadata(metadata, template = 'standard') { + const errors = []; + const templateConfig = this.metadataTemplates[template]; + const customFields = this.systemSettings.metadata.customFields; + + // Validate required custom fields + customFields.forEach(field => { + if (field.required && (!metadata[field.name] || metadata[field.name].toString().trim() === '')) { + errors.push(`${field.name} is required`); + } + + // Validate field options for dropdown/select types + if (field.options && metadata[field.name] && !field.options.includes(metadata[field.name])) { + errors.push(`Invalid value for ${field.name}`); + } + }); + + // Validate document naming convention + if (this.systemSettings.documents.namingConventions.autoGenerate) { + const pattern = this.systemSettings.documents.namingConventions.pattern; + const requiredFields = pattern.match(/{(\w+)}/g)?.map(match => match.slice(1, -1)) || []; + + requiredFields.forEach(field => { + if (!metadata[field]) { + errors.push(`${field} is required for auto-generated naming`); + } + }); + } + + return { + isValid: errors.length === 0, + errors + }; + }, + + // Generate document name based on naming convention + generateDocumentName(metadata, originalFileName) { + if (!this.systemSettings.documents.namingConventions.autoGenerate) { + return originalFileName; + } + + let pattern = this.systemSettings.documents.namingConventions.pattern; + const date = new Date().toISOString().split('T')[0]; + + // Replace placeholders + pattern = pattern.replace(/{department}/g, metadata.department || 'unknown'); + pattern = pattern.replace(/{title}/g, metadata.title || 'document'); + pattern = pattern.replace(/{date}/g, date); + pattern = pattern.replace(/{author}/g, metadata.author || 'unknown'); + pattern = pattern.replace(/{projectCode}/g, metadata.projectCode || ''); + + // Get file extension + const extension = originalFileName.split('.').pop(); + + return `${pattern}.${extension}`; + }, + + // Enhanced upload with metadata and validation + async uploadFileWithMetadata(file, metadata, currentPath) { + // Validate file + const fileValidation = this.validateFile(file); + if (!fileValidation.isValid) { + throw new Error(`File validation failed: ${fileValidation.errors.join(', ')}`); + } + + // Validate metadata + const metadataValidation = this.validateMetadata(metadata); + if (!metadataValidation.isValid) { + throw new Error(`Metadata validation failed: ${metadataValidation.errors.join(', ')}`); + } + + this.isLoading = true; + + try { + // Generate document name + const documentName = this.generateDocumentName(metadata, file.name); + + // Create document object + const newDocument = { + id: `doc_${Date.now()}`, + name: documentName, + originalName: file.name, + type: 'file', + extension: file.name.split('.').pop().toLowerCase(), + size: this.formatFileSize(file.size), + modified: new Date().toLocaleDateString(), + author: metadata.author || 'Current User', + department: metadata.department, + description: metadata.description, + tags: metadata.tags || [], + priority: metadata.priority, + projectCode: metadata.projectCode, + reviewDate: metadata.reviewDate, + version: 1, + hasAccess: true, + accessType: metadata.accessType || 'private', + metadata: { ...metadata } + }; + + // Add to items (simulate upload) + this.items.push(newDocument); + + // Update user quota + this.userQuotas.used += file.size; + this.userQuotas.documents += 1; + + // Initialize version tracking if enabled + if (this.systemSettings.documents.versionControl.enabled) { + this.documentVersions[newDocument.id] = [{ + version: 1, + uploadDate: new Date().toISOString(), + author: metadata.author, + changes: 'Initial upload', + fileSize: file.size + }]; + } + + return newDocument; + } catch (error) { + console.error('Upload failed:', error); + throw error; + } finally { + this.isLoading = false; + } + }, + + // Version control actions + async createNewVersion(documentId, file, metadata) { + if (!this.systemSettings.documents.versionControl.enabled) { + throw new Error('Version control is not enabled'); + } + + const document = this.items.find(item => item.id === documentId); + if (!document) { + throw new Error('Document not found'); + } + + // Check version limit + const versions = this.documentVersions[documentId] || []; + if (versions.length >= this.systemSettings.documents.versionControl.maxVersions) { + // Remove oldest version + versions.shift(); + } + + // Create new version + const newVersion = { + version: document.version + 1, + uploadDate: new Date().toISOString(), + author: metadata.author, + changes: metadata.changes || 'Updated document', + fileSize: file.size + }; + + // Update document + document.version = newVersion.version; + document.modified = new Date().toLocaleDateString(); + document.size = this.formatFileSize(file.size); + + // Add version to tracking + versions.push(newVersion); + this.documentVersions[documentId] = versions; + + return newVersion; + }, + + // Get document versions + getDocumentVersions(documentId) { + return this.documentVersions[documentId] || []; + }, + + // Enhanced search with metadata + async advancedSearch(query, filters = {}) { + this.isLoading = true; + this.searchQuery = query; + Object.assign(this.advancedSearchFilters, filters); + + try { + // Mock API delay + await new Promise(resolve => setTimeout(resolve, 300)); + + let results = this.items.filter(item => item.type === 'file'); + + // Text search + if (query) { + const searchLower = query.toLowerCase(); + results = results.filter(item => + item.name.toLowerCase().includes(searchLower) || + item.description?.toLowerCase().includes(searchLower) || + item.department?.toLowerCase().includes(searchLower) || + item.author?.toLowerCase().includes(searchLower) || + item.projectCode?.toLowerCase().includes(searchLower) || + item.tags?.some(tag => tag.toLowerCase().includes(searchLower)) + ); + } + + // Filter by file type + if (filters.fileType && filters.fileType.length > 0) { + results = results.filter(item => filters.fileType.includes(item.extension)); + } + + // Filter by department + if (filters.department && filters.department.length > 0) { + results = results.filter(item => filters.department.includes(item.department)); + } + + // Filter by tags + if (filters.tags && filters.tags.length > 0) { + results = results.filter(item => + item.tags?.some(tag => filters.tags.includes(tag)) + ); + } + + // Filter by priority + if (filters.priority && filters.priority.length > 0) { + results = results.filter(item => filters.priority.includes(item.priority)); + } + + // Filter by date range + if (filters.dateRange?.start || filters.dateRange?.end) { + results = results.filter(item => { + const itemDate = new Date(item.modified); + const startDate = filters.dateRange.start ? new Date(filters.dateRange.start) : null; + const endDate = filters.dateRange.end ? new Date(filters.dateRange.end) : null; + + if (startDate && itemDate < startDate) return false; + if (endDate && itemDate > endDate) return false; + + return true; + }); + } + + // Filter by version existence + if (filters.hasVersions) { + results = results.filter(item => this.documentVersions[item.id]?.length > 1); + } + + this.searchResults = results; + return results; + } catch (error) { + console.error('Advanced search failed:', error); + throw error; + } finally { + this.isLoading = false; + } + }, + + // Tag suggestions + getTagSuggestions(input) { + if (!this.systemSettings.metadata.tagSuggestions) return []; + + const allTags = [ + ...this.systemSettings.metadata.predefinedTags, + ...new Set(this.items.flatMap(item => item.tags || [])) + ]; + + return allTags.filter(tag => + tag.toLowerCase().includes(input.toLowerCase()) + ).slice(0, 10); + }, + + // Update system settings + updateSystemSettings(category, settings) { + if (this.systemSettings[category]) { + Object.assign(this.systemSettings[category], settings); + } + }, + + // Format file size helper + formatFileSize(bytes) { + if (bytes === 0) return '0 B'; + const k = 1024; + const sizes = ['B', 'KB', 'MB', 'GB']; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; + }, + // Cabinet access actions async requestCabinetAccess(cabinetId, reason) { this.isLoading = true;