Download utils/helpers/utils.py from EGYADMIN/v3: direct link, hf CLI and curl.
- Browser
- Download file 8.48 kB
-
https://huggingface.co/spaces/EGYADMIN/v3/resolve/main/utils/helpers/utils.py
- Command line
-
hf download hf://spaces/EGYADMIN/v3/utils/helpers/utils.py
-
curl -L -o utils.py https://huggingface.co/spaces/EGYADMIN/v3/resolve/main/utils/helpers/utils.py
8.48 kB
| #!/usr/bin/env python | |
| # -*- coding: utf-8 -*- | |
| """ | |
| وحدة المساعدات العامة | |
| توفر هذه الوحدة مجموعة من الدوال المساعدة المستخدمة في مختلف أجزاء النظام | |
| """ | |
| import os | |
| import datetime | |
| import json | |
| import re | |
| import streamlit as st | |
| def create_directory_if_not_exists(directory_path): | |
| """إنشاء مجلد إذا لم يكن موجوداً بالفعل""" | |
| if not os.path.exists(directory_path): | |
| os.makedirs(directory_path) | |
| return True | |
| return False | |
| def get_data_folder(): | |
| """الحصول على مسار مجلد البيانات""" | |
| data_folder = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'data')) | |
| create_directory_if_not_exists(data_folder) | |
| return data_folder | |
| def format_time(timestamp=None): | |
| """تنسيق الوقت بصيغة قابلة للقراءة""" | |
| if timestamp is None: | |
| timestamp = datetime.datetime.now() | |
| return timestamp.strftime("%Y-%m-%d %H:%M:%S") | |
| def get_user_info(): | |
| """الحصول على معلومات المستخدم الحالي""" | |
| # في الوقت الحالي، نستخدم معلومات مستخدم افتراضية | |
| # يمكن تعديل هذه الدالة لاحقاً للتكامل مع نظام المصادقة | |
| return { | |
| "id": 1, | |
| "username": "admin", | |
| "name": "مدير النظام", | |
| "role": "admin" | |
| } | |
| def load_css(): | |
| """تحميل أنماط CSS المخصصة""" | |
| st.markdown(""" | |
| <style> | |
| .module-title { | |
| color: #1E88E5; | |
| text-align: center; | |
| margin-bottom: 20px; | |
| font-weight: bold; | |
| } | |
| .section-title { | |
| color: #1565C0; | |
| margin-top: 20px; | |
| margin-bottom: 10px; | |
| font-weight: bold; | |
| } | |
| .info-box { | |
| background-color: #E3F2FD; | |
| padding: 15px; | |
| border-radius: 5px; | |
| margin-bottom: 15px; | |
| } | |
| .warning-box { | |
| background-color: #FFF8E1; | |
| padding: 15px; | |
| border-radius: 5px; | |
| margin-bottom: 15px; | |
| } | |
| .error-box { | |
| background-color: #FFEBEE; | |
| padding: 15px; | |
| border-radius: 5px; | |
| margin-bottom: 15px; | |
| } | |
| .success-box { | |
| background-color: #E8F5E9; | |
| padding: 15px; | |
| border-radius: 5px; | |
| margin-bottom: 15px; | |
| } | |
| .centered { | |
| text-align: center; | |
| } | |
| .footer { | |
| text-align: center; | |
| margin-top: 30px; | |
| color: #78909C; | |
| font-size: 0.8em; | |
| } | |
| /* تحسين تصميم الجداول */ | |
| table { | |
| width: 100%; | |
| } | |
| thead th { | |
| background-color: #1976D2 !important; | |
| color: white !important; | |
| } | |
| tbody tr:nth-child(even) { | |
| background-color: #f2f2f2; | |
| } | |
| tbody tr:hover { | |
| background-color: #E3F2FD; | |
| } | |
| /* تحسين ظهور الفورم */ | |
| input, select, textarea { | |
| border-radius: 5px !important; | |
| border: 1px solid #ddd !important; | |
| padding: 10px !important; | |
| } | |
| .stButton>button { | |
| border-radius: 5px !important; | |
| } | |
| /* زيادة حجم الخط للتوافق مع اللغة العربية */ | |
| html, body, [class*="css"] { | |
| font-family: 'Tajawal', sans-serif; | |
| } | |
| </style> | |
| <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Tajawal:wght@400;700&display=swap"> | |
| """, unsafe_allow_html=True) | |
| def render_credits(): | |
| """عرض المعلومات عن حقوق الملكية وإصدار النظام""" | |
| st.markdown(""" | |
| <div class="footer"> | |
| <p>هذا النظام يعمل لصالح شركة شبه الجزيرة للمقاولات، جميع الحقوق محفوظة 2025</p> | |
| <p>نظام WAHBi AI - الإصدار 2.0</p> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| def load_icons(): | |
| """تحميل الأيقونات المستخدمة في النظام""" | |
| icons = { | |
| "project": "🏗️", | |
| "document": "📄", | |
| "analysis": "🔍", | |
| "warning": "⚠️", | |
| "success": "✅", | |
| "error": "❌", | |
| "info": "ℹ️", | |
| "settings": "⚙️", | |
| "user": "👤", | |
| "money": "💰", | |
| "time": "⏱️", | |
| "location": "📍", | |
| "notification": "🔔", | |
| "edit": "✏️", | |
| "delete": "🗑️", | |
| "upload": "📤", | |
| "download": "📥", | |
| "save": "💾", | |
| "cancel": "❌", | |
| "add": "➕", | |
| "calendar": "📅", | |
| "chat": "💬", | |
| "search": "🔎", | |
| "star": "⭐", | |
| "trophy": "🏆", | |
| "medal": "🥇", | |
| "chart": "📊", | |
| "map": "🗺️", | |
| "building": "🏢", | |
| "road": "🛣️", | |
| "bridge": "🌉", | |
| } | |
| return icons | |
| def format_number(number, decimal_places=2): | |
| """تنسيق الأرقام بطريقة أنيقة""" | |
| if isinstance(number, (int, float)): | |
| if decimal_places == 0: | |
| return "{:,.0f}".format(number) | |
| else: | |
| return "{:,.{dp}f}".format(number, dp=decimal_places) | |
| return str(number) | |
| def format_currency(amount, currency="ريال", decimal_places=2): | |
| """تنسيق المبالغ المالية""" | |
| if amount is None: | |
| return "غير محدد" | |
| formatted = format_number(amount, decimal_places) | |
| return f"{formatted} {currency}" | |
| def styled_button(label, key=None, type="primary", on_click=None, args=None, full_width=False, icon=None, is_link=False, help=None): | |
| """ | |
| إنشاء زر بتنسيق معين | |
| :param label: نص الزر | |
| :param key: مفتاح الزر الفريد | |
| :param type: نوع التنسيق ('primary', 'secondary', 'success', 'warning', 'danger', 'info', 'glass', 'flat') | |
| :param on_click: الدالة التي سيتم تنفيذها عند النقر | |
| :param args: معاملات الدالة | |
| :param full_width: هل يأخذ الزر العرض كاملاً | |
| :param icon: أيقونة لعرضها قبل النص (emoji أو HTML) | |
| :param is_link: إذا كان الزر رابطاً بدلاً من زر عادي | |
| :param help: نص المساعدة للزر | |
| :return: زر مُنسّق | |
| """ | |
| if is_link: | |
| btn_class = f"{type}-btn" | |
| if icon: | |
| btn_class += " action-btn" | |
| label_with_icon = f"{icon} {label}" | |
| else: | |
| label_with_icon = label | |
| button_html = f""" | |
| <div class="{btn_class}"> | |
| {label_with_icon} | |
| </div> | |
| """ | |
| return st.markdown(button_html, unsafe_allow_html=True) | |
| else: | |
| with st.container(): | |
| btn_class = f"{type}-btn" | |
| if icon: | |
| btn_class += " action-btn" | |
| label_with_icon = f"{icon} {label}" | |
| else: | |
| label_with_icon = label | |
| st.markdown(f'<div class="{btn_class}">', unsafe_allow_html=True) | |
| clicked = st.button(label_with_icon, key=key, on_click=on_click, args=args, use_container_width=full_width, help=help) | |
| st.markdown('</div>', unsafe_allow_html=True) | |
| return clicked | |
| def filter_dataframe(df, column, value): | |
| """ترشيح إطار البيانات""" | |
| if value == "الكل": | |
| return df | |
| return df[df[column] == value] | |
| def get_file_extension(filename): | |
| """استخراج امتداد الملف""" | |
| if not filename: | |
| return "" | |
| return os.path.splitext(filename)[-1].lower() | |
| def extract_numbers_from_text(text): | |
| """استخراج الأرقام من النص | |
| Args: | |
| text (str): النص المراد استخراج الأرقام منه | |
| Returns: | |
| list: قائمة بالأرقام المستخرجة | |
| """ | |
| if not text: | |
| return [] | |
| # نمط للعثور على الأرقام (صحيحة أو عشرية) في النص | |
| pattern = r'[-+]?\d*\.\d+|\d+' | |
| # استخراج جميع الأرقام من النص | |
| numbers = re.findall(pattern, text) | |
| # تحويل النصوص المستخرجة إلى أرقام (صحيحة أو عشرية) | |
| converted_numbers = [] | |
| for num in numbers: | |
| if '.' in num: | |
| converted_numbers.append(float(num)) | |
| else: | |
| converted_numbers.append(int(num)) | |
| return converted_numbers |