Showing preview only (3,526K chars total). Download the full file or copy to clipboard to get everything.
Repository: ColorlibHQ/gentelella
Branch: master
Commit: dd38278294b4
Files: 137
Total size: 3.3 MB
Directory structure:
gitextract_kv1kv1do/
├── .editorconfig
├── .github/
│ └── workflows/
│ └── jekyll-gh-pages.yml
├── .gitignore
├── .npmignore
├── .prettierignore
├── .prettierrc
├── LICENSE.txt
├── README.md
├── README_CN.md
├── changelog.md
├── dev-watch.sh
├── docs/
│ ├── Gemfile
│ ├── README.md
│ ├── _config.yml
│ ├── _site/
│ │ ├── api-integration/
│ │ │ └── index.html
│ │ ├── assets/
│ │ │ ├── css/
│ │ │ │ ├── just-the-docs-dark.css
│ │ │ │ ├── just-the-docs-default.css
│ │ │ │ ├── just-the-docs-head-nav.css
│ │ │ │ └── just-the-docs-light.css
│ │ │ └── js/
│ │ │ ├── just-the-docs.js
│ │ │ └── search-data.json
│ │ ├── bundle-analysis/
│ │ │ └── index.html
│ │ ├── bundle-analysis.md
│ │ ├── components/
│ │ │ └── index.html
│ │ ├── configuration/
│ │ │ └── index.html
│ │ ├── customization/
│ │ │ └── index.html
│ │ ├── daterangepicker-fix/
│ │ │ └── index.html
│ │ ├── daterangepicker-fix.md
│ │ ├── deployment/
│ │ │ └── index.html
│ │ ├── feed.xml
│ │ ├── index.html
│ │ ├── installation/
│ │ │ └── index.html
│ │ ├── jquery-elimination-complete/
│ │ │ └── index.html
│ │ ├── jquery-elimination-complete.md
│ │ ├── robots.txt
│ │ ├── security-headers/
│ │ │ └── index.html
│ │ ├── security-headers.md
│ │ └── sitemap.xml
│ ├── api-integration.md
│ ├── bundle-analysis.md
│ ├── components.md
│ ├── configuration.md
│ ├── customization.md
│ ├── deployment.md
│ ├── index.md
│ ├── installation.md
│ ├── jquery-elimination-complete.md
│ ├── performance.md
│ └── security-headers.md
├── eslint.config.js
├── package.json
├── production/
│ ├── calendar.html
│ ├── chartjs.html
│ ├── contacts.html
│ ├── e_commerce.html
│ ├── echarts.html
│ ├── fixed_footer.html
│ ├── fixed_sidebar.html
│ ├── form.html
│ ├── form_advanced.html
│ ├── form_buttons.html
│ ├── form_upload.html
│ ├── form_validation.html
│ ├── form_wizards.html
│ ├── general_elements.html
│ ├── icons.html
│ ├── inbox.html
│ ├── index.html
│ ├── index2.html
│ ├── index3.html
│ ├── index4.html
│ ├── invoice.html
│ ├── landing.html
│ ├── level2.html
│ ├── login.html
│ ├── map.html
│ ├── media_gallery.html
│ ├── other_charts.html
│ ├── page_403.html
│ ├── page_404.html
│ ├── page_500.html
│ ├── plain_page.html
│ ├── pricing_tables.html
│ ├── profile.html
│ ├── project_detail.html
│ ├── projects.html
│ ├── tables.html
│ ├── tables_dynamic.html
│ ├── theme-comparison.html
│ ├── typography.html
│ └── widgets.html
├── public/
│ └── site.webmanifest
├── src/
│ ├── chart-initializer.js
│ ├── js/
│ │ ├── helpers/
│ │ │ └── smartresize.js
│ │ ├── init.js
│ │ ├── page/
│ │ │ └── index3-analytics.js
│ │ └── sidebar.js
│ ├── main-calendar.js
│ ├── main-core.js
│ ├── main-form-basic.js
│ ├── main-inbox.js
│ ├── main-minimal.js
│ ├── main-tables.js
│ ├── main-upload.js
│ ├── main.scss
│ ├── modules/
│ │ ├── chart-core.js
│ │ ├── charts.js
│ │ ├── dashboard-pages.js
│ │ ├── dashboard.js
│ │ ├── echarts.js
│ │ ├── forms.js
│ │ ├── maps.js
│ │ ├── tables.js
│ │ ├── ui-components.js
│ │ └── weather.js
│ ├── scss/
│ │ ├── _color-schemes.scss
│ │ ├── _variables-modern.scss
│ │ ├── _variables.scss
│ │ ├── custom.scss
│ │ ├── daterangepicker.scss
│ │ ├── font-optimization.scss
│ │ ├── index2.scss
│ │ ├── index4.scss
│ │ └── landing.scss
│ ├── test/
│ │ └── setup.js
│ └── utils/
│ ├── dom.js
│ ├── dom.test.js
│ ├── logger.js
│ ├── logger.test.js
│ ├── security.js
│ ├── security.test.js
│ ├── table-optimizer.js
│ ├── validation.js
│ └── validation.test.js
├── tests/
│ └── README.md
├── vite.config.js
└── vitest.config.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
# EditorConfig helps maintain consistent coding styles for multiple developers
# working on the same project across various editors and IDEs
# See https://editorconfig.org
root = true
# Unix-style newlines with a newline ending every file
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
# JavaScript files
[*.{js,mjs,jsx,ts,tsx}]
indent_style = space
indent_size = 2
max_line_length = 100
# JSON files
[*.{json,jsonc}]
indent_style = space
indent_size = 2
# HTML files
[*.html]
indent_style = space
indent_size = 2
max_line_length = 120
# CSS/SCSS files
[*.{css,scss,sass}]
indent_style = space
indent_size = 2
max_line_length = 120
# Markdown files
[*.{md,mdx}]
indent_style = space
indent_size = 2
trim_trailing_whitespace = false
max_line_length = 120
# YAML files
[*.{yml,yaml}]
indent_style = space
indent_size = 2
# Package.json - use 2 spaces
[package.json]
indent_style = space
indent_size = 2
# Makefiles - use tabs
[Makefile]
indent_style = tab
# Batch files
[*.{bat,cmd}]
end_of_line = crlf
================================================
FILE: .github/workflows/jekyll-gh-pages.yml
================================================
# Build and deploy Jekyll documentation site to GitHub Pages
name: Deploy Documentation to GitHub Pages
on:
push:
branches: ["master"]
paths:
- 'docs/**'
- '.github/workflows/jekyll-gh-pages.yml'
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.3'
bundler-cache: true
working-directory: docs
- name: Setup Pages
uses: actions/configure-pages@v5
- name: Build with Jekyll
run: |
cd docs
bundle exec jekyll build --baseurl "/gentelella"
env:
JEKYLL_ENV: production
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: docs/_site
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
================================================
FILE: .gitignore
================================================
nbproject
npm-debug.log
node_modules
.sass-cache
CLAUDE.md
# Build outputs
dist/
# Vendor dependencies (generated from node_modules)
vendors/
bower_components/
# IDE files
.vscode/
.idea/
*.swp
*.swo
# OS files
.DS_Store
Thumbs.db
# Logs
*.log
JQUERY_PHASE_OUT_PLAN.md
COMPREHENSIVE_IMPROVEMENT_PLAN.md
release.md
JQUERY_ELIMINATION_PLAN.md
================================================
FILE: .npmignore
================================================
# Development files
.editorconfig
.prettierignore
.prettierrc
.github/
.claude/
eslint.config.js
vite.config.js
GITHUB_RELEASE_TEMPLATE.md
RELEASE_NOTES_2.1.0.md
# Documentation
docs/
README_CN.md
# Test files
tests/
production/debug-test.html
production/browser-test.html
production/csp-template.html
production/sidebar_test.html
# Build artifacts
dist/
*.tgz
# Other
.DS_Store
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
*.log
# Keep only essential files for npm package
================================================
FILE: .prettierignore
================================================
# Dependencies
node_modules/
# Build outputs
dist/
docs/_site/
# Generated files
*.min.js
*.min.css
package-lock.json
# Images and binary files
production/images/
*.jpg
*.jpeg
*.png
*.gif
*.svg
*.ico
# Logs
*.log
# Legacy files (to be cleaned up later)
production/*.html
================================================
FILE: .prettierrc
================================================
{
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"quoteProps": "as-needed",
"trailingComma": "none",
"bracketSpacing": true,
"bracketSameLine": false,
"arrowParens": "avoid",
"endOfLine": "lf",
"overrides": [
{
"files": "*.html",
"options": {
"printWidth": 120,
"tabWidth": 2
}
},
{
"files": "*.scss",
"options": {
"printWidth": 120,
"singleQuote": false
}
}
]
}
================================================
FILE: LICENSE.txt
================================================
The MIT License (MIT)
Copyright (c) 2025 Aigars Silkalns & Colorlib
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: README.md
================================================
# Gentelella Admin Template
**Modern Bootstrap 5 Admin Dashboard Template with Vite Build System**
Gentelella is a powerful, free-to-use Bootstrap 5 admin template that has been completely modernized with Vite, performance optimizations, and the latest web technologies. This template provides a comprehensive foundation for building admin panels, dashboards, and back-end applications.
[](https://colorlib.com/polygon/gentelella/index.html)
**[View Live Demo](https://colorlib.com/polygon/gentelella/index.html)**
## What's New in v2.1.4 (Latest Release - January 13, 2026)
- **Go Pro Sidebar Link** - Premium templates promotion with UTM tracking
- **Sidebar Badge System** - Colorful Pro, Hot, New, and Updated badges
- **Avatar Redesign** - Colorful circular backgrounds with white icons
- **Progress Bar Fixes** - Fixed invisible progress bars across dashboards
- **Uppy File Upload** - Replaced Dropzone.js with modern Uppy uploader
- **Cross-Page Consistency** - Unified sidebar menu across all 33 template pages
### Previous Release: v2.1.3
- **Bootstrap Icons Integration** - Added Bootstrap Icons for modern, minimalist sidebar navigation
- **Header Navigation Rebuilt** - Proper Bootstrap 5 flexbox utilities for top navigation layout
- **Sidebar UI Improvements** - Centered collapsed logo, right-aligned chevron arrows
- **Code Quality & Cleanup** - Removed legacy jQuery files, standardized naming conventions
- **126 Unit Tests** - Comprehensive test coverage with Vitest framework
- **CSS Variables System** - New custom properties for easier theming
### Previous Release: v2.1.2
- **Comprehensive Dependency Updates** - All dependencies updated to their latest versions
- **Vite 7.3.1** - Latest build system with performance improvements
- **ESLint 9.39.2** - Updated linting with comprehensive browser globals configuration
- **Font Awesome 7.1.0** - Latest icon library
### Previous Release: v2.1.1
- **jQuery-Free Core System** - Complete main-core.js modernization with vanilla JavaScript
- **Brand-Consistent Favicon Suite** - Modern favicon system with comprehensive browser support
- **Perfect UI Alignment** - Precision vertical centering for navigation elements
- **Production-Ready Code** - Clean console output with professional debugging
- **Enhanced Mobile Experience** - Improved touch interactions and responsive behavior
- **Modern DOM Utilities** - Comprehensive jQuery-free DOM manipulation library
### Previous Major Release: v2.0.0
- **🚀 Vite Build System** - Lightning-fast development and optimized production builds
- **📦 Bootstrap 5.3.7** - Latest Bootstrap with modern design system
- **⚡ Performance Optimized** - 90% smaller initial bundle size with smart code splitting
- **🔧 Modern JavaScript** - ES6+ modules with dynamic imports
- **🎯 TypeScript Ready** - Full TypeScript support available
- **📱 Mobile First** - Responsive design optimized for all devices
- **🎨 Morris.js Eliminated** - Complete replacement with modern Chart.js
## 📊 Performance Improvements
- **Before**: 779 KB monolithic JavaScript bundle
- **After**: 79 KB initial load + smart chunk loading
- **Result**: **90% smaller initial bundle** with **40-70% faster page loads**
## Premium Dashboards from DashboardPack
Loved Gentelella? Supercharge your workflow with our premium templates on [DashboardPack](https://dashboardpack.com/?utm_source=github&utm_medium=readme&utm_campaign=gentelella) — built for production, backed by dedicated support.
<table>
<tr>
<td align="center" width="50%">
<a href="https://dashboardpack.com/theme-details/tailpanel/?utm_source=github&utm_medium=readme&utm_campaign=gentelella">
<img src="screenshots/tailpanel.png" alt="TailPanel — cutting-edge React admin dashboard styled with Tailwind CSS" width="100%">
</a>
<br>
<a href="https://dashboardpack.com/theme-details/tailpanel/?utm_source=github&utm_medium=readme&utm_campaign=gentelella"><strong>TailPanel</strong></a>
<br>
<sub>React + TypeScript + Tailwind CSS. 9 dashboards, dark/light themes, blazing fast with Vite.</sub>
</td>
<td align="center" width="50%">
<a href="https://dashboardpack.com/theme-details/admindek-html/?utm_source=github&utm_medium=readme&utm_campaign=gentelella">
<img src="screenshots/admindek.png" alt="Admindek — comprehensive Bootstrap 5 admin template with theme customizer" width="100%">
</a>
<br>
<a href="https://dashboardpack.com/theme-details/admindek-html/?utm_source=github&utm_medium=readme&utm_campaign=gentelella"><strong>Admindek</strong></a>
<br>
<sub>Bootstrap 5 + vanilla JS. 100+ components, theme customizer, RTL, 10 color palettes.</sub>
</td>
</tr>
<tr>
<td align="center" width="50%">
<a href="https://dashboardpack.com/theme-details/adminty-html-dashboard/?utm_source=github&utm_medium=readme&utm_campaign=gentelella">
<img src="screenshots/adminty.png" alt="Adminty — feature-packed Bootstrap admin with 160+ application pages" width="100%">
</a>
<br>
<a href="https://dashboardpack.com/theme-details/adminty-html-dashboard/?utm_source=github&utm_medium=readme&utm_campaign=gentelella"><strong>Adminty</strong></a>
<br>
<sub>Bootstrap 5. 160+ pages covering analytics, apps, forms, and data visualization.</sub>
</td>
<td align="center" width="50%">
<a href="https://dashboardpack.com/theme-details/architectui-dashboard-html-pro/?utm_source=github&utm_medium=readme&utm_campaign=gentelella">
<img src="screenshots/architectui.png" alt="ArchitectUI — full-stack admin UI system with 250+ integrated widgets" width="100%">
</a>
<br>
<a href="https://dashboardpack.com/theme-details/architectui-dashboard-html-pro/?utm_source=github&utm_medium=readme&utm_campaign=gentelella"><strong>ArchitectUI</strong></a>
<br>
<sub>Bootstrap 5. 250+ integrated widgets, plug-and-play architecture, 9 dashboards.</sub>
</td>
</tr>
<tr>
<td align="center" width="50%">
<a href="https://dashboardpack.com/theme-details/kero-jquery-html-dashboard-pro/?utm_source=github&utm_medium=readme&utm_campaign=gentelella">
<img src="screenshots/kero.png" alt="Kero — polished admin template with dual layout and Webpack integration" width="100%">
</a>
<br>
<a href="https://dashboardpack.com/theme-details/kero-jquery-html-dashboard-pro/?utm_source=github&utm_medium=readme&utm_campaign=gentelella"><strong>Kero</strong></a>
<br>
<sub>Bootstrap 5 + Webpack. Dual layout system (horizontal + sidebar), SASS customization.</sub>
</td>
<td align="center" width="50%">
<a href="https://dashboardpack.com/theme-details/cryptocurrency-dashboard/?utm_source=github&utm_medium=readme&utm_campaign=gentelella">
<img src="screenshots/cryptocurrency.png" alt="Cryptocurrency Dashboard — specialized admin for blockchain and token projects" width="100%">
</a>
<br>
<a href="https://dashboardpack.com/theme-details/cryptocurrency-dashboard/?utm_source=github&utm_medium=readme&utm_campaign=gentelella"><strong>Cryptocurrency Dashboard</strong></a>
<br>
<sub>Bootstrap. Specialized for blockchain projects, token sales, and crypto portfolio management.</sub>
</td>
</tr>
</table>
<p align="center">
<a href="https://dashboardpack.com/?utm_source=github&utm_medium=readme&utm_campaign=gentelella"><strong>Get Premium Templates on DashboardPack</strong></a>
</p>
## 🚀 Quick Start
### Prerequisites
- [Node.js](https://nodejs.org/) (v16 or higher)
- [npm](https://npmjs.com/) or [yarn](https://yarnpkg.com/)
### Installation
```bash
# Clone the repository
git clone https://github.com/puikinsh/gentelella.git
cd gentelella
# Install dependencies
npm install
# Start development server
npm run dev
# Build for production
npm run build
# Preview production build
npm run preview
```
### Development Commands
```bash
# Development with hot reload
npm run dev
# Production build with optimizations
npm run build
# Preview production build locally
npm run preview
```
## 🏗️ Project Structure
```
gentelella/
├── production/ # HTML templates and static assets
│ ├── *.html # 42 pre-built admin pages
│ └── images/ # Image assets
├── src/ # Source files
│ ├── main-core.js # Core essentials (79 KB, jQuery-free)
│ ├── main.scss # Styles entry point
│ ├── js/ # Custom JavaScript (modernized)
│ ├── scss/ # Custom SASS files
│ ├── utils/ # Modern utility libraries
│ │ └── dom-modern.js # jQuery-free DOM manipulation
│ └── modules/ # Feature-specific modules
│ ├── charts.js # Chart functionality (219 KB)
│ ├── forms.js # Form enhancements (200 KB)
│ ├── tables.js # DataTables functionality
│ └── dashboard.js # Dashboard widgets
├── dist/ # Production build output
├── vite.config.js # Vite configuration
└── package.json # Dependencies and scripts
```
## 🎯 Smart Loading System
The template uses intelligent code splitting with modern JavaScript:
- **Core Bundle** (79 KB): Essential libraries with jQuery-free DOM utilities
- **Chart Module** (219 KB): Only loads on pages with charts
- **Form Module** (200 KB): Only loads on pages with advanced forms
- **Table Module**: Only loads on pages with DataTables
- **Dashboard Module**: Only loads dashboard-specific widgets
## ⚡ Modern JavaScript Architecture
### jQuery-Free Core System
- **Vanilla JavaScript**: All core functionality uses modern DOM APIs
- **Dynamic Loading**: Intelligent module loading with caching and performance monitoring
- **Error Boundaries**: Robust error handling with development debugging tools
- **Loading States**: Visual indicators for better user experience
### DOM Utilities Library
- **Complete jQuery Replacement**: Full-featured DOM manipulation without dependencies
- **Animation Support**: Slide, fade, and custom animations using CSS transitions
- **Event Management**: Modern event handling with custom event support
- **Responsive Utilities**: Mobile-first responsive behavior management
## 📱 Responsive Design
Built with mobile-first approach:
- **Phones**: Optimized touch interfaces
- **Tablets**: Adaptive layouts
- **Desktops**: Full-featured experience
- **Large Screens**: Enhanced productivity layouts
## 🛠️ Customization
### Adding New Pages
1. Create HTML file in `production/` directory
2. Add entry to `vite.config.js` input configuration
3. Reference appropriate modules for functionality needed
### Custom Styling
```scss
// src/scss/custom.scss
.my-custom-component {
// Your custom styles
}
```
### Color Schemes (2026 Modern Collection)
Gentelella includes 10 professionally designed color schemes that users can switch between at runtime. Each theme is carefully crafted for accessibility and modern aesthetics.
#### Available Themes
| Theme | Primary Color | Description | Best For |
| ------------- | ------------------- | ---------------------- | -------------------------- |
| **Default** | Emerald `#10b981` | Modern emerald green | General purpose |
| **Ocean** | Sky `#0ea5e9` | Deep blue professional | Corporate, enterprise |
| **Sunset** | Orange `#f97316` | Warm coral/orange | Creative, marketing |
| **Lavender** | Violet `#8b5cf6` | Soft purple/violet | Design tools, SaaS |
| **Forest** | Green `#22c55e` | Natural green tones | Health, environmental |
| **Midnight** | Cyan `#22d3ee` | Dark mode optimized | Developer tools, night use |
| **Rose** | Pink `#ec4899` | Modern pink/magenta | Fashion, lifestyle |
| **Slate** | Slate `#64748b` | Neutral monochrome | Content-focused apps |
| **Indigo** | Indigo `#6366f1` | Classic tech blue | Tech, productivity |
| **Teal** | Teal `#14b8a6` | Calming teal | Healthcare, wellness |
#### Usage
##### HTML Attribute (Recommended)
```html
<html data-theme="ocean">
```
##### CSS Class
```html
<body class="theme-ocean">
```
##### JavaScript Theme Switcher
```javascript
// Set theme
function setTheme(themeName) {
document.documentElement.setAttribute('data-theme', themeName);
localStorage.setItem('theme', themeName);
}
// Load saved theme on page load
function loadTheme() {
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
document.documentElement.setAttribute('data-theme', savedTheme);
}
}
// Initialize
loadTheme();
// Switch to ocean theme
setTheme('ocean');
```
##### Theme Selector Dropdown Example
```html
<select onchange="setTheme(this.value)">
<option value="">Default (Emerald)</option>
<option value="ocean">Ocean</option>
<option value="sunset">Sunset</option>
<option value="lavender">Lavender</option>
<option value="forest">Forest</option>
<option value="midnight">Midnight (Dark)</option>
<option value="rose">Rose</option>
<option value="slate">Slate</option>
<option value="indigo">Indigo</option>
<option value="teal">Teal</option>
</select>
```
### Adding Features
```javascript
// Load modules conditionally
if (document.querySelector('.chart-container')) {
const charts = await loadModule('charts');
}
```
### Modern Favicon System
The template includes a comprehensive favicon suite optimized for 2025 standards:
- **SVG-first approach** - Sharp display across all devices and screen densities
- **Apple Touch Icon** - Optimized for iOS devices and web apps
- **Android Chrome Icons** - PWA-ready with multiple sizes (192x192, 512x512)
- **Legacy ICO support** - Fallback for older browsers
- **Web App Manifest** - Complete PWA integration with theme colors
## 📦 Available Components
### Dashboard Features
- **Multiple Dashboard Layouts** - 3 different dashboard designs
- **Widgets** - Various dashboard widgets and cards
- **Charts** - Chart.js, ECharts, Sparklines integration
- **Maps** - Interactive world maps with jVectorMap
### Form Components
- **Advanced Forms** - Multi-step wizards, validation
- **Form Elements** - Rich text editors, date pickers
- **File Upload** - Drag & drop file upload with progress
- **Input Enhancements** - Autocomplete, tags, switches
### UI Elements
- **Tables** - DataTables with sorting, filtering, pagination
- **Typography** - Comprehensive typography system
- **Icons** - Font Awesome 7 + Bootstrap Icons
- **Media Gallery** - Image gallery with lightbox
- **Calendar** - Full-featured calendar component
### Additional Pages
- **E-commerce** - Product listings, shopping cart
- **User Management** - Profiles, contacts, projects
- **Authentication** - Login, registration pages
- **Error Pages** - 403, 404, 500 error pages
## 🎨 Built With
### Core Technologies
- **🚀 Vite 7.0.6** - Ultra-fast ES module build system with 90% smaller bundle size
- **📦 Bootstrap 5.3.6** - Latest Bootstrap with modern design system
- **🎨 SASS Modules** - Modern CSS architecture with custom theme variables
- **⚡ Vanilla JavaScript** - Modern DOM APIs with jQuery-free core system
- **🔧 Modern DOM Utilities** - Custom library for jQuery-free DOM manipulation
### Charts & Visualization
- **Chart.js 4.4.2** - Modern charting library (Morris.js completely removed)
- **ECharts 5.6.0** - Professional data visualization
- **Sparklines** - Mini charts and graphs
- **jVectorMap** - Interactive world maps
### Form & UI Libraries
- **Select2** - Enhanced select dropdowns
- **Tempus Dominus** - Bootstrap 5 date/time picker
- **Ion Range Slider** - Range slider component
- **Switchery** - iOS-style toggle switches
- **DataTables** - Advanced table functionality
### Utilities
- **Day.js** - Lightweight date library
- **NProgress** - Progress bars for page loading
- **Autosize** - Auto-resizing textareas
- **Font Awesome 7 + Bootstrap Icons** - Icon libraries
## 🔧 Configuration
### Vite Configuration
The template includes optimized Vite configuration with:
- Smart code splitting for optimal loading
- Asset optimization with cache-busting
- Development server with hot reload
- Production builds with compression
### Performance Features
- **Tree Shaking** - Removes unused code
- **Code Splitting** - Loads only what's needed
- **Caching Strategy** - Optimized for browser caching
## 🚀 Deployment
### Build for Production
```bash
npm run build
```
### Deploy to Various Platforms
- **Netlify**: Drag and drop the `dist` folder
- **Vercel**: Connect your GitHub repository
- **GitHub Pages**: Use the built-in GitHub Actions
- **Traditional Hosting**: Upload `dist` folder contents
## 🤝 Contributing
We welcome contributions! To contribute:
1. **Fork** the repository
2. **Create** a feature branch (`git checkout -b feature/amazing-feature`)
3. **Commit** your changes (`git commit -m 'Add amazing feature'`)
4. **Push** to the branch (`git push origin feature/amazing-feature`)
5. **Open** a Pull Request
### Development Setup
```bash
git clone https://github.com/your-username/gentelella.git
cd gentelella
npm install
npm run dev
```
## 📚 Documentation & Demo
- **[Live Demo](https://colorlib.com/polygon/gentelella/index.html)** - See the template in action
- **[Component Documentation](https://colorlibhq.github.io/gentelella/)** - Detailed component guide
- **[Performance Guide](PERFORMANCE_OPTIMIZATIONS.md)** - Optimization details
- **[Componentization Plan](COMPONENTIZATION_GAMEPLAN.md)** - Future modularization
## 💼 Showcase Your Work
We would love to see how you use this awesome admin template. You can notify us about your site, app or service by tweeting to [@colorlib](https://twitter.com/colorlib). Once the list grows long enough we will write a post similar to [this showcase](https://colorlib.com/wp/avada-theme-examples/) to feature the best examples.
## 📦 Installation via Package Managers
```bash
# npm
npm install gentelella --save
# yarn
yarn add gentelella
# bower (legacy)
bower install gentelella --save
```
## 🌍 Community Integrations
Gentelella has been integrated into various frameworks:
- **[Rails](https://github.com/mwlang/gentelella-rails)** - Ruby on Rails integration
- **[Laravel](https://github.com/Labs64/laravel-boilerplate)** - PHP Laravel boilerplate
- **[Django](https://github.com/GiriB/django-gentelella)** - Python Django app
- **[Angular](https://github.com/kmkatsma/angular2-webpack-starter-gentelella)** - Angular integration
- **[React](https://github.com/thomaslwq/react-admin)** - React implementation
- **[Symfony](https://github.com/mamless/Gentella-admin-Symfony-6)** - Symfony 6 integration
- **[Yii](https://github.com/yiister/yii2-gentelella)** - Yii framework integration
- **[Flask](https://github.com/afourmy/flask-gentelella)** - Python Flask app
- **[CakePHP](https://github.com/backstageel/cakephp-gentelella-theme)** - CakePHP integration
- **[Aurelia](https://github.com/kmkatsma/aurelia-gentelella)** - Aurelia TypeScript integration
- **[Gentelella RTL](https://github.com/mortezakarimi/gentelella-rtl)** - Right-to-left language support
Let us know if you have done integration for this admin template on other platforms and frameworks and we'll be happy to share your work.
## 🎨 Other Templates and Resources by Colorlib
- **[Free Bootstrap Admin Templates](https://colorlib.com/wp/free-bootstrap-admin-dashboard-templates/)** - Collection of the best free Bootstrap admin dashboard templates
- **[Free Admin Templates](https://colorlib.com/wp/free-html5-admin-dashboard-templates/)** - Comprehensive list of free HTML5 admin dashboard templates
- **[Angular Templates](https://colorlib.com/wp/angularjs-admin-templates/)** - Popular admin templates based on Angular
- **[WordPress Admin Templates](https://colorlib.com/wp/wordpress-admin-dashboard-themes-plugins/)** - WordPress admin dashboard templates and plugins
- **[WordPress Themes](https://colorlib.com/wp/free-wordpress-themes/)** - Large selection of free WordPress themes
- **[Colorlib Blog](https://colorlib.com/)** - Web design and development resources
## 📄 License
Gentelella is licensed under **The MIT License (MIT)**. You can use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software.
**Attribution Required**: [Colorlib](https://colorlib.com/) must be credited as the original author.
## 👥 Maintainers
- **[Colorlib](https://colorlib.com/)** - Original design and development
- **[Aigars Silkalns](https://github.com/silkalns)** - Lead developer and maintainer
## 🙏 Acknowledgments
- Bootstrap team for the amazing CSS framework
- All contributors who have helped improve this template
- The open-source community for the excellent libraries
---
**Made with ❤️ by [Colorlib](https://colorlib.com/)**
================================================
FILE: README_CN.md
================================================
# gentelella
Gentelella 管理后台是一个免费使用的Bootstrap管理模版。
这个模版默认使用Bootstrap 3 风格,还有一系列强大的jQuery插件和工具去创造一个强大的框架,用来创建管理面板或者后端仪表盘。
该主题使用了不同的库,用来创建表格,日历,表单验证,引导式风格的接口,导航菜单,文本表格,日期范围,上传区域,表格自动填充,范围滑块,进度条,提示以及更多。
我们很乐意看到你使用这个令人惊叹的管理模版。你可以通过tweet [@colorlib](https://twitter.com/colorlib)告知我们你的网站,app或者服务。一旦列表量够了,我们将会写一篇文章去展示这个最佳案例[this](https://colorlib.com/wp/avada-theme-examples/)。
## 主题例子

**[模版例子](https://colorlib.com/polygon/gentelella/index.html)**
## 文档
**[文档](https://puikinsh.github.io/gentelella/)**
## 通过Package Manager安装
我们的目标是使它在不同的包管理器中都可以安装!你有你倾向使用的包管理器还有你知道为什么吗?随时随地通过pull request告诉我们!
现在这是一些可以安装的包管理器:
**Bower**
```
bower install gentelella --save
```
**npm**
```
npm install gentelella --save
```
**yarn**
```
yarn add gentelella
```
## 如何贡献
为了贡献,请确保你安装有稳定的 [Node.js](https://nodejs.org/) 和[npm](https://npmjs.com)
测试Gulp CLI 是否安装,可以运行`gulp --version`.如果命令行没有找到,运行`npm install -g gulp`。关于更多如何安装Gulp,可以看一下Gulp的使用指南[Getting Started](https://github.com/gulpjs/gulp/blob/master/docs/getting-started.md)。
安装所有的gulp依赖,可以运行```npm install```
如果`gulp` 已经安装了,遵循一下的步骤。
1. Fork和克隆这个仓库
2. 运行`gulp`,会在你的默认浏览器中运行 gentelella 。
3. 现在你可以开始写代码了!
4. 提交一个pull request
## Gentelella 在其它平台和框架
* [Gentelella on Ruby on Rails 4](https://github.com/iogbole/gentelella_on_rails) thanks to Israel Ogbole.
* [Gentelella on Rails 5.x](https://github.com/mwlang/gentelella-rails) thanks to Michael Lang
* [Gentelella on Smarty 3](https://github.com/microvb/otp-thing) with one time password generator, validator, and QR code generator that has no web dependencies (self-contained) in PHP thanks to MicroVB INC
* [Gentelella integrated into Symfony 3](https://github.com/krzysiekpiasecki/Gentelella) full stack PHP framework thanks to Krzysztof Piasecki.
* [Gentelella on Yii framework 2](https://github.com/yiister/yii2-gentelella) with an asset bundle, a layout template and some widgets.
* [Gentelella on Angular 2](https://github.com/kmkatsma/angular2-webpack-starter-gentelella) Angular Webpack Starter modified to utilize the Gentelella.
* [Gentelella on Aurelia](https://github.com/kmkatsma/aurelia-gentelella) Typescript webpack skeleton modified to utilize the Gentelella.
* [Gentelella on Laravel](https://github.com/Labs64/laravel-boilerplate) PHP / Laravel 5 boilerplate project with Gentelella Admin theme support.
* [Gentelella on Django](https://github.com/GiriB/django-gentelella) Gentelella modified to fit as a Django app
* [Gentelella on Flask](https://github.com/afourmy/flask-gentelella) Gentelella modified to fit as a Flask app
* [Gentelella on CakePHP 3](https://github.com/backstageel/cakephp-gentelella-theme) Gentelella modified to work on CakePHP
* [Gentelella right to left](https://github.com/mortezakarimi/gentelella-rtl) Gentelella modified to work with right to left languages like Persian
* [Gentelella-rtl on Yii framework 2](https://github.com/mortezakarimi/yii2-gentelella-rtl) with an asset bundle, a layout template and some widgets. inspired from [Gentelella on Yii framework 2](https://github.com/yiister/yii2-gentelella)
让我们知道你是否为其它管理模版或者平台、框架集成了Gentelella,我们会很乐意分享你的工作。
## Scripts 包括:
* Bootstrap
* Font Awesome
* jQuery-Autocomplete
* FullCalendar
* Charts.js
* Bootstrap Colorpicker
* Cropper
* dataTables
* Date Range Picker for Bootstrap
* Dropzone
* easyPieChart
* ECharts
* bootstrap-wysiwyg
* Flot - Javascript plotting library for jQuery.
* gauge.js
* jquery.inputmask plugin
* Ion.RangeSlider
* jQuery
* jVectorMap
* moment.js
* Chart.js - 现代响应式图表
* PNotify - Awesome JavaScript notifications
* NProgress
* Pace
* Parsley
* bootstrap-progressbar
* select2
* Sidebar Transitions - simple off-canvas navigations
* Skycons - canvas based wather icons
* jQuery Sparklines plugin
* switchery - Turns HTML checkbox inputs into beautiful iOS style switches
* jQuery Tags Input Plugin
* Autosize - resizes text area to fit text
* validator - HTML from validator using jQuery
* jQuery Smart Wizard
## 其它模版和有用的资源
* [Free Bootstrap Admin Templates](https://colorlib.com/wp/free-bootstrap-admin-dashboard-templates/ "Bootstrap Admin Templates on Colorlib") - List of the best Free Bootstrap admin dashboard templates that are available for free for personal and commercial use.
* [Free Admin Templates](https://colorlib.com/wp/free-html5-admin-dashboard-templates/ "List of free HTML based admin templates by Colorlib") - Long list of the best free HTML5 powered admin dashboard templates. Available for personal and commercial use.
* [Angular Templates](https://colorlib.com/wp/angularjs-admin-templates/ "Angular Admin Templates on Colorlib") - List of the most popular admin templates based on AngularJS.
* [HTML Admin Templates](https://colorlib.com/wp/html-admin-templates/ "Material Design Admin Templates on Colorlib") - Most of these templates are based on AngularJS and uses a stunning Material design.
* [Bootstrap Admin Templates](https://colorlib.com/wp/bootstrap-admin-templates/ "List of Premium Bootstrap Admin Templates by Colorlib") - List of premium Bootstrap admin templates that uses a minimal flat or material design. Majority of these themes uses AngularJS but HTML5 versions are also available.
* [WordPress Admin Templates](https://colorlib.com/wp/wordpress-admin-dashboard-themes-plugins/ "List of WordPress Admin Dashboard Templates and Plugins by Colorlib") - List of the best WordPress admin dashboard templates and plugins that will add a personal touch to your WordPress dashboard.
* [WordPress Themes](https://colorlib.com/wp/free-wordpress-themes/ "List of Free WordPress themes by Colorlib") - A huge selection of the best free WordPress themes that are all licensed under GPL and are available for personal and commercial use without restrictions.
## License information
Gentelella is licensed under The MIT License (MIT). Which means that you can use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software. But you always need to state that Colorlib is the original author of this template.
Project is developed and maintained by [Colorlib](https://colorlib.com/ "Colorlib - Make Your First Blog") and Aigars Silkalns
================================================
FILE: changelog.md
================================================
# Gentelella Changelog
## 2.1.5 - 15.02.2026
**Documentation Overhaul & jQuery Cleanup Release**
### Documentation Site Fixes
- **GitHub Pages Deployment**: Fixed broken Jekyll documentation site at colorlibhq.github.io/gentelella
- Rewrote GitHub Actions workflow to build from `docs/` directory instead of repo root
- Bumped Ruby from 3.1 to 3.3 to resolve Bundler compatibility failure
- Fixed base URL from `puikinsh.github.io` to `colorlibhq.github.io`
- Removed orphaned `docs/.github/workflows/pages.yml` (GitHub only discovers workflows at repo root)
- **Fixed All Broken Documentation Links**: Resolved 17 broken cross-links across 6 documentation files
- Removed incorrect `/docs/` prefix from internal links site-wide
- Replaced references to non-existent pages (security.md, testing.md, monitoring.md, examples.md) with valid targets
- **New Documentation Pages**:
- Created `docs/performance.md` - Performance optimization guide with code splitting strategy and bundle analysis
- Added Jekyll front matter to `bundle-analysis.md`, `jquery-elimination-complete.md`, `security-headers.md`
### Documentation Content Updates
- **Updated All Dependency Versions**: Aligned documentation with actual package.json versions
- Vite 6.3.5 → 7.3.1, Bootstrap 5.3.7 → 5.3.8, Node.js v16 → v18
- Removed references to eliminated libraries: jQuery, Morris.js, Select2, jVectorMap, Gauge.js, Ion.RangeSlider
- Updated code examples: Select2 → Choices.js, Morris.js → ECharts, jVectorMap → Leaflet
- Corrected `manualChunks` configuration examples in configuration.md and deployment.md
### jQuery Reference Cleanup
- **Removed All Stale jQuery References**: Template is fully jQuery-free
- Updated HTML comments in 17 production files: "includes jQuery, Bootstrap, and all vendor scripts" → "Bootstrap and vendor scripts"
- Fixed outdated `$().DataTable()` reference in tables_dynamic.html to modern `new DataTable('#myTable')`
- Renamed "jQuery Smart Wizard" SCSS section comments to "Smart Wizard"
### Page Identifiers
- **Added `page-*` Body Classes**: All 24 pages missing identifiers now have proper `page-*` body classes for CSS targeting
- Enables page-specific styling via `body.page-calendar`, `body.page-form-wizards`, etc.
- Documented complete reference table in CLAUDE.md
### Cleanup
- Deleted orphaned documentation files: `BOOTSTRAP_MIGRATION_GUIDE.md`, `daterangepicker-fix.md`
- Deleted stale release files: `JQUERY_ELIMINATION_PLAN.md`, `RELEASE_v2.1.4.md`
---
## 2.1.4 - 13.01.2026
**UI Polish & Navigation Enhancement Release**
### New Features
- **Go Pro Sidebar Link**: Added prominent "Go Pro" menu item linking to DashboardPack premium templates
- Positioned at top of sidebar for visibility
- Includes UTM tracking for analytics
- Opens in new tab for seamless user experience
- **Sidebar Badge System**: Introduced colorful badges throughout sidebar navigation
- "Pro" badge (yellow) on Go Pro link
- "Hot" badge (red) on UI Elements menu
- "New" badge (green) on Data Presentation menu
- "Updated" badge (blue) on ECharts and Landing Page items
- Consistent 52px width across all badges with right alignment
### UI/UX Improvements
- **Avatar/Profile Thumbnails**: Redesigned profile icons in activity feeds
- Colorful circular backgrounds (aero, green, blue, purple, orange, red)
- White icons for better contrast and modern look
- Flexbox centering for perfect alignment
- **Progress Bar Fixes**: Fixed invisible progress bars across dashboard pages
- Added proper background color to `.progress` container
- Removed conflicting CSS variable override that was zeroing out widths
- Consistent 8px height with rounded corners
- **Spacing Consistency**: Removed extra `<br>` tag causing uneven card spacing on index.html
### File Upload Modernization
- **Uppy Integration**: Replaced legacy Dropzone.js with modern Uppy file uploader
- Drag & drop support with visual feedback
- Image preview thumbnails
- Progress indicators for uploads
- Cleaner, more maintainable codebase
### Cross-Page Consistency
- **Unified Sidebar Menu**: All 33 HTML template pages now share identical sidebar navigation
- Consistent menu structure and badges across all pages
- Improved user experience when navigating between pages
### Code Quality
- **Removed Inline CSS**: Cleaned up inline styles, moved to proper SCSS files
- **SCSS Organization**: Consolidated badge and progress bar styles
---
## 2.1.3 - 12.01.2026
**Code Quality, Naming Standardization & UI Modernization Release**
### UI Modernization
- **Bootstrap Icons Integration**: Added Bootstrap Icons as alternative to Font Awesome
- Installed `bootstrap-icons` package (v1.13.1)
- Sidebar navigation now uses thinner, more modern Bootstrap Icons
- Icon mappings: `fa-home` → `bi-house`, `fa-edit` → `bi-pencil-square`, `fa-desktop` → `bi-display`, etc.
- All 35 HTML files updated with new icon classes
- **Header Navigation Fixes**: Rebuilt top navigation using proper Bootstrap 5 flexbox utilities
- Uses `d-flex`, `align-items-center`, `justify-content-between`, `ms-auto`, `gap-3` classes
- Dropdown order corrected: notifications first, then user profile
- Dropdown menus widened (320px for notifications, 200px for user profile)
- Proper `dropdown-menu-end` alignment for right-side dropdowns
- **Sidebar Improvements**:
- Hamburger menu properly positioned for both expanded (230px) and collapsed (70px) sidebar states
- Logo icon centered in collapsed sidebar mode using flexbox
- Chevron arrows positioned to right side of menu items with `margin-left: auto`
### Code Cleanup
- **Removed Legacy Files**: Deleted orphaned jQuery-based files no longer in use
- `src/js/examples.js` - Legacy jQuery popover and Flot chart examples
- `src/js/form-validation-init.js` - Unused validation demo file
- `src/main.js` - Legacy full jQuery bundle
- `src/main-minimal.js` (old) - Legacy jQuery minimal bundle
- `src/main-form-advanced.js` - Unreferenced form entry point
- `src/main-form-basic-simple.js` - Orphaned stub file
- `src/js/require-shim.js` - Legacy CommonJS shim
### Naming Standardization
- **Removed "-modern" suffixes**: Standardized file naming throughout the codebase
- `dom-modern.js` → `dom.js`
- `sidebar-modern.js` → `sidebar.js`
- `init-modern.js` → `init.js`
- `smartresize-modern.js` → `smartresize.js`
- `tables-modern.js` → `tables.js`
- `echarts-modern.js` → `echarts.js`
- `main-minimal-modern.js` → `main-minimal.js`
### New Features
- **Test Suite**: Added comprehensive unit testing infrastructure
- Vitest testing framework with JSDOM environment
- 126 unit tests covering all utility modules
- Test coverage for security.js, validation.js, dom.js, logger.js
- New npm scripts: `test`, `test:watch`, `test:coverage`
- **Logger Utility**: Added centralized development-only logging (`src/utils/logger.js`)
- Wraps console methods with environment checks
- Automatic suppression in production builds
- Group logging support for better debugging
- **CSS Variables System**: Added comprehensive CSS custom properties (`src/scss/_variables.scss`)
- Brand colors, semantic colors, neutral palette
- Spacing, typography, shadows, transitions
- Z-index scale and border radius tokens
### Bundle Optimization
- **Removed Unused Dependencies**: Eliminated dead weight from bundle
- Removed `flot` (4.2 MB package, never imported)
- Removed `moment` (67 KB, dayjs already used as lightweight alternative)
- **Smart Chunk Splitting**: Optimized vendor chunks for better caching
- Split Chart.js (203 KB) and ECharts (1,109 KB) into separate chunks
- Pages using only Chart.js now save ~1 MB vs loading both
- Added `vendor-calendar` chunk for FullCalendar (256 KB)
- Extended `vendor-tables-ext` to include all DataTables extensions
- **Production Build Optimization**
- Disabled CSS source maps in production (saves ~8 MB build size)
- Enhanced Terser compression with `pure_getters`, `reduce_vars`, `collapse_vars`
- 3-pass minification for additional size reduction
### SCSS Improvements
- **Fixed Color Inconsistencies**: Resolved `.aero` color class conflict between files
- **Improved Organization**: Added table of contents to custom.scss for navigation
### Bootstrap 5 Consolidation (Migration Phase 1-3)
- **CSS Variables Integration**: Replaced ~90 hardcoded color values with CSS custom properties
- Primary colors (#1abb9c, #2a3f54, #e74c3c, etc.) now use `var(--gt-*)` references
- Enables easier theming and dark mode support
- **Reduced !important Declarations**: Cut from 278 to 138 (50% reduction)
- Sidebar toggle states now use `body.nav-md`/`body.nav-sm` for specificity
- Typography hierarchy uses body prefix instead of !important
- Profile and panel sections modernized
- **Bootstrap Collapse Integration**: Panel toolbox now uses Bootstrap 5's Collapse API
- Collapse/expand functionality leverages native Bootstrap component
- Automatic icon rotation via collapse events
- Removed dependency on custom slideUp/slideDown for panels
- **Float to Flexbox Conversion**: Modernized key layout sections
- `.profile` section uses flexbox instead of float
- `.x_title` panel header uses flexbox for title/filter alignment
- `.nav_menu` converted to flexbox layout
- Removed float from `.x_content`
- **Color Utility Documentation**: Added migration guide comments for legacy color classes
- Documents Bootstrap equivalents (.blue → .text-info, .bg-green → .bg-success)
- Classes kept for backward compatibility with existing HTML
### Documentation Updates
- Updated CLAUDE.md with new file structure and renamed modules
- Updated directory layout to reflect cleaned-up architecture
---
## 2.1.2 - 12.01.2026
Maintenance Release - Comprehensive Dependency Updates
### Dependency Updates
All dependencies updated to their latest versions for improved security, performance, and compatibility.
#### Dev Dependencies
- **Vite** 7.1.5 → 7.3.1 (build system improvements)
- **ESLint** 9.35.0 → 9.39.2 (linting engine)
- **@eslint/js** 9.35.0 → 9.39.2
- **@typescript-eslint/eslint-plugin** 8.43.0 → 8.52.0
- **@typescript-eslint/parser** 8.43.0 → 8.52.0
- **TypeScript** 5.9.2 → 5.9.3
- **Prettier** 3.6.2 → 3.7.4 (code formatter)
- **SASS** 1.92.1 → 1.97.2 (CSS preprocessor)
- **Terser** 5.44.0 → 5.44.1 (JS minifier)
- **glob** 11.0.3 → 13.0.0 (major version upgrade)
- **rollup-plugin-visualizer** 6.0.3 → 6.0.5
#### Runtime Dependencies
- **Font Awesome** 7.0.1 → 7.1.0 (icon library)
- **FullCalendar** 6.1.19 → 6.1.20 (all packages)
- **Chart.js** 4.5.0 → 4.5.1
- **CropperJS** 2.0.1 → 2.1.0
- **DataTables** 2.3.4 → 2.3.6 (core and BS5 styling)
- **DataTables Buttons** 3.2.5 → 3.2.6
- **DataTables FixedHeader** 4.0.3 → 4.0.5
- **DataTables KeyTable** 2.12.1 → 2.12.2
- **DataTables Responsive** 3.0.6 → 3.0.7
- **Day.js** 1.11.18 → 1.11.19
- **DOMPurify** 3.2.6 → 3.3.1 (security library)
### Code Quality Improvements
- **ESLint Configuration**: Added comprehensive browser globals to eliminate false-positive errors
- Added all standard browser APIs (setTimeout, fetch, localStorage, etc.)
- Added DOM interfaces (HTMLElement, Event, CustomEvent, etc.)
- Added library globals (TempusDominus, Skycons, DataTable, etc.)
- **Bug Fix**: Fixed parsing error in main-form-advanced.js (incomplete console statement)
### Known Issues
- Sass deprecation warnings in build output are from Bootstrap's internal SCSS files and will be resolved in future Bootstrap releases
- All functionality tested and verified working with updated dependencies
---
## 2.1.1 - 11.09.2025
**Maintenance Release - Dependency Updates, Chart Fixes & UI Improvements**
### Dependency Updates
- **Latest Dependencies**: All dependencies updated to latest versions for security and performance
- Vite 7.1.4 → 7.1.5
- Bootstrap 5.3.6 → 5.3.8
- ECharts 5.6.0 → 6.0.0 (major version upgrade)
- Chart.js 4.4.2 → 4.5.0
- jQuery 3.6.1 → 3.7.1
- TypeScript 5.8.3 → 5.9.2
- ESLint 9.34.0 → 9.35.0
- SASS 1.92.0 → 1.92.1
- DataTables 2.3.3 → 2.3.4 with all related packages
- Font Awesome 7.0.0 → 7.0.1
- **Security Updates**: Ruby 3.3.9 and Nokogiri 1.18.9 resolve all CVE vulnerabilities
### Chart & Widget Improvements
- **ECharts Functionality**: Fixed all missing charts on echarts.html page
- Added missing pyramid sales funnel chart with improved readability
- Fixed world map visualization
- Enhanced chart sizing and positioning
- **Widget System Enhancement**: Improved content density in widgets.html
- Enhanced metric cards with additional context information
- Added growth indicators and supplementary metrics
- Professional styling with hover effects and better typography
- **Chart Color Consistency**: Fixed Device Usage chart colors to match label indicators
- **Interactive Maps**: Fixed visitors location map and skycons weather icons on index.html
### UI/UX Improvements
- **Sidebar Profile Enhancement**: Improved sidebar name section for better scalability
- Reduced font size from default h4 to 14px for optimal space utilization
- Added proper typography with font-weight 400 and line-height 1.2
- Enhanced profile_info container with flexbox layout for better vertical centering
- Added word-wrapping and break-word support for long names
- Limited to 2.4em max-height to prevent sidebar expansion while allowing up to 2 lines
- Gracefully handles both short names and longer names without breaking layout
### Developer Experience
- **Dev Server Stability**: Fixed development server crashes with auto-restart capability
- Enhanced Vite configuration for better stability
- Added dev:watch script for automatic server restart
- Improved file watching and HMR reliability
- **Console Log Cleanup**: Production builds now clean with comprehensive console statement removal
- Enhanced Terser configuration for complete console removal
- Development-only console logging with environment checks
- **Build Optimization**: Enhanced production build configuration
- Better chunk splitting and manual chunks optimization
- Improved Terser settings with additional compression options
### Technical Enhancements
- **ES Module Support**: Added "type": "module" to package.json for modern JavaScript
- **Code Quality**: Enhanced ESLint and Prettier configurations
- **Bundle Analysis**: Improved build analysis tools and documentation
## 2.1.0 - 28.07.2025
**Enhancement Release - jQuery-Free Core System & Brand Refresh**
### New Features
- **jQuery-Free Core System**: Complete main-core.js modernization with vanilla JavaScript
- Dynamic module loading with caching and performance monitoring
- Loading states and visual indicators for better UX
- Enhanced error handling and development debugging tools
- **Brand-Consistent Favicon Suite**: Modern favicon system with complete browser support
- SVG-first approach for sharp display across all devices
- Apple Touch Icon, Android Chrome icons, and PWA manifest
- Modern standard implementation with proper fallbacks
### UI/UX Improvements
- **Top Navigation Alignment**: Perfect vertical centering of user profile and notification elements
- **Modern DOM Utilities**: Comprehensive jQuery-free DOM manipulation library
- Slide animations, fade effects, and smooth transitions
- Event handling and element manipulation without jQuery dependency
- **Enhanced Visual Consistency**: Improved spacing and alignment throughout interface
### Technical Enhancements
- **Console Log Cleanup**: Production-ready code with clean, professional output
- Development-only logging wrapped in environment checks
- Removed verbose initialization messages and debug output
- **Code Quality**: Streamlined codebase with reduced development artifacts
- **Performance Optimizations**: Further improvements to module loading system
### Bug Fixes
- Fixed loadModule reference errors when using main-minimal.js
- Resolved favicon display issues in legacy browsers
- Corrected navigation element positioning and alignment
- Eliminated development console noise in production builds
### File Structure
- Added centralized DOM utilities (`src/utils/dom-modern.js`)
- Updated favicon implementation with proper size variants
- Cleaned development files and reduced repository size
### Developer Experience
- Improved error boundaries and debugging capabilities
- Enhanced module performance monitoring and statistics
- Better development vs production environment handling
## 2.0.0 - 20.06.2025 🎉
**Major Stable Release - Bootstrap 5 with Modern Build System**
### 🚀 New Features
- **Vite Build System**: Lightning-fast development with hot-reload and optimized production builds
- **Bootstrap 5.3.7**: Complete migration to latest Bootstrap with modern design system
- **Smart Code Splitting**: 90% smaller initial bundle (79KB vs 779KB) with conditional module loading
- **Modern JavaScript**: ES6+ modules with dynamic imports and tree shaking
- **Performance Optimized**: 40-70% faster page loads with intelligent caching
### 🔧 Major Improvements
- **Morris.js Complete Removal**: Replaced with modern Chart.js implementation
- Renamed `morisjs.html` → `chart3.html` with updated navigation
- Removed all Morris.js CSS and JavaScript code
- Updated 35+ HTML files with new Chart.js references
- **jQuery Easing Fixes**: Resolved all `TypeError: jQuery.easing[this.easing] is not a function` errors
- Added jQuery UI easing effects with fallback functions
- Fixed EasyPieChart and progress bar animations
- **Enhanced Navigation**: Consistent search bar implementation across all pages
- **Error Page Redesign**: Modern 403, 404, 500 pages with consistent branding
### 🎨 UI/UX Enhancements
- **Responsive Design**: Mobile-first approach with optimized touch interfaces
- **Login Page**: Complete redesign with modern card layout and form validation
- **Pricing Tables**: Pure Bootstrap 5 implementation with interactive features
- **Fixed Sidebar/Footer**: Proper Bootstrap 5 compatibility and positioning
### 🛠️ Technical Updates
- **Dependencies**: Updated all packages to latest stable versions
- **SASS Structure**: Organized and optimized stylesheet architecture
- **TypeScript Ready**: Full TypeScript support available
- **Cross-Browser**: Tested compatibility with modern browsers
### 📦 Bundle Optimization
- **Core Bundle**: 79KB essential libraries
- **Chart Module**: 219KB (loads only on chart pages)
- **Form Module**: 200KB (loads only on form pages)
- **Table Module**: DataTables functionality on demand
- **Dashboard Module**: Dashboard-specific widgets
### 🐛 Bug Fixes
- Fixed all reported Bootstrap 4 to 5 migration issues
- Resolved SASS deprecation warnings
- Fixed dropdown functionality across all pages
- Corrected responsive behavior on mobile devices
- Eliminated JavaScript console errors
### 💻 Developer Experience
- Hot-reload development server
- Optimized build process with cache-busting
- Smart asset optimization
- Improved documentation and examples
### Note
Earlier there were no changelog at all and we have introduced one now and we will start from version 1.0.0. However, keep in mind that this is far from being first version as there have been dozens of commits.
### 1.0.0 - 25.03.2016
* Fixed dataTables
* Added new dataTable variations
### 1.1.0 - 26.04.2016
* Add multilevel menu
* Mobile comptibility enhancement
### 1.2.0 - 19.05.2016
* Fix menu not become active if url contains parameters
* Fix form upload form not adjust on large number of files
* Remove invalid css
* Add compose message functionalities
* Add fixed sidebar functionalities
### 1.3.0 - 01.06.2016
* Fix menu not become active if url contains parameters
* Fix form upload form not adjust on large number of files
* Remove invalid css
* Add compose message functionalities
* Add fixed footer functionalities
### Gentelella 2.0-beta1
* Updated Bootstrap to 4.3.1
* Updated all dependencies
* Fixed all reported bugs
This version is tested but we would recommend not to use it in production right away. Please install it for testing purposes and report back if there are any problems to be fixed.
================================================
FILE: dev-watch.sh
================================================
#!/bin/bash
# Dev server auto-restart script
# This script will automatically restart the dev server if it crashes
echo "🚀 Starting Gentelella dev server with auto-restart..."
while true; do
echo "📡 Starting dev server on http://localhost:3000"
npm run dev
exit_code=$?
echo "⚠️ Dev server stopped with exit code: $exit_code"
if [ $exit_code -eq 0 ]; then
echo "✅ Dev server stopped normally"
break
else
echo "🔄 Dev server crashed, restarting in 2 seconds..."
sleep 2
fi
done
================================================
FILE: docs/Gemfile
================================================
source "https://rubygems.org"
# GitHub Pages compatible Jekyll version
gem "github-pages", group: :jekyll_plugins
# Override nokogiri to get latest security patches
gem "nokogiri", ">= 1.16.0"
# Theme
gem "just-the-docs"
# Jekyll plugins
group :jekyll_plugins do
gem "jekyll-feed"
gem "jekyll-sitemap"
gem "jekyll-seo-tag"
end
# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem
# and associated library.
platforms :mingw, :x64_mingw, :mswin, :jruby do
gem "tzinfo", "~> 1.2"
gem "tzinfo-data"
end
# Performance-booster for watching directories on Windows
gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin]
================================================
FILE: docs/README.md
================================================
# Gentelella Admin Template Documentation
This directory contains the complete documentation for Gentelella Admin Template, built with Jekyll and deployable to GitHub Pages.
## 📚 Documentation Structure
- **[index.md](index.md)** - Main landing page with overview and quick start
- **[installation.md](installation.md)** - Detailed installation guide
- **[configuration.md](configuration.md)** - Configuration and setup options
- **[components.md](components.md)** - Complete component reference
- **[performance.md](performance.md)** - Performance optimization guide
- **[deployment.md](deployment.md)** - Production deployment instructions
- **[customization.md](customization.md)** - Advanced customization techniques
- **[api-integration.md](api-integration.md)** - API integration and data management
## 🚀 Local Development
### Prerequisites
- Ruby 3.1 or higher
- Bundler gem
- Git
### Setup
1. **Clone the repository:**
```bash
git clone https://github.com/puikinsh/gentelella.git
cd gentelella/docs
```
2. **Install dependencies:**
```bash
bundle install
```
3. **Start the development server:**
```bash
bundle exec jekyll serve
```
4. **Open your browser:**
Navigate to `http://localhost:4000`
### Development Commands
```bash
# Start development server
bundle exec jekyll serve
# Start with live reload
bundle exec jekyll serve --livereload
# Build for production
bundle exec jekyll build
# Build with specific base URL
bundle exec jekyll build --baseurl "/gentelella"
# Clean generated files
bundle exec jekyll clean
```
## 🌐 GitHub Pages Deployment
The documentation is automatically deployed to GitHub Pages using GitHub Actions.
### Automatic Deployment
The site automatically deploys when changes are pushed to the `main` branch in the `docs/` directory. The workflow is defined in `.github/workflows/pages.yml`.
### Manual Deployment
To deploy manually:
1. **Enable GitHub Pages:**
- Go to repository Settings → Pages
- Set Source to "GitHub Actions"
2. **Trigger deployment:**
- Push changes to the `main` branch
- Or manually trigger the workflow in the Actions tab
### Custom Domain Setup
To use a custom domain:
1. **Add CNAME file:**
```bash
echo "docs.yoursite.com" > CNAME
```
2. **Configure DNS:**
Add CNAME record pointing to `username.github.io`
3. **Update _config.yml:**
```yaml
url: "https://docs.yoursite.com"
baseurl: ""
```
## 📝 Content Management
### Adding New Pages
1. **Create new markdown file:**
```bash
touch new-page.md
```
2. **Add front matter:**
```yaml
---
layout: default
title: Your Page Title
nav_order: 9
---
```
3. **Write content using markdown**
### Page Structure
Each page should include:
```yaml
---
layout: default
title: Page Title
nav_order: 1
description: "Page description for SEO"
permalink: /custom-url/
---
# Page Title
{: .no_toc }
Page description
{: .fs-6 .fw-300 }
## Table of contents
{: .no_toc .text-delta }
1. TOC
{:toc}
---
## Your Content Here
```
### Navigation
Navigation is automatically generated based on:
- `nav_order` - Controls position in menu
- `title` - Displays in navigation
- File structure for sub-pages
### Styling and Components
The documentation uses [Just the Docs](https://just-the-docs.github.io/just-the-docs/) theme with custom styling.
#### Available Components
**Callouts:**
```markdown
{: .highlight }
💡 **Pro Tip**: Your tip content here
{: .warning }
⚠️ **Warning**: Important warning here
```
**Code Blocks:**
```markdown
```javascript
// Code with syntax highlighting
const example = 'hello world';
```
**Tables:**
```markdown
| Column 1 | Column 2 |
|----------|----------|
| Data 1 | Data 2 |
```
**Buttons:**
```markdown
[Button Text](link){: .btn .btn-primary }
```
## 🔧 Configuration
### _config.yml
Key configuration options:
```yaml
# Site settings
title: Gentelella Admin Template
description: Modern Bootstrap 5 Admin Dashboard Template
url: "https://puikinsh.github.io"
baseurl: "/gentelella"
# Theme
theme: just-the-docs
# Search
search_enabled: true
# Navigation
nav_sort: case_insensitive
# Footer
footer_content: "Copyright © 2025 Colorlib"
# External links
aux_links:
"GitHub": "//github.com/puikinsh/gentelella"
"Colorlib": "//colorlib.com"
```
### Gemfile
Dependencies managed through Bundler:
```ruby
source "https://rubygems.org"
# GitHub Pages compatible Jekyll version
gem "github-pages", group: :jekyll_plugins
# Theme
gem "just-the-docs"
# Jekyll plugins
group :jekyll_plugins do
gem "jekyll-feed"
gem "jekyll-sitemap"
gem "jekyll-seo-tag"
end
```
## 📊 Analytics and SEO
### Google Analytics
Add tracking ID to `_config.yml`:
```yaml
ga_tracking: UA-XXXXXXXX-X
```
### SEO Optimization
- All pages include meta descriptions
- Structured data for documentation
- Sitemap automatically generated
- Social media meta tags
### Performance
- Static site generation for fast loading
- Image optimization
- Minified CSS and HTML
- CDN-ready assets
## 🤝 Contributing
### Documentation Guidelines
1. **Clear and concise writing**
2. **Include code examples**
3. **Add table of contents for long pages**
4. **Use consistent formatting**
5. **Include links to related sections**
### Editing Process
1. **Fork the repository**
2. **Create feature branch**
3. **Make changes to documentation**
4. **Test locally with Jekyll**
5. **Submit pull request**
### Style Guide
- Use sentence case for headings
- Include code examples for all features
- Add screenshots when helpful
- Link to external resources appropriately
- Keep paragraphs concise
## 🐛 Troubleshooting
### Common Issues
**Bundle install fails:**
```bash
# Update RubyGems
gem update --system
# Clear bundle cache
bundle clean --force
rm Gemfile.lock
bundle install
```
**Jekyll serve fails:**
```bash
# Clear Jekyll cache
bundle exec jekyll clean
# Regenerate
bundle exec jekyll serve --trace
```
**GitHub Pages build fails:**
- Check Jekyll build logs in Actions tab
- Ensure all gems are GitHub Pages compatible
- Validate YAML front matter
### Getting Help
- Check [Jekyll documentation](https://jekyllrb.com/docs/)
- Review [Just the Docs guide](https://just-the-docs.github.io/just-the-docs/)
- Open issue in repository
## 📄 License
Documentation is licensed under MIT License - see main repository LICENSE file for details.
## 🙏 Acknowledgments
- Built with [Jekyll](https://jekyllrb.com/)
- Styled with [Just the Docs](https://just-the-docs.github.io/just-the-docs/)
- Hosted on [GitHub Pages](https://pages.github.com/)
- Template by [Colorlib](https://colorlib.com/)
================================================
FILE: docs/_config.yml
================================================
title: Gentelella Admin Template
description: Modern Bootstrap 5 Admin Dashboard Template with Performance Optimizations
url: "https://colorlibhq.github.io"
baseurl: "/gentelella"
# Theme
theme: just-the-docs
# Just the Docs configuration
color_scheme: light
search_enabled: true
search:
heading_level: 2
previews: 3
preview_words_before: 5
preview_words_after: 10
tokenizer_separator: /[\s/]+/
rel_url: true
button: false
# Navigation structure
nav_sort: case_insensitive
# Footer content
footer_content: "Copyright © {{ 'now' | date: '%Y' }} Colorlib. Distributed under the <a href=\"https://github.com/puikinsh/gentelella/blob/master/LICENSE.txt\">MIT license</a>."
# Google Analytics (optional)
# ga_tracking: UA-XXXXXXXX-X
# Social links in footer
aux_links:
"Gentelella on GitHub":
- "//github.com/puikinsh/gentelella"
"Colorlib":
- "//colorlib.com"
# Back to top link
back_to_top: true
back_to_top_text: "Back to top"
# Plugins
plugins:
- jekyll-feed
- jekyll-sitemap
- jekyll-seo-tag
# Build settings
markdown: kramdown
highlighter: rouge
permalink: pretty
# Exclude from processing
exclude:
- README.md
- Gemfile
- Gemfile.lock
- node_modules
- vendor
- .bundle
- .sass-cache
- .jekyll-cache
- .jekyll-metadata
# Collections for organizing documentation
collections:
docs:
permalink: "/:collection/:name/"
output: true
# Default values
defaults:
- scope:
path: ""
type: "pages"
values:
layout: "default"
- scope:
path: ""
type: "docs"
values:
layout: "default"
- scope:
path: ""
values:
image: "/assets/images/gentelella-preview.jpg"
# Add site icon/favicon
favicon_ico: "/favicon.ico"
================================================
FILE: docs/_site/api-integration/index.html
================================================
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<link rel="stylesheet" href="/gentelella/assets/css/just-the-docs-default.css">
<link rel="stylesheet" href="/gentelella/assets/css/just-the-docs-head-nav.css" id="jtd-head-nav-stylesheet">
<style id="jtd-nav-activation">
.site-nav > ul.nav-list:first-child > li:not(:nth-child(7)) > a,
.site-nav > ul.nav-list:first-child > li > ul > li a {
background-image: none;
}
.site-nav > ul.nav-list:not(:first-child) a,
.site-nav li.external a {
background-image: none;
}
.site-nav > ul.nav-list:first-child > li:nth-child(7) > a {
font-weight: 600;
text-decoration: none;
}.site-nav > ul.nav-list:first-child > li:nth-child(7) > button svg {
transform: rotate(-90deg);
}.site-nav > ul.nav-list:first-child > li.nav-list-item:nth-child(7) > ul.nav-list {
display: block;
}
</style>
<script src="/gentelella/assets/js/vendor/lunr.min.js"></script>
<script src="/gentelella/assets/js/just-the-docs.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="/gentelella/favicon.ico" type="image/x-icon">
<!-- Begin Jekyll SEO tag v2.8.0 -->
<title>API Integration | Gentelella Admin Template</title>
<meta name="generator" content="Jekyll v3.10.0" />
<meta property="og:title" content="API Integration" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="Modern Bootstrap 5 Admin Dashboard Template with Performance Optimizations" />
<meta property="og:description" content="Modern Bootstrap 5 Admin Dashboard Template with Performance Optimizations" />
<link rel="canonical" href="https://puikinsh.github.io/gentelella/api-integration/" />
<meta property="og:url" content="https://puikinsh.github.io/gentelella/api-integration/" />
<meta property="og:site_name" content="Gentelella Admin Template" />
<meta property="og:image" content="https://puikinsh.github.io/gentelella/assets/images/gentelella-preview.jpg" />
<meta property="og:type" content="website" />
<meta name="twitter:card" content="summary_large_image" />
<meta property="twitter:image" content="https://puikinsh.github.io/gentelella/assets/images/gentelella-preview.jpg" />
<meta property="twitter:title" content="API Integration" />
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"WebPage","description":"Modern Bootstrap 5 Admin Dashboard Template with Performance Optimizations","headline":"API Integration","image":"https://puikinsh.github.io/gentelella/assets/images/gentelella-preview.jpg","url":"https://puikinsh.github.io/gentelella/api-integration/"}</script>
<!-- End Jekyll SEO tag -->
</head>
<body>
<a class="skip-to-main" href="#main-content">Skip to main content</a>
<svg xmlns="http://www.w3.org/2000/svg" class="d-none">
<symbol id="svg-link" viewBox="0 0 24 24">
<title>Link</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link">
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
</svg>
</symbol>
<symbol id="svg-menu" viewBox="0 0 24 24">
<title>Menu</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-menu">
<line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line>
</svg>
</symbol>
<symbol id="svg-arrow-right" viewBox="0 0 24 24">
<title>Expand</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right">
<polyline points="9 18 15 12 9 6"></polyline>
</svg>
</symbol>
<!-- Feather. MIT License: https://github.com/feathericons/feather/blob/master/LICENSE -->
<symbol id="svg-external-link" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-external-link">
<title id="svg-external-link-title">(external link)</title>
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line>
</symbol>
<symbol id="svg-doc" viewBox="0 0 24 24">
<title>Document</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file">
<path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline>
</svg>
</symbol>
<symbol id="svg-search" viewBox="0 0 24 24">
<title>Search</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search">
<circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
</symbol>
<!-- Bootstrap Icons. MIT License: https://github.com/twbs/icons/blob/main/LICENSE.md -->
<symbol id="svg-copy" viewBox="0 0 16 16">
<title>Copy</title>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard" viewBox="0 0 16 16">
<path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"/>
<path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"/>
</svg>
</symbol>
<symbol id="svg-copied" viewBox="0 0 16 16">
<title>Copied</title>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard-check-fill" viewBox="0 0 16 16">
<path d="M6.5 0A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3Zm3 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3Z"/>
<path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1A2.5 2.5 0 0 1 9.5 5h-3A2.5 2.5 0 0 1 4 2.5v-1Zm6.854 7.354-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 0 1 .708-.708L7.5 10.793l2.646-2.647a.5.5 0 0 1 .708.708Z"/>
</svg>
</symbol>
</svg>
<div class="side-bar">
<div class="site-header" role="banner">
<a href="/gentelella/" class="site-title lh-tight">
Gentelella Admin Template
</a>
<button id="menu-button" class="site-button btn-reset" aria-label="Toggle menu" aria-pressed="false">
<svg viewBox="0 0 24 24" class="icon" aria-hidden="true"><use xlink:href="#svg-menu"></use></svg>
</button>
</div>
<nav aria-label="Main" id="site-nav" class="site-nav">
<ul class="nav-list"><li class="nav-list-item"><a href="/gentelella/" class="nav-list-link">Gentelella Admin Template Documentation</a></li><li class="nav-list-item"><a href="/gentelella/installation/" class="nav-list-link">Installation Guide</a></li><li class="nav-list-item"><a href="/gentelella/configuration/" class="nav-list-link">Configuration</a></li><li class="nav-list-item"><a href="/gentelella/components/" class="nav-list-link">Components Guide</a></li><li class="nav-list-item"><a href="/gentelella/deployment/" class="nav-list-link">Deployment Guide</a></li><li class="nav-list-item"><a href="/gentelella/customization/" class="nav-list-link">Customization Guide</a></li><li class="nav-list-item"><a href="/gentelella/api-integration/" class="nav-list-link">API Integration</a></li><li class="nav-list-item"><a href="/gentelella/bundle-analysis/" class="nav-list-link">Bundle Analysis Guide</a></li><li class="nav-list-item"><a href="/gentelella/jquery-elimination-complete/" class="nav-list-link">Complete jQuery Elimination Achievement 🎉</a></li><li class="nav-list-item"><a href="/gentelella/daterangepicker-fix/" class="nav-list-link">Date Range Picker Fix Documentation</a></li><li class="nav-list-item"><a href="/gentelella/security-headers/" class="nav-list-link">Security Headers Implementation Guide</a></li></ul>
</nav>
<footer class="site-footer">
This site uses <a href="https://github.com/just-the-docs/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.
</footer>
</div>
<div class="main" id="top">
<div id="main-header" class="main-header">
<div class="search" role="search">
<div class="search-input-wrap">
<input type="text" id="search-input" class="search-input" tabindex="0" placeholder="Search Gentelella Admin Template" aria-label="Search Gentelella Admin Template" autocomplete="off">
<label for="search-input" class="search-label"><svg viewBox="0 0 24 24" class="search-icon"><use xlink:href="#svg-search"></use></svg></label>
</div>
<div id="search-results" class="search-results"></div>
</div>
<nav aria-label="Auxiliary" class="aux-nav">
<ul class="aux-nav-list">
<li class="aux-nav-list-item">
<a href="//github.com/puikinsh/gentelella" class="site-button"
>
Gentelella on GitHub
</a>
</li>
<li class="aux-nav-list-item">
<a href="//colorlib.com" class="site-button"
>
Colorlib
</a>
</li>
</ul>
</nav>
</div>
<div class="main-content-wrap">
<div id="main-content" class="main-content">
<main>
<h1 class="no_toc" id="api-integration-guide">
<a href="#api-integration-guide" class="anchor-heading" aria-labelledby="api-integration-guide"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> API Integration Guide
</h1>
<p class="fs-6 fw-300">Learn how to integrate Gentelella Admin Template with backend APIs and external services</p>
<h2 class="no_toc text-delta" id="table-of-contents">
<a href="#table-of-contents" class="anchor-heading" aria-labelledby="table-of-contents"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Table of contents
</h2>
<ol id="markdown-toc">
<li><a href="#rest-api-integration" id="markdown-toc-rest-api-integration">REST API Integration</a> <ol>
<li><a href="#http-client-setup" id="markdown-toc-http-client-setup">HTTP Client Setup</a> <ol>
<li><a href="#axios-configuration" id="markdown-toc-axios-configuration">Axios Configuration</a></li>
</ol>
</li>
<li><a href="#api-service-layer" id="markdown-toc-api-service-layer">API Service Layer</a> <ol>
<li><a href="#base-service-class" id="markdown-toc-base-service-class">Base Service Class</a></li>
<li><a href="#specific-service-classes" id="markdown-toc-specific-service-classes">Specific Service Classes</a></li>
</ol>
</li>
</ol>
</li>
<li><a href="#real-time-integration" id="markdown-toc-real-time-integration">Real-time Integration</a> <ol>
<li><a href="#websocket-connection" id="markdown-toc-websocket-connection">WebSocket Connection</a></li>
<li><a href="#real-time-dashboard-updates" id="markdown-toc-real-time-dashboard-updates">Real-time Dashboard Updates</a></li>
</ol>
</li>
<li><a href="#data-management" id="markdown-toc-data-management">Data Management</a> <ol>
<li><a href="#state-management" id="markdown-toc-state-management">State Management</a></li>
<li><a href="#data-caching" id="markdown-toc-data-caching">Data Caching</a></li>
</ol>
</li>
<li><a href="#authentication-integration" id="markdown-toc-authentication-integration">Authentication Integration</a> <ol>
<li><a href="#jwt-token-management" id="markdown-toc-jwt-token-management">JWT Token Management</a></li>
</ol>
</li>
<li><a href="#error-handling" id="markdown-toc-error-handling">Error Handling</a> <ol>
<li><a href="#global-error-handler" id="markdown-toc-global-error-handler">Global Error Handler</a></li>
</ol>
</li>
<li><a href="#performance-optimization" id="markdown-toc-performance-optimization">Performance Optimization</a> <ol>
<li><a href="#request-batching" id="markdown-toc-request-batching">Request Batching</a></li>
</ol>
</li>
<li><a href="#next-steps" id="markdown-toc-next-steps">Next Steps</a></li>
</ol><hr />
<h2 id="rest-api-integration">
<a href="#rest-api-integration" class="anchor-heading" aria-labelledby="rest-api-integration"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> REST API Integration
</h2>
<h3 id="http-client-setup">
<a href="#http-client-setup" class="anchor-heading" aria-labelledby="http-client-setup"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> HTTP Client Setup
</h3>
<h4 id="axios-configuration">
<a href="#axios-configuration" class="anchor-heading" aria-labelledby="axios-configuration"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Axios Configuration
</h4>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// src/js/api/http-client.js</span>
<span class="k">import</span> <span class="nx">axios</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">axios</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">class</span> <span class="nx">HttpClient</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">client</span> <span class="o">=</span> <span class="nx">axios</span><span class="p">.</span><span class="nx">create</span><span class="p">({</span>
<span class="na">baseURL</span><span class="p">:</span> <span class="k">import</span><span class="p">.</span><span class="nx">meta</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">VITE_API_URL</span> <span class="o">||</span> <span class="dl">'</span><span class="s1">http://localhost:8080/api</span><span class="dl">'</span><span class="p">,</span>
<span class="na">timeout</span><span class="p">:</span> <span class="mi">10000</span><span class="p">,</span>
<span class="na">headers</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">'</span><span class="s1">Content-Type</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">application/json</span><span class="dl">'</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">Accept</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">application/json</span><span class="dl">'</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setupInterceptors</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">setupInterceptors</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">// Request interceptor - add auth token</span>
<span class="k">this</span><span class="p">.</span><span class="nx">client</span><span class="p">.</span><span class="nx">interceptors</span><span class="p">.</span><span class="nx">request</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span>
<span class="p">(</span><span class="nx">config</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">token</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">auth_token</span><span class="dl">'</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">token</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">config</span><span class="p">.</span><span class="nx">headers</span><span class="p">.</span><span class="nx">Authorization</span> <span class="o">=</span> <span class="s2">`Bearer </span><span class="p">${</span><span class="nx">token</span><span class="p">}</span><span class="s2">`</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">config</span><span class="p">;</span>
<span class="p">},</span>
<span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="o">=></span> <span class="nb">Promise</span><span class="p">.</span><span class="nx">reject</span><span class="p">(</span><span class="nx">error</span><span class="p">)</span>
<span class="p">);</span>
<span class="c1">// Response interceptor - handle errors</span>
<span class="k">this</span><span class="p">.</span><span class="nx">client</span><span class="p">.</span><span class="nx">interceptors</span><span class="p">.</span><span class="nx">response</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span>
<span class="p">(</span><span class="nx">response</span><span class="p">)</span> <span class="o">=></span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span>
<span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">error</span><span class="p">.</span><span class="nx">response</span><span class="p">?.</span><span class="nx">status</span> <span class="o">===</span> <span class="mi">401</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">handleUnauthorized</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nb">Promise</span><span class="p">.</span><span class="nx">reject</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">formatError</span><span class="p">(</span><span class="nx">error</span><span class="p">));</span>
<span class="p">}</span>
<span class="p">);</span>
<span class="p">}</span>
<span class="nx">handleUnauthorized</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">removeItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">auth_token</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">removeItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">user_data</span><span class="dl">'</span><span class="p">);</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">href</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">/login.html</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">formatError</span><span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">error</span><span class="p">.</span><span class="nx">response</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">message</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">response</span><span class="p">.</span><span class="nx">data</span><span class="p">?.</span><span class="nx">message</span> <span class="o">||</span> <span class="dl">'</span><span class="s1">Server error</span><span class="dl">'</span><span class="p">,</span>
<span class="na">status</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">response</span><span class="p">.</span><span class="nx">status</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">response</span><span class="p">.</span><span class="nx">data</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">error</span><span class="p">.</span><span class="nx">request</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">message</span><span class="p">:</span> <span class="dl">'</span><span class="s1">Network error - please check your connection</span><span class="dl">'</span><span class="p">,</span>
<span class="na">status</span><span class="p">:</span> <span class="mi">0</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">message</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span> <span class="o">||</span> <span class="dl">'</span><span class="s1">Unknown error occurred</span><span class="dl">'</span><span class="p">,</span>
<span class="na">status</span><span class="p">:</span> <span class="o">-</span><span class="mi">1</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// HTTP methods</span>
<span class="kd">get</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">config</span> <span class="o">=</span> <span class="p">{})</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">client</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">config</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">post</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">data</span> <span class="o">=</span> <span class="p">{},</span> <span class="nx">config</span> <span class="o">=</span> <span class="p">{})</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">client</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">config</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">put</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">data</span> <span class="o">=</span> <span class="p">{},</span> <span class="nx">config</span> <span class="o">=</span> <span class="p">{})</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">client</span><span class="p">.</span><span class="nx">put</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">config</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">patch</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">data</span> <span class="o">=</span> <span class="p">{},</span> <span class="nx">config</span> <span class="o">=</span> <span class="p">{})</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">client</span><span class="p">.</span><span class="nx">patch</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">config</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">delete</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">config</span> <span class="o">=</span> <span class="p">{})</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">client</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">config</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// File upload</span>
<span class="nx">upload</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">file</span><span class="p">,</span> <span class="nx">onProgress</span> <span class="o">=</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">formData</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">FormData</span><span class="p">();</span>
<span class="nx">formData</span><span class="p">.</span><span class="nx">append</span><span class="p">(</span><span class="dl">'</span><span class="s1">file</span><span class="dl">'</span><span class="p">,</span> <span class="nx">file</span><span class="p">);</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">client</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">formData</span><span class="p">,</span> <span class="p">{</span>
<span class="na">headers</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">'</span><span class="s1">Content-Type</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">multipart/form-data</span><span class="dl">'</span>
<span class="p">},</span>
<span class="na">onUploadProgress</span><span class="p">:</span> <span class="p">(</span><span class="nx">progressEvent</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">onProgress</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">progress</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">round</span><span class="p">(</span>
<span class="p">(</span><span class="nx">progressEvent</span><span class="p">.</span><span class="nx">loaded</span> <span class="o">*</span> <span class="mi">100</span><span class="p">)</span> <span class="o">/</span> <span class="nx">progressEvent</span><span class="p">.</span><span class="nx">total</span>
<span class="p">);</span>
<span class="nx">onProgress</span><span class="p">(</span><span class="nx">progress</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Create singleton instance</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">httpClient</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">HttpClient</span><span class="p">();</span>
</code></pre></div></div>
<h3 id="api-service-layer">
<a href="#api-service-layer" class="anchor-heading" aria-labelledby="api-service-layer"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> API Service Layer
</h3>
<h4 id="base-service-class">
<a href="#base-service-class" class="anchor-heading" aria-labelledby="base-service-class"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Base Service Class
</h4>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// src/js/api/base-service.js</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">httpClient</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">./http-client.js</span><span class="dl">'</span><span class="p">;</span>
<span class="k">export</span> <span class="kd">class</span> <span class="nx">BaseService</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">(</span><span class="nx">endpoint</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">endpoint</span> <span class="o">=</span> <span class="nx">endpoint</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">http</span> <span class="o">=</span> <span class="nx">httpClient</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">getAll</span><span class="p">(</span><span class="nx">params</span> <span class="o">=</span> <span class="p">{})</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">endpoint</span><span class="p">,</span> <span class="p">{</span> <span class="nx">params</span> <span class="p">});</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span>
<span class="na">meta</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">meta</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="p">,</span>
<span class="na">details</span><span class="p">:</span> <span class="nx">error</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">getById</span><span class="p">(</span><span class="nx">id</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="s2">`</span><span class="p">${</span><span class="k">this</span><span class="p">.</span><span class="nx">endpoint</span><span class="p">}</span><span class="s2">/</span><span class="p">${</span><span class="nx">id</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="p">,</span>
<span class="na">details</span><span class="p">:</span> <span class="nx">error</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">create</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">endpoint</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="p">,</span>
<span class="na">details</span><span class="p">:</span> <span class="nx">error</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">update</span><span class="p">(</span><span class="nx">id</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="nx">put</span><span class="p">(</span><span class="s2">`</span><span class="p">${</span><span class="k">this</span><span class="p">.</span><span class="nx">endpoint</span><span class="p">}</span><span class="s2">/</span><span class="p">${</span><span class="nx">id</span><span class="p">}</span><span class="s2">`</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="p">,</span>
<span class="na">details</span><span class="p">:</span> <span class="nx">error</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="k">delete</span><span class="p">(</span><span class="nx">id</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="s2">`</span><span class="p">${</span><span class="k">this</span><span class="p">.</span><span class="nx">endpoint</span><span class="p">}</span><span class="s2">/</span><span class="p">${</span><span class="nx">id</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="p">,</span>
<span class="na">details</span><span class="p">:</span> <span class="nx">error</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">search</span><span class="p">(</span><span class="nx">query</span><span class="p">,</span> <span class="nx">params</span> <span class="o">=</span> <span class="p">{})</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="s2">`</span><span class="p">${</span><span class="k">this</span><span class="p">.</span><span class="nx">endpoint</span><span class="p">}</span><span class="s2">/search`</span><span class="p">,</span> <span class="p">{</span>
<span class="na">params</span><span class="p">:</span> <span class="p">{</span> <span class="na">q</span><span class="p">:</span> <span class="nx">query</span><span class="p">,</span> <span class="p">...</span><span class="nx">params</span> <span class="p">}</span>
<span class="p">});</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span>
<span class="na">meta</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">meta</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="p">,</span>
<span class="na">details</span><span class="p">:</span> <span class="nx">error</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<h4 id="specific-service-classes">
<a href="#specific-service-classes" class="anchor-heading" aria-labelledby="specific-service-classes"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Specific Service Classes
</h4>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// src/js/api/user-service.js</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">BaseService</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">./base-service.js</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">class</span> <span class="nx">UserService</span> <span class="kd">extends</span> <span class="nx">BaseService</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">()</span> <span class="p">{</span>
<span class="k">super</span><span class="p">(</span><span class="dl">'</span><span class="s1">/users</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">authenticate</span><span class="p">(</span><span class="nx">credentials</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">'</span><span class="s1">/auth/login</span><span class="dl">'</span><span class="p">,</span> <span class="nx">credentials</span><span class="p">);</span>
<span class="c1">// Store auth token</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">token</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">auth_token</span><span class="dl">'</span><span class="p">,</span> <span class="nx">response</span><span class="p">.</span><span class="nx">token</span><span class="p">);</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">user_data</span><span class="dl">'</span><span class="p">,</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">user</span><span class="p">));</span>
<span class="p">}</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">logout</span><span class="p">()</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">'</span><span class="s1">/auth/logout</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">warn</span><span class="p">(</span><span class="dl">'</span><span class="s1">Logout API call failed:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="p">);</span>
<span class="p">}</span> <span class="k">finally</span> <span class="p">{</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">removeItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">auth_token</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">removeItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">user_data</span><span class="dl">'</span><span class="p">);</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">href</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">/login.html</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">getCurrentUser</span><span class="p">()</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/auth/me</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">updateProfile</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="nx">put</span><span class="p">(</span><span class="dl">'</span><span class="s1">/auth/profile</span><span class="dl">'</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
<span class="c1">// Update stored user data</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">user_data</span><span class="dl">'</span><span class="p">,</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">data</span><span class="p">));</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">changePassword</span><span class="p">(</span><span class="nx">passwordData</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">'</span><span class="s1">/auth/change-password</span><span class="dl">'</span><span class="p">,</span> <span class="nx">passwordData</span><span class="p">);</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">uploadAvatar</span><span class="p">(</span><span class="nx">file</span><span class="p">,</span> <span class="nx">onProgress</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="nx">upload</span><span class="p">(</span><span class="dl">'</span><span class="s1">/auth/avatar</span><span class="dl">'</span><span class="p">,</span> <span class="nx">file</span><span class="p">,</span> <span class="nx">onProgress</span><span class="p">);</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">userService</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">UserService</span><span class="p">();</span>
<span class="c1">// src/js/api/dashboard-service.js</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">BaseService</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">./base-service.js</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">class</span> <span class="nx">DashboardService</span> <span class="kd">extends</span> <span class="nx">BaseService</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">()</span> <span class="p">{</span>
<span class="k">super</span><span class="p">(</span><span class="dl">'</span><span class="s1">/dashboard</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">getStats</span><span class="p">(</span><span class="nx">dateRange</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">30d</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/dashboard/stats</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
<span class="na">params</span><span class="p">:</span> <span class="p">{</span> <span class="na">range</span><span class="p">:</span> <span class="nx">dateRange</span> <span class="p">}</span>
<span class="p">});</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">getChartData</span><span class="p">(</span><span class="nx">chartType</span><span class="p">,</span> <span class="nx">params</span> <span class="o">=</span> <span class="p">{})</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="s2">`/dashboard/charts/</span><span class="p">${</span><span class="nx">chartType</span><span class="p">}</span><span class="s2">`</span><span class="p">,</span> <span class="p">{</span>
<span class="nx">params</span>
<span class="p">});</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">getRecentActivity</span><span class="p">(</span><span class="nx">limit</span> <span class="o">=</span> <span class="mi">10</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/dashboard/activity</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
<span class="na">params</span><span class="p">:</span> <span class="p">{</span> <span class="nx">limit</span> <span class="p">}</span>
<span class="p">});</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">dashboardService</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">DashboardService</span><span class="p">();</span>
</code></pre></div></div><hr />
<h2 id="real-time-integration">
<a href="#real-time-integration" class="anchor-heading" aria-labelledby="real-time-integration"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Real-time Integration
</h2>
<h3 id="websocket-connection">
<a href="#websocket-connection" class="anchor-heading" aria-labelledby="websocket-connection"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> WebSocket Connection
</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// src/js/api/websocket-client.js</span>
<span class="kd">class</span> <span class="nx">WebSocketClient</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ws</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">reconnectAttempts</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">maxReconnectAttempts</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">reconnectDelay</span> <span class="o">=</span> <span class="mi">1000</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">listeners</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">isConnected</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">connect</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">wsUrl</span> <span class="o">=</span> <span class="k">import</span><span class="p">.</span><span class="nx">meta</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">VITE_WS_URL</span> <span class="o">||</span> <span class="dl">'</span><span class="s1">ws://localhost:8080/ws</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">token</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">auth_token</span><span class="dl">'</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ws</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">WebSocket</span><span class="p">(</span><span class="s2">`</span><span class="p">${</span><span class="nx">wsUrl</span><span class="p">}</span><span class="s2">?token=</span><span class="p">${</span><span class="nx">token</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ws</span><span class="p">.</span><span class="nx">onopen</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">WebSocket connected</span><span class="dl">'</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">isConnected</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">reconnectAttempts</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="dl">'</span><span class="s1">connected</span><span class="dl">'</span><span class="p">);</span>
<span class="p">};</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ws</span><span class="p">.</span><span class="nx">onmessage</span> <span class="o">=</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">message</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">handleMessage</span><span class="p">(</span><span class="nx">message</span><span class="p">);</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Failed to parse WebSocket message:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ws</span><span class="p">.</span><span class="nx">onclose</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">WebSocket disconnected</span><span class="dl">'</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">isConnected</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="dl">'</span><span class="s1">disconnected</span><span class="dl">'</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">reconnect</span><span class="p">();</span>
<span class="p">};</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ws</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">WebSocket error:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="dl">'</span><span class="s1">error</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="nx">reconnect</span><span class="p">()</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">reconnectAttempts</span> <span class="o">>=</span> <span class="k">this</span><span class="p">.</span><span class="nx">maxReconnectAttempts</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Max reconnection attempts reached</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">this</span><span class="p">.</span><span class="nx">reconnectAttempts</span><span class="o">++</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">delay</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">reconnectDelay</span> <span class="o">*</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">reconnectAttempts</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`Reconnecting in </span><span class="p">${</span><span class="nx">delay</span><span class="p">}</span><span class="s2">ms (attempt </span><span class="p">${</span><span class="k">this</span><span class="p">.</span><span class="nx">reconnectAttempts</span><span class="p">}</span><span class="s2">)`</span><span class="p">);</span>
<span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">connect</span><span class="p">();</span>
<span class="p">},</span> <span class="nx">delay</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">handleMessage</span><span class="p">(</span><span class="nx">message</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="p">{</span> <span class="nx">type</span><span class="p">,</span> <span class="nx">data</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">message</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="nx">type</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">send</span><span class="p">(</span><span class="nx">type</span><span class="p">,</span> <span class="nx">data</span> <span class="o">=</span> <span class="p">{})</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">isConnected</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">warn</span><span class="p">(</span><span class="dl">'</span><span class="s1">WebSocket not connected</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="nx">message</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">({</span> <span class="nx">type</span><span class="p">,</span> <span class="nx">data</span> <span class="p">});</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ws</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="nx">message</span><span class="p">);</span>
<span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">on</span><span class="p">(</span><span class="nx">event</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span><span class="nx">event</span><span class="p">))</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="nx">event</span><span class="p">,</span> <span class="p">[]);</span>
<span class="p">}</span>
<span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">event</span><span class="p">).</span><span class="nx">push</span><span class="p">(</span><span class="nx">callback</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">off</span><span class="p">(</span><span class="nx">event</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span><span class="nx">event</span><span class="p">))</span> <span class="k">return</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">callbacks</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">event</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">index</span> <span class="o">=</span> <span class="nx">callbacks</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">callback</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">index</span> <span class="o">></span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">callbacks</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="nx">index</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">emit</span><span class="p">(</span><span class="nx">event</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span><span class="nx">event</span><span class="p">))</span> <span class="k">return</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">event</span><span class="p">).</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">callback</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="nx">callback</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="s2">`Error in WebSocket event handler for </span><span class="p">${</span><span class="nx">event</span><span class="p">}</span><span class="s2">:`</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="nx">disconnect</span><span class="p">()</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">ws</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ws</span><span class="p">.</span><span class="nx">close</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ws</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">this</span><span class="p">.</span><span class="nx">isConnected</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Create singleton instance</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">wsClient</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">WebSocketClient</span><span class="p">();</span>
<span class="c1">// Auto-connect if user is authenticated</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">auth_token</span><span class="dl">'</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">wsClient</span><span class="p">.</span><span class="nx">connect</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="real-time-dashboard-updates">
<a href="#real-time-dashboard-updates" class="anchor-heading" aria-labelledby="real-time-dashboard-updates"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Real-time Dashboard Updates
</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// src/js/dashboard/real-time-dashboard.js</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">wsClient</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">../api/websocket-client.js</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">dashboardService</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">../api/dashboard-service.js</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">class</span> <span class="nx">RealTimeDashboard</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">charts</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">stats</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">init</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">init</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setupWebSocketListeners</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">loadInitialData</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">setupWebSocketListeners</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">// Listen for real-time stats updates</span>
<span class="nx">wsClient</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">'</span><span class="s1">stats.update</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">updateStats</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
<span class="p">});</span>
<span class="c1">// Listen for new chart data</span>
<span class="nx">wsClient</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">'</span><span class="s1">chart.data</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">updateChart</span><span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">chartId</span><span class="p">,</span> <span class="nx">data</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>
<span class="p">});</span>
<span class="c1">// Listen for new notifications</span>
<span class="nx">wsClient</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">'</span><span class="s1">notification</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">showNotification</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
<span class="p">});</span>
<span class="c1">// Listen for user activity</span>
<span class="nx">wsClient</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">'</span><span class="s1">user.activity</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">updateActivityFeed</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">loadInitialData</span><span class="p">()</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="c1">// Load dashboard stats</span>
<span class="kd">const</span> <span class="nx">statsResult</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">dashboardService</span><span class="p">.</span><span class="nx">getStats</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">statsResult</span><span class="p">.</span><span class="nx">success</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">renderStats</span><span class="p">(</span><span class="nx">statsResult</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// Load chart data</span>
<span class="kd">const</span> <span class="nx">chartTypes</span> <span class="o">=</span> <span class="p">[</span><span class="dl">'</span><span class="s1">sales</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">users</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">revenue</span><span class="dl">'</span><span class="p">];</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">const</span> <span class="nx">chartType</span> <span class="k">of</span> <span class="nx">chartTypes</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">chartResult</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">dashboardService</span><span class="p">.</span><span class="nx">getChartData</span><span class="p">(</span><span class="nx">chartType</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">chartResult</span><span class="p">.</span><span class="nx">success</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">renderChart</span><span class="p">(</span><span class="nx">chartType</span><span class="p">,</span> <span class="nx">chartResult</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Load recent activity</span>
<span class="kd">const</span> <span class="nx">activityResult</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">dashboardService</span><span class="p">.</span><span class="nx">getRecentActivity</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">activityResult</span><span class="p">.</span><span class="nx">success</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">renderActivity</span><span class="p">(</span><span class="nx">activityResult</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Failed to load dashboard data:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">updateStats</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">Object</span><span class="p">.</span><span class="nx">entries</span><span class="p">(</span><span class="nx">data</span><span class="p">).</span><span class="nx">forEach</span><span class="p">(([</span><span class="nx">key</span><span class="p">,</span> <span class="nx">value</span><span class="p">])</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">element</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s2">`[data-stat="</span><span class="p">${</span><span class="nx">key</span><span class="p">}</span><span class="s2">"]`</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">element</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// Animate value change</span>
<span class="k">this</span><span class="p">.</span><span class="nx">animateValue</span><span class="p">(</span><span class="nx">element</span><span class="p">,</span> <span class="nx">value</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="nx">animateValue</span><span class="p">(</span><span class="nx">element</span><span class="p">,</span> <span class="nx">newValue</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">currentValue</span> <span class="o">=</span> <span class="nb">parseFloat</span><span class="p">(</span><span class="nx">element</span><span class="p">.</span><span class="nx">textContent</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">[^</span><span class="sr">0-9.-</span><span class="se">]</span><span class="sr">/g</span><span class="p">,</span> <span class="dl">''</span><span class="p">))</span> <span class="o">||</span> <span class="mi">0</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">difference</span> <span class="o">=</span> <span class="nx">newValue</span> <span class="o">-</span> <span class="nx">currentValue</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">steps</span> <span class="o">=</span> <span class="mi">30</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">stepValue</span> <span class="o">=</span> <span class="nx">difference</span> <span class="o">/</span> <span class="nx">steps</span><span class="p">;</span>
<span class="kd">let</span> <span class="nx">current</span> <span class="o">=</span> <span class="nx">currentValue</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">timer</span> <span class="o">=</span> <span class="nx">setInterval</span><span class="p">(()</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">current</span> <span class="o">+=</span> <span class="nx">stepValue</span><span class="p">;</span>
<span class="nx">element</span><span class="p">.</span><span class="nx">textContent</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">formatValue</span><span class="p">(</span><span class="nx">current</span><span class="p">,</span> <span class="nx">element</span><span class="p">.</span><span class="nx">dataset</span><span class="p">.</span><span class="nx">format</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">--</span><span class="nx">steps</span> <span class="o"><=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">clearInterval</span><span class="p">(</span><span class="nx">timer</span><span class="p">);</span>
<span class="nx">element</span><span class="p">.</span><span class="nx">textContent</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">formatValue</span><span class="p">(</span><span class="nx">newValue</span><span class="p">,</span> <span class="nx">element</span><span class="p">.</span><span class="nx">dataset</span><span class="p">.</span><span class="nx">format</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">},</span> <span class="mi">16</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">formatValue</span><span class="p">(</span><span class="nx">value</span><span class="p">,</span> <span class="nx">format</span><span class="p">)</span> <span class="p">{</span>
<span class="k">switch</span> <span class="p">(</span><span class="nx">format</span><span class="p">)</span> <span class="p">{</span>
<span class="k">case</span> <span class="dl">'</span><span class="s1">currency</span><span class="dl">'</span><span class="p">:</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Intl</span><span class="p">.</span><span class="nx">NumberFormat</span><span class="p">(</span><span class="dl">'</span><span class="s1">en-US</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
<span class="na">style</span><span class="p">:</span> <span class="dl">'</span><span class="s1">currency</span><span class="dl">'</span><span class="p">,</span>
<span class="na">currency</span><span class="p">:</span> <span class="dl">'</span><span class="s1">USD</span><span class="dl">'</span>
<span class="p">}).</span><span class="nx">format</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
<span class="k">case</span> <span class="dl">'</span><span class="s1">percentage</span><span class="dl">'</span><span class="p">:</span>
<span class="k">return</span> <span class="s2">`</span><span class="p">${</span><span class="nx">value</span><span class="p">.</span><span class="nx">toFixed</span><span class="p">(</span><span class="mi">1</span><span class="p">)}</span><span class="s2">%`</span><span class="p">;</span>
<span class="k">case</span> <span class="dl">'</span><span class="s1">number</span><span class="dl">'</span><span class="p">:</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Intl</span><span class="p">.</span><span class="nx">NumberFormat</span><span class="p">(</span><span class="dl">'</span><span class="s1">en-US</span><span class="dl">'</span><span class="p">).</span><span class="nx">format</span><span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nx">round</span><span class="p">(</span><span class="nx">value</span><span class="p">));</span>
<span class="nl">default</span><span class="p">:</span>
<span class="k">return</span> <span class="nx">value</span><span class="p">.</span><span class="nx">toString</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">updateChart</span><span class="p">(</span><span class="nx">chartId</span><span class="p">,</span> <span class="nx">newData</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">chart</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">charts</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">chartId</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">chart</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span>
<span class="c1">// Update chart data</span>
<span class="nx">chart</span><span class="p">.</span><span class="nx">data</span> <span class="o">=</span> <span class="nx">newData</span><span class="p">;</span>
<span class="nx">chart</span><span class="p">.</span><span class="nx">update</span><span class="p">(</span><span class="dl">'</span><span class="s1">active</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">showNotification</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// Use notification plugin or create custom notification</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">GentelellaPlugins</span> <span class="o">&&</span> <span class="nb">window</span><span class="p">.</span><span class="nx">GentelellaPlugins</span><span class="p">.</span><span class="nx">getPlugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">notifications</span><span class="dl">'</span><span class="p">))</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">notifications</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">GentelellaPlugins</span><span class="p">.</span><span class="nx">getPlugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">notifications</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">notifications</span><span class="p">.</span><span class="nx">show</span><span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">message</span><span class="p">,</span> <span class="nx">data</span><span class="p">.</span><span class="nx">type</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">updateActivityFeed</span><span class="p">(</span><span class="nx">activity</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">feedContainer</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">#activity-feed</span><span class="dl">'</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">feedContainer</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">activityItem</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">div</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">activityItem</span><span class="p">.</span><span class="nx">className</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">activity-item</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">activityItem</span><span class="p">.</span><span class="nx">innerHTML</span> <span class="o">=</span> <span class="s2">`
<div class="activity-icon">
<i class="fa fa-</span><span class="p">${</span><span class="nx">activity</span><span class="p">.</span><span class="nx">icon</span><span class="p">}</span><span class="s2">"></i>
</div>
<div class="activity-content">
<div class="activity-text"></span><span class="p">${</span><span class="nx">activity</span><span class="p">.</span><span class="nx">message</span><span class="p">}</span><span class="s2"></div>
<div class="activity-time"></span><span class="p">${</span><span class="k">this</span><span class="p">.</span><span class="nx">formatTime</span><span class="p">(</span><span class="nx">activity</span><span class="p">.</span><span class="nx">timestamp</span><span class="p">)}</span><span class="s2"></div>
</div>
`</span><span class="p">;</span>
<span class="c1">// Add to top of feed</span>
<span class="nx">feedContainer</span><span class="p">.</span><span class="nx">insertBefore</span><span class="p">(</span><span class="nx">activityItem</span><span class="p">,</span> <span class="nx">feedContainer</span><span class="p">.</span><span class="nx">firstChild</span><span class="p">);</span>
<span class="c1">// Remove oldest items if feed is too long</span>
<span class="kd">const</span> <span class="nx">items</span> <span class="o">=</span> <span class="nx">feedContainer</span><span class="p">.</span><span class="nx">querySelectorAll</span><span class="p">(</span><span class="dl">'</span><span class="s1">.activity-item</span><span class="dl">'</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">items</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">10</span><span class="p">)</span> <span class="p">{</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">items</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">items</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">remove</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">formatTime</span><span class="p">(</span><span class="nx">timestamp</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">date</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">(</span><span class="nx">timestamp</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">now</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">();</span>
<span class="kd">const</span> <span class="nx">diff</span> <span class="o">=</span> <span class="nx">now</span> <span class="o">-</span> <span class="nx">date</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">diff</span> <span class="o"><</span> <span class="mi">60000</span><span class="p">)</span> <span class="k">return</span> <span class="dl">'</span><span class="s1">Just now</span><span class="dl">'</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">diff</span> <span class="o"><</span> <span class="mi">3600000</span><span class="p">)</span> <span class="k">return</span> <span class="s2">`</span><span class="p">${</span><span class="nb">Math</span><span class="p">.</span><span class="nx">floor</span><span class="p">(</span><span class="nx">diff</span> <span class="o">/</span> <span class="mi">60000</span><span class="p">)}</span><span class="s2">m ago`</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">diff</span> <span class="o"><</span> <span class="mi">86400000</span><span class="p">)</span> <span class="k">return</span> <span class="s2">`</span><span class="p">${</span><span class="nb">Math</span><span class="p">.</span><span class="nx">floor</span><span class="p">(</span><span class="nx">diff</span> <span class="o">/</span> <span class="mi">3600000</span><span class="p">)}</span><span class="s2">h ago`</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">date</span><span class="p">.</span><span class="nx">toLocaleDateString</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Initialize real-time dashboard</span>
<span class="k">new</span> <span class="nx">RealTimeDashboard</span><span class="p">();</span>
</code></pre></div></div><hr />
<h2 id="data-management">
<a href="#data-management" class="anchor-heading" aria-labelledby="data-management"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Data Management
</h2>
<h3 id="state-management">
<a href="#state-management" class="anchor-heading" aria-labelledby="state-management"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> State Management
</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// src/js/store/app-store.js</span>
<span class="kd">class</span> <span class="nx">AppStore</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">state</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">user</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
<span class="na">theme</span><span class="p">:</span> <span class="dl">'</span><span class="s1">light</span><span class="dl">'</span><span class="p">,</span>
<span class="na">sidebarCollapsed</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">notifications</span><span class="p">:</span> <span class="p">[],</span>
<span class="na">loading</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="kc">null</span>
<span class="p">};</span>
<span class="k">this</span><span class="p">.</span><span class="nx">listeners</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">loadFromStorage</span><span class="p">();</span>
<span class="p">}</span>
<span class="c1">// Get current state</span>
<span class="nx">getState</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span> <span class="p">...</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span> <span class="p">};</span>
<span class="p">}</span>
<span class="c1">// Update state</span>
<span class="nx">setState</span><span class="p">(</span><span class="nx">updates</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">prevState</span> <span class="o">=</span> <span class="p">{</span> <span class="p">...</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span> <span class="p">};</span>
<span class="k">this</span><span class="p">.</span><span class="nx">state</span> <span class="o">=</span> <span class="p">{</span> <span class="p">...</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">,</span> <span class="p">...</span><span class="nx">updates</span> <span class="p">};</span>
<span class="c1">// Notify listeners</span>
<span class="k">this</span><span class="p">.</span><span class="nx">notifyListeners</span><span class="p">(</span><span class="nx">prevState</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">);</span>
<span class="c1">// Persist certain state to localStorage</span>
<span class="k">this</span><span class="p">.</span><span class="nx">saveToStorage</span><span class="p">();</span>
<span class="p">}</span>
<span class="c1">// Subscribe to state changes</span>
<span class="nx">subscribe</span><span class="p">(</span><span class="nx">listener</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">id</span> <span class="o">=</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">()</span> <span class="o">+</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="nx">id</span><span class="p">,</span> <span class="nx">listener</span><span class="p">);</span>
<span class="c1">// Return unsubscribe function</span>
<span class="k">return</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">id</span><span class="p">);</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="nx">notifyListeners</span><span class="p">(</span><span class="nx">prevState</span><span class="p">,</span> <span class="nx">newState</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">listener</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="nx">listener</span><span class="p">(</span><span class="nx">newState</span><span class="p">,</span> <span class="nx">prevState</span><span class="p">);</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Error in state listener:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="nx">loadFromStorage</span><span class="p">()</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">userData</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">user_data</span><span class="dl">'</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">userData</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">user</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">userData</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="nx">theme</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">theme</span><span class="dl">'</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">theme</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">theme</span> <span class="o">=</span> <span class="nx">theme</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="nx">sidebarCollapsed</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">sidebar-collapsed</span><span class="dl">'</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">sidebarCollapsed</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">sidebarCollapsed</span> <span class="o">=</span> <span class="nx">sidebarCollapsed</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">true</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Failed to load state from storage:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">saveToStorage</span><span class="p">()</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">user</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">user_data</span><span class="dl">'</span><span class="p">,</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">user</span><span class="p">));</span>
<span class="p">}</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">theme</span><span class="dl">'</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">theme</span><span class="p">);</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">sidebar-collapsed</span><span class="dl">'</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">sidebarCollapsed</span><span class="p">.</span><span class="nx">toString</span><span class="p">());</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Failed to save state to storage:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Action methods</span>
<span class="nx">setUser</span><span class="p">(</span><span class="nx">user</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span> <span class="nx">user</span> <span class="p">});</span>
<span class="p">}</span>
<span class="nx">clearUser</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span> <span class="na">user</span><span class="p">:</span> <span class="kc">null</span> <span class="p">});</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">removeItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">user_data</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">removeItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">auth_token</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">setTheme</span><span class="p">(</span><span class="nx">theme</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span> <span class="nx">theme</span> <span class="p">});</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">documentElement</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="dl">'</span><span class="s1">data-theme</span><span class="dl">'</span><span class="p">,</span> <span class="nx">theme</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">toggleSidebar</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span> <span class="na">sidebarCollapsed</span><span class="p">:</span> <span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">sidebarCollapsed</span> <span class="p">});</span>
<span class="p">}</span>
<span class="nx">addNotification</span><span class="p">(</span><span class="nx">notification</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">notifications</span> <span class="o">=</span> <span class="p">[...</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">notifications</span><span class="p">,</span> <span class="p">{</span>
<span class="na">id</span><span class="p">:</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">(),</span>
<span class="na">timestamp</span><span class="p">:</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">(),</span>
<span class="p">...</span><span class="nx">notification</span>
<span class="p">}];</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span> <span class="nx">notifications</span> <span class="p">});</span>
<span class="p">}</span>
<span class="nx">removeNotification</span><span class="p">(</span><span class="nx">id</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">notifications</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">notifications</span><span class="p">.</span><span class="nx">filter</span><span class="p">(</span><span class="nx">n</span> <span class="o">=></span> <span class="nx">n</span><span class="p">.</span><span class="nx">id</span> <span class="o">!==</span> <span class="nx">id</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span> <span class="nx">notifications</span> <span class="p">});</span>
<span class="p">}</span>
<span class="nx">setLoading</span><span class="p">(</span><span class="nx">loading</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span> <span class="nx">loading</span> <span class="p">});</span>
<span class="p">}</span>
<span class="nx">setError</span><span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span> <span class="nx">error</span> <span class="p">});</span>
<span class="p">}</span>
<span class="nx">clearError</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span> <span class="na">error</span><span class="p">:</span> <span class="kc">null</span> <span class="p">});</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Create singleton instance</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">appStore</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">AppStore</span><span class="p">();</span>
<span class="c1">// Helper hook for components</span>
<span class="k">export</span> <span class="kd">function</span> <span class="nx">useStore</span><span class="p">(</span><span class="nx">selector</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">state</span> <span class="o">=</span> <span class="nx">appStore</span><span class="p">.</span><span class="nx">getState</span><span class="p">();</span>
<span class="k">return</span> <span class="nx">selector</span> <span class="p">?</span> <span class="nx">selector</span><span class="p">(</span><span class="nx">state</span><span class="p">)</span> <span class="p">:</span> <span class="nx">state</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="data-caching">
<a href="#data-caching" class="anchor-heading" aria-labelledby="data-caching"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Data Caching
</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// src/js/cache/data-cache.js</span>
<span class="kd">class</span> <span class="nx">DataCache</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">cache</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">expiry</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">defaultTTL</span> <span class="o">=</span> <span class="mi">5</span> <span class="o">*</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">;</span> <span class="c1">// 5 minutes</span>
<span class="p">}</span>
<span class="kd">set</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">ttl</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">defaultTTL</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">cache</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">expiry</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">()</span> <span class="o">+</span> <span class="nx">ttl</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">get</span><span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">cache</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span><span class="nx">key</span><span class="p">))</span> <span class="p">{</span>
<span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="nx">expiryTime</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">expiry</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">()</span> <span class="o">></span> <span class="nx">expiryTime</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
<span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">cache</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">has</span><span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="o">!==</span> <span class="kc">null</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">delete</span><span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">cache</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">expiry</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">clear</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">cache</span><span class="p">.</span><span class="nx">clear</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">expiry</span><span class="p">.</span><span class="nx">clear</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">cleanup</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">now</span> <span class="o">=</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">();</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">const</span> <span class="p">[</span><span class="nx">key</span><span class="p">,</span> <span class="nx">expiryTime</span><span class="p">]</span> <span class="k">of</span> <span class="k">this</span><span class="p">.</span><span class="nx">expiry</span><span class="p">.</span><span class="nx">entries</span><span class="p">())</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">now</span> <span class="o">></span> <span class="nx">expiryTime</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">size</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">cache</span><span class="p">.</span><span class="nx">size</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Create singleton instance</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">dataCache</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">DataCache</span><span class="p">();</span>
<span class="c1">// Auto cleanup every 5 minutes</span>
<span class="nx">setInterval</span><span class="p">(()</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">dataCache</span><span class="p">.</span><span class="nx">cleanup</span><span class="p">();</span>
<span class="p">},</span> <span class="mi">5</span> <span class="o">*</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">);</span>
</code></pre></div></div><hr />
<h2 id="authentication-integration">
<a href="#authentication-integration" class="anchor-heading" aria-labelledby="authentication-integration"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Authentication Integration
</h2>
<h3 id="jwt-token-management">
<a href="#jwt-token-management" class="anchor-heading" aria-labelledby="jwt-token-management"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> JWT Token Management
</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// src/js/auth/auth-manager.js</span>
<span class="kd">class</span> <span class="nx">AuthManager</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">token</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">auth_token</span><span class="dl">'</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">refreshTimer</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">init</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">init</span><span class="p">()</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">token</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">scheduleTokenRefresh</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">login</span><span class="p">(</span><span class="nx">credentials</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">userService</span><span class="p">.</span><span class="nx">authenticate</span><span class="p">(</span><span class="nx">credentials</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">success</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">token</span> <span class="o">=</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">token</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">scheduleTokenRefresh</span><span class="p">();</span>
<span class="c1">// Update app state</span>
<span class="nx">appStore</span><span class="p">.</span><span class="nx">setUser</span><span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">user</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">response</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">response</span><span class="p">;</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">logout</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">clearTokenRefresh</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">token</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="c1">// Clear app state</span>
<span class="nx">appStore</span><span class="p">.</span><span class="nx">clearUser</span><span class="p">();</span>
<span class="c1">// Call logout service</span>
<span class="nx">userService</span><span class="p">.</span><span class="nx">logout</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">isAuthenticated</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="o">!!</span><span class="k">this</span><span class="p">.</span><span class="nx">token</span> <span class="o">&&</span> <span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">isTokenExpired</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">isTokenExpired</span><span class="p">()</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">token</span><span class="p">)</span> <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span>
gitextract_kv1kv1do/ ├── .editorconfig ├── .github/ │ └── workflows/ │ └── jekyll-gh-pages.yml ├── .gitignore ├── .npmignore ├── .prettierignore ├── .prettierrc ├── LICENSE.txt ├── README.md ├── README_CN.md ├── changelog.md ├── dev-watch.sh ├── docs/ │ ├── Gemfile │ ├── README.md │ ├── _config.yml │ ├── _site/ │ │ ├── api-integration/ │ │ │ └── index.html │ │ ├── assets/ │ │ │ ├── css/ │ │ │ │ ├── just-the-docs-dark.css │ │ │ │ ├── just-the-docs-default.css │ │ │ │ ├── just-the-docs-head-nav.css │ │ │ │ └── just-the-docs-light.css │ │ │ └── js/ │ │ │ ├── just-the-docs.js │ │ │ └── search-data.json │ │ ├── bundle-analysis/ │ │ │ └── index.html │ │ ├── bundle-analysis.md │ │ ├── components/ │ │ │ └── index.html │ │ ├── configuration/ │ │ │ └── index.html │ │ ├── customization/ │ │ │ └── index.html │ │ ├── daterangepicker-fix/ │ │ │ └── index.html │ │ ├── daterangepicker-fix.md │ │ ├── deployment/ │ │ │ └── index.html │ │ ├── feed.xml │ │ ├── index.html │ │ ├── installation/ │ │ │ └── index.html │ │ ├── jquery-elimination-complete/ │ │ │ └── index.html │ │ ├── jquery-elimination-complete.md │ │ ├── robots.txt │ │ ├── security-headers/ │ │ │ └── index.html │ │ ├── security-headers.md │ │ └── sitemap.xml │ ├── api-integration.md │ ├── bundle-analysis.md │ ├── components.md │ ├── configuration.md │ ├── customization.md │ ├── deployment.md │ ├── index.md │ ├── installation.md │ ├── jquery-elimination-complete.md │ ├── performance.md │ └── security-headers.md ├── eslint.config.js ├── package.json ├── production/ │ ├── calendar.html │ ├── chartjs.html │ ├── contacts.html │ ├── e_commerce.html │ ├── echarts.html │ ├── fixed_footer.html │ ├── fixed_sidebar.html │ ├── form.html │ ├── form_advanced.html │ ├── form_buttons.html │ ├── form_upload.html │ ├── form_validation.html │ ├── form_wizards.html │ ├── general_elements.html │ ├── icons.html │ ├── inbox.html │ ├── index.html │ ├── index2.html │ ├── index3.html │ ├── index4.html │ ├── invoice.html │ ├── landing.html │ ├── level2.html │ ├── login.html │ ├── map.html │ ├── media_gallery.html │ ├── other_charts.html │ ├── page_403.html │ ├── page_404.html │ ├── page_500.html │ ├── plain_page.html │ ├── pricing_tables.html │ ├── profile.html │ ├── project_detail.html │ ├── projects.html │ ├── tables.html │ ├── tables_dynamic.html │ ├── theme-comparison.html │ ├── typography.html │ └── widgets.html ├── public/ │ └── site.webmanifest ├── src/ │ ├── chart-initializer.js │ ├── js/ │ │ ├── helpers/ │ │ │ └── smartresize.js │ │ ├── init.js │ │ ├── page/ │ │ │ └── index3-analytics.js │ │ └── sidebar.js │ ├── main-calendar.js │ ├── main-core.js │ ├── main-form-basic.js │ ├── main-inbox.js │ ├── main-minimal.js │ ├── main-tables.js │ ├── main-upload.js │ ├── main.scss │ ├── modules/ │ │ ├── chart-core.js │ │ ├── charts.js │ │ ├── dashboard-pages.js │ │ ├── dashboard.js │ │ ├── echarts.js │ │ ├── forms.js │ │ ├── maps.js │ │ ├── tables.js │ │ ├── ui-components.js │ │ └── weather.js │ ├── scss/ │ │ ├── _color-schemes.scss │ │ ├── _variables-modern.scss │ │ ├── _variables.scss │ │ ├── custom.scss │ │ ├── daterangepicker.scss │ │ ├── font-optimization.scss │ │ ├── index2.scss │ │ ├── index4.scss │ │ └── landing.scss │ ├── test/ │ │ └── setup.js │ └── utils/ │ ├── dom.js │ ├── dom.test.js │ ├── logger.js │ ├── logger.test.js │ ├── security.js │ ├── security.test.js │ ├── table-optimizer.js │ ├── validation.js │ └── validation.test.js ├── tests/ │ └── README.md ├── vite.config.js └── vitest.config.js
SYMBOL INDEX (152 symbols across 22 files)
FILE: docs/_site/assets/js/just-the-docs.js
function initNav (line 24) | function initNav() {
function disableHeadStyleSheets (line 65) | function disableHeadStyleSheets() {
function initSearch (line 78) | function initSearch() {
function searchLoaded (line 119) | function searchLoaded(index, docs) {
function navLink (line 465) | function navLink() {
function scrollNav (line 492) | function scrollNav() {
function activateNav (line 503) | function activateNav() {
FILE: src/chart-initializer.js
constant CHART_CONFIGS (line 7) | const CHART_CONFIGS = {
constant SAMPLE_DATA (line 131) | const SAMPLE_DATA = {
class ChartInitializer (line 317) | class ChartInitializer {
method constructor (line 318) | constructor() {
method createDOMUtils (line 323) | createDOMUtils() {
method waitForChart (line 334) | async waitForChart(maxAttempts = 100) {
method createCanvas (line 351) | createCanvas(container, width = 400, height = 200) {
method getCanvasContext (line 360) | getCanvasContext(canvasOrId, containerWidth, containerHeight) {
method initChart (line 383) | initChart(canvasOrId, chartType, customData = null, customOptions = {}) {
method initSparkline (line 416) | initSparkline(container, data = null, color = '#26B99A', chartType = '...
method initKnobChart (line 452) | initKnobChart(container, percent = 50) {
method initializeAllCharts (line 488) | async initializeAllCharts() {
method initChartjsPages (line 518) | initChartjsPages() {
method initDashboardCharts (line 528) | initDashboardCharts() {
method initWidgetCharts (line 795) | initWidgetCharts() {
method initSparklineCharts (line 857) | initSparklineCharts() {
method initKnobCharts (line 940) | initKnobCharts() {
method initMaps (line 1000) | initMaps() {
method initDataTables (line 1089) | initDataTables() {
method destroyAllCharts (line 1186) | destroyAllCharts() {
FILE: src/js/helpers/smartresize.js
function debounce (line 10) | function debounce(func, wait = 250, immediate = false) {
method add (line 33) | add(handler, wait = 250) {
method remove (line 41) | remove(handler) {
method clear (line 47) | clear() {
FILE: src/js/init.js
function initializeDatePickers (line 23) | async function initializeDatePickers() {
function initializePanelToolbox (line 85) | function initializePanelToolbox() {
function initializeProgressBars (line 152) | function initializeProgressBars() {
function initializeFormValidation (line 190) | function initializeFormValidation() {
function initializeTabsAndAccordions (line 234) | function initializeTabsAndAccordions() {
function initializeModals (line 272) | function initializeModals() {
function initializeDragAndDrop (line 297) | function initializeDragAndDrop() {
function initializeSearchAndFilter (line 332) | function initializeSearchAndFilter() {
function initializeKeyboardShortcuts (line 368) | function initializeKeyboardShortcuts() {
function initializeModernComponents (line 405) | async function initializeModernComponents() {
function showLoadingStatus (line 427) | function showLoadingStatus() {
FILE: src/js/page/index3-analytics.js
function initSalesAnalytics (line 10) | function initSalesAnalytics() {
FILE: src/js/sidebar.js
function initSidebar (line 9) | function initSidebar() {
FILE: src/main-calendar.js
function formatDateForInput (line 95) | function formatDateForInput(date) {
function generateEventId (line 108) | function generateEventId() {
function openNewEventModal (line 172) | function openNewEventModal(selectInfo) {
function showEventDetails (line 191) | function showEventDetails(event) {
function openEditEventModal (line 269) | function openEditEventModal(event) {
function setupModalHandlers (line 285) | function setupModalHandlers() {
function showToast (line 384) | function showToast(message, type = 'info') {
function createToastContainer (line 414) | function createToastContainer() {
FILE: src/main-core.js
function checkReady (line 209) | function checkReady() {
FILE: src/main-form-basic.js
function check (line 66) | function check() {
FILE: src/main-minimal.js
constant DOM (line 5) | const DOM = {
function initProgressBars (line 269) | function initProgressBars() {
function initUniversalProgressBars (line 293) | function initUniversalProgressBars() {
FILE: src/main-tables.js
constant DOM (line 33) | const DOM = {
FILE: src/modules/chart-core.js
function initializeCharts (line 17) | function initializeCharts() {
function initializeNetworkCharts (line 81) | function initializeNetworkCharts() {
function generateNetworkData (line 158) | function generateNetworkData() {
function startNetworkUpdates (line 175) | function startNetworkUpdates(chart, chartId) {
function createGaugeChart (line 198) | function createGaugeChart(canvasId, value, options = {}) {
method destroyAllCharts (line 278) | destroyAllCharts() {
method updateChart (line 291) | updateChart(chartId, newData) {
method resizeAllCharts (line 304) | resizeAllCharts() {
method exportChart (line 315) | exportChart(chartId, filename = 'chart.png') {
method getChartData (line 331) | getChartData(chartId) {
function setupResponsiveCharts (line 340) | function setupResponsiveCharts() {
function initializeIndexDashboardCharts (line 363) | function initializeIndexDashboardCharts() {
FILE: src/modules/dashboard-pages.js
function initializeIndex2 (line 17) | function initializeIndex2() {
function initializeWeeklySummaryChart (line 37) | function initializeWeeklySummaryChart() {
function initializeDailyActivitiesChart (line 108) | function initializeDailyActivitiesChart() {
function initializeIndex3 (line 151) | function initializeIndex3() {
function initializeSalesOverviewChart (line 172) | function initializeSalesOverviewChart() {
function initializeRevenueChart (line 249) | function initializeRevenueChart() {
function initializeTopProductsChart (line 288) | function initializeTopProductsChart() {
function initializeIndex4 (line 329) | function initializeIndex4() {
function initializeStoreAnalyticsChart (line 350) | function initializeStoreAnalyticsChart() {
function initializeCustomerSegmentChart (line 410) | function initializeCustomerSegmentChart() {
function initializeInventoryChart (line 447) | function initializeInventoryChart() {
function initializeSidebarGauges (line 486) | function initializeSidebarGauges() {
function initializeProfileCompletionGauge (line 507) | function initializeProfileCompletionGauge() {
function initializeSystemHealthGauges (line 571) | function initializeSystemHealthGauges() {
function generateWeeklyData (line 645) | function generateWeeklyData() {
function generateSalesData (line 653) | function generateSalesData() {
FILE: src/modules/echarts.js
function initializeECharts (line 17) | function initializeECharts() {
function initializePieCharts (line 53) | function initializePieCharts() {
function initializeBarCharts (line 176) | function initializeBarCharts() {
function initializeLineCharts (line 296) | function initializeLineCharts() {
function initializeScatterCharts (line 331) | function initializeScatterCharts() {
function initializeMapCharts (line 370) | function initializeMapCharts() {
function initializeGaugeCharts (line 425) | function initializeGaugeCharts() {
function initializeMixedCharts (line 488) | function initializeMixedCharts() {
function setupEChartsResize (line 636) | function setupEChartsResize() {
method getChart (line 668) | getChart(chartId) {
method updateChart (line 676) | updateChart(chartId, newOption) {
method exportChart (line 688) | exportChart(chartId, options = {}) {
method disposeAllCharts (line 711) | disposeAllCharts() {
FILE: src/modules/maps.js
function initializeMaps (line 14) | function initializeMaps() {
function initializeLocationMap (line 73) | function initializeLocationMap() {
function initializeWorldMapGDP (line 107) | function initializeWorldMapGDP() {
function initializeContactMap (line 184) | function initializeContactMap() {
function initializeMultiLocationMap (line 227) | function initializeMultiLocationMap(locations = []) {
method geocode (line 301) | async geocode(address) {
method calculateDistance (line 316) | calculateDistance(lat1, lng1, lat2, lng2) {
method addCustomControls (line 333) | addCustomControls(map) {
FILE: src/modules/tables.js
function initializeModernDataTables (line 24) | function initializeModernDataTables() {
function getTableConfig (line 72) | function getTableConfig(table) {
function initializeAdvancedTables (line 127) | function initializeAdvancedTables() {
function initializeExportTables (line 155) | function initializeExportTables() {
function initializeResponsiveTables (line 216) | function initializeResponsiveTables() {
function updateTableData (line 249) | function updateTableData(tableId, newData) {
method getTableData (line 283) | getTableData(tableId) {
method addRow (line 294) | addRow(tableId, rowData) {
method removeRow (line 306) | removeRow(tableId, rowIndex) {
method searchTable (line 318) | searchTable(tableId, searchTerm) {
method exportTable (line 330) | exportTable(tableId, format = 'csv') {
method destroyAllTables (line 360) | destroyAllTables() {
method reinitializeTable (line 373) | reinitializeTable(tableId) {
function initializeSampleTables (line 393) | function initializeSampleTables() {
FILE: src/modules/ui-components.js
function initializePanelToolbox (line 18) | function initializePanelToolbox() {
function initializeProgressBars (line 45) | function initializeProgressBars() {
function initializeToasts (line 119) | function initializeToasts() {
function initializeBootstrapComponents (line 142) | function initializeBootstrapComponents() {
FILE: src/modules/weather.js
function initializeSkycons (line 14) | function initializeSkycons() {
function simulateWeatherData (line 101) | function simulateWeatherData() {
function fetchWeatherData (line 137) | async function fetchWeatherData(location = 'New York') {
FILE: src/utils/dom.js
constant DOM (line 6) | const DOM = {
FILE: src/utils/security.js
function sanitizeHtml (line 10) | function sanitizeHtml(html, options = {}) {
function sanitizeText (line 45) | function sanitizeText(text) {
function setSafeInnerHTML (line 62) | function setSafeInnerHTML(element, html, options = {}) {
FILE: src/utils/table-optimizer.js
function optimizeTablePerformance (line 12) | function optimizeTablePerformance() {
function addTableLoadingSkeletons (line 29) | function addTableLoadingSkeletons() {
function initializeTablesProgressively (line 74) | function initializeTablesProgressively() {
function initializeSpecificTable (line 92) | function initializeSpecificTable(tableId) {
function implementLazyTableLoading (line 150) | function implementLazyTableLoading() {
function optimizeTableDimensions (line 189) | function optimizeTableDimensions() {
FILE: src/utils/validation.js
function isValidEmail (line 11) | function isValidEmail(email) {
function isValidPhone (line 21) | function isValidPhone(phone) {
function isValidURL (line 34) | function isValidURL(url) {
function validatePassword (line 48) | function validatePassword(password) {
function isValidCreditCard (line 99) | function isValidCreditCard(cardNumber) {
function isValidDate (line 134) | function isValidDate(dateString, format = 'YYYY-MM-DD') {
function isAlphanumeric (line 162) | function isAlphanumeric(value, allowSpaces = false) {
function isInRange (line 174) | function isInRange(value, min, max) {
function isRequired (line 184) | function isRequired(value) {
function isValidFileType (line 203) | function isValidFileType(file, allowedTypes) {
function isValidFileSize (line 228) | function isValidFileSize(file, maxSizeInMB) {
function validateForm (line 242) | function validateForm(form, rules) {
function displayValidationErrors (line 286) | function displayValidationErrors(form, errors) {
function clearValidationErrors (line 320) | function clearValidationErrors(form) {
Condensed preview — 137 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,694K chars).
[
{
"path": ".editorconfig",
"chars": 1061,
"preview": "# EditorConfig helps maintain consistent coding styles for multiple developers\n# working on the same project across vari"
},
{
"path": ".github/workflows/jekyll-gh-pages.yml",
"chars": 1324,
"preview": "# Build and deploy Jekyll documentation site to GitHub Pages\nname: Deploy Documentation to GitHub Pages\n\non:\n push:\n "
},
{
"path": ".gitignore",
"chars": 345,
"preview": "nbproject\nnpm-debug.log\nnode_modules\n.sass-cache\nCLAUDE.md\n\n# Build outputs\ndist/\n\n# Vendor dependencies (generated from"
},
{
"path": ".npmignore",
"chars": 494,
"preview": "# Development files\n.editorconfig\n.prettierignore\n.prettierrc\n.github/\n.claude/\neslint.config.js\nvite.config.js\nGITHUB_R"
},
{
"path": ".prettierignore",
"chars": 275,
"preview": "# Dependencies\nnode_modules/\n\n# Build outputs\ndist/\ndocs/_site/\n\n# Generated files\n*.min.js\n*.min.css\npackage-lock.json\n"
},
{
"path": ".prettierrc",
"chars": 512,
"preview": "{\n \"printWidth\": 100,\n \"tabWidth\": 2,\n \"useTabs\": false,\n \"semi\": true,\n \"singleQuote\": true,\n \"quoteProps\": \"as-n"
},
{
"path": "LICENSE.txt",
"chars": 1093,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2025 Aigars Silkalns & Colorlib\n\nPermission is hereby granted, free of charge, to a"
},
{
"path": "README.md",
"chars": 21096,
"preview": "# Gentelella Admin Template\n\n**Modern Bootstrap 5 Admin Dashboard Template with Vite Build System**\n\nGentelella is a pow"
},
{
"path": "README_CN.md",
"chars": 6270,
"preview": "# gentelella\n\nGentelella 管理后台是一个免费使用的Bootstrap管理模版。\n这个模版默认使用Bootstrap 3 风格,还有一系列强大的jQuery插件和工具去创造一个强大的框架,用来创建管理面板或者后端仪表盘"
},
{
"path": "changelog.md",
"chars": 20321,
"preview": "# Gentelella Changelog\n\n## 2.1.5 - 15.02.2026\n\n**Documentation Overhaul & jQuery Cleanup Release**\n\n### Documentation Si"
},
{
"path": "dev-watch.sh",
"chars": 549,
"preview": "#!/bin/bash\n\n# Dev server auto-restart script\n# This script will automatically restart the dev server if it crashes\n\nech"
},
{
"path": "docs/Gemfile",
"chars": 669,
"preview": "source \"https://rubygems.org\"\n\n# GitHub Pages compatible Jekyll version\ngem \"github-pages\", group: :jekyll_plugins\n\n# Ov"
},
{
"path": "docs/README.md",
"chars": 6665,
"preview": "# Gentelella Admin Template Documentation\n\nThis directory contains the complete documentation for Gentelella Admin Templ"
},
{
"path": "docs/_config.yml",
"chars": 1739,
"preview": "title: Gentelella Admin Template\ndescription: Modern Bootstrap 5 Admin Dashboard Template with Performance Optimizations"
},
{
"path": "docs/_site/api-integration/index.html",
"chars": 168740,
"preview": "\n\n<!DOCTYPE html>\n\n<html lang=\"en-US\">\n<head>\n <meta charset=\"UTF-8\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE="
},
{
"path": "docs/_site/assets/css/just-the-docs-dark.css",
"chars": 121944,
"preview": "@charset \"UTF-8\";\n.highlight, pre.highlight { background: #f9f9f9; color: #383942; }\n\n.highlight pre { background: #f9f9"
},
{
"path": "docs/_site/assets/css/just-the-docs-default.css",
"chars": 119462,
"preview": "@charset \"UTF-8\";\n.highlight, pre.highlight { background: #f9f9f9; color: #383942; }\n\n.highlight pre { background: #f9f9"
},
{
"path": "docs/_site/assets/css/just-the-docs-head-nav.css",
"chars": 10429,
"preview": "\n\n<!DOCTYPE html>\n\n<html lang=\"en-US\">\n<head>\n <meta charset=\"UTF-8\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE="
},
{
"path": "docs/_site/assets/css/just-the-docs-light.css",
"chars": 119462,
"preview": "@charset \"UTF-8\";\n.highlight, pre.highlight { background: #f9f9f9; color: #383942; }\n\n.highlight pre { background: #f9f9"
},
{
"path": "docs/_site/assets/js/just-the-docs.js",
"chars": 18993,
"preview": "(function (jtd, undefined) {\n\n// Event handling\n\njtd.addEvent = function(el, type, handler) {\n if (el.attachEvent) el.a"
},
{
"path": "docs/_site/assets/js/search-data.json",
"chars": 152663,
"preview": "{\"0\": {\n \"doc\": \"API Integration\",\n \"title\": \"API Integration Guide\",\n \"content\": \"Learn how to integrate Gente"
},
{
"path": "docs/_site/bundle-analysis/index.html",
"chars": 19671,
"preview": "\n\n<!DOCTYPE html>\n\n<html lang=\"en-US\">\n<head>\n <meta charset=\"UTF-8\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE="
},
{
"path": "docs/_site/bundle-analysis.md",
"chars": 2973,
"preview": "# Bundle Analysis Guide\n\nThis guide explains how to use the bundle analyzer to monitor and optimize the bundle size of t"
},
{
"path": "docs/_site/components/index.html",
"chars": 110459,
"preview": "\n\n<!DOCTYPE html>\n\n<html lang=\"en-US\">\n<head>\n <meta charset=\"UTF-8\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE="
},
{
"path": "docs/_site/configuration/index.html",
"chars": 76967,
"preview": "\n\n<!DOCTYPE html>\n\n<html lang=\"en-US\">\n<head>\n <meta charset=\"UTF-8\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE="
},
{
"path": "docs/_site/customization/index.html",
"chars": 197310,
"preview": "\n\n<!DOCTYPE html>\n\n<html lang=\"en-US\">\n<head>\n <meta charset=\"UTF-8\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE="
},
{
"path": "docs/_site/daterangepicker-fix/index.html",
"chars": 27467,
"preview": "\n\n<!DOCTYPE html>\n\n<html lang=\"en-US\">\n<head>\n <meta charset=\"UTF-8\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE="
},
{
"path": "docs/_site/daterangepicker-fix.md",
"chars": 4922,
"preview": "# Date Range Picker Fix Documentation\n\n## Issue\nThe daterangepicker plugin was throwing an error:\n```\nError setting defa"
},
{
"path": "docs/_site/deployment/index.html",
"chars": 96189,
"preview": "\n\n<!DOCTYPE html>\n\n<html lang=\"en-US\">\n<head>\n <meta charset=\"UTF-8\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE="
},
{
"path": "docs/_site/feed.xml",
"chars": 596,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed xmlns=\"http://www.w3.org/2005/Atom\" ><generator uri=\"https://jekyllrb.com/\" "
},
{
"path": "docs/_site/index.html",
"chars": 22003,
"preview": "\n\n<!DOCTYPE html>\n\n<html lang=\"en-US\">\n<head>\n <meta charset=\"UTF-8\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE="
},
{
"path": "docs/_site/installation/index.html",
"chars": 33910,
"preview": "\n\n<!DOCTYPE html>\n\n<html lang=\"en-US\">\n<head>\n <meta charset=\"UTF-8\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE="
},
{
"path": "docs/_site/jquery-elimination-complete/index.html",
"chars": 38774,
"preview": "\n\n<!DOCTYPE html>\n\n<html lang=\"en-US\">\n<head>\n <meta charset=\"UTF-8\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE="
},
{
"path": "docs/_site/jquery-elimination-complete.md",
"chars": 10657,
"preview": "# Complete jQuery Elimination Achievement 🎉\n\n## Executive Summary\n\nWe have successfully **eliminated 100% of jQuery depe"
},
{
"path": "docs/_site/robots.txt",
"chars": 59,
"preview": "Sitemap: https://puikinsh.github.io/gentelella/sitemap.xml\n"
},
{
"path": "docs/_site/security-headers/index.html",
"chars": 43582,
"preview": "\n\n<!DOCTYPE html>\n\n<html lang=\"en-US\">\n<head>\n <meta charset=\"UTF-8\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE="
},
{
"path": "docs/_site/security-headers.md",
"chars": 10621,
"preview": "# Security Headers Implementation Guide\n\nThis guide explains how to implement security headers for the Gentelella admin "
},
{
"path": "docs/_site/sitemap.xml",
"chars": 1138,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation="
},
{
"path": "docs/api-integration.md",
"chars": 29378,
"preview": "---\nlayout: default\ntitle: API Integration\nnav_order: 8\n---\n\n# API Integration Guide\n{: .no_toc }\n\nLearn how to integrat"
},
{
"path": "docs/bundle-analysis.md",
"chars": 3453,
"preview": "---\nlayout: default\ntitle: Bundle Analysis\nnav_order: 9\n---\n\n# Bundle Analysis Guide\n\nThis guide explains how to use the"
},
{
"path": "docs/components.md",
"chars": 16965,
"preview": "---\nlayout: default\ntitle: Components Guide\nnav_order: 4\n---\n\n# Components Guide\n{: .no_toc }\n\nComplete reference for al"
},
{
"path": "docs/configuration.md",
"chars": 13625,
"preview": "---\nlayout: default\ntitle: Configuration\nnav_order: 3\n---\n\n# Configuration Guide\n{: .no_toc }\n\nComplete guide to configu"
},
{
"path": "docs/customization.md",
"chars": 34493,
"preview": "---\nlayout: default\ntitle: Customization Guide\nnav_order: 7\n---\n\n# Customization Guide\n{: .no_toc }\n\nLearn how to custom"
},
{
"path": "docs/deployment.md",
"chars": 19388,
"preview": "---\nlayout: default\ntitle: Deployment Guide\nnav_order: 6\n---\n\n# Deployment Guide\n{: .no_toc }\n\nComplete guide to deployi"
},
{
"path": "docs/index.md",
"chars": 4395,
"preview": "---\nlayout: default\ntitle: Gentelella Admin Template Documentation\nnav_order: 1\ndescription: \"Modern Bootstrap 5 Admin D"
},
{
"path": "docs/installation.md",
"chars": 7684,
"preview": "---\nlayout: default\ntitle: Installation Guide\nnav_order: 2\n---\n\n# Installation Guide\n{: .no_toc }\n\nComplete installation"
},
{
"path": "docs/jquery-elimination-complete.md",
"chars": 10720,
"preview": "---\nlayout: default\ntitle: jQuery Elimination\nnav_order: 10\n---\n\n# Complete jQuery Elimination Achievement\n\n## Executive"
},
{
"path": "docs/performance.md",
"chars": 4086,
"preview": "---\nlayout: default\ntitle: Performance Guide\nnav_order: 5\ndescription: \"Performance optimization strategies for Gentelel"
},
{
"path": "docs/security-headers.md",
"chars": 10684,
"preview": "---\nlayout: default\ntitle: Security Headers\nnav_order: 11\n---\n\n# Security Headers Implementation Guide\n\nThis guide expla"
},
{
"path": "eslint.config.js",
"chars": 3513,
"preview": "import js from '@eslint/js';\nimport prettierConfig from 'eslint-config-prettier';\n\nexport default [\n js.configs.recomme"
},
{
"path": "package.json",
"chars": 2888,
"preview": "{\n \"name\": \"gentelella\",\n \"version\": \"2.1.5\",\n \"type\": \"module\",\n \"description\": \"Gentelella Admin is a free to use "
},
{
"path": "production/calendar.html",
"chars": 31062,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/chartjs.html",
"chars": 21826,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <m"
},
{
"path": "production/contacts.html",
"chars": 55126,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/e_commerce.html",
"chars": 36006,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/echarts.html",
"chars": 27272,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/fixed_footer.html",
"chars": 18799,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/fixed_sidebar.html",
"chars": 15629,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/form.html",
"chars": 57748,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t<!-- Met"
},
{
"path": "production/form_advanced.html",
"chars": 49184,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <m"
},
{
"path": "production/form_buttons.html",
"chars": 34985,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!-- Me"
},
{
"path": "production/form_upload.html",
"chars": 15638,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <"
},
{
"path": "production/form_validation.html",
"chars": 39043,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!-"
},
{
"path": "production/form_wizards.html",
"chars": 35788,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/general_elements.html",
"chars": 61001,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <"
},
{
"path": "production/icons.html",
"chars": 60756,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/inbox.html",
"chars": 33351,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/index.html",
"chars": 76950,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/index2.html",
"chars": 39610,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/index3.html",
"chars": 38572,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/index4.html",
"chars": 29830,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <"
},
{
"path": "production/invoice.html",
"chars": 24377,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/landing.html",
"chars": 29979,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <m"
},
{
"path": "production/level2.html",
"chars": 13778,
"preview": "\n<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <"
},
{
"path": "production/login.html",
"chars": 10833,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/map.html",
"chars": 15175,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!-- Me"
},
{
"path": "production/media_gallery.html",
"chars": 44446,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <"
},
{
"path": "production/other_charts.html",
"chars": 25100,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/page_403.html",
"chars": 4706,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/page_404.html",
"chars": 4727,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/page_500.html",
"chars": 5878,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/plain_page.html",
"chars": 15496,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/pricing_tables.html",
"chars": 37701,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/profile.html",
"chars": 37955,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/project_detail.html",
"chars": 55481,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/projects.html",
"chars": 68820,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/tables.html",
"chars": 46239,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/tables_dynamic.html",
"chars": 85983,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/theme-comparison.html",
"chars": 23236,
"preview": "<!DOCTYPE html>\n<html lang=\"en\" data-theme=\"forest\">\n <head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" conte"
},
{
"path": "production/typography.html",
"chars": 35210,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "production/widgets.html",
"chars": 45145,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <!"
},
{
"path": "public/site.webmanifest",
"chars": 568,
"preview": "{\n \"name\": \"Gentelella Admin\",\n \"short_name\": \"Gentelella\",\n \"description\": \"Bootstrap 5 Admin Template\",\n \""
},
{
"path": "src/chart-initializer.js",
"chars": 36532,
"preview": "/**\n * Comprehensive Chart Initialization System\n * Handles ALL chart types across ALL pages systematically\n */\n\n// Char"
},
{
"path": "src/js/helpers/smartresize.js",
"chars": 1653,
"preview": "/**\n * Modern SmartResize - jQuery-free version\n * Debounced resize event handler for better performance\n */\n\n// Import "
},
{
"path": "src/js/init.js",
"chars": 13547,
"preview": "/**\n * Modern Init.js - jQuery Eliminated\n * This is the new, modernized version of init.js with all jQuery dependencies"
},
{
"path": "src/js/page/index3-analytics.js",
"chars": 2217,
"preview": "// Sales Analytics Widget Initialization\n\n// Get security utilities from window if available\nconst sanitizeHtml =\n wind"
},
{
"path": "src/js/sidebar.js",
"chars": 4976,
"preview": "/**\n * Modern Sidebar - jQuery-free version\n * Enhanced sidebar menu with proper multilevel support\n */\n\n// Import canon"
},
{
"path": "src/main-calendar.js",
"chars": 13847,
"preview": "// Calendar.html specific JavaScript with FullCalendar integration\n\n// Import DOMPurify for XSS protection\nimport DOMPur"
},
{
"path": "src/main-core.js",
"chars": 6646,
"preview": "// CORE ESSENTIALS - Only what every page needs (jQuery-free)\n\n// Import and expose security utilities globally\nimport {"
},
{
"path": "src/main-form-basic.js",
"chars": 6089,
"preview": "// jQuery-free main.js for form_advanced.html - modern alternatives\n\n// Bootstrap 5 - No jQuery dependency needed\nimport"
},
{
"path": "src/main-inbox.js",
"chars": 3608,
"preview": "// Inbox.html specific JavaScript with Quill rich text editor\n\n// Import security utilities\nimport { sanitizeHtml } from"
},
{
"path": "src/main-minimal.js",
"chars": 10739,
"preview": "// Modern jQuery-Free Minimal Bundle\n// Complete replacement for jQuery dependencies\n\n// Native DOM utilities (jQuery re"
},
{
"path": "src/main-tables.js",
"chars": 4188,
"preview": "// Dedicated entry point for tables_dynamic.html\n// Ensures proper DataTables initialization without conflicts\n\n// Impor"
},
{
"path": "src/main-upload.js",
"chars": 2836,
"preview": "// Form Upload.html specific JavaScript with Uppy integration (jQuery-free)\n\n// Bootstrap 5\nimport * as bootstrap from '"
},
{
"path": "src/main.scss",
"chars": 2112,
"preview": "// SCSS files using @use (must come first)\n@use \"bootstrap/scss/bootstrap\";\n\n// ========================================"
},
{
"path": "src/modules/chart-core.js",
"chars": 14031,
"preview": "/**\n * Chart Core Module\n * Modernized chart initialization and utilities\n * Extracted and modernized from init.js - jQu"
},
{
"path": "src/modules/charts.js",
"chars": 574,
"preview": "// Charts Module - Only loaded when needed\n\n// Chart.js v4 - Modern charting library\nimport { Chart, registerables } fro"
},
{
"path": "src/modules/dashboard-pages.js",
"chars": 15985,
"preview": "/**\n * Dashboard Pages Module\n * Page-specific functionality extracted from init.js\n * Modernized from jQuery to vanilla"
},
{
"path": "src/modules/dashboard.js",
"chars": 266,
"preview": "// Dashboard Module - Only loaded on dashboard pages\n\n// Dashboard-specific widgets and functionality\n// Uses Chart.js f"
},
{
"path": "src/modules/echarts.js",
"chars": 19826,
"preview": "/**\n * Modern ECharts Module\n * Extracted and modernized from init.js - jQuery eliminated\n * Handles all ECharts impleme"
},
{
"path": "src/modules/forms.js",
"chars": 1170,
"preview": "// Forms Module - Only loaded on form pages\n\n// Tempus Dominus DateTimePicker (Bootstrap 5 compatible)\nimport { TempusDo"
},
{
"path": "src/modules/maps.js",
"chars": 10586,
"preview": "/**\n * Maps Module\n * Handles Leaflet map initialization and customization\n * Already modern JavaScript - extracted from"
},
{
"path": "src/modules/tables.js",
"chars": 12109,
"preview": "/**\n * Modern Tables Module - jQuery-Free DataTables\n * Uses DataTables 2.x with native JavaScript and Bootstrap 5\n * Co"
},
{
"path": "src/modules/ui-components.js",
"chars": 5498,
"preview": "/**\n * UI Components Module\n * Handles panel toolbox, progress bars, and toast notifications\n * Modernized from jQuery t"
},
{
"path": "src/modules/weather.js",
"chars": 5095,
"preview": "/**\n * Weather Module\n * Handles Skycons weather icon animations\n * Already modern JavaScript - extracted from init.js\n "
},
{
"path": "src/scss/_color-schemes.scss",
"chars": 19449,
"preview": "// =============================================================================\n// Gentelella Color Schemes - 2026 Mode"
},
{
"path": "src/scss/_variables-modern.scss",
"chars": 7894,
"preview": "// =============================================================================\n// Gentelella CSS Variables - MODERN TH"
},
{
"path": "src/scss/_variables.scss",
"chars": 6361,
"preview": "// =============================================================================\n// Gentelella CSS Variables\n// ========"
},
{
"path": "src/scss/custom.scss",
"chars": 125929,
"preview": "// =============================================================================\n// Gentelella Custom Styles\n// ========"
},
{
"path": "src/scss/daterangepicker.scss",
"chars": 2926,
"preview": ".daterangepicker {\n .ranges {\n li {\n color: var(--gt-text-primary);\n\n &.active,\n &:hover {\n ba"
},
{
"path": "src/scss/font-optimization.scss",
"chars": 1765,
"preview": "// Font Display Optimization\n// This file adds font-display: swap to all @font-face declarations\n// to improve perceived"
},
{
"path": "src/scss/index2.scss",
"chars": 4025,
"preview": "/* index2.html specific styles */\n\n/* Top Profiles Styling */\n.top_profiles {\n .media.event {\n position: relative;\n "
},
{
"path": "src/scss/index4.scss",
"chars": 1313,
"preview": "/*\n* index4.scss\n* ------------------\n* Styles for the Store Analytics dashboard page (index4.html).\n*/\n\n// Custom style"
},
{
"path": "src/scss/landing.scss",
"chars": 27456,
"preview": "// Landing page specific styles\n// ========================================\n\nbody.landing-page {\n // CSS Custom Propert"
},
{
"path": "src/test/setup.js",
"chars": 1169,
"preview": "/**\n * Vitest Test Setup\n * Configures the testing environment with necessary globals and mocks\n */\n\nimport { vi } from "
},
{
"path": "src/utils/dom.js",
"chars": 7969,
"preview": "/**\n * Modern DOM Utilities - jQuery-free DOM manipulation\n * Provides a consistent API for DOM operations across the co"
},
{
"path": "src/utils/dom.test.js",
"chars": 14317,
"preview": "/**\n * DOM Utilities Tests\n * Tests for jQuery-free DOM manipulation functions\n */\n\nimport { describe, it, expect, befor"
},
{
"path": "src/utils/logger.js",
"chars": 804,
"preview": "/**\n * Development-only Logger Utility\n * Wraps console methods to only output in development mode\n * Production builds "
},
{
"path": "src/utils/logger.test.js",
"chars": 4892,
"preview": "/**\n * Logger Utility Tests\n * Tests for development-only logging functionality\n */\n\nimport { describe, it, expect, befo"
},
{
"path": "src/utils/security.js",
"chars": 1979,
"preview": "// Security utilities for XSS prevention\nimport DOMPurify from 'dompurify';\n\n/**\n * Sanitizes HTML content to prevent XS"
},
{
"path": "src/utils/security.test.js",
"chars": 3749,
"preview": "/**\n * Security Utilities Tests\n * Tests for XSS prevention and HTML sanitization functions\n */\n\nimport { describe, it, "
},
{
"path": "src/utils/table-optimizer.js",
"chars": 6548,
"preview": "/**\n * Table Performance Optimizer\n * Fixes performance issues with large DataTables\n */\n\n// Import development logger\ni"
},
{
"path": "src/utils/validation.js",
"chars": 9233,
"preview": "/**\n * Input Validation Utilities\n * Provides comprehensive validation functions for form inputs\n */\n\n/**\n * Email valid"
},
{
"path": "src/utils/validation.test.js",
"chars": 12825,
"preview": "/**\n * Validation Utilities Tests\n * Comprehensive tests for all form validation functions\n */\n\nimport { describe, it, e"
},
{
"path": "tests/README.md",
"chars": 159,
"preview": "# Test Directory\n\nThis directory contains secure test files for development purposes.\nTest files should never contain ha"
},
{
"path": "vite.config.js",
"chars": 6978,
"preview": "import { defineConfig } from 'vite';\nimport { visualizer } from 'rollup-plugin-visualizer';\n\nexport default defineConfig"
},
{
"path": "vitest.config.js",
"chars": 462,
"preview": "import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n test: {\n globals: true,\n environmen"
}
]
About this extraction
This page contains the full source code of the ColorlibHQ/gentelella GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 137 files (3.3 MB), approximately 882.1k tokens, and a symbol index with 152 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.