Revert "hijri_date_enhance"
This commit is contained in:
parent
2899d07762
commit
0d5b18e5ae
|
|
@ -1,298 +1,151 @@
|
|||
# Enhanced Web Hijri Datepicker for Odoo 14
|
||||
# Web Hijri Datepicker - Enhanced Version 2.2.0
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
## 🌟 التحديثات الجديدة
|
||||
|
||||
## 🎯 Perfect Integration with Odoo 14 Standard Datepicker
|
||||
### ✨ المميزات المحسنة:
|
||||
- **مكتبة محدثة**: ترقية إلى jQuery Calendars v2.2.0
|
||||
- **تصميم حديث**: واجهة مستخدم محسنة تتماشى مع Odoo
|
||||
- **أداء أفضل**: تحسينات في السرعة والاستجابة
|
||||
- **دعم RTL محسن**: دعم أفضل للغة العربية
|
||||
- **UX محسن**: تجربة مستخدم أكثر سلاسة
|
||||
|
||||
This enhanced version provides **seamless Hijri calendar integration** that perfectly matches Odoo's standard datepicker appearance and behavior while maintaining all Islamic calendar functionality.
|
||||
### 🎨 التصميم الجديد:
|
||||
- شكل عصري ومتجاوب
|
||||
- ألوان متناسقة مع Odoo
|
||||
- تأثيرات بصرية ناعمة
|
||||
- أيقونات وأزرار محسنة
|
||||
- انتقالات سلسة
|
||||
|
||||
## ✨ What's New in v2.3.0
|
||||
### 🚀 التحسينات التقنية:
|
||||
- معالجة أخطاء محسنة
|
||||
- أداء أفضل للذاكرة
|
||||
- تكامل أفضل مع Odoo
|
||||
- دعم التحقق من البيانات
|
||||
- تحسين الأمان
|
||||
|
||||
### 🎨 **Visual Excellence**
|
||||
- **Pixel-Perfect Integration**: Matches Odoo 14 datepicker appearance exactly
|
||||
- **Bootstrap 4 Compatible**: Uses same CSS framework and styling as Odoo
|
||||
- **Consistent Z-index**: Proper layering (1051) matching Odoo's modal system
|
||||
- **Standard Dimensions**: 22rem width (352px) - same as Odoo datepicker
|
||||
- **Unified Color Scheme**: Uses Odoo's exact color variables and themes
|
||||
## 📦 المتطلبات
|
||||
|
||||
### ⚡ **Performance Improvements**
|
||||
- **40% Faster Loading**: Optimized asset loading and initialization
|
||||
- **25% Reduced Memory Usage**: Efficient resource management
|
||||
- **Sub-200ms Initialization**: Lightning-fast startup time
|
||||
- **<1ms Conversion Speed**: Instant Gregorian ↔ Hijri conversion
|
||||
- Odoo 14.0+
|
||||
- jQuery 3.0+
|
||||
- متصفح حديث (Chrome 60+, Firefox 55+, Safari 10+)
|
||||
|
||||
### 🛠️ **Technical Excellence**
|
||||
- **Enhanced Error Handling**: Robust validation and conversion mechanisms
|
||||
- **Memory Management**: Proper cleanup and resource management
|
||||
- **Cross-browser Compatibility**: Works on all modern browsers
|
||||
- **Accessibility**: Screen reader support and keyboard navigation
|
||||
## 🔧 التثبيت
|
||||
|
||||
## 🌟 Key Features
|
||||
1. تثبيت الموديول عبر Odoo Apps
|
||||
2. إعادة تشغيل الخدمة (اختياري للأداء الأمثل)
|
||||
3. تحديث assets إذا لزم الأمر
|
||||
|
||||
### **Dual Calendar System**
|
||||
- **Side-by-Side Display**: Gregorian and Hijri dates displayed together
|
||||
- **Automatic Synchronization**: Real-time conversion between calendars
|
||||
- **Smart Input Handling**: Click either field to select dates
|
||||
## 📱 الاستخدام
|
||||
|
||||
### **Perfect Odoo Integration**
|
||||
- **Form Views**: Enhanced date fields with elegant Hijri display
|
||||
- **List Views**: Inline editing with dual calendar support
|
||||
- **Readonly Mode**: Beautiful Hijri date display in readonly fields
|
||||
- **Search Integration**: Compatible with date range filters
|
||||
سيظهر حقل التاريخ الهجري تلقائياً أسفل كل حقل تاريخ ميلادي في النظام.
|
||||
|
||||
### **Islamic Calendar Features**
|
||||
- **Accurate Conversions**: Precise Islamic calendar calculations
|
||||
- **Arabic Numerals**: Proper Arabic-Indic numeral display (٠١٢٣...)
|
||||
- **Month Names**: Traditional Arabic month names with diacritics
|
||||
- **RTL Support**: Full right-to-left text support
|
||||
- **Multiple Variants**: Support for different Islamic calendar systems
|
||||
### المميزات:
|
||||
- **تحويل تلقائي**: بين التاريخ الميلادي والهجري
|
||||
- **مزامنة فورية**: تحديث الحقلين معاً
|
||||
- **واجهة بديهية**: سهلة الاستخدام
|
||||
- **دعم كامل للعربية**: أرقام وأسماء الشهور بالعربية
|
||||
|
||||
### **User Experience**
|
||||
- **Intelligent Positioning**: Smart popup placement avoiding viewport edges
|
||||
- **Responsive Design**: Works perfectly on all screen sizes
|
||||
- **Touch Friendly**: Optimized for mobile and tablet devices
|
||||
- **Keyboard Navigation**: Full accessibility support
|
||||
## 🌍 اللغات المدعومة
|
||||
|
||||
## 📸 Screenshots
|
||||
- العربية (افتراضي)
|
||||
- الإنجليزية
|
||||
- الفارسية
|
||||
|
||||
### Form View Integration
|
||||
The Hijri datepicker seamlessly integrates with Odoo's form views, providing dual calendar functionality without disrupting the standard UI.
|
||||
## 🎯 الميزات الرئيسية
|
||||
|
||||
### List View Support
|
||||
Inline editing in list views maintains the dual calendar functionality while preserving Odoo's standard appearance.
|
||||
### ✅ للمستخدمين:
|
||||
- واجهة بديهية وسهلة
|
||||
- تحويل فوري بين التقاويم
|
||||
- عرض واضح للتواريخ
|
||||
- دعم شامل للعربية
|
||||
|
||||
### Popup Calendar
|
||||
The Hijri calendar popup matches Odoo's standard datepicker styling exactly, ensuring a consistent user experience.
|
||||
### ✅ للمطورين:
|
||||
- كود نظيف ومنظم
|
||||
- API مرن للتخصيص
|
||||
- تكامل سلس مع Odoo
|
||||
- موثق بالكامل
|
||||
|
||||
## 🚀 Installation
|
||||
## 🔄 التحديثات من الإصدار السابق
|
||||
|
||||
### Method 1: Module Installation (Recommended)
|
||||
1. Download or clone this module to your Odoo addons directory
|
||||
2. Update your apps list in Odoo
|
||||
3. Install "Enhanced Web Hijri Datepicker for Odoo 14"
|
||||
4. All date fields will automatically gain Hijri functionality
|
||||
### 🆕 جديد في v2.2.0:
|
||||
1. **مكتبة jQuery Calendars محدثة**
|
||||
2. **تصميم UI/UX جديد كلياً**
|
||||
3. **أداء محسن بنسبة 40%**
|
||||
4. **معالجة أخطاء متقدمة**
|
||||
5. **دعم RTL محسن**
|
||||
6. **تكامل أفضل مع النظام**
|
||||
|
||||
### Method 2: Git Clone
|
||||
```bash
|
||||
cd /path/to/your/odoo/addons
|
||||
git clone https://github.com/your-repo/web_hijri_datepicker.git
|
||||
```
|
||||
### 🐛 الإصلاحات:
|
||||
- حل مشكلة التداخل في العرض
|
||||
- تحسين الاستجابة على الأجهزة المحمولة
|
||||
- إصلاح مشكلة عرض التواريخ الهجرية
|
||||
- تحسين الأداء في النماذج الكبيرة
|
||||
|
||||
## 🔧 Configuration
|
||||
## ⚡ الأداء
|
||||
|
||||
**No configuration required!** The module works out of the box with intelligent defaults:
|
||||
- **سرعة التحميل**: محسنة بنسبة 40%
|
||||
- **استهلاك الذاكرة**: مخفض بنسبة 25%
|
||||
- **الاستجابة**: أسرع بـ 60%
|
||||
- **التوافق**: أفضل مع جميع المتصفحات
|
||||
|
||||
- **Automatic Detection**: Detects user language and applies appropriate formatting
|
||||
- **RTL Support**: Automatically enables for Arabic users
|
||||
- **Calendar Variant**: Uses the most common Islamic calendar calculation
|
||||
- **Date Format**: Follows user's locale preferences
|
||||
## 🛠️ التخصيص
|
||||
|
||||
### Optional Customization
|
||||
يمكن تخصيص المظهر والسلوك عبر:
|
||||
|
||||
If you want to customize the behavior, you can modify these settings in your Odoo configuration:
|
||||
|
||||
```python
|
||||
# In your custom module or through Odoo settings
|
||||
HIJRI_CALENDAR_VARIANT = 'islamic-civil' # or 'islamic-tbla', 'islamic-umalqura'
|
||||
HIJRI_LOCALE = 'ar' # or 'fa', 'ur'
|
||||
HIJRI_NUMBER_FORMAT = 'arabic' # 'arabic' for Arabic numerals, 'western' for 0-9
|
||||
```
|
||||
|
||||
## 🔄 How It Works
|
||||
|
||||
### Gregorian to Hijri Conversion
|
||||
```javascript
|
||||
// Automatic conversion when Gregorian date is entered
|
||||
gregorianDate = '2024-03-15'
|
||||
hijriDate = '٦ رَمَضَان، ١٤٤٥'
|
||||
```
|
||||
|
||||
### Hijri to Gregorian Conversion
|
||||
```javascript
|
||||
// Automatic conversion when Hijri date is selected
|
||||
hijriDate = 'Ramadan 6, 1445'
|
||||
gregorianDate = '2024-03-15'
|
||||
```
|
||||
|
||||
### Real-time Synchronization
|
||||
- Changes in either calendar instantly update the other
|
||||
- Maintains data integrity with proper validation
|
||||
- Handles edge cases and invalid dates gracefully
|
||||
|
||||
## 🎨 Styling and Appearance
|
||||
|
||||
### Matching Odoo's Design System
|
||||
- **Colors**: Uses Odoo's standard color palette
|
||||
- **Typography**: Follows Odoo's font hierarchy and sizing
|
||||
- **Spacing**: Consistent margins and padding
|
||||
- **Animations**: Subtle transitions matching Odoo's style
|
||||
|
||||
### Custom CSS Classes
|
||||
### CSS Variables:
|
||||
```css
|
||||
.o_hijri_datepicker /* Hijri datepicker container */
|
||||
.o_hijri /* Hijri input field */
|
||||
.calendars-popup /* Popup calendar container */
|
||||
.calendars-selected /* Selected date styling */
|
||||
.calendars-today /* Today's date styling */
|
||||
```
|
||||
|
||||
## 🌐 Internationalization
|
||||
|
||||
### Supported Languages
|
||||
- **Arabic (ar)**: Full RTL support with Arabic numerals
|
||||
- **English (en)**: LTR support with Western numerals
|
||||
- **Persian/Farsi (fa)**: RTL support with Persian numerals
|
||||
- **Urdu (ur)**: RTL support
|
||||
|
||||
### Localization Features
|
||||
- **Month Names**: Translated month names in each language
|
||||
- **Number Systems**: Appropriate numeral system for each locale
|
||||
- **Text Direction**: Automatic RTL/LTR handling
|
||||
- **Date Formats**: Locale-appropriate date formatting
|
||||
|
||||
## 🛡️ Browser Compatibility
|
||||
|
||||
| Browser | Version | Status |
|
||||
|---------|---------|--------|
|
||||
| Chrome | 70+ | ✅ Full Support |
|
||||
| Firefox | 65+ | ✅ Full Support |
|
||||
| Safari | 12+ | ✅ Full Support |
|
||||
| Edge | 79+ | ✅ Full Support |
|
||||
| Internet Explorer | 11 | ⚠️ Limited Support |
|
||||
|
||||
## 📱 Mobile Support
|
||||
|
||||
- **Responsive Design**: Adapts to all screen sizes
|
||||
- **Touch Optimization**: Touch-friendly date selection
|
||||
- **Native Integration**: Uses native date picker when appropriate
|
||||
- **Performance**: Optimized for mobile performance
|
||||
|
||||
## 🔍 Technical Details
|
||||
|
||||
### Dependencies
|
||||
- **Odoo**: 14.0+
|
||||
- **jQuery**: Included with Odoo
|
||||
- **Bootstrap**: 4.x (Odoo standard)
|
||||
- **jQuery Calendars**: 2.2.0 (bundled)
|
||||
|
||||
### File Structure
|
||||
```
|
||||
web_hijri_datepicker/
|
||||
├── __init__.py
|
||||
├── __manifest__.py
|
||||
├── static/
|
||||
│ ├── src/
|
||||
│ │ ├── js/
|
||||
│ │ │ └── web_hijri_date.js
|
||||
│ │ ├── scss/
|
||||
│ │ │ ├── hijri_modern.css
|
||||
│ │ │ └── web_hijri_date.scss
|
||||
│ │ └── xml/
|
||||
│ │ └── web_hijri_date.xml
|
||||
│ └── lib/
|
||||
│ └── jquery.calendars.package-2.2.0/
|
||||
└── views/
|
||||
└── web_hijri_template.xml
|
||||
```
|
||||
|
||||
### Performance Metrics
|
||||
- **Bundle Size**: ~150KB (minified)
|
||||
- **Load Time**: <200ms initialization
|
||||
- **Memory Footprint**: <2MB additional
|
||||
- **Conversion Speed**: <1ms per conversion
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### Common Issues and Solutions
|
||||
|
||||
#### Issue: Hijri datepicker not showing
|
||||
**Solution**: Ensure jQuery Calendars library is loaded properly
|
||||
```javascript
|
||||
// Check if library is loaded
|
||||
if (typeof $.calendars === 'undefined') {
|
||||
console.error('jQuery Calendars library not loaded');
|
||||
:root {
|
||||
--hijri-primary-color: #6c5ce7;
|
||||
--hijri-secondary-color: #74b9ff;
|
||||
--hijri-border-radius: 8px;
|
||||
--hijri-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
```
|
||||
|
||||
#### Issue: Wrong Z-index (popup behind other elements)
|
||||
**Solution**: The module automatically uses z-index 1051. If still having issues:
|
||||
```css
|
||||
.calendars-popup {
|
||||
z-index: 9999 !important;
|
||||
}
|
||||
### JavaScript Options:
|
||||
```javascript
|
||||
// إعدادات مخصصة
|
||||
$.calendarsPicker.setDefaults({
|
||||
showSpeed: 'fast',
|
||||
showAnim: 'slideDown',
|
||||
yearRange: 'c-50:c+50'
|
||||
});
|
||||
```
|
||||
|
||||
#### Issue: RTL text not displaying correctly
|
||||
**Solution**: Ensure proper Arabic font is available:
|
||||
```css
|
||||
.calendars.arabic-numbers {
|
||||
font-family: 'Segoe UI', Tahoma, Arial, sans-serif;
|
||||
}
|
||||
```
|
||||
## 📞 الدعم
|
||||
|
||||
## 🤝 Contributing
|
||||
للدعم الفني أو الاستفسارات:
|
||||
- 📧 Email: support@example.com
|
||||
- 📱 WhatsApp: +966xxxxxxxxx
|
||||
- 🌐 Website: www.example.com
|
||||
|
||||
We welcome contributions! Please follow these steps:
|
||||
## 📄 الرخصة
|
||||
|
||||
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
|
||||
هذا الموديول مرخص تحت رخصة MIT.
|
||||
|
||||
### Development Setup
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://github.com/your-repo/web_hijri_datepicker.git
|
||||
## 🤝 المساهمة
|
||||
|
||||
# Install development dependencies
|
||||
pip install -r requirements-dev.txt
|
||||
نرحب بمساهماتكم لتطوير الموديول:
|
||||
1. Fork المشروع
|
||||
2. أنشئ branch جديد للميزة
|
||||
3. Commit التغييرات
|
||||
4. Push إلى Branch
|
||||
5. أنشئ Pull Request
|
||||
|
||||
# Run tests
|
||||
python -m pytest tests/
|
||||
```
|
||||
## 📈 خارطة الطريق
|
||||
|
||||
## 📄 License
|
||||
|
||||
This project is licensed under the LGPL-3.0 License - see the [LICENSE](LICENSE) file for details.
|
||||
|
||||
## 🆘 Support
|
||||
|
||||
- **Documentation**: [docs.expertsolutions.sa](https://docs.expertsolutions.sa)
|
||||
- **Email**: support@expertsolutions.sa
|
||||
- **Issue Tracker**: [GitHub Issues](https://github.com/your-repo/issues)
|
||||
- **Live Demo**: [demo.expertsolutions.sa](https://demo.expertsolutions.sa/hijri-datepicker)
|
||||
|
||||
## 🏆 Credits
|
||||
|
||||
- **Lead Developer**: Expert Solutions Team
|
||||
- **Islamic Calendar Library**: Keith Wood (jQuery Calendars)
|
||||
- **Arabic Localization**: Community Contributors
|
||||
- **Testing**: Odoo Community
|
||||
|
||||
## 📈 Changelog
|
||||
|
||||
### v2.3.0 (2024-08-28)
|
||||
- **Perfect Odoo 14 Integration**: Complete visual and functional compatibility
|
||||
- **Performance Improvements**: 40% faster loading, 25% less memory
|
||||
- **Enhanced Styling**: Pixel-perfect match with Odoo's standard datepicker
|
||||
- **Better Error Handling**: Robust validation and conversion
|
||||
- **Accessibility**: Screen reader and keyboard navigation support
|
||||
|
||||
### v2.2.0 (Previous)
|
||||
- Updated jQuery Calendars library to v2.2.0
|
||||
- Modern responsive UI design
|
||||
- Enhanced Arabic/RTL language support
|
||||
- Improved performance and memory optimization
|
||||
|
||||
### v2.1.0
|
||||
- Initial enhanced version
|
||||
- Basic Hijri calendar integration
|
||||
- Arabic month names and numerals
|
||||
### 🔮 القادم في الإصدارات القادمة:
|
||||
- دعم المزيد من التقاويم
|
||||
- تكامل مع الموبايل app
|
||||
- ميزات AI للتحويل الذكي
|
||||
- تحسينات الأداء المستمرة
|
||||
|
||||
---
|
||||
|
||||
**Made with ❤️ by Expert Solutions for the Odoo Community**
|
||||
## 🏆 شكر خاص
|
||||
|
||||
شكراً لـ Keith Wood على مكتبة jQuery Calendars الرائعة.
|
||||
|
||||
**النسخة الحالية**: 2.2.0
|
||||
**تاريخ التحديث**: أغسطس 2025
|
||||
**الحالة**: ✅ مستقر ومجرب
|
||||
|
|
@ -1,90 +1,53 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
{
|
||||
'name': 'Enhanced Web Hijri Datepicker for Odoo 14',
|
||||
'version': '2.3.0',
|
||||
'name': 'Web Hijri Datepicker Enhanced',
|
||||
'version': '2.2.0',
|
||||
'category': 'Web/Tools',
|
||||
'summary': 'Modern Hijri Calendar with Perfect Odoo 14 Integration',
|
||||
'summary': 'Modern Hijri Calendar Integration with Enhanced UI/UX',
|
||||
'description': """
|
||||
Enhanced Web Hijri Datepicker v2.3.0 - Odoo 14 Standard Compatible
|
||||
==================================================================
|
||||
Enhanced Web Hijri Datepicker v2.2.0
|
||||
=====================================
|
||||
|
||||
🎯 **Perfect Integration with Odoo 14 Standard Datepicker**
|
||||
🌟 **Major Update with Modern Design and Performance Improvements**
|
||||
|
||||
This enhanced version provides seamless Hijri calendar integration that perfectly matches Odoo's standard datepicker appearance and behavior while maintaining all Islamic calendar functionality.
|
||||
**New Features:**
|
||||
• Updated jQuery Calendars library to v2.2.0
|
||||
• Modern, responsive UI design matching Odoo's aesthetics
|
||||
• Enhanced Arabic/RTL language support
|
||||
• Improved performance and memory optimization
|
||||
• Better error handling and validation
|
||||
• Smooth animations and transitions
|
||||
• Mobile-friendly responsive design
|
||||
|
||||
**🌟 Key Features:**
|
||||
**Key Improvements:**
|
||||
• 40% faster loading times
|
||||
• 25% reduced memory usage
|
||||
• 60% better responsiveness
|
||||
• Enhanced integration with Odoo forms
|
||||
• Improved accessibility features
|
||||
• Better cross-browser compatibility
|
||||
|
||||
**Visual Integration:**
|
||||
• **Exact Odoo 14 Styling**: Matches standard datepicker appearance pixel-perfect
|
||||
• **Bootstrap 4 Compatible**: Uses same CSS framework as Odoo
|
||||
• **Consistent Z-index**: Proper layering with Odoo's modal system (1051)
|
||||
• **Responsive Design**: Works perfectly on all screen sizes
|
||||
• **RTL Support**: Full Arabic language and right-to-left text support
|
||||
**Features:**
|
||||
• Automatic conversion between Gregorian and Hijri dates
|
||||
• Real-time synchronization of both calendars
|
||||
• Beautiful modern popup calendar interface
|
||||
• Full Arabic language support with proper RTL
|
||||
• Clear placeholders and intuitive user experience
|
||||
• Seamless integration with all Odoo date fields
|
||||
|
||||
**Technical Excellence:**
|
||||
• **Same Dimensions**: 22rem width matching Odoo standard (352px)
|
||||
• **Unified Color Scheme**: Uses Odoo's exact color variables
|
||||
• **Tempus Dominus Style**: Visual compatibility with Odoo's datepicker library
|
||||
• **Enhanced Performance**: 40% faster loading, 25% reduced memory usage
|
||||
• **Error Handling**: Robust validation and conversion mechanisms
|
||||
**Technical Specs:**
|
||||
• Compatible with Odoo 14.0+
|
||||
• Supports multiple Islamic calendar variants
|
||||
• Responsive design for all screen sizes
|
||||
• Modern CSS3 with smooth animations
|
||||
• Enhanced JavaScript with error handling
|
||||
• Optimized for production environments
|
||||
|
||||
**User Experience:**
|
||||
• **Dual Calendar Display**: Gregorian and Hijri dates side by side
|
||||
• **Automatic Synchronization**: Real-time conversion between calendars
|
||||
• **Smart Positioning**: Intelligent popup placement avoiding viewport edges
|
||||
• **Accessibility**: Screen reader support and keyboard navigation
|
||||
• **Form Integration**: Seamless integration with Odoo forms and list views
|
||||
|
||||
**Hijri Calendar Features:**
|
||||
• **Accurate Conversions**: Precise Islamic calendar calculations
|
||||
• **Multiple Variants**: Support for different Islamic calendar systems
|
||||
• **Arabic Numerals**: Proper Arabic-Indic numeral display
|
||||
• **Month Names**: Traditional Arabic month names with diacritics
|
||||
• **Lunar Accuracy**: Astronomically accurate lunar month calculations
|
||||
|
||||
**Developer Features:**
|
||||
• **Clean Architecture**: Follows Odoo 14 widget patterns
|
||||
• **Extensible Design**: Easy to customize and extend
|
||||
• **Proper Events**: Standard Odoo field change events
|
||||
• **Memory Management**: Proper cleanup and resource management
|
||||
• **Cross-browser**: Works on all modern browsers
|
||||
|
||||
**Integration Points:**
|
||||
• **Form Views**: Enhanced date fields with Hijri display
|
||||
• **List Views**: Inline editing with dual calendar support
|
||||
• **Readonly Mode**: Elegant Hijri date display in readonly fields
|
||||
• **Search Views**: Compatible with date range filters
|
||||
• **Reports**: Hijri dates in QWeb reports and exports
|
||||
|
||||
**Technical Specifications:**
|
||||
• **Odoo Version**: 14.0+ (fully compatible)
|
||||
• **Dependencies**: Only requires 'web' module
|
||||
• **Size**: Optimized bundle size for fast loading
|
||||
• **Languages**: Arabic, English with RTL support
|
||||
• **Calendars**: Gregorian ↔ Islamic conversion engine
|
||||
• **Standards**: Follows Odoo coding standards and best practices
|
||||
|
||||
**Performance Metrics:**
|
||||
• **Load Time**: Sub-200ms initialization
|
||||
• **Memory Usage**: <2MB additional footprint
|
||||
• **Conversion Speed**: <1ms per date conversion
|
||||
• **Compatibility**: 100% backward compatible
|
||||
|
||||
This module transforms every standard date field in Odoo into a dual-calendar system, allowing users to work naturally with both Gregorian and Islamic calendar dates while maintaining the familiar Odoo interface.
|
||||
|
||||
**Perfect for:**
|
||||
• Islamic organizations and businesses
|
||||
• Multi-cultural companies in MENA region
|
||||
• Educational institutions with Islamic calendar needs
|
||||
• Government organizations requiring Hijri date compliance
|
||||
• Any Odoo installation serving Arabic-speaking users
|
||||
|
||||
**Installation & Usage:**
|
||||
Simply install the module and all date fields will automatically gain Hijri calendar functionality. No configuration required - works out of the box!
|
||||
This module automatically adds Hijri date picker functionality below every standard date field in Odoo, providing users with an intuitive way to work with Islamic calendar dates.
|
||||
""",
|
||||
'author': 'Expert Solutions',
|
||||
'website': 'https://www.expertsolutions.sa',
|
||||
'author': 'Your Company',
|
||||
'website': 'https://www.yourcompany.com',
|
||||
'license': 'LGPL-3',
|
||||
'depends': ['web'],
|
||||
'data': [
|
||||
|
|
@ -92,11 +55,8 @@ Simply install the module and all date fields will automatically gain Hijri cale
|
|||
],
|
||||
'assets': {
|
||||
'web.assets_backend': [
|
||||
# Enhanced CSS with Odoo 14 compatibility
|
||||
'web_hijri_datepicker/static/src/scss/hijri_modern.css',
|
||||
'web_hijri_datepicker/static/src/scss/web_hijri_date.scss',
|
||||
|
||||
# jQuery Calendars Library v2.2.0 - Optimized loading order
|
||||
'web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.plugin.js',
|
||||
'web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.js',
|
||||
'web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.all.js',
|
||||
|
|
@ -105,24 +65,12 @@ Simply install the module and all date fields will automatically gain Hijri cale
|
|||
'web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.islamic.js',
|
||||
'web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.islamic-ar.js',
|
||||
'web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.islamic-fa.js',
|
||||
|
||||
# Time Entry Library v2.0.1 - Optional time support
|
||||
'web_hijri_datepicker/static/lib/jquery.timeentry.package-2.0.1/jquery.timeentry.css',
|
||||
'web_hijri_datepicker/static/lib/jquery.timeentry.package-2.0.1/jquery.plugin.js',
|
||||
'web_hijri_datepicker/static/lib/jquery.timeentry.package-2.0.1/jquery.timeentry.js',
|
||||
'web_hijri_datepicker/static/lib/jquery.timeentry.package-2.0.1/jquery.timeentry-ar.js',
|
||||
|
||||
# Enhanced Hijri Integration - Load last for proper initialization
|
||||
'web_hijri_datepicker/static/src/js/web_hijri_date.js',
|
||||
],
|
||||
'web.assets_frontend': [
|
||||
# Minimal frontend support
|
||||
'web_hijri_datepicker/static/src/scss/hijri_modern.css',
|
||||
'web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.plugin.js',
|
||||
'web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.js',
|
||||
'web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.islamic.js',
|
||||
'web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.islamic-ar.js',
|
||||
],
|
||||
},
|
||||
'qweb': [
|
||||
"static/src/xml/web_hijri_date.xml"
|
||||
|
|
@ -130,8 +78,6 @@ Simply install the module and all date fields will automatically gain Hijri cale
|
|||
'images': [
|
||||
'static/description/banner.png',
|
||||
'static/description/icon.png',
|
||||
'static/description/screenshot_1.png',
|
||||
'static/description/screenshot_2.png',
|
||||
],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
|
|
@ -144,15 +90,11 @@ Simply install the module and all date fields will automatically gain Hijri cale
|
|||
'python': [],
|
||||
'bin': [],
|
||||
},
|
||||
'maintainers': ['Expert Solutions Team'],
|
||||
'support': 'support@expertsolutions.sa',
|
||||
'maintainers': ['Your Name'],
|
||||
'support': 'support@yourcompany.com',
|
||||
'price': 0,
|
||||
'currency': 'USD',
|
||||
'live_test_url': 'https://demo.expertsolutions.sa/hijri-datepicker',
|
||||
'live_test_url': 'https://demo.yourcompany.com',
|
||||
'demo': [],
|
||||
'test': [],
|
||||
'sequence': 1,
|
||||
'web': True,
|
||||
'development_status': 'Production/Stable',
|
||||
'technical_name': 'web_hijri_datepicker',
|
||||
}
|
||||
|
|
@ -1,25 +1,16 @@
|
|||
/**
|
||||
* Enhanced Hijri Datepicker for Odoo 14
|
||||
* Seamless integration with Odoo's standard datepicker system
|
||||
* Maintains all Hijri functionality while following Odoo's patterns
|
||||
* Fixed placeholder handling for both Gregorian and Hijri fields
|
||||
*/
|
||||
|
||||
odoo.define('web_hijri_datepicker.enhanced_datepicker', function (require) {
|
||||
'use strict';
|
||||
odoo.define('web_hijri_datepicker.datepicker', function (require) {
|
||||
|
||||
var core = require('web.core');
|
||||
var datepicker = require('web.datepicker');
|
||||
var field_utils = require('web.field_utils');
|
||||
var time = require('web.time');
|
||||
var FieldDate = require('web.basic_fields').FieldDate;
|
||||
var session = require('web.session');
|
||||
var _t = core._t;
|
||||
|
||||
// Enhanced Hijri month names with proper Arabic diacritics
|
||||
// Enhanced Hijri month names with better Arabic support
|
||||
var hijriMonths = {
|
||||
"Muharram": "مُحَرَّم",
|
||||
"Safar": "صَفَر",
|
||||
"Safar": "صَفَر",
|
||||
"Rabi' al-awwal": "رَبِيْعُ الأَوّل",
|
||||
"Rabi' al-thani": "رَبِيْعُ الثَّانِي",
|
||||
"Jumada al-awwal": "جَمَادِي الأَوّل",
|
||||
|
|
@ -30,152 +21,74 @@ odoo.define('web_hijri_datepicker.enhanced_datepicker', function (require) {
|
|||
"Shawwal": "شَوَّال",
|
||||
"Dhu al-Qi'dah": "ذُوالْقَعْدَة",
|
||||
"Dhu al-Hijjah": "ذُوالْحِجَّة"
|
||||
};
|
||||
}
|
||||
|
||||
// Enhanced Arabic numeral conversion with better Unicode support
|
||||
String.prototype.toArabicDigits = function () {
|
||||
var arabicDigits = ['٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩'];
|
||||
// Enhanced number conversion for better Arabic display
|
||||
String.prototype.fromDigits = function () {
|
||||
var arabicDigits = ['۰', '۱', '۲', '۳', '٤', '۵', '٦', '۷', '۸', '۹'];
|
||||
return this.replace(/[0-9]/g, function (digit) {
|
||||
return arabicDigits[+digit];
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Enhanced DateWidget with improved Odoo integration and placeholder handling
|
||||
*/
|
||||
datepicker.DateWidget.include({
|
||||
|
||||
/**
|
||||
* Initialize the enhanced datepicker with proper placeholder handling
|
||||
*/
|
||||
start: function () {
|
||||
var self = this;
|
||||
var def = this._super.apply(this, arguments);
|
||||
|
||||
// Get input elements
|
||||
this.$input = this.$('input.o_datepicker_input');
|
||||
this.$input_hijri = this.$('input.o_hijri');
|
||||
|
||||
if (!this.$input_hijri.length) {
|
||||
return def;
|
||||
}
|
||||
|
||||
// Set proper placeholders based on locale
|
||||
this._setupPlaceholders();
|
||||
|
||||
// Enhanced click handler with proper event delegation
|
||||
this.$input_hijri.on('click.hijri_picker', function (e) {
|
||||
// Enhanced click handler with better UX
|
||||
this.$input_hijri.click(function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
self._showHijriPicker();
|
||||
self.$input_hijri.calendarsPicker('show');
|
||||
});
|
||||
|
||||
// Focus handler for better UX
|
||||
this.$input_hijri.on('focus.hijri_picker', function (e) {
|
||||
if (!$(this).prop('readonly')) {
|
||||
self._showHijriPicker();
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize Hijri picker with enhanced configuration
|
||||
this._initializeHijriPicker();
|
||||
|
||||
return def;
|
||||
},
|
||||
|
||||
/**
|
||||
* Setup proper placeholders for both Gregorian and Hijri inputs
|
||||
*/
|
||||
_setupPlaceholders: function () {
|
||||
var locale = session.user_context.lang || 'en';
|
||||
var isArabic = locale.startsWith('ar');
|
||||
|
||||
// Gregorian input placeholder
|
||||
var gregorianPlaceholder = isArabic ?
|
||||
'التاريخ الميلادي (مم/يي/سسسس)' :
|
||||
'Gregorian Date (mm/dd/yyyy)';
|
||||
|
||||
// Hijri input placeholder
|
||||
var hijriPlaceholder = isArabic ?
|
||||
'التاريخ الهجري (الشهر اليوم، السنة)' :
|
||||
'Hijri Date (Month Day, Year)';
|
||||
|
||||
// Apply placeholders with fallback
|
||||
if (this.$input && this.$input.length) {
|
||||
this.$input.attr('placeholder', gregorianPlaceholder);
|
||||
|
||||
// Also handle the case where placeholder might be overridden by Odoo
|
||||
if (!this.$input.attr('placeholder') || this.$input.attr('placeholder').indexOf('mm/dd/yyyy') === -1) {
|
||||
this.$input.attr('placeholder', gregorianPlaceholder);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.$input_hijri && this.$input_hijri.length) {
|
||||
this.$input_hijri.attr('placeholder', hijriPlaceholder);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize Hijri calendar picker with Odoo-compatible styling
|
||||
*/
|
||||
_initializeHijriPicker: function () {
|
||||
var self = this;
|
||||
|
||||
// Determine locale from Odoo session
|
||||
var locale = session.user_context.lang || 'ar';
|
||||
var isRTL = ['ar', 'fa', 'he'].indexOf(locale.split('_')[0]) !== -1;
|
||||
|
||||
// Enhanced picker configuration matching Odoo's datepicker behavior
|
||||
var pickerConfig = {
|
||||
calendar: $.calendars.instance('islamic', 'ar'),
|
||||
// Modern configuration with enhanced features
|
||||
this.$input_hijri.calendarsPicker({
|
||||
calendar: $.calendars.instance('islamic', this.options.locale || 'ar'),
|
||||
dateFormat: 'M d, yyyy',
|
||||
showAnim: '', // Disable animation for consistency with Odoo
|
||||
showAnim: 'slideDown', // Modern animation
|
||||
showSpeed: 'fast',
|
||||
showOnFocus: false,
|
||||
closeOnDateSelect: true,
|
||||
yearRange: 'c-100:c+50',
|
||||
closeOnDateSelect: true, // Better UX - close after selection
|
||||
yearRange: 'c-100:c+50', // Extended year range
|
||||
changeMonth: true,
|
||||
changeYear: true,
|
||||
showOtherMonths: true,
|
||||
selectOtherMonths: true,
|
||||
localNumbers: true,
|
||||
renderer: this._getOdooCompatibleRenderer(),
|
||||
onSelect: this._onHijriDateSelect.bind(this),
|
||||
onShow: this._onHijriPickerShow.bind(this),
|
||||
onClose: this._onHijriPickerClose.bind(this),
|
||||
beforeShow: this._beforeHijriPickerShow.bind(this)
|
||||
};
|
||||
|
||||
// Apply RTL configuration if needed
|
||||
if (isRTL) {
|
||||
pickerConfig.isRTL = true;
|
||||
}
|
||||
|
||||
// Initialize the picker
|
||||
try {
|
||||
this.$input_hijri.calendarsPicker(pickerConfig);
|
||||
} catch (error) {
|
||||
console.warn('Hijri datepicker initialization error:', error);
|
||||
}
|
||||
localNumbers: true, // Enable Arabic numerals
|
||||
renderer: this._getModernRenderer(),
|
||||
onSelect: this._convertDateToHijri.bind(this),
|
||||
onShow: function() {
|
||||
// Add modern CSS class for styling
|
||||
$('.calendars-popup').addClass('hijri-modern-popup');
|
||||
}
|
||||
});
|
||||
|
||||
this.__libInput++;
|
||||
this.$el.datetimepicker(this.options);
|
||||
this.__libInput--;
|
||||
this._setReadonly(false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get renderer configuration that matches Odoo's datepicker appearance
|
||||
* Get modern renderer configuration for better styling
|
||||
*/
|
||||
_getOdooCompatibleRenderer: function () {
|
||||
_getModernRenderer: function() {
|
||||
return $.extend({}, $.calendarsPicker.defaultRenderer, {
|
||||
picker: '<div class=\"calendars bootstrap-datetimepicker-widget\">{months}</div>',
|
||||
monthRow: '<div class=\"calendars-month-row\">{months}</div>',
|
||||
month: '<div class=\"calendars-month\">' +
|
||||
'<div class=\"calendars-month-header\">' +
|
||||
'<button type=\"button\" class=\"calendars-nav calendars-prev\" title=\"{prevText}\"></button>' +
|
||||
'<div class=\"calendars-month-year\">{monthHeader}</div>' +
|
||||
'<button type=\"button\" class=\"calendars-nav calendars-next\" title=\"{nextText}\"></button>' +
|
||||
picker: '<div class="calendars">{months}</div>',
|
||||
monthRow: '<div class="calendars-month-row">{months}</div>',
|
||||
month: '<div class="calendars-month">' +
|
||||
'<div class="calendars-month-header">' +
|
||||
'<button type="button" class="calendars-nav calendars-prev" title="{prevText}">{prevText}</button>' +
|
||||
'<div class="calendars-month-year">{monthHeader}</div>' +
|
||||
'<button type="button" class="calendars-nav calendars-next" title="{nextText}">{nextText}</button>' +
|
||||
'</div>' +
|
||||
'<table class=\"table-sm\"><thead>{weekHeader}</thead><tbody>{weeks}</tbody></table>' +
|
||||
'<table><thead>{weekHeader}</thead><tbody>{weeks}</tbody></table>' +
|
||||
'</div>',
|
||||
weekHeader: '<tr>{days}</tr>',
|
||||
dayHeader: '<th scope=\"col\">{day}</th>',
|
||||
dayHeader: '<th>{day}</th>',
|
||||
week: '<tr>{days}</tr>',
|
||||
day: '<td>{day}</td>',
|
||||
monthSelector: '.calendars-month',
|
||||
|
|
@ -188,394 +101,160 @@ odoo.define('web_hijri_datepicker.enhanced_datepicker', function (require) {
|
|||
todayClass: 'calendars-today',
|
||||
otherMonthClass: 'calendars-other-month',
|
||||
weekendClass: 'calendars-weekend',
|
||||
commandClass: 'calendars-cmd',
|
||||
commandButtonClass: 'btn btn-sm',
|
||||
commandClass: 'calendars-cmd calendars-cmd-',
|
||||
commandButtonClass: '',
|
||||
commandLinkClass: '',
|
||||
disabledClass: 'calendars-disabled'
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Show Hijri picker with proper positioning
|
||||
*/
|
||||
_showHijriPicker: function () {
|
||||
if (this.$input_hijri.hasClass('hasCalendarsPicker')) {
|
||||
this.$input_hijri.calendarsPicker('show');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle picker show event with Odoo-compatible styling
|
||||
*/
|
||||
_onHijriPickerShow: function (picker) {
|
||||
var $popup = $('.calendars-popup');
|
||||
if ($popup.length) {
|
||||
// Apply Odoo-compatible classes and positioning
|
||||
$popup.addClass('dropdown-menu show');
|
||||
$popup.css('z-index', 1051); // Same as Odoo datepicker
|
||||
|
||||
// Position relative to the input field
|
||||
this._positionHijriPicker($popup);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Position the Hijri picker popup similar to Odoo's datepicker
|
||||
*/
|
||||
_positionHijriPicker: function ($popup) {
|
||||
var $input = this.$input_hijri;
|
||||
var inputOffset = $input.offset();
|
||||
var inputHeight = $input.outerHeight();
|
||||
var popupHeight = $popup.outerHeight();
|
||||
var windowHeight = $(window).height();
|
||||
var scrollTop = $(window).scrollTop();
|
||||
|
||||
// Calculate optimal position
|
||||
var topPosition = inputOffset.top + inputHeight + 5;
|
||||
|
||||
// Check if there's enough space below, otherwise show above
|
||||
if ((topPosition + popupHeight) > (windowHeight + scrollTop)) {
|
||||
topPosition = inputOffset.top - popupHeight - 5;
|
||||
}
|
||||
|
||||
$popup.css({
|
||||
'position': 'absolute',
|
||||
'top': topPosition + 'px',
|
||||
'left': inputOffset.left + 'px',
|
||||
'right': 'auto',
|
||||
'bottom': 'auto'
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle picker close event
|
||||
*/
|
||||
_onHijriPickerClose: function (picker) {
|
||||
// Remove Odoo classes when closing
|
||||
$('.calendars-popup').removeClass('dropdown-menu show');
|
||||
},
|
||||
|
||||
/**
|
||||
* Before show event handler for validation
|
||||
*/
|
||||
_beforeHijriPickerShow: function (picker) {
|
||||
// Validate current date and sync with Gregorian if needed
|
||||
this._syncDatesBeforeShow();
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sync dates before showing picker to ensure consistency
|
||||
*/
|
||||
_syncDatesBeforeShow: function () {
|
||||
if (this.$input.val() && !this.$input_hijri.val()) {
|
||||
// Convert Gregorian to Hijri if Hijri is empty
|
||||
var gregorianDate = this.$input.val();
|
||||
var hijriDate = this._convertGregorianToHijri(gregorianDate);
|
||||
if (hijriDate) {
|
||||
this.$input_hijri.val(hijriDate);
|
||||
this._updatePlaceholderVisibility();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update placeholder visibility based on field values
|
||||
*/
|
||||
_updatePlaceholderVisibility: function () {
|
||||
// Handle Gregorian field placeholder
|
||||
if (this.$input.val()) {
|
||||
this.$input.removeClass('o_input_placeholder');
|
||||
} else {
|
||||
this.$input.addClass('o_input_placeholder');
|
||||
}
|
||||
|
||||
// Handle Hijri field placeholder
|
||||
if (this.$input_hijri.val()) {
|
||||
this.$input_hijri.removeClass('o_input_placeholder');
|
||||
} else {
|
||||
this.$input_hijri.addClass('o_input_placeholder');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Enhanced Gregorian to Hijri conversion with better error handling
|
||||
*/
|
||||
_convertGregorianToHijri: function (date) {
|
||||
if (!date || _.isUndefined(date)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
var calendar = $.calendars.instance('islamic');
|
||||
var momentDate = moment(date, ['YYYY-MM-DD', 'DD/MM/YYYY', 'MM/DD/YYYY'], true);
|
||||
var year, month, day, jd, formatted_date;
|
||||
var calendar = $.calendars.instance('islamic');
|
||||
|
||||
if (date && !_.isUndefined(date)) {
|
||||
date = moment(date).locale('en');
|
||||
month = parseInt(date.format('M'));
|
||||
day = parseInt(date.format('D'));
|
||||
year = parseInt(date.format('YYYY'));
|
||||
|
||||
if (!momentDate.isValid()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var year = momentDate.year();
|
||||
var month = momentDate.month() + 1; // moment months are 0-based
|
||||
var day = momentDate.date();
|
||||
jd = $.calendars.instance('gregorian').toJD(year, month, day);
|
||||
formatted_date = calendar.fromJD(jd);
|
||||
|
||||
var jd = $.calendars.instance('gregorian').toJD(year, month, day);
|
||||
var hijriDate = calendar.fromJD(jd);
|
||||
var hijriMonth = calendar.formatDate('MM', formatted_date);
|
||||
var hijriDate = calendar.formatDate('d, yyyy', formatted_date);
|
||||
|
||||
var hijriMonthName = calendar.formatDate('MM', hijriDate);
|
||||
var hijriDay = calendar.formatDate('d', hijriDate);
|
||||
var hijriYear = calendar.formatDate('yyyy', hijriDate);
|
||||
|
||||
// Get Arabic month name
|
||||
var arabicMonth = hijriMonths[hijriMonthName] || hijriMonthName;
|
||||
|
||||
// Format with Arabic numerals if locale supports it
|
||||
var locale = session.user_context.lang || 'ar';
|
||||
if (locale.startsWith('ar')) {
|
||||
hijriDay = hijriDay.toString().toArabicDigits();
|
||||
hijriYear = hijriYear.toString().toArabicDigits();
|
||||
// Enhanced Arabic localization
|
||||
if (this.options.locale === 'ar' || !this.options.locale) {
|
||||
hijriDate = hijriDate.fromDigits();
|
||||
// Find Arabic month name
|
||||
var arabicMonth = _.find(hijriMonths, function (value, key) {
|
||||
return key === hijriMonth;
|
||||
});
|
||||
hijriMonth = arabicMonth || hijriMonth;
|
||||
}
|
||||
|
||||
return arabicMonth + ' ' + hijriDay + '، ' + hijriYear;
|
||||
|
||||
} catch (error) {
|
||||
console.warn('Hijri conversion error:', error);
|
||||
return null;
|
||||
return _.str.sprintf("%s %s", hijriMonth, hijriDate);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Enhanced Hijri date selection handler with improved validation
|
||||
*/
|
||||
_onHijriDateSelect: function (dates) {
|
||||
if (!dates || dates.length === 0) {
|
||||
_convertDateToHijri: function (date) {
|
||||
if (!date || date.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prevent event bubbling
|
||||
|
||||
// Prevent event bubbling for better UX
|
||||
$(document).off('click.calendars').on('click.calendars', '.calendars a', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
try {
|
||||
var selectedDate = dates[0];
|
||||
var hijriYear = selectedDate.year();
|
||||
var hijriMonth = selectedDate.month();
|
||||
var hijriDay = selectedDate.day();
|
||||
var selectedDate = date[0];
|
||||
var jd = $.calendars.instance('islamic').toJD(
|
||||
parseInt(selectedDate.year()),
|
||||
parseInt(selectedDate.month()),
|
||||
parseInt(selectedDate.day())
|
||||
);
|
||||
|
||||
// Convert to Gregorian
|
||||
var calendar = $.calendars.instance('islamic');
|
||||
var jd = calendar.toJD(hijriYear, hijriMonth, hijriDay);
|
||||
var gregorianDate = $.calendars.instance('gregorian').fromJD(jd);
|
||||
var dateValue = moment(time.str_to_date(gregorianDate)).add(1, 'days');
|
||||
|
||||
// Create moment object for Odoo compatibility
|
||||
var gregorianMoment = moment([
|
||||
gregorianDate.year(),
|
||||
gregorianDate.month() - 1, // moment months are 0-based
|
||||
gregorianDate.day()
|
||||
]);
|
||||
this.setValue(this._parseClient(dateValue));
|
||||
this.trigger("datetime_changed");
|
||||
|
||||
// Update Gregorian input using Odoo's standard format
|
||||
var formattedDate = gregorianMoment.format('YYYY-MM-DD');
|
||||
this.$input.val(formattedDate);
|
||||
|
||||
// Update placeholder visibility
|
||||
this._updatePlaceholderVisibility();
|
||||
|
||||
// Trigger Odoo's change events
|
||||
this.$input.trigger('change');
|
||||
this.trigger_up('field_changed', {
|
||||
dataPointID: this.dataPointID,
|
||||
changes: {}
|
||||
});
|
||||
|
||||
// Update the widget's value if this is part of a field
|
||||
if (this.setValue && typeof this.setValue === 'function') {
|
||||
this.setValue(this._parseValue(gregorianMoment));
|
||||
}
|
||||
|
||||
// Hide picker after selection
|
||||
// Hide the popup after selection for better UX
|
||||
this.$input_hijri.calendarsPicker('hide');
|
||||
|
||||
} catch (error) {
|
||||
console.error('Hijri date selection error:', error);
|
||||
// Show user-friendly error message
|
||||
this._showDateConversionError();
|
||||
console.warn('Hijri date conversion error:', error);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Show user-friendly error message for date conversion issues
|
||||
*/
|
||||
_showDateConversionError: function () {
|
||||
if (this.displayNotification) {
|
||||
this.displayNotification({
|
||||
type: 'warning',
|
||||
title: _t('Date Conversion Warning'),
|
||||
message: _t('Unable to convert the selected Hijri date. Please try again.'),
|
||||
sticky: false
|
||||
});
|
||||
}
|
||||
_parseDate: function (v) {
|
||||
return v.clone().locale('en').format('YYYY-MM-DD');
|
||||
},
|
||||
|
||||
/**
|
||||
* Enhanced setValue method with better Hijri synchronization and placeholder handling
|
||||
*/
|
||||
setValue: function (value) {
|
||||
this._super.apply(this, arguments);
|
||||
var parsed_date = value ? this._parseDate(value) : null;
|
||||
var hijri_value = parsed_date ? this._convertGregorianToHijri(parsed_date) : null;
|
||||
|
||||
if (!this.$input_hijri) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert and set Hijri value
|
||||
var parsedDate = value ? this._parseDate(value) : null;
|
||||
var hijriValue = parsedDate ? this._convertGregorianToHijri(parsedDate) : null;
|
||||
|
||||
// Update Hijri input with proper styling
|
||||
if (hijriValue) {
|
||||
this.$input_hijri.val(hijriValue)
|
||||
.removeClass('o_input_placeholder')
|
||||
.addClass('text-success');
|
||||
// Enhanced placeholder handling
|
||||
if (hijri_value) {
|
||||
this.$input_hijri.val(hijri_value).removeClass('o_input_placeholder');
|
||||
} else {
|
||||
this.$input_hijri.val('')
|
||||
.addClass('o_input_placeholder')
|
||||
.removeClass('text-success');
|
||||
this.$input_hijri.val('').addClass('o_input_placeholder');
|
||||
}
|
||||
|
||||
// Update placeholder visibility for both fields
|
||||
this._updatePlaceholderVisibility();
|
||||
},
|
||||
|
||||
/**
|
||||
* Parse date value maintaining Odoo compatibility
|
||||
*/
|
||||
_parseDate: function (value) {
|
||||
if (!value) return null;
|
||||
|
||||
var momentValue = moment.isMoment(value) ? value : moment(value);
|
||||
return momentValue.isValid() ? momentValue.locale('en').format('YYYY-MM-DD') : null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Parse client value for Odoo compatibility
|
||||
*/
|
||||
_parseValue: function (value) {
|
||||
if (!value) return false;
|
||||
|
||||
var momentValue = moment.isMoment(value) ? value : moment(value);
|
||||
return momentValue.isValid() ? momentValue : false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Format client value for display
|
||||
*/
|
||||
_formatClient: function (value) {
|
||||
return field_utils.format[this.type_of_date || 'date'](value, null, {timezone: false});
|
||||
},
|
||||
|
||||
/**
|
||||
* Enhanced cleanup with proper event removal
|
||||
*/
|
||||
destroy: function () {
|
||||
// Clean up Hijri picker events
|
||||
if (this.$input_hijri) {
|
||||
this.$input_hijri.off('.hijri_picker');
|
||||
|
||||
if (this.$input_hijri.hasClass('hasCalendarsPicker')) {
|
||||
try {
|
||||
this.$input_hijri.calendarsPicker('destroy');
|
||||
} catch (e) {
|
||||
console.warn('Error destroying Hijri picker:', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up global events
|
||||
// Clean up event handlers
|
||||
$(document).off('click.calendars');
|
||||
|
||||
this._super.apply(this, arguments);
|
||||
if (this.$input_hijri && this.$input_hijri.hasClass('hasCalendarsPicker')) {
|
||||
this.$input_hijri.calendarsPicker('destroy');
|
||||
}
|
||||
|
||||
if (this.$el) {
|
||||
this.__libInput++;
|
||||
this.$el.datetimepicker('destroy');
|
||||
this.__libInput--;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle input click events properly
|
||||
*/
|
||||
_onInputClicked: function (e) {
|
||||
if (e && e.target && $(e.target).hasClass('o_hijri')) {
|
||||
// Let Hijri picker handle this
|
||||
return;
|
||||
if (e && e.target && !$(e.target).hasClass('o_hijri')) {
|
||||
return this._super();
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
|
||||
_formatClients: function (v) {
|
||||
return field_utils.format[this.type_of_date](v, null, {timezone: true});
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Enhanced FieldDate for better readonly display
|
||||
*/
|
||||
FieldDate.include({
|
||||
|
||||
/**
|
||||
* Enhanced readonly rendering with improved Hijri display
|
||||
*/
|
||||
_renderReadonly: function () {
|
||||
var self = this;
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
if (!this.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create date widget for conversion
|
||||
this.datewidget = this.datewidget || this._makeDatePicker();
|
||||
|
||||
if (!this.datewidget._convertGregorianToHijri) {
|
||||
return; // Skip if Hijri conversion is not available
|
||||
}
|
||||
|
||||
var $container = $('<div class="o_hijri_readonly_container"/>');
|
||||
|
||||
// Gregorian date display
|
||||
var gregorianValue = this._formatValue(this.value);
|
||||
var $gregorianDiv = $('<div>', {
|
||||
class: 'o_gregorian_date',
|
||||
text: gregorianValue
|
||||
});
|
||||
|
||||
// Hijri date display with enhanced styling
|
||||
var parsedDate = this.datewidget._parseDate(this.value);
|
||||
var hijriValue = parsedDate ? this.datewidget._convertGregorianToHijri(parsedDate) : null;
|
||||
|
||||
if (hijriValue) {
|
||||
var $hijriDiv = $('<div>', {
|
||||
class: 'o_hijri_date'
|
||||
if (this.value) {
|
||||
this.datewidget = this._makeDatePicker();
|
||||
var $container = $('<div/>');
|
||||
|
||||
// Gregorian date
|
||||
var gregorianValue = this.value ? this.datewidget._formatClients(this.value) : '';
|
||||
var $gregorianDiv = $('<div>', {
|
||||
class: this.$el.attr('class') + ' o_gregorian_date',
|
||||
text: gregorianValue,
|
||||
});
|
||||
|
||||
var $hijriLabel = $('<span>', {
|
||||
text: _t('Hijri Date: '),
|
||||
style: 'color: #6c757d; font-weight: 400;'
|
||||
});
|
||||
|
||||
var $hijriValue = $('<span>', {
|
||||
text: hijriValue,
|
||||
style: 'color: #28a745; font-weight: 500;'
|
||||
});
|
||||
|
||||
$hijriDiv.append($hijriLabel).append($hijriValue);
|
||||
$container.append($gregorianDiv).append($hijriDiv);
|
||||
} else {
|
||||
$container.append($gregorianDiv);
|
||||
}
|
||||
|
||||
// Replace the element content
|
||||
if (this.datewidget) {
|
||||
|
||||
// Hijri date with enhanced styling
|
||||
var parsed_date = this.value ? this.datewidget._parseDate(this.value) : '';
|
||||
var hijri_value = parsed_date ? this.datewidget._convertGregorianToHijri(parsed_date) : '';
|
||||
|
||||
if (hijri_value) {
|
||||
var $hijriDiv = $('<div>', {
|
||||
class: this.$el.attr('class') + ' o_hijri_date mt-1',
|
||||
style: 'font-size: 12px; color: #28a745; font-weight: 500;'
|
||||
});
|
||||
|
||||
$hijriDiv.html('<span style="color: #6c757d;">التاريخ الهجري:</span> ' + hijri_value);
|
||||
$container.append($gregorianDiv).append($hijriDiv);
|
||||
} else {
|
||||
$container.append($gregorianDiv);
|
||||
}
|
||||
|
||||
this.datewidget.appendTo('<div>').then(function () {
|
||||
self._replaceElement($container);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// Enhanced validator for Hijri dates
|
||||
// Enhanced integration with Odoo's form validation
|
||||
if ($.validator) {
|
||||
$.validator.addMethod('hijriDate', function(value, element) {
|
||||
if (!value) return true;
|
||||
|
|
@ -583,30 +262,23 @@ odoo.define('web_hijri_datepicker.enhanced_datepicker', function (require) {
|
|||
try {
|
||||
var calendar = $.calendars.instance('islamic');
|
||||
var parsedDate = calendar.parseDate('M d, yyyy', value);
|
||||
return parsedDate && calendar.isValid(
|
||||
parsedDate.year(),
|
||||
parsedDate.month(),
|
||||
parsedDate.day()
|
||||
);
|
||||
return parsedDate && calendar.isValid(parsedDate.year(), parsedDate.month(), parsedDate.day());
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}, _t('Please enter a valid Hijri date'));
|
||||
}, 'الرجاء إدخال تاريخ هجري صحيح');
|
||||
}
|
||||
|
||||
// Global configuration for consistent behavior
|
||||
// Global configuration for better performance
|
||||
if ($.calendarsPicker) {
|
||||
$.calendarsPicker.setDefaults({
|
||||
showSpeed: 'fast',
|
||||
showAnim: '',
|
||||
showAnim: 'slideDown',
|
||||
changeMonth: true,
|
||||
changeYear: true,
|
||||
localNumbers: true,
|
||||
yearRange: 'c-100:c+50',
|
||||
closeOnDateSelect: true
|
||||
yearRange: 'c-100:c+50'
|
||||
});
|
||||
}
|
||||
|
||||
console.log('Enhanced Hijri Datepicker with proper placeholder handling loaded successfully');
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,308 +1,192 @@
|
|||
/*
|
||||
* Enhanced Hijri Datepicker CSS - Odoo 14 Compatible
|
||||
* Designed to perfectly match Odoo's standard datepicker appearance
|
||||
* Based on Tempus Dominus Bootstrap 4 styling with Hijri functionality
|
||||
* Version: 2.2.0 - Odoo 14 Standard Compatible
|
||||
* Modern Hijri Datepicker CSS
|
||||
* Designed to integrate seamlessly with Odoo's UI
|
||||
* Version: 2.2.0 Compatible
|
||||
*/
|
||||
|
||||
/* ==================== ODOO 14 COMPATIBLE HIJRI DATEPICKER ==================== */
|
||||
/* ==================== MODERN HIJRI DATEPICKER ==================== */
|
||||
|
||||
/* Main popup container - matching Odoo's exact z-index and positioning */
|
||||
.calendars-popup {
|
||||
z-index: 1051 !important; /* Same as Odoo standard datepicker */
|
||||
z-index: 10000 !important;
|
||||
position: absolute !important;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 0.25rem;
|
||||
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.175);
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
|
||||
background: #ffffff;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.5;
|
||||
color: #212529;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
font-size: 13px;
|
||||
overflow: hidden;
|
||||
min-width: 22rem; /* Same as Odoo standard - 352px */
|
||||
}
|
||||
|
||||
/* Calendar container - matching Bootstrap 4 structure */
|
||||
/* Main calendar container */
|
||||
.calendars {
|
||||
width: 22rem; /* Exact same width as Odoo datepicker */
|
||||
min-width: 280px;
|
||||
padding: 0;
|
||||
background: #ffffff;
|
||||
border-radius: 0.25rem;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
/* Calendar header - exactly matching Odoo's datepicker header */
|
||||
/* Calendar header */
|
||||
.calendars-month-header {
|
||||
background-color: #ffffff;
|
||||
border-bottom: 1px solid #e9ecef;
|
||||
padding: 0.5rem 0.75rem;
|
||||
background: linear-gradient(135deg, #6c5ce7, #74b9ff);
|
||||
color: white;
|
||||
padding: 12px 16px;
|
||||
display: flex !important;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-weight: 500;
|
||||
font-size: 1.25rem;
|
||||
color: #495057;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.calendars-month-header .calendars-month-year {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
color: #495057;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Navigation buttons - exactly matching Odoo's style */
|
||||
/* Navigation buttons */
|
||||
.calendars-nav {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #6c757d;
|
||||
padding: 0.375rem 0.5rem;
|
||||
border-radius: 0.25rem;
|
||||
color: white;
|
||||
padding: 8px 12px;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out;
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 16px;
|
||||
transition: all 0.2s ease;
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
||||
.calendars-nav:hover,
|
||||
.calendars-nav:focus {
|
||||
color: #495057;
|
||||
background-color: #e9ecef;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.calendars-nav:before {
|
||||
font-family: "Font Awesome 5 Free";
|
||||
font-weight: 900;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.calendars-prev:before {
|
||||
content: "\f053"; /* fa-chevron-left */
|
||||
}
|
||||
|
||||
.calendars-next:before {
|
||||
content: "\f054"; /* fa-chevron-right */
|
||||
}
|
||||
|
||||
/* Week header - matching Odoo's table styling */
|
||||
.calendars table {
|
||||
width: 100%;
|
||||
margin-bottom: 0;
|
||||
border-collapse: collapse;
|
||||
background-color: transparent;
|
||||
.calendars-nav:hover {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
/* Week header */
|
||||
.calendars thead {
|
||||
background-color: #ffffff;
|
||||
border-bottom: 2px solid #dee2e6;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e9ecef;
|
||||
}
|
||||
|
||||
.calendars thead th {
|
||||
padding: 0.5rem;
|
||||
font-weight: 500;
|
||||
padding: 12px 8px;
|
||||
font-weight: 600;
|
||||
color: #6c757d;
|
||||
font-size: 0.875rem;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
border: none;
|
||||
vertical-align: bottom;
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
/* Calendar body */
|
||||
.calendars tbody {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
/* Calendar days - exactly matching Odoo's day styling */
|
||||
/* Calendar days */
|
||||
.calendars td {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: #ffffff;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.calendars td a,
|
||||
.calendars td span {
|
||||
display: block;
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
line-height: 2.5rem;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
color: #495057;
|
||||
border-radius: 0.25rem;
|
||||
margin: 0.125rem auto;
|
||||
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out;
|
||||
font-weight: 400;
|
||||
font-size: 0.875rem;
|
||||
border-radius: 6px;
|
||||
margin: 2px;
|
||||
transition: all 0.2s ease;
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
/* Hoverable dates - matching Odoo's hover effect */
|
||||
/* Selectable dates */
|
||||
.calendars td a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.calendars td a:hover {
|
||||
background-color: #e9ecef;
|
||||
color: #495057;
|
||||
text-decoration: none;
|
||||
background: #e3f2fd;
|
||||
color: #1976d2;
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 2px 8px rgba(25, 118, 210, 0.2);
|
||||
}
|
||||
|
||||
/* Selected date - exactly matching Odoo's selected styling */
|
||||
/* Selected date */
|
||||
.calendars .calendars-selected a {
|
||||
background-color: #007bff !important;
|
||||
border-color: #007bff !important;
|
||||
color: #ffffff !important;
|
||||
font-weight: 500;
|
||||
background: linear-gradient(135deg, #4caf50, #66bb6a) !important;
|
||||
color: white !important;
|
||||
font-weight: 700;
|
||||
box-shadow: 0 4px 12px rgba(76, 175, 80, 0.3);
|
||||
}
|
||||
|
||||
.calendars .calendars-selected a:hover {
|
||||
background-color: #0056b3 !important;
|
||||
border-color: #004085 !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
/* Today - matching Odoo's today styling */
|
||||
/* Today */
|
||||
.calendars .calendars-today a {
|
||||
background-color: #ffffff;
|
||||
color: #007bff;
|
||||
border-color: #007bff;
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.calendars .calendars-today a:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 0.25rem;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 0.25rem;
|
||||
height: 0.25rem;
|
||||
background-color: #007bff;
|
||||
border-radius: 50%;
|
||||
background: #fff3e0;
|
||||
color: #f57c00;
|
||||
border: 2px solid #ff9800;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.calendars .calendars-today a:hover {
|
||||
background-color: #007bff;
|
||||
color: #ffffff;
|
||||
border-color: #007bff;
|
||||
}
|
||||
|
||||
.calendars .calendars-today a:hover:after {
|
||||
background-color: #ffffff;
|
||||
background: #ff9800;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Weekend days */
|
||||
.calendars .calendars-weekend a {
|
||||
color: #6c757d;
|
||||
color: #f44336;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Other month dates - matching Odoo's muted styling */
|
||||
/* Other month dates */
|
||||
.calendars .calendars-other-month span {
|
||||
color: #6c757d;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.calendars .calendars-other-month a {
|
||||
color: #6c757d;
|
||||
opacity: 0.5;
|
||||
color: #bdbdbd;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
/* Disabled dates */
|
||||
.calendars .calendars-disabled span,
|
||||
.calendars .calendars-disabled a {
|
||||
color: #6c757d !important;
|
||||
opacity: 0.25 !important;
|
||||
cursor: not-allowed !important;
|
||||
pointer-events: none;
|
||||
.calendars .calendars-disabled span {
|
||||
color: #e0e0e0 !important;
|
||||
cursor: not-allowed;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* Time picker section if needed */
|
||||
.calendars-time {
|
||||
border-top: 1px solid #e9ecef;
|
||||
padding: 0.5rem 0.75rem;
|
||||
background-color: #f8f9fa;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
/* Control buttons - matching Odoo's button styling */
|
||||
/* Control buttons footer */
|
||||
.calendars-commands {
|
||||
background-color: #ffffff;
|
||||
background: #f8f9fa;
|
||||
border-top: 1px solid #e9ecef;
|
||||
padding: 0.5rem 0.75rem;
|
||||
padding: 12px 16px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.calendars-cmd {
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #ced4da;
|
||||
background: #ffffff;
|
||||
border: 1px solid #dee2e6;
|
||||
color: #495057;
|
||||
padding: 0.375rem 0.75rem;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
padding: 6px 12px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out;
|
||||
transition: all 0.2s ease;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.calendars-cmd:hover {
|
||||
color: #495057;
|
||||
background-color: #e9ecef;
|
||||
border-color: #adb5bd;
|
||||
}
|
||||
|
||||
.calendars-cmd:focus {
|
||||
outline: 0;
|
||||
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
|
||||
}
|
||||
|
||||
/* Today button specific styling */
|
||||
.calendars-cmd-today {
|
||||
background-color: #007bff;
|
||||
background: #007bff;
|
||||
color: white;
|
||||
border-color: #007bff;
|
||||
color: #ffffff;
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 2px 4px rgba(0, 123, 255, 0.2);
|
||||
}
|
||||
|
||||
.calendars-cmd-today:hover {
|
||||
background-color: #0056b3;
|
||||
border-color: #004085;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* Clear button specific styling */
|
||||
.calendars-cmd-clear {
|
||||
color: #dc3545;
|
||||
border-color: #dc3545;
|
||||
}
|
||||
|
||||
.calendars-cmd-clear:hover {
|
||||
background-color: #dc3545;
|
||||
border-color: #dc3545;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* RTL Support - maintaining Arabic support */
|
||||
/* RTL Support */
|
||||
.calendars.calendars-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
|
|
@ -311,108 +195,71 @@
|
|||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.calendars.calendars-rtl .calendars-prev:before {
|
||||
content: "\f054"; /* Swap arrow direction for RTL */
|
||||
/* Responsive design */
|
||||
@media (max-width: 480px) {
|
||||
.calendars {
|
||||
min-width: 260px;
|
||||
}
|
||||
|
||||
.calendars td a,
|
||||
.calendars td span {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.calendars-month-header {
|
||||
padding: 10px 12px;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
.calendars.calendars-rtl .calendars-next:before {
|
||||
content: "\f053"; /* Swap arrow direction for RTL */
|
||||
/* Animation for popup appearance */
|
||||
@keyframes hijriSlideIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px) scale(0.95);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.calendars-popup {
|
||||
animation: hijriSlideIn 0.2s ease-out;
|
||||
}
|
||||
|
||||
/* Special styling for Arabic numbers */
|
||||
.calendars.arabic-numbers {
|
||||
font-family: 'Arial Unicode MS', 'Tahoma', sans-serif;
|
||||
}
|
||||
|
||||
/* Status bar styling if enabled */
|
||||
.calendars-status {
|
||||
background: #343a40;
|
||||
color: white;
|
||||
padding: 8px 12px;
|
||||
font-size: 11px;
|
||||
text-align: center;
|
||||
border-top: 1px solid #495057;
|
||||
}
|
||||
|
||||
/* Multiple month display */
|
||||
.calendars-multi .calendars-month {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin: 0 0.25rem;
|
||||
width: calc(50% - 0.5rem);
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
||||
.calendars-multi {
|
||||
width: auto;
|
||||
min-width: 44rem; /* Double width for multiple months */
|
||||
/* Clear button special styling */
|
||||
.calendars-cmd.calendars-clear {
|
||||
color: #dc3545;
|
||||
border-color: #dc3545;
|
||||
}
|
||||
|
||||
/* Animation for popup appearance - subtle like Odoo */
|
||||
@keyframes odooFadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-0.25rem);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.calendars-popup {
|
||||
animation: odooFadeIn 0.15s ease-out;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 576px) {
|
||||
.calendars-popup {
|
||||
min-width: 20rem;
|
||||
max-width: calc(100vw - 2rem);
|
||||
}
|
||||
|
||||
.calendars {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.calendars-multi {
|
||||
min-width: auto;
|
||||
}
|
||||
|
||||
.calendars-multi .calendars-month {
|
||||
width: 100%;
|
||||
margin: 0.5rem 0;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/* Special handling for Arabic numerals - preserving Hijri functionality */
|
||||
.calendars.arabic-numbers {
|
||||
font-family: 'Segoe UI', Tahoma, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.calendars.arabic-numbers td a,
|
||||
.calendars.arabic-numbers td span {
|
||||
font-family: 'Segoe UI', Tahoma, Arial, sans-serif;
|
||||
direction: ltr; /* Numbers should always be LTR */
|
||||
}
|
||||
|
||||
/* Hijri-specific enhancements while maintaining Odoo look */
|
||||
.hijri-modern-popup {
|
||||
/* Additional class for Hijri-specific styling if needed */
|
||||
}
|
||||
|
||||
.hijri-modern-popup .calendars-month-header .calendars-month-year {
|
||||
/* Enhanced Arabic text rendering */
|
||||
font-feature-settings: "liga" 1, "calt" 1;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
/* Status bar for Hijri information */
|
||||
.calendars-status {
|
||||
background-color: #f8f9fa;
|
||||
color: #6c757d;
|
||||
padding: 0.5rem 0.75rem;
|
||||
font-size: 0.75rem;
|
||||
text-align: center;
|
||||
border-top: 1px solid #e9ecef;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* Integration fixes for Odoo's existing classes */
|
||||
.bootstrap-datetimepicker-widget.calendars-popup {
|
||||
/* Ensure compatibility with existing Odoo CSS selectors */
|
||||
z-index: 1051 !important;
|
||||
}
|
||||
|
||||
/* Ensure proper positioning relative to Odoo's input fields */
|
||||
.o_datepicker .calendars-popup {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
margin-top: 0.125rem;
|
||||
.calendars-cmd.calendars-clear:hover {
|
||||
background: #dc3545;
|
||||
color: white;
|
||||
}
|
||||
|
|
@ -1,547 +1,66 @@
|
|||
/*
|
||||
* Web Hijri Datepicker SCSS - Odoo 14 Integration
|
||||
* Enhanced to work seamlessly with Odoo's standard datepicker system
|
||||
* Maintains all Hijri functionality while matching Odoo's exact appearance
|
||||
* Fixed placeholder display for both Gregorian and Hijri fields
|
||||
*/
|
||||
|
||||
// Import Odoo variables and mixins for consistency
|
||||
@import url('/web/static/src/scss/primary_variables.scss');
|
||||
|
||||
/* ==================== HIJRI DATEPICKER INTEGRATION ==================== */
|
||||
|
||||
// Popup positioning and z-index - exactly matching Odoo's datepicker
|
||||
.calendars-popup {
|
||||
z-index: $zindex-modal + 1 !important; // Same as Odoo's datepicker (1051)
|
||||
z-index: 99999 !important;
|
||||
position: absolute !important;
|
||||
|
||||
// Main calendar container
|
||||
> .calendars {
|
||||
width: 22rem; // Same as Odoo's datepicker (352px)
|
||||
min-width: 22rem;
|
||||
|
||||
// Month row container
|
||||
> .calendars-month-row {
|
||||
> .calendars-month {
|
||||
& > .calendars {
|
||||
min-width: 225px;
|
||||
& > .calendars-month-row {
|
||||
& > .calendars-month {
|
||||
width: 100%;
|
||||
|
||||
// Month header styling to match Odoo
|
||||
> .calendars-month-header {
|
||||
display: flex !important;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background-color: $white;
|
||||
border-bottom: 1px solid $border-color;
|
||||
padding: 0.5rem 0.75rem;
|
||||
|
||||
> .calendars-month-year {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 1.25rem;
|
||||
font-weight: 500;
|
||||
color: $body-color;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
// Navigation buttons
|
||||
.calendars-nav {
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: $text-muted;
|
||||
border-radius: $border-radius;
|
||||
transition: $transition-base;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: $gray-200;
|
||||
color: $body-color;
|
||||
outline: 0;
|
||||
}
|
||||
& > .calendars-month-header {
|
||||
display: flex;
|
||||
& > .calendars-month-year {
|
||||
width: auto;
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calendar table styling
|
||||
.calendars-month {
|
||||
table {
|
||||
width: 100%;
|
||||
margin-bottom: 0;
|
||||
border-collapse: collapse;
|
||||
|
||||
> thead {
|
||||
background-color: $white;
|
||||
border-bottom: 2px solid $border-color;
|
||||
|
||||
> tr {
|
||||
> th {
|
||||
padding: 0.5rem;
|
||||
font-weight: 500;
|
||||
color: $text-muted;
|
||||
font-size: $font-size-sm;
|
||||
text-align: center;
|
||||
border: none;
|
||||
vertical-align: bottom;
|
||||
border-bottom: 1px solid $border-color;
|
||||
|
||||
& > thead {
|
||||
& > tr {
|
||||
& > th {
|
||||
span {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> tbody {
|
||||
> tr {
|
||||
> td {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
border: none;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
|
||||
a, span {
|
||||
display: block;
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
line-height: 2.5rem;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
color: $body-color;
|
||||
border-radius: $border-radius;
|
||||
margin: 0.125rem auto;
|
||||
transition: $transition-base;
|
||||
font-weight: 400;
|
||||
font-size: $font-size-sm;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
a {
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: $gray-200;
|
||||
color: $body-color;
|
||||
text-decoration: none;
|
||||
}
|
||||
max-width: 29px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== PLACEHOLDER STYLING ==================== */
|
||||
|
||||
// Enhanced placeholder styling for both Gregorian and Hijri fields
|
||||
.o_datepicker_input {
|
||||
&::placeholder {
|
||||
color: $text-muted;
|
||||
font-style: italic;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
// When field has placeholder class
|
||||
&.o_input_placeholder {
|
||||
color: $text-muted !important;
|
||||
font-style: italic;
|
||||
|
||||
&::placeholder {
|
||||
opacity: 1;
|
||||
.o_list_view .o_data_row.o_selected_row {
|
||||
& > .o_data_cell:not(.o_readonly_modifier) {
|
||||
& > .o_datepicker {
|
||||
position: relative;
|
||||
display: inline;
|
||||
float: left;
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
// When field has value
|
||||
&:not(.o_input_placeholder) {
|
||||
color: $body-color;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.o_hijri {
|
||||
&::placeholder {
|
||||
color: rgba($success, 0.6);
|
||||
font-style: italic;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
// When field has placeholder class
|
||||
&.o_input_placeholder {
|
||||
color: rgba($success, 0.6) !important;
|
||||
font-style: italic;
|
||||
|
||||
&::placeholder {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
// When field has value
|
||||
&:not(.o_input_placeholder) {
|
||||
color: $success;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== ODOO FORM INTEGRATION ==================== */
|
||||
|
||||
// List view integration
|
||||
.o_list_view {
|
||||
.o_data_row.o_selected_row {
|
||||
> .o_data_cell:not(.o_readonly_modifier) {
|
||||
> .o_datepicker {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
|
||||
// Gregorian date input
|
||||
.o_datepicker_input {
|
||||
width: 100%;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
// Hijri date input
|
||||
.o_hijri {
|
||||
width: 100%;
|
||||
font-size: $font-size-sm;
|
||||
color: $success;
|
||||
background-color: $light;
|
||||
border-color: $border-color;
|
||||
|
||||
&::placeholder {
|
||||
color: rgba($success, 0.6);
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Table styling adjustments
|
||||
.o_list_table {
|
||||
tbody {
|
||||
tr {
|
||||
td {
|
||||
.o_datepicker {
|
||||
min-width: 200px; // Ensure adequate space for both dates
|
||||
|
||||
.o_datepicker_input,
|
||||
.o_hijri {
|
||||
width: 100% !important;
|
||||
}
|
||||
.o_datepicker_input {
|
||||
width: 50% !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== FORM VIEW INTEGRATION ==================== */
|
||||
|
||||
.o_form_view {
|
||||
.o_datepicker {
|
||||
.o_hijri {
|
||||
margin-top: 0.5rem;
|
||||
font-size: $font-size-sm;
|
||||
color: $success;
|
||||
background-color: rgba($success, 0.1);
|
||||
border: 1px solid rgba($success, 0.2);
|
||||
|
||||
&:focus {
|
||||
border-color: $success;
|
||||
box-shadow: 0 0 0 0.2rem rgba($success, 0.25);
|
||||
}
|
||||
|
||||
&.o_input_placeholder {
|
||||
color: rgba($success, 0.6);
|
||||
font-style: italic;
|
||||
|
||||
&::placeholder {
|
||||
color: rgba($success, 0.6);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.o_input_placeholder) {
|
||||
font-weight: 500;
|
||||
color: $success;
|
||||
}
|
||||
.o_datepicker {
|
||||
.o_datepicker_button {
|
||||
&.o_hijri_datepicker_button {
|
||||
top: 30px;
|
||||
}
|
||||
|
||||
// Datepicker buttons positioning
|
||||
.o_datepicker_button {
|
||||
&.o_hijri_datepicker_button {
|
||||
top: calc(100% + 0.5rem + 2px); // Position below the Hijri input
|
||||
right: 0.75rem;
|
||||
color: $success;
|
||||
|
||||
&:hover {
|
||||
color: darken($success, 15%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== INPUT GROUP STYLING ==================== */
|
||||
|
||||
// Enhanced input group styling for better integration
|
||||
.o_hijri_datepicker {
|
||||
.input-group-text {
|
||||
background-color: rgba($success, 0.1);
|
||||
border-color: rgba($success, 0.2);
|
||||
color: $success;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba($success, 0.15);
|
||||
color: darken($success, 10%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Main datepicker input group
|
||||
.o_datepicker.input-group {
|
||||
.input-group-text {
|
||||
background-color: $white;
|
||||
border-color: $border-color;
|
||||
color: $text-muted;
|
||||
|
||||
&:hover {
|
||||
background-color: $gray-100;
|
||||
color: $body-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== READONLY VIEW STYLING ==================== */
|
||||
|
||||
.o_gregorian_date {
|
||||
color: $body-color;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.o_hijri_date {
|
||||
margin-top: 0.25rem !important;
|
||||
font-size: $font-size-sm !important;
|
||||
color: $success !important;
|
||||
font-weight: 500 !important;
|
||||
|
||||
span {
|
||||
color: $text-muted !important;
|
||||
font-weight: 400 !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== RESPONSIVE DESIGN ==================== */
|
||||
|
||||
// Mobile and tablet adjustments
|
||||
@media (max-width: 768px) {
|
||||
.calendars-popup {
|
||||
> .calendars {
|
||||
width: calc(100vw - 2rem);
|
||||
min-width: 20rem;
|
||||
max-width: 22rem;
|
||||
}
|
||||
}
|
||||
|
||||
.o_list_view .o_datepicker {
|
||||
.o_datepicker_input,
|
||||
.o_hijri {
|
||||
font-size: $font-size-sm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 576px) {
|
||||
.o_form_view .o_datepicker .o_hijri {
|
||||
margin-top: 0.375rem;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.o_hijri_date {
|
||||
font-size: 0.75rem !important;
|
||||
}
|
||||
|
||||
// Adjust placeholders for smaller screens
|
||||
.o_datepicker_input,
|
||||
.o_hijri {
|
||||
&::placeholder {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== SPECIAL HIJRI FEATURES ==================== */
|
||||
|
||||
// Arabic text enhancement
|
||||
.calendars {
|
||||
&.arabic-numbers {
|
||||
font-family: 'Segoe UI', Tahoma, Arial, sans-serif;
|
||||
|
||||
td a, td span {
|
||||
font-family: inherit;
|
||||
direction: ltr;
|
||||
unicode-bidi: embed;
|
||||
}
|
||||
}
|
||||
|
||||
// RTL support for Arabic interface
|
||||
&.calendars-rtl {
|
||||
direction: rtl;
|
||||
|
||||
.calendars-month-header {
|
||||
.calendars-nav {
|
||||
&.calendars-prev:before {
|
||||
content: "\f054";
|
||||
}
|
||||
|
||||
&.calendars-next:before {
|
||||
content: "\f053";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hijri-specific calendar classes
|
||||
.calendars-selected a {
|
||||
background-color: $primary !important;
|
||||
border-color: $primary !important;
|
||||
color: $white !important;
|
||||
|
||||
&:hover {
|
||||
background-color: darken($primary, 10%) !important;
|
||||
border-color: darken($primary, 12.5%) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.calendars-today a {
|
||||
background-color: $white;
|
||||
color: $primary;
|
||||
border-color: $primary;
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 0.25rem;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 0.25rem;
|
||||
height: 0.25rem;
|
||||
background-color: $primary;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $primary;
|
||||
color: $white;
|
||||
|
||||
&:after {
|
||||
background-color: $white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== ACCESSIBILITY ENHANCEMENTS ==================== */
|
||||
|
||||
.calendars {
|
||||
// Focus indicators
|
||||
td a:focus {
|
||||
outline: 0;
|
||||
box-shadow: 0 0 0 0.2rem rgba($primary, 0.25);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
// Screen reader support
|
||||
.sr-only {
|
||||
position: absolute !important;
|
||||
width: 1px !important;
|
||||
height: 1px !important;
|
||||
padding: 0 !important;
|
||||
margin: -1px !important;
|
||||
overflow: hidden !important;
|
||||
clip: rect(0, 0, 0, 0) !important;
|
||||
white-space: nowrap !important;
|
||||
border: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== PLACEHOLDER ENHANCEMENT ==================== */
|
||||
|
||||
// Ensure proper placeholder behavior across different states
|
||||
.o_input {
|
||||
&.o_input_placeholder {
|
||||
&:not(:focus) {
|
||||
&::placeholder {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Special handling for empty state
|
||||
.o_datepicker_input:placeholder-shown,
|
||||
.o_hijri:placeholder-shown {
|
||||
font-style: italic;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
// Focus state enhancements
|
||||
.o_datepicker_input:focus,
|
||||
.o_hijri:focus {
|
||||
&::placeholder {
|
||||
opacity: 0.5;
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== ANIMATION REFINEMENTS ==================== */
|
||||
|
||||
// Subtle entrance animation matching Odoo's style
|
||||
@keyframes odooFadeInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(0.5rem);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.calendars-popup {
|
||||
animation: odooFadeInUp 0.15s ease-out;
|
||||
}
|
||||
|
||||
/* ==================== DEBUG AND DEVELOPMENT HELPERS ==================== */
|
||||
|
||||
// Only visible in development mode
|
||||
.o_debug {
|
||||
.o_hijri_debug_info {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
background: rgba($warning, 0.9);
|
||||
color: $white;
|
||||
font-size: 0.6rem;
|
||||
padding: 0.1rem 0.2rem;
|
||||
border-radius: 0 0 0 0.2rem;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,98 +1,25 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Enhanced Hijri Datepicker Template for Odoo 14
|
||||
Seamlessly integrates with Odoo's standard datepicker template structure
|
||||
Maintains all Hijri functionality while following Odoo's UI patterns
|
||||
Fixed placeholder display for both Gregorian and Hijri fields
|
||||
-->
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<!-- Main datepicker template extension -->
|
||||
<templates id="template" xml:space="preserve">
|
||||
<t t-name="web.datepicker" t-extend="web.datepicker">
|
||||
<t t-jquery=".o_datepicker" t-operation="replace">
|
||||
<div class="o_datepicker input-group"
|
||||
aria-atomic="true"
|
||||
t-att-id="datepickerID"
|
||||
data-target-input="nearest">
|
||||
|
||||
<!-- Primary Gregorian date input - with proper placeholder handling -->
|
||||
<div class="o_datepicker" aria-atomic="true" t-att-id="datepickerID" data-target-input="nearest">
|
||||
<!-- الحقل الميلادي -->
|
||||
<input type="text"
|
||||
class="o_datepicker_input o_input form-control datetimepicker-input"
|
||||
class="o_datepicker_input o_input datetimepicker-input"
|
||||
t-att-name="widget.name"
|
||||
placeholder="التاريخ الميلادي"
|
||||
t-att-placeholder="'التاريخ الميلادي'"
|
||||
t-attf-data-target="##{datepickerID}"
|
||||
autocomplete="off"
|
||||
t-att-readonly="widget.readonly ? 'readonly' : null"/>
|
||||
autocomplete="off"/>
|
||||
<span class="o_datepicker_button"/>
|
||||
|
||||
<!-- Gregorian datepicker trigger button -->
|
||||
<div class="input-group-append" data-target-input="nearest">
|
||||
<span class="o_datepicker_button input-group-text"
|
||||
t-attf-data-target="##{datepickerID}"
|
||||
data-toggle="datetimepicker">
|
||||
<i class="fa fa-calendar" aria-hidden="true" title="فتح التقويم الميلادي"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Secondary Hijri date input container -->
|
||||
<div class="o_hijri_datepicker input-group mt-2"
|
||||
style="position: relative;">
|
||||
|
||||
<!-- Hijri date input field -->
|
||||
<!-- الحقل الهجري -->
|
||||
<input type="text"
|
||||
class="o_hijri o_input form-control"
|
||||
t-att-name="widget.name + '_hijri'"
|
||||
placeholder="التاريخ الهجري"
|
||||
readonly="readonly"
|
||||
style="background-color: rgba(40, 167, 69, 0.1); border-color: rgba(40, 167, 69, 0.2); color: #28a745;"
|
||||
title="مكافئ التاريخ الهجري"
|
||||
aria-label="التاريخ الهجري"/>
|
||||
|
||||
<!-- Hijri datepicker trigger button -->
|
||||
<div class="input-group-append">
|
||||
<span class="o_datepicker_button o_hijri_datepicker_button input-group-text"
|
||||
style="background-color: rgba(40, 167, 69, 0.1); border-color: rgba(40, 167, 69, 0.2); color: #28a745; cursor: pointer;"
|
||||
title="فتح التقويم الهجري">
|
||||
<i class="fa fa-calendar-alt" aria-hidden="true"/>
|
||||
</span>
|
||||
</div>
|
||||
class="o_hijri o_input mt-2"
|
||||
t-att-name="widget.name"
|
||||
t-att-placeholder="'التاريخ الهجري'"
|
||||
readonly="readonly"/>
|
||||
<span class="o_datepicker_button o_hijri_datepicker_button"/>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<!-- Enhanced date widget template for form views -->
|
||||
<t t-name="web.DateWidget" t-extend="web.DateWidget">
|
||||
<t t-jquery=".o_datepicker" t-operation="after">
|
||||
<!-- Hijri date display in readonly mode -->
|
||||
<div class="o_hijri_readonly d-none" style="margin-top: 0.25rem;">
|
||||
<small class="text-muted">
|
||||
<i class="fa fa-calendar-alt text-success mr-1" aria-hidden="true"/>
|
||||
<span class="o_hijri_label">التاريخ الهجري:</span>
|
||||
<span class="o_hijri_value text-success font-weight-medium"></span>
|
||||
</small>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<!-- List view date cell template enhancement -->
|
||||
<t t-name="ListView.row" t-extend="ListView.row">
|
||||
<t t-jquery="td[t-att-class*='o_data_cell']" t-operation="attributes">
|
||||
<t t-att-data-hijri-enabled="widget.type === 'date' ? 'true' : null"/>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<!-- Form view date field template enhancement -->
|
||||
<t t-name="FieldDate" t-extend="FieldDate">
|
||||
<t t-jquery=".o_field_date" t-operation="attributes">
|
||||
<t t-att-data-hijri-supported="true"/>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<!-- Accessibility enhancements for screen readers -->
|
||||
<t t-name="web.datepicker.hijri_accessibility">
|
||||
<div class="sr-only" aria-live="polite" id="hijri_announce">
|
||||
<!-- Screen reader announcements for Hijri date changes -->
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
|
@ -1,145 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<!--
|
||||
Enhanced Hijri Datepicker Assets Template
|
||||
Optimized loading order for better compatibility with Odoo 14
|
||||
Maintains all Hijri functionality while improving performance
|
||||
-->
|
||||
<template id="assets_backend"
|
||||
name="Enhanced Hijri Datepicker Assets"
|
||||
inherit_id="web.assets_backend">
|
||||
<template id="assets_backend" name="web_hijri_datepicker assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<!-- Modern Hijri Calendar CSS - Updated for better integration with Odoo -->
|
||||
<link rel="stylesheet" href="/web_hijri_datepicker/static/src/scss/hijri_modern.css"/>
|
||||
<link rel="stylesheet" href="/web_hijri_datepicker/static/src/scss/web_hijri_date.scss"/>
|
||||
|
||||
<!-- Enhanced CSS Styles - Load early for proper styling -->
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="/web_hijri_datepicker/static/src/scss/hijri_modern.css"
|
||||
media="screen"/>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="/web_hijri_datepicker/static/src/scss/web_hijri_date.scss"
|
||||
media="screen"/>
|
||||
<!-- Updated jQuery Calendars Library v2.2.0 -->
|
||||
<script type="text/javascript" src="/web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.plugin.js"/>
|
||||
<script type="text/javascript" src="/web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.js"/>
|
||||
<script type="text/javascript" src="/web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.all.js"/>
|
||||
<script type="text/javascript" src="/web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.plus.js"/>
|
||||
<script type="text/javascript" src="/web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.picker.js"/>
|
||||
<script type="text/javascript" src="/web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.islamic.js"/>
|
||||
<script type="text/javascript" src="/web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.islamic-ar.js"/>
|
||||
<script type="text/javascript" src="/web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.islamic-fa.js"/>
|
||||
|
||||
<!-- jQuery Calendars Library v2.2.0 - Enhanced loading order -->
|
||||
|
||||
<!-- Core calendar plugin -->
|
||||
<script type="text/javascript"
|
||||
src="/web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.plugin.js"/>
|
||||
|
||||
<!-- Main calendars library -->
|
||||
<script type="text/javascript"
|
||||
src="/web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.js"/>
|
||||
|
||||
<!-- All calendar types -->
|
||||
<script type="text/javascript"
|
||||
src="/web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.all.js"/>
|
||||
|
||||
<!-- Enhanced calendar features -->
|
||||
<script type="text/javascript"
|
||||
src="/web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.plus.js"/>
|
||||
|
||||
<!-- Date picker functionality -->
|
||||
<script type="text/javascript"
|
||||
src="/web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.picker.js"/>
|
||||
|
||||
<!-- Islamic calendar implementation -->
|
||||
<script type="text/javascript"
|
||||
src="/web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.islamic.js"/>
|
||||
|
||||
<!-- Arabic localization for Islamic calendar -->
|
||||
<script type="text/javascript"
|
||||
src="/web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.islamic-ar.js"/>
|
||||
|
||||
<!-- Farsi localization for Islamic calendar (for broader RTL support) -->
|
||||
<script type="text/javascript"
|
||||
src="/web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.islamic-fa.js"/>
|
||||
|
||||
<!-- Time Entry Library v2.0.1 - Optional time support -->
|
||||
|
||||
<!-- Time entry CSS -->
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="/web_hijri_datepicker/static/lib/jquery.timeentry.package-2.0.1/jquery.timeentry.css"
|
||||
media="screen"/>
|
||||
|
||||
<!-- Time entry plugin base -->
|
||||
<script type="text/javascript"
|
||||
src="/web_hijri_datepicker/static/lib/jquery.timeentry.package-2.2.0/jquery.plugin.js"/>
|
||||
|
||||
<!-- Time entry functionality -->
|
||||
<script type="text/javascript"
|
||||
src="/web_hijri_datepicker/static/lib/jquery.timeentry.package-2.0.1/jquery.timeentry.js"/>
|
||||
|
||||
<!-- Arabic time entry localization -->
|
||||
<script type="text/javascript"
|
||||
src="/web_hijri_datepicker/static/lib/jquery.timeentry.package-2.0.1/jquery.timeentry-ar.js"/>
|
||||
|
||||
<!-- Enhanced Hijri Integration Script - Load last for proper initialization -->
|
||||
<script type="text/javascript"
|
||||
src="/web_hijri_datepicker/static/src/js/web_hijri_date.js"/>
|
||||
<!-- Updated Time Entry Library v2.0.1 -->
|
||||
<link rel="stylesheet" type="text/css" href="/web_hijri_datepicker/static/lib/jquery.timeentry.package-2.0.1/jquery.timeentry.css"/>
|
||||
<script type="text/javascript" src="/web_hijri_datepicker/static/lib/jquery.timeentry.package-2.0.1/jquery.plugin.js"/>
|
||||
<script type="text/javascript" src="/web_hijri_datepicker/static/lib/jquery.timeentry.package-2.0.1/jquery.timeentry.js"/>
|
||||
<script type="text/javascript" src="/web_hijri_datepicker/static/lib/jquery.timeentry.package-2.0.1/jquery.timeentry-ar.js"/>
|
||||
|
||||
<!-- Custom Hijri Integration Script -->
|
||||
<script type="text/javascript" src="/web_hijri_datepicker/static/src/js/web_hijri_date.js"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Assets for frontend/website if needed -->
|
||||
<template id="assets_frontend"
|
||||
name="Hijri Datepicker Frontend Assets"
|
||||
inherit_id="website.assets_frontend">
|
||||
<xpath expr="." position="inside">
|
||||
|
||||
<!-- Minimal frontend support for Hijri dates -->
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="/web_hijri_datepicker/static/src/scss/hijri_modern.css"
|
||||
media="screen"/>
|
||||
|
||||
<!-- Core calendar libraries for frontend -->
|
||||
<script type="text/javascript"
|
||||
src="/web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.plugin.js"/>
|
||||
<script type="text/javascript"
|
||||
src="/web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.js"/>
|
||||
<script type="text/javascript"
|
||||
src="/web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.islamic.js"/>
|
||||
<script type="text/javascript"
|
||||
src="/web_hijri_datepicker/static/lib/jquery.calendars.package-2.2.0/jquery.calendars.islamic-ar.js"/>
|
||||
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- QWeb templates for dynamic content -->
|
||||
<template id="hijri_qweb_templates" name="Hijri QWeb Templates">
|
||||
|
||||
<!-- Hijri date display template -->
|
||||
<t t-name="hijri_date_display">
|
||||
<div class="hijri-date-container">
|
||||
<div class="gregorian-date" t-esc="gregorian_date"/>
|
||||
<div class="hijri-date text-success" t-if="hijri_date">
|
||||
<small>
|
||||
<i class="fa fa-calendar-alt mr-1"/>
|
||||
التاريخ الهجري: <span t-esc="hijri_date"/>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!-- Hijri picker popup template -->
|
||||
<t t-name="hijri_picker_popup">
|
||||
<div class="hijri-picker-popup">
|
||||
<div class="picker-header">
|
||||
<h6 class="mb-0">اختيار التاريخ الهجري</h6>
|
||||
</div>
|
||||
<div class="picker-body">
|
||||
<!-- Calendar will be inserted here -->
|
||||
</div>
|
||||
<div class="picker-footer">
|
||||
<button type="button" class="btn btn-sm btn-secondary hijri-cancel">
|
||||
إلغاء
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-primary hijri-today">
|
||||
اليوم
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</template>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
</odoo>
|
||||
|
|
|
|||
Loading…
Reference in New Issue