Spaces:
Running
Running
| /** | |
| * Token Manager JavaScript | |
| * Handles token management functionality | |
| */ | |
| class TokenManager { | |
| constructor() { | |
| this.tokens = []; | |
| this.init(); | |
| } | |
| init() { | |
| this.loadTokens(); | |
| this.setupEventListeners(); | |
| this.setupTokenTypeHelp(); | |
| } | |
| setupEventListeners() { | |
| // Token form submission | |
| document.getElementById('token-form').addEventListener('submit', (e) => { | |
| e.preventDefault(); | |
| this.saveToken(); | |
| }); | |
| // Token validation | |
| document.getElementById('validate-token').addEventListener('click', () => { | |
| this.validateToken(); | |
| }); | |
| // Token type change | |
| document.getElementById('token-type').addEventListener('change', (e) => { | |
| this.updateTokenTypeHelp(e.target.value); | |
| }); | |
| // Task type change | |
| document.getElementById('task-type').addEventListener('change', (e) => { | |
| this.updateTaskHelp(e.target.value); | |
| }); | |
| // Get task token | |
| document.getElementById('get-task-token').addEventListener('click', () => { | |
| this.getTaskToken(); | |
| }); | |
| } | |
| setupTokenTypeHelp() { | |
| const tokenTypeHelp = { | |
| 'read': 'للتطوير والتعلم - قراءة فقط', | |
| 'write': 'لمشاركة النماذج - قراءة وكتابة', | |
| 'fine_grained': 'للمشاريع التجارية - أذونات مخصصة' | |
| }; | |
| this.tokenTypeHelp = tokenTypeHelp; | |
| this.updateTokenTypeHelp('read'); | |
| // Task type help | |
| const taskTypeHelp = { | |
| 'read': 'قراءة النماذج والبيانات العامة - يستخدم رمز القراءة', | |
| 'download': 'تحميل النماذج من Hugging Face - يستخدم رمز القراءة', | |
| 'medical': 'الوصول للبيانات الطبية الحساسة - يستخدم الرمز المخصص', | |
| 'private': 'الوصول للنماذج الخاصة والمحدودة - يستخدم الرمز المخصص', | |
| 'write': 'رفع النماذج الجديدة - يستخدم رمز الكتابة', | |
| 'upload': 'مشاركة المحتوى مع المجتمع - يستخدم رمز الكتابة', | |
| 'commercial': 'المشاريع التجارية والحساسة - يستخدم الرمز المخصص', | |
| 'enterprise': 'استخدام المؤسسات الكبيرة - يستخدم الرمز المخصص' | |
| }; | |
| this.taskTypeHelp = taskTypeHelp; | |
| this.updateTaskHelp('read'); | |
| } | |
| updateTokenTypeHelp(tokenType) { | |
| const helpElement = document.getElementById('token-type-help'); | |
| helpElement.textContent = this.tokenTypeHelp[tokenType] || ''; | |
| } | |
| updateTaskHelp(taskType) { | |
| const helpElement = document.getElementById('task-help'); | |
| helpElement.textContent = this.taskTypeHelp[taskType] || ''; | |
| } | |
| async getTaskToken() { | |
| const taskType = document.getElementById('task-type').value; | |
| const button = document.getElementById('get-task-token'); | |
| const resultDiv = document.getElementById('task-token-result'); | |
| const infoDiv = document.getElementById('selected-token-info'); | |
| // Show loading | |
| const originalText = button.innerHTML; | |
| button.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>جاري البحث...'; | |
| button.disabled = true; | |
| try { | |
| const response = await fetch(`/api/tokens/for-task/${taskType}`); | |
| const data = await response.json(); | |
| if (response.ok && data.token_info) { | |
| // Show token information | |
| infoDiv.innerHTML = ` | |
| <div class="row"> | |
| <div class="col-md-6"> | |
| <strong>نوع الرمز:</strong> ${data.token_info.type_name}<br> | |
| <strong>مستوى الأمان:</strong> ${data.token_info.security_level}<br> | |
| <strong>الاستخدام المناسب:</strong> ${data.token_info.recommended_for} | |
| </div> | |
| <div class="col-md-6"> | |
| <strong>الرمز المحدد:</strong> ${data.token_info.token_name}<br> | |
| <strong>آخر استخدام:</strong> ${data.token_info.last_used || 'لم يُستخدم بعد'}<br> | |
| <strong>عدد مرات الاستخدام:</strong> ${data.token_info.usage_count || 0} | |
| </div> | |
| </div> | |
| <div class="mt-2"> | |
| <small class="text-muted"> | |
| <strong>الوصف:</strong> ${data.token_info.description} | |
| </small> | |
| </div> | |
| `; | |
| resultDiv.style.display = 'block'; | |
| // Store selected token for use | |
| this.selectedTaskToken = { | |
| taskType: taskType, | |
| tokenName: data.token_info.token_name, | |
| tokenType: data.token_info.type | |
| }; | |
| } else { | |
| this.showError(data.error || 'لم يتم العثور على رمز مناسب لهذه المهمة'); | |
| resultDiv.style.display = 'none'; | |
| } | |
| } catch (error) { | |
| console.error('Error getting task token:', error); | |
| this.showError('خطأ في الحصول على الرمز المناسب'); | |
| resultDiv.style.display = 'none'; | |
| } finally { | |
| button.innerHTML = originalText; | |
| button.disabled = false; | |
| } | |
| } | |
| async loadTokens() { | |
| try { | |
| const response = await fetch('/api/tokens'); | |
| const data = await response.json(); | |
| if (response.ok) { | |
| this.tokens = data.tokens; | |
| this.renderTokens(); | |
| } else { | |
| this.showError('فشل في تحميل الرموز'); | |
| } | |
| } catch (error) { | |
| console.error('Error loading tokens:', error); | |
| this.showError('خطأ في الاتصال بالخادم'); | |
| } | |
| } | |
| renderTokens() { | |
| const container = document.getElementById('tokens-list'); | |
| if (this.tokens.length === 0) { | |
| container.innerHTML = ` | |
| <div class="text-center text-muted py-4"> | |
| <i class="fas fa-key fa-3x mb-3"></i> | |
| <h5>لا توجد رموز محفوظة</h5> | |
| <p>أضف رمز Hugging Face الأول للبدء</p> | |
| </div> | |
| `; | |
| return; | |
| } | |
| const tokensHtml = this.tokens.map(token => this.renderTokenCard(token)).join(''); | |
| container.innerHTML = tokensHtml; | |
| } | |
| renderTokenCard(token) { | |
| const typeInfo = token.type_info || {}; | |
| const securityLevel = typeInfo.security_level || 'medium'; | |
| const securityClass = `security-${securityLevel.replace('_', '-')}`; | |
| const defaultBadge = token.is_default ? | |
| '<span class="badge bg-success me-2">افتراضي</span>' : ''; | |
| const activeBadge = token.is_active ? | |
| '<span class="badge bg-primary me-2">نشط</span>' : | |
| '<span class="badge bg-secondary me-2">غير نشط</span>'; | |
| return ` | |
| <div class="token-card"> | |
| <div class="d-flex justify-content-between align-items-start"> | |
| <div class="flex-grow-1"> | |
| <h5 class="mb-2"> | |
| ${token.name} | |
| ${defaultBadge} | |
| ${activeBadge} | |
| </h5> | |
| <div class="mb-2"> | |
| <span class="token-type-badge badge bg-info me-2">${typeInfo.name || token.type}</span> | |
| <span class="security-level ${securityClass}">${this.getSecurityLevelText(securityLevel)}</span> | |
| </div> | |
| ${token.description ? `<p class="text-muted mb-2">${token.description}</p>` : ''} | |
| <small class="text-muted"> | |
| <i class="fas fa-calendar me-1"></i> | |
| أُنشئ: ${this.formatDate(token.created_at)} | |
| ${token.last_used ? `| آخر استخدام: ${this.formatDate(token.last_used)}` : ''} | |
| | مرات الاستخدام: ${token.usage_count || 0} | |
| </small> | |
| </div> | |
| <div class="token-actions"> | |
| ${!token.is_default ? ` | |
| <button class="btn btn-sm btn-outline-primary" onclick="tokenManager.setDefaultToken('${token.name}')"> | |
| <i class="fas fa-star"></i> | |
| </button> | |
| ` : ''} | |
| <button class="btn btn-sm btn-outline-danger" onclick="tokenManager.deleteToken('${token.name}')"> | |
| <i class="fas fa-trash"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Token Type Details --> | |
| <div class="mt-3"> | |
| <small class="text-muted"> | |
| <strong>الاستخدامات المناسبة:</strong> | |
| ${(typeInfo.use_cases || []).join('، ')} | |
| </small> | |
| </div> | |
| </div> | |
| `; | |
| } | |
| getSecurityLevelText(level) { | |
| const levels = { | |
| 'medium': 'متوسط', | |
| 'high': 'عالي', | |
| 'very_high': 'فائق' | |
| }; | |
| return levels[level] || level; | |
| } | |
| formatDate(dateString) { | |
| if (!dateString) return 'غير محدد'; | |
| const date = new Date(dateString); | |
| return date.toLocaleDateString('ar-SA', { | |
| year: 'numeric', | |
| month: 'short', | |
| day: 'numeric', | |
| hour: '2-digit', | |
| minute: '2-digit' | |
| }); | |
| } | |
| async saveToken() { | |
| const formData = new FormData(); | |
| formData.append('name', document.getElementById('token-name').value); | |
| formData.append('token', document.getElementById('token-value').value); | |
| formData.append('token_type', document.getElementById('token-type').value); | |
| formData.append('description', document.getElementById('token-description').value); | |
| formData.append('is_default', document.getElementById('is-default').checked); | |
| try { | |
| const response = await fetch('/api/tokens', { | |
| method: 'POST', | |
| body: formData | |
| }); | |
| const data = await response.json(); | |
| if (response.ok) { | |
| this.showSuccess(data.message); | |
| this.clearForm(); | |
| this.loadTokens(); | |
| } else { | |
| this.showError(data.detail || 'فشل في حفظ الرمز'); | |
| } | |
| } catch (error) { | |
| console.error('Error saving token:', error); | |
| this.showError('خطأ في الاتصال بالخادم'); | |
| } | |
| } | |
| async validateToken() { | |
| const tokenValue = document.getElementById('token-value').value; | |
| if (!tokenValue) { | |
| this.showError('يرجى إدخال قيمة الرمز أولاً'); | |
| return; | |
| } | |
| const button = document.getElementById('validate-token'); | |
| const originalText = button.innerHTML; | |
| button.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>جاري التحقق...'; | |
| button.disabled = true; | |
| try { | |
| const formData = new FormData(); | |
| formData.append('token', tokenValue); | |
| const response = await fetch('/api/tokens/validate', { | |
| method: 'POST', | |
| body: formData | |
| }); | |
| const data = await response.json(); | |
| if (data.valid) { | |
| this.showSuccess(`الرمز صحيح! المستخدم: ${data.username}, الخطة: ${data.plan}`); | |
| } else { | |
| this.showError(`الرمز غير صحيح: ${data.error}`); | |
| } | |
| } catch (error) { | |
| console.error('Error validating token:', error); | |
| this.showError('خطأ في التحقق من الرمز'); | |
| } finally { | |
| button.innerHTML = originalText; | |
| button.disabled = false; | |
| } | |
| } | |
| async setDefaultToken(tokenName) { | |
| try { | |
| const response = await fetch(`/api/tokens/${tokenName}/set-default`, { | |
| method: 'POST' | |
| }); | |
| const data = await response.json(); | |
| if (response.ok) { | |
| this.showSuccess(data.message); | |
| this.loadTokens(); | |
| } else { | |
| this.showError(data.detail || 'فشل في تعيين الرمز الافتراضي'); | |
| } | |
| } catch (error) { | |
| console.error('Error setting default token:', error); | |
| this.showError('خطأ في الاتصال بالخادم'); | |
| } | |
| } | |
| async deleteToken(tokenName) { | |
| if (!confirm(`هل أنت متأكد من حذف الرمز "${tokenName}"؟`)) { | |
| return; | |
| } | |
| try { | |
| const response = await fetch(`/api/tokens/${tokenName}`, { | |
| method: 'DELETE' | |
| }); | |
| const data = await response.json(); | |
| if (response.ok) { | |
| this.showSuccess(data.message); | |
| this.loadTokens(); | |
| } else { | |
| this.showError(data.detail || 'فشل في حذف الرمز'); | |
| } | |
| } catch (error) { | |
| console.error('Error deleting token:', error); | |
| this.showError('خطأ في الاتصال بالخادم'); | |
| } | |
| } | |
| clearForm() { | |
| document.getElementById('token-form').reset(); | |
| this.updateTokenTypeHelp('read'); | |
| } | |
| showSuccess(message) { | |
| document.getElementById('success-message').textContent = message; | |
| const toast = new bootstrap.Toast(document.getElementById('success-toast')); | |
| toast.show(); | |
| } | |
| showError(message) { | |
| document.getElementById('error-message').textContent = message; | |
| const toast = new bootstrap.Toast(document.getElementById('error-toast')); | |
| toast.show(); | |
| } | |
| } | |
| // Initialize token manager when page loads | |
| document.addEventListener('DOMContentLoaded', () => { | |
| window.tokenManager = new TokenManager(); | |
| }); | |