| <!DOCTYPE html> |
| <html lang="ar" dir="rtl"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Auto-Guardian Dashboard</title> |
| <meta name="google-site-verification" content="google7cceda004d653872" /> |
| <meta name="description" content="Auto-Guardian: A comprehensive security and monitoring system dashboard for modern infrastructure. Automated security monitoring and protection core system." /> |
| <meta name="keywords" content="security, monitoring, automation, guardian, dashboard, infrastructure, protection" /> |
| <meta name="author" content="Abdulelah Othman Gwaith" /> |
| <meta property="og:title" content="Auto-Guardian Dashboard" /> |
| <meta property="og:description" content="Automated security monitoring and protection core system." /> |
| <meta property="og:url" content="https://abdulelahothmangwaith.github.io/Auto-Guardian-Core/" /> |
| <meta property="og:type" content="website" /> |
| <script type="application/ld+json"> |
| { |
| "@context": "https://schema.org", |
| "@type": "SoftwareApplication", |
| "name": "Auto-Guardian-Core", |
| "operatingSystem": "Linux, Windows, macOS", |
| "applicationCategory": "SecurityApplication", |
| "offers": { |
| "@type": "Offer", |
| "price": "0", |
| "priceCurrency": "USD" |
| }, |
| "author": { |
| "@type": "Person", |
| "name": "Abdulelah Othman Gwaith" |
| }, |
| "description": "An automated security monitoring and protection core system designed for modern infrastructure.", |
| "url": "https://abdulelahothmangwaith.github.io/Auto-Guardian-Core/" |
| } |
| </script> |
| <style> |
| * { |
| margin: 0; |
| padding: 0; |
| box-sizing: border-box; |
| } |
| |
| :root { |
| --primary: #0F172A; |
| --secondary: #3B82F6; |
| --success: #10B981; |
| --danger: #EF4444; |
| --warning: #F59E0B; |
| --bg: #F8FAFC; |
| --card-bg: #FFFFFF; |
| --text: #1E293B; |
| --text-muted: #64748B; |
| --border: #E2E8F0; |
| } |
| |
| body { |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; |
| background-color: var(--bg); |
| color: var(--text); |
| min-height: 100vh; |
| overflow-x: hidden; |
| } |
| |
| .dashboard { |
| display: flex; |
| flex-direction: row; |
| min-height: 100vh; |
| width: 100%; |
| } |
| |
| |
| .sidebar { |
| background: var(--primary); |
| color: white; |
| padding: 20px 0; |
| width: 240px; |
| height: 100vh; |
| overflow-y: auto; |
| flex-shrink: 0; |
| position: sticky; |
| top: 0; |
| } |
| |
| .logo { |
| padding: 20px; |
| text-align: center; |
| border-bottom: 1px solid rgba(255,255,255,0.1); |
| margin-bottom: 20px; |
| } |
| |
| .logo h1 { |
| font-size: 20px; |
| font-weight: 700; |
| color: var(--secondary); |
| } |
| |
| .logo span { |
| font-size: 12px; |
| color: var(--text-muted); |
| } |
| |
| .nav-menu { |
| list-style: none; |
| } |
| |
| .nav-item { |
| padding: 12px 20px; |
| display: flex; |
| align-items: center; |
| gap: 12px; |
| cursor: pointer; |
| transition: all 0.3s ease; |
| border-right: 3px solid transparent; |
| } |
| |
| .nav-item:hover, .nav-item.active { |
| background: rgba(59, 130, 246, 0.1); |
| border-right-color: var(--secondary); |
| } |
| |
| .nav-item svg { |
| width: 20px; |
| height: 20px; |
| } |
| |
| .nav-item span { |
| font-size: 14px; |
| } |
| |
| |
| .main-content { |
| flex: 1; |
| padding: 20px 30px; |
| min-width: 0; |
| overflow-x: hidden; |
| } |
| |
| |
| .header { |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| margin-bottom: 30px; |
| flex-wrap: wrap; |
| gap: 15px; |
| } |
| |
| .header h2 { |
| font-size: 24px; |
| font-weight: 600; |
| } |
| |
| .header-actions { |
| display: flex; |
| gap: 12px; |
| align-items: center; |
| } |
| |
| .search-box { |
| display: flex; |
| align-items: center; |
| background: var(--card-bg); |
| border: 1px solid var(--border); |
| border-radius: 8px; |
| padding: 8px 16px; |
| gap: 8px; |
| position: relative; |
| } |
| |
| .search-box:hover { |
| border-color: var(--secondary); |
| } |
| |
| .search-box input { |
| border: none; |
| outline: none; |
| font-size: 14px; |
| width: 150px; |
| background: transparent; |
| flex: 1; |
| min-width: 100px; |
| } |
| |
| .search-results { |
| display: none; |
| position: absolute; |
| top: 100%; |
| left: 0; |
| right: 0; |
| background: white; |
| border: 1px solid var(--border); |
| border-radius: 8px; |
| margin-top: 8px; |
| max-height: 300px; |
| overflow-y: auto; |
| box-shadow: 0 4px 20px rgba(0,0,0,0.1); |
| z-index: 100; |
| } |
| |
| .search-results.active { |
| display: block; |
| } |
| |
| .search-result-item { |
| padding: 12px 16px; |
| border-bottom: 1px solid var(--border); |
| cursor: pointer; |
| transition: background 0.3s ease; |
| } |
| |
| .search-result-item:hover { |
| background: var(--bg); |
| } |
| |
| .search-result-item:last-child { |
| border-bottom: none; |
| } |
| |
| .notification-btn { |
| position: relative; |
| background: var(--card-bg); |
| border: 1px solid var(--border); |
| border-radius: 8px; |
| padding: 8px 12px; |
| cursor: pointer; |
| transition: all 0.3s ease; |
| } |
| |
| .notification-btn:hover { |
| border-color: var(--secondary); |
| } |
| |
| .notification-badge { |
| position: absolute; |
| top: -5px; |
| right: -5px; |
| background: var(--danger); |
| color: white; |
| font-size: 10px; |
| padding: 2px 6px; |
| border-radius: 10px; |
| } |
| |
| |
| .settings-panel { |
| display: none; |
| position: fixed; |
| top: 0; |
| left: 0; |
| width: 100%; |
| height: 100%; |
| background: rgba(0,0,0,0.5); |
| z-index: 1000; |
| justify-content: center; |
| align-items: center; |
| } |
| |
| .settings-panel.active { |
| display: flex; |
| } |
| |
| .settings-content { |
| background: white; |
| border-radius: 16px; |
| padding: 30px; |
| width: 90%; |
| max-width: 500px; |
| max-height: 80vh; |
| overflow-y: auto; |
| } |
| |
| .settings-header { |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| margin-bottom: 24px; |
| } |
| |
| .settings-header h3 { |
| font-size: 20px; |
| } |
| |
| .close-btn { |
| background: none; |
| border: none; |
| font-size: 24px; |
| cursor: pointer; |
| color: var(--text-muted); |
| } |
| |
| .setting-item { |
| margin-bottom: 20px; |
| } |
| |
| .setting-label { |
| display: block; |
| font-size: 14px; |
| font-weight: 500; |
| margin-bottom: 8px; |
| } |
| |
| .setting-description { |
| font-size: 12px; |
| color: var(--text-muted); |
| margin-bottom: 8px; |
| } |
| |
| .setting-input { |
| width: 100%; |
| padding: 10px 14px; |
| border: 1px solid var(--border); |
| border-radius: 8px; |
| font-size: 14px; |
| transition: all 0.3s ease; |
| } |
| |
| .setting-input:focus { |
| outline: none; |
| border-color: var(--secondary); |
| } |
| |
| .setting-select { |
| width: 100%; |
| padding: 10px 14px; |
| border: 1px solid var(--border); |
| border-radius: 8px; |
| font-size: 14px; |
| background: white; |
| cursor: pointer; |
| } |
| |
| .setting-toggle { |
| display: flex; |
| align-items: center; |
| gap: 12px; |
| cursor: pointer; |
| } |
| |
| .toggle-switch { |
| position: relative; |
| width: 50px; |
| height: 26px; |
| background: var(--border); |
| border-radius: 13px; |
| transition: all 0.3s ease; |
| } |
| |
| .toggle-switch.active { |
| background: var(--secondary); |
| } |
| |
| .toggle-switch::after { |
| content: ''; |
| position: absolute; |
| width: 22px; |
| height: 22px; |
| background: white; |
| border-radius: 50%; |
| top: 2px; |
| left: 2px; |
| transition: all 0.3s ease; |
| } |
| |
| .toggle-switch.active::after { |
| left: 26px; |
| } |
| |
| .save-btn { |
| width: 100%; |
| padding: 12px; |
| background: var(--secondary); |
| color: white; |
| border: none; |
| border-radius: 8px; |
| font-size: 14px; |
| font-weight: 500; |
| cursor: pointer; |
| transition: all 0.3s ease; |
| } |
| |
| .save-btn:hover { |
| background: var(--primary); |
| } |
| |
| |
| .stats-grid { |
| display: grid; |
| grid-template-columns: repeat(4, 1fr); |
| gap: 20px; |
| margin-bottom: 30px; |
| } |
| |
| .stat-card { |
| background: var(--card-bg); |
| border-radius: 12px; |
| padding: 20px; |
| box-shadow: 0 1px 3px rgba(0,0,0,0.1); |
| transition: transform 0.3s ease, box-shadow 0.3s ease; |
| cursor: pointer; |
| } |
| |
| .stat-card:hover { |
| transform: translateY(-2px); |
| box-shadow: 0 4px 12px rgba(0,0,0,0.15); |
| } |
| |
| .stat-header { |
| display: flex; |
| justify-content: space-between; |
| align-items: flex-start; |
| margin-bottom: 12px; |
| } |
| |
| .stat-icon { |
| width: 40px; |
| height: 40px; |
| border-radius: 10px; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| } |
| |
| .stat-icon.blue { background: rgba(59, 130, 246, 0.1); color: var(--secondary); } |
| .stat-icon.green { background: rgba(16, 185, 129, 0.1); color: var(--success); } |
| .stat-icon.red { background: rgba(239, 68, 68, 0.1); color: var(--danger); } |
| .stat-icon.yellow { background: rgba(245, 158, 11, 0.1); color: var(--warning); } |
| |
| .stat-trend { |
| font-size: 12px; |
| display: flex; |
| align-items: center; |
| gap: 4px; |
| } |
| |
| .stat-trend.up { color: var(--success); } |
| .stat-trend.down { color: var(--danger); } |
| |
| .stat-value { |
| font-size: 28px; |
| font-weight: 700; |
| margin-bottom: 4px; |
| } |
| |
| .stat-label { |
| font-size: 13px; |
| color: var(--text-muted); |
| } |
| |
| |
| .charts-section { |
| display: grid; |
| grid-template-columns: 2fr 1fr; |
| gap: 20px; |
| margin-bottom: 30px; |
| } |
| |
| .chart-card { |
| background: var(--card-bg); |
| border-radius: 12px; |
| padding: 20px; |
| box-shadow: 0 1px 3px rgba(0,0,0,0.1); |
| } |
| |
| .chart-header { |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| margin-bottom: 20px; |
| } |
| |
| .chart-title { |
| font-size: 16px; |
| font-weight: 600; |
| } |
| |
| .chart-tabs { |
| display: flex; |
| gap: 8px; |
| } |
| |
| .chart-tab { |
| padding: 6px 12px; |
| border-radius: 6px; |
| font-size: 12px; |
| cursor: pointer; |
| background: var(--bg); |
| border: none; |
| transition: all 0.3s ease; |
| } |
| |
| .chart-tab.active { |
| background: var(--secondary); |
| color: white; |
| } |
| |
| .chart-tab:hover:not(.active) { |
| background: var(--border); |
| } |
| |
| |
| .area-chart { |
| height: 250px; |
| position: relative; |
| } |
| |
| .chart-svg { |
| width: 100%; |
| height: 100%; |
| } |
| |
| |
| .donut-chart { |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| gap: 30px; |
| } |
| |
| .donut-svg { |
| width: 180px; |
| height: 180px; |
| } |
| |
| .donut-legend { |
| display: flex; |
| flex-direction: column; |
| gap: 12px; |
| } |
| |
| .legend-item { |
| display: flex; |
| align-items: center; |
| gap: 8px; |
| } |
| |
| .legend-color { |
| width: 12px; |
| height: 12px; |
| border-radius: 3px; |
| } |
| |
| .legend-label { |
| font-size: 13px; |
| color: var(--text-muted); |
| } |
| |
| .legend-value { |
| font-size: 14px; |
| font-weight: 600; |
| margin-right: auto; |
| } |
| |
| |
| .activity-section { |
| display: grid; |
| grid-template-columns: 1fr 1fr; |
| gap: 20px; |
| } |
| |
| .activity-card { |
| background: var(--card-bg); |
| border-radius: 12px; |
| padding: 20px; |
| box-shadow: 0 1px 3px rgba(0,0,0,0.1); |
| } |
| |
| .activity-header { |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| margin-bottom: 16px; |
| } |
| |
| .activity-title { |
| font-size: 16px; |
| font-weight: 600; |
| } |
| |
| .view-all { |
| font-size: 13px; |
| color: var(--secondary); |
| cursor: pointer; |
| } |
| |
| .view-all:hover { |
| text-decoration: underline; |
| } |
| |
| |
| .issues-list { |
| display: flex; |
| flex-direction: column; |
| gap: 12px; |
| } |
| |
| .issue-item { |
| display: flex; |
| align-items: center; |
| gap: 12px; |
| padding: 12px; |
| background: var(--bg); |
| border-radius: 8px; |
| transition: all 0.3s ease; |
| cursor: pointer; |
| } |
| |
| .issue-item:hover { |
| background: rgba(59, 130, 246, 0.05); |
| } |
| |
| .issue-icon { |
| width: 32px; |
| height: 32px; |
| border-radius: 8px; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| } |
| |
| .issue-content { |
| flex: 1; |
| } |
| |
| .issue-title { |
| font-size: 13px; |
| font-weight: 500; |
| margin-bottom: 2px; |
| } |
| |
| .issue-meta { |
| font-size: 11px; |
| color: var(--text-muted); |
| } |
| |
| .issue-badge { |
| padding: 4px 10px; |
| border-radius: 20px; |
| font-size: 11px; |
| font-weight: 500; |
| } |
| |
| .badge-critical { background: rgba(239, 68, 68, 0.1); color: var(--danger); } |
| .badge-warning { background: rgba(245, 158, 11, 0.1); color: var(--warning); } |
| .badge-info { background: rgba(59, 130, 246, 0.1); color: var(--secondary); } |
| .badge-success { background: rgba(16, 185, 129, 0.1); color: var(--success); } |
| |
| |
| .repos-list { |
| display: flex; |
| flex-direction: column; |
| gap: 12px; |
| } |
| |
| .repo-item { |
| display: flex; |
| align-items: center; |
| gap: 12px; |
| padding: 12px; |
| background: var(--bg); |
| border-radius: 8px; |
| transition: all 0.3s ease; |
| cursor: pointer; |
| } |
| |
| .repo-item:hover { |
| background: rgba(59, 130, 246, 0.05); |
| } |
| |
| .repo-icon { |
| width: 36px; |
| height: 36px; |
| border-radius: 8px; |
| background: var(--primary); |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| color: white; |
| } |
| |
| .repo-content { |
| flex: 1; |
| } |
| |
| .repo-name { |
| font-size: 13px; |
| font-weight: 500; |
| margin-bottom: 2px; |
| } |
| |
| .repo-stats { |
| display: flex; |
| gap: 12px; |
| font-size: 11px; |
| color: var(--text-muted); |
| } |
| |
| .repo-status { |
| display: flex; |
| align-items: center; |
| gap: 4px; |
| font-size: 12px; |
| } |
| |
| .status-dot { |
| width: 8px; |
| height: 8px; |
| border-radius: 50%; |
| } |
| |
| .status-dot.active { background: var(--success); } |
| .status-dot.warning { background: var(--warning); } |
| .status-dot.error { background: var(--danger); } |
| |
| |
| .toast-container { |
| position: fixed; |
| top: 20px; |
| left: 50%; |
| transform: translateX(-50%); |
| z-index: 2000; |
| display: flex; |
| flex-direction: column; |
| gap: 10px; |
| } |
| |
| .toast { |
| padding: 14px 20px; |
| background: var(--primary); |
| color: white; |
| border-radius: 10px; |
| box-shadow: 0 4px 20px rgba(0,0,0,0.2); |
| display: flex; |
| align-items: center; |
| gap: 10px; |
| animation: slideIn 0.3s ease, fadeOut 0.3s ease 2.7s; |
| } |
| |
| .toast.success { background: var(--success); } |
| .toast.error { background: var(--danger); } |
| .toast.warning { background: var(--warning); } |
| .toast.info { background: var(--secondary); } |
| |
| @keyframes slideIn { |
| from { transform: translateY(-20px); opacity: 0; } |
| to { transform: translateY(0); opacity: 1; } |
| } |
| |
| @keyframes fadeOut { |
| from { opacity: 1; } |
| to { opacity: 0; } |
| } |
| |
| |
| @media (max-width: 1200px) { |
| .stats-grid { |
| grid-template-columns: repeat(2, 1fr); |
| } |
| .charts-section { |
| grid-template-columns: 1fr; |
| } |
| .activity-section { |
| grid-template-columns: 1fr; |
| } |
| } |
| |
| @media (max-width: 992px) { |
| .sidebar { |
| position: fixed; |
| right: -240px; |
| top: 0; |
| z-index: 1000; |
| transition: right 0.3s ease; |
| box-shadow: -4px 0 20px rgba(0,0,0,0.1); |
| } |
| |
| .sidebar.active { |
| right: 0; |
| } |
| |
| .sidebar-overlay { |
| display: none; |
| position: fixed; |
| top: 0; |
| left: 0; |
| width: 100%; |
| height: 100%; |
| background: rgba(0,0,0,0.5); |
| z-index: 999; |
| } |
| |
| .sidebar-overlay.active { |
| display: block; |
| } |
| |
| .main-content { |
| width: 100%; |
| padding: 15px 20px; |
| } |
| |
| .mobile-menu-btn { |
| display: flex !important; |
| } |
| |
| .header-actions { |
| gap: 8px; |
| } |
| |
| .search-box { |
| min-width: 120px; |
| } |
| |
| .search-box input { |
| width: 80px; |
| } |
| } |
| |
| @media (max-width: 768px) { |
| .dashboard { |
| flex-direction: column; |
| } |
| |
| .stats-grid { |
| grid-template-columns: 1fr; |
| gap: 12px; |
| } |
| |
| .stat-card { |
| padding: 15px; |
| display: flex; |
| align-items: center; |
| justify-content: space-between; |
| flex-wrap: wrap; |
| } |
| |
| .stat-header { |
| margin-bottom: 0; |
| width: auto; |
| } |
| |
| .stat-value { |
| font-size: 24px; |
| text-align: left; |
| } |
| |
| .stat-label { |
| text-align: left; |
| width: 100%; |
| } |
| |
| .charts-section { |
| gap: 15px; |
| margin-bottom: 20px; |
| } |
| |
| .chart-card { |
| padding: 15px; |
| } |
| |
| .area-chart { |
| height: 200px; |
| } |
| |
| .donut-chart { |
| flex-direction: column; |
| gap: 15px; |
| } |
| |
| .donut-svg { |
| width: 150px; |
| height: 150px; |
| } |
| |
| .activity-section { |
| gap: 15px; |
| } |
| |
| .activity-card { |
| padding: 15px; |
| } |
| |
| .header { |
| margin-bottom: 20px; |
| } |
| |
| .header h2 { |
| font-size: 20px; |
| width: 100%; |
| } |
| |
| .header-actions { |
| width: 100%; |
| justify-content: space-between; |
| } |
| |
| .search-box { |
| flex: 1; |
| min-width: 0; |
| } |
| |
| .search-box input { |
| width: 100%; |
| } |
| |
| .notification-btn { |
| padding: 8px; |
| } |
| } |
| |
| @media (max-width: 480px) { |
| .stat-card { |
| padding: 12px; |
| } |
| |
| .stat-icon { |
| width: 36px; |
| height: 36px; |
| } |
| |
| .stat-value { |
| font-size: 20px; |
| } |
| |
| .stat-label { |
| font-size: 12px; |
| } |
| |
| .chart-title { |
| font-size: 14px; |
| } |
| |
| .chart-tabs { |
| gap: 4px; |
| } |
| |
| .chart-tab { |
| padding: 4px 8px; |
| font-size: 11px; |
| } |
| |
| .issue-item, .repo-item { |
| padding: 10px; |
| } |
| |
| .issue-icon { |
| width: 28px; |
| height: 28px; |
| } |
| |
| .issue-title { |
| font-size: 12px; |
| } |
| |
| .issue-meta { |
| font-size: 10px; |
| } |
| } |
| |
| |
| .mobile-menu-btn { |
| display: none; |
| position: fixed; |
| bottom: 20px; |
| left: 20px; |
| width: 50px; |
| height: 50px; |
| border-radius: 50%; |
| background: var(--secondary); |
| color: white; |
| border: none; |
| cursor: pointer; |
| z-index: 1001; |
| box-shadow: 0 4px 15px rgba(59, 130, 246, 0.4); |
| align-items: center; |
| justify-content: center; |
| transition: all 0.3s ease; |
| } |
| |
| .mobile-menu-btn:hover { |
| transform: scale(1.1); |
| background: var(--primary); |
| } |
| |
| .mobile-menu-btn svg { |
| width: 24px; |
| height: 24px; |
| } |
| |
| |
| .sidebar-overlay { |
| display: none; |
| } |
| </style> |
| </head> |
| <body> |
| <div class="dashboard"> |
| |
| <div class="sidebar-overlay" id="sidebarOverlay" onclick="toggleMobileMenu()"></div> |
| |
| |
| <aside class="sidebar" id="sidebar"> |
| <div class="logo"> |
| <h1>Auto-Guardian</h1> |
| <span>Security Dashboard</span> |
| </div> |
| <ul class="nav-menu"> |
| <li class="nav-item active" data-view="dashboard"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z"/> |
| </svg> |
| <span>لوحة التحكم</span> |
| </li> |
| <li class="nav-item" data-view="protection"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/> |
| </svg> |
| <span>الحماية</span> |
| </li> |
| <li class="nav-item" data-view="analysis"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01"/> |
| </svg> |
| <span>الفحص والتحليل</span> |
| </li> |
| <li class="nav-item" data-view="reports"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/> |
| </svg> |
| <span>التقارير</span> |
| </li> |
| <li class="nav-item" data-view="settings" id="settingsNavItem"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/> |
| </svg> |
| <span>الإعدادات</span> |
| </li> |
| <li class="nav-item" data-view="help"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/> |
| </svg> |
| <span>المساعدة</span> |
| </li> |
| </ul> |
| </aside> |
| |
| |
| <button class="mobile-menu-btn" id="mobileMenuBtn" onclick="toggleMobileMenu()"> |
| <svg fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/> |
| </svg> |
| </button> |
| |
| |
| <main class="main-content"> |
| |
| <header class="header"> |
| <h2>لوحة تحكم Auto-Guardian</h2> |
| <div class="header-actions"> |
| <div class="search-box" id="searchBox"> |
| <svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/> |
| </svg> |
| <input type="text" placeholder="بحث..." id="searchInput"> |
| <div class="search-results" id="searchResults"></div> |
| </div> |
| <button class="notification-btn" id="notificationBtn"> |
| <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"/> |
| </svg> |
| <span class="notification-badge" id="notificationBadge">5</span> |
| </button> |
| </div> |
| </header> |
| |
| |
| <div class="stats-grid"> |
| <div class="stat-card" onclick="filterIssues('critical')"> |
| <div class="stat-header"> |
| <div class="stat-icon blue"> |
| <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/> |
| </svg> |
| </div> |
| <span class="stat-trend up" id="trendCritical">↑ 12%</span> |
| </div> |
| <div class="stat-value" id="statThreats">1,247</div> |
| <div class="stat-label">التهديدات المحظورة</div> |
| </div> |
| |
| <div class="stat-card"> |
| <div class="stat-header"> |
| <div class="stat-icon green"> |
| <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/> |
| </svg> |
| </div> |
| <span class="stat-trend up" id="trendSuccess">↑ 8%</span> |
| </div> |
| <div class="stat-value" id="statSuccess">99.9%</div> |
| <div class="stat-label">معدل النجاح</div> |
| </div> |
| |
| <div class="stat-card" onclick="filterIssues('open')"> |
| <div class="stat-header"> |
| <div class="stat-icon red"> |
| <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/> |
| </svg> |
| </div> |
| <span class="stat-trend down" id="trendOpen">↓ 3%</span> |
| </div> |
| <div class="stat-value" id="statOpen">23</div> |
| <div class="stat-label">المشكلات المفتوحة</div> |
| </div> |
| |
| <div class="stat-card"> |
| <div class="stat-header"> |
| <div class="stat-icon yellow"> |
| <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/> |
| </svg> |
| </div> |
| <span class="stat-trend up" id="trendResponse">↑ 15%</span> |
| </div> |
| <div class="stat-value" id="statResponse">0.3s</div> |
| <div class="stat-label">زمن الاستجابة</div> |
| </div> |
| </div> |
| |
| |
| <div class="charts-section"> |
| <div class="chart-card"> |
| <div class="chart-header"> |
| <h3 class="chart-title">نشاط الفحص والأمان</h3> |
| <div class="chart-tabs"> |
| <button class="chart-tab" data-period="day" onclick="changePeriod('day')">24 ساعة</button> |
| <button class="chart-tab active" data-period="week" onclick="changePeriod('week')">أسبوع</button> |
| <button class="chart-tab" data-period="month" onclick="changePeriod('month')">شهر</button> |
| </div> |
| </div> |
| <div class="area-chart"> |
| <svg class="chart-svg" viewBox="0 0 800 250" id="mainChart"> |
| |
| <line x1="50" y1="30" x2="750" y2="30" stroke="#E2E8F0" stroke-width="1"/> |
| <line x1="50" y1="80" x2="750" y2="80" stroke="#E2E8F0" stroke-width="1"/> |
| <line x1="50" y1="130" x2="750" y2="130" stroke="#E2E8F0" stroke-width="1"/> |
| <line x1="50" y1="180" x2="750" y2="180" stroke="#E2E8F0" stroke-width="1"/> |
| |
| |
| <defs> |
| <linearGradient id="areaGradient" x1="0%" y1="0%" x2="0%" y2="100%"> |
| <stop offset="0%" style="stop-color:#3B82F6;stop-opacity:0.3"/> |
| <stop offset="100%" style="stop-color:#3B82F6;stop-opacity:0.05"/> |
| </linearGradient> |
| </defs> |
| |
| |
| <path d="M50,180 L100,150 L150,160 L200,120 L250,140 L300,100 L350,110 L400,70 L450,90 L500,60 L550,80 L600,50 L650,65 L700,40 L750,55 L750,180 Z" fill="url(#areaGradient)"/> |
| |
| |
| <path d="M50,180 L100,150 L150,160 L200,120 L250,140 L300,100 L350,110 L400,70 L450,90 L500,60 L550,80 L600,50 L650,65 L700,40 L750,55" fill="none" stroke="#3B82F6" stroke-width="3" stroke-linecap="round"/> |
| |
| |
| <circle cx="100" cy="150" r="5" fill="#3B82F6" class="chart-point" data-value="45"/> |
| <circle cx="200" cy="120" r="5" fill="#3B82F6" class="chart-point" data-value="60"/> |
| <circle cx="300" cy="100" r="5" fill="#3B82F6" class="chart-point" data-value="70"/> |
| <circle cx="400" cy="70" r="5" fill="#3B82F6" class="chart-point" data-value="85"/> |
| <circle cx="500" cy="60" r="5" fill="#3B82F6" class="chart-point" data-value="90"/> |
| <circle cx="600" cy="50" r="5" fill="#3B82F6" class="chart-point" data-value="95"/> |
| <circle cx="700" cy="40" r="5" fill="#3B82F6" class="chart-point" data-value="100"/> |
| |
| |
| <text x="50" y="200" fill="#64748B" font-size="11">السبت</text> |
| <text x="150" y="200" fill="#64748B" font-size="11">الأحد</text> |
| <text x="250" y="200" fill="#64748B" font-size="11">الاثنين</text> |
| <text x="350" y="200" fill="#64748B" font-size="11">الثلاثاء</text> |
| <text x="450" y="200" fill="#64748B" font-size="11">الأربعاء</text> |
| <text x="550" y="200" fill="#64748B" font-size="11">الخميس</text> |
| <text x="650" y="200" fill="#64748B" font-size="11">الجمعة</text> |
| |
| |
| <text x="45" y="35" text-anchor="end" fill="#64748B" font-size="10">100</text> |
| <text x="45" y="85" text-anchor="end" fill="#64748B" font-size="10">75</text> |
| <text x="45" y="135" text-anchor="end" fill="#64748B" font-size="10">50</text> |
| <text x="45" y="185" text-anchor="end" fill="#64748B" font-size="10">25</text> |
| </svg> |
| </div> |
| </div> |
| |
| <div class="chart-card"> |
| <div class="chart-header"> |
| <h3 class="chart-title">توزيع المشكلات</h3> |
| </div> |
| <div class="donut-chart"> |
| <svg class="donut-svg" viewBox="0 0 180 180"> |
| <circle cx="90" cy="90" r="70" fill="none" stroke="#E2E8F0" stroke-width="25"/> |
| <circle cx="90" cy="90" r="70" fill="none" stroke="#EF4444" stroke-width="25" stroke-dasharray="110 308" stroke-dashoffset="0" transform="rotate(-90 90 90)"/> |
| <circle cx="90" cy="90" r="70" fill="none" stroke="#F59E0B" stroke-width="25" stroke-dasharray="88 308" stroke-dashoffset="-110" transform="rotate(-90 90 90)"/> |
| <circle cx="90" cy="90" r="70" fill="none" stroke="#3B82F6" stroke-width="25" stroke-dasharray="66 308" stroke-dashoffset="-198" transform="rotate(-90 90 90)"/> |
| <circle cx="90" cy="90" r="70" fill="none" stroke="#10B981" stroke-width="25" stroke-dasharray="44 308" stroke-dashoffset="-264" transform="rotate(-90 90 90)"/> |
| <text x="90" y="85" text-anchor="middle" font-size="24" font-weight="bold" fill="#0F172A" id="donutTotal">23</text> |
| <text x="90" y="105" text-anchor="middle" font-size="12" fill="#64748B">إجمالي</text> |
| </svg> |
| <div class="donut-legend"> |
| <div class="legend-item"> |
| <div class="legend-color" style="background:#EF4444"></div> |
| <span class="legend-label">حرجة</span> |
| <span class="legend-value" id="legendCritical">5</span> |
| </div> |
| <div class="legend-item"> |
| <div class="legend-color" style="background:#F59E0B"></div> |
| <span class="legend-label">عالية</span> |
| <span class="legend-value" id="legendHigh">7</span> |
| </div> |
| <div class="legend-item"> |
| <div class="legend-color" style="background:#3B82F6"></div> |
| <span class="legend-label">متوسطة</span> |
| <span class="legend-value" id="legendMedium">6</span> |
| </div> |
| <div class="legend-item"> |
| <div class="legend-color" style="background:#10B981"></div> |
| <span class="legend-label">منخفضة</span> |
| <span class="legend-value" id="legendLow">5</span> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="activity-section"> |
| <div class="activity-card"> |
| <div class="activity-header"> |
| <h3 class="activity-title">أحدث المشكلات</h3> |
| <span class="view-all" onclick="filterIssues('all')">عرض الكل →</span> |
| </div> |
| <div class="issues-list" id="issuesList"> |
| |
| </div> |
| </div> |
| |
| <div class="activity-card"> |
| <div class="activity-header"> |
| <h3 class="activity-title">المستودعات النشطة</h3> |
| <span class="view-all">عرض الكل →</span> |
| </div> |
| <div class="repos-list" id="reposList"> |
| |
| </div> |
| </div> |
| </div> |
| </main> |
| </div> |
| |
| |
| <div class="settings-panel" id="settingsPanel"> |
| <div class="settings-content"> |
| <div class="settings-header"> |
| <h3>⚙️ الإعدادات</h3> |
| <button class="close-btn" onclick="closeSettings()">×</button> |
| </div> |
| |
| <div class="setting-item"> |
| <label class="setting-label">اسم المستخدم</label> |
| <input type="text" class="setting-input" id="settingUsername" placeholder="أدخل اسم المستخدم"> |
| </div> |
| |
| <div class="setting-item"> |
| <label class="setting-label">البريد الإلكتروني</label> |
| <input type="email" class="setting-input" id="settingEmail" placeholder="أدخل البريد الإلكتروني"> |
| </div> |
| |
| <div class="setting-item"> |
| <label class="setting-label">لغة الواجهة</label> |
| <select class="setting-select" id="settingLanguage"> |
| <option value="ar">العربية</option> |
| <option value="en">English</option> |
| </select> |
| </div> |
| |
| <div class="setting-item"> |
| <label class="setting-label">السمة</label> |
| <select class="setting-select" id="settingTheme"> |
| <option value="light">فاتحة</option> |
| <option value="dark">داكنة</option> |
| <option value="auto">تلقائي</option> |
| </select> |
| </div> |
| |
| <div class="setting-item"> |
| <label class="setting-label">فحص تلقائي عند الحفظ</label> |
| <div class="setting-toggle" onclick="toggleSetting('autoScan')"> |
| <div class="toggle-switch" id="toggleAutoScan"></div> |
| <span>تشغيل</span> |
| </div> |
| <p class="setting-description">إجراء فحص تلقائي للكود عند حفظ الملفات</p> |
| </div> |
| |
| <div class="setting-item"> |
| <label class="setting-label">إشعارات المشاكل الحرجة</label> |
| <div class="setting-toggle" onclick="toggleSetting('criticalAlerts')"> |
| <div class="toggle-switch" id="toggleCriticalAlerts"></div> |
| <span>تشغيل</span> |
| </div> |
| <p class="setting-description">إرسال إشعارات فورية للمشاكل الأمنية الحرجة</p> |
| </div> |
| |
| <div class="setting-item"> |
| <label class="setting-label">الإصلاح التلقائي الآمن</label> |
| <div class="setting-toggle" onclick="toggleSetting('autoFix')"> |
| <div class="toggle-switch" id="toggleAutoFix"></div> |
| <span>تشغيل</span> |
| </div> |
| <p class="setting-description">إصلاح المشاكل الآمنة تلقائياً دون تدخل</p> |
| </div> |
| |
| <button class="save-btn" onclick="saveSettings()">💾 حفظ الإعدادات</button> |
| </div> |
| </div> |
| |
| |
| <div class="toast-container" id="toastContainer"></div> |
|
|
| <script> |
| |
| let currentData = { |
| threats: 1247, |
| successRate: 99.9, |
| openIssues: 23, |
| responseTime: 0.3, |
| issues: [], |
| repos: [] |
| }; |
| |
| let settings = { |
| username: '', |
| email: '', |
| language: 'ar', |
| theme: 'light', |
| autoScan: true, |
| criticalAlerts: true, |
| autoFix: true |
| }; |
| |
| |
| const sampleIssues = [ |
| { id: 1, title: 'ثغرة أمنية في وحدة المصادقة', file: 'auth-module.py', time: 'قبل 5 دقائق', severity: 'critical' }, |
| { id: 2, title: 'فشل في اختبارات الأداء', file: 'performance_test.py', time: 'قبل 23 دقيقة', severity: 'warning' }, |
| { id: 3, title: 'تحذير في تنسيق الكود', file: 'main_controller.dart', time: 'قبل ساعة', severity: 'info' }, |
| { id: 4, title: 'تم إصلاح مشكلة التنسيق تلقائياً', file: 'utils_helper.js', time: 'قبل ساعتين', severity: 'success' }, |
| { id: 5, title: 'مشكلة في اتصال قاعدة البيانات', file: 'db_connection.java', time: 'قبل ساعتين', severity: 'critical' }, |
| { id: 6, title: 'تحذير: استخدام دالة قديمة', file: 'legacy_code.py', time: 'قبل 3 ساعات', severity: 'warning' } |
| ]; |
| |
| const sampleRepos = [ |
| { id: 1, name: 'auto-guardian-system', stars: 124, pullRequests: 45, bugs: 3, status: 'active' }, |
| { id: 2, name: 'payment-gateway-api', stars: 89, pullRequests: 32, bugs: 5, status: 'warning' }, |
| { id: 3, name: 'user-management-service', stars: 56, pullRequests: 18, bugs: 1, status: 'active' }, |
| { id: 4, name: 'data-analytics-platform', stars: 234, pullRequests: 67, bugs: 8, status: 'error' } |
| ]; |
| |
| |
| document.addEventListener('DOMContentLoaded', function() { |
| loadSettings(); |
| loadData(); |
| renderIssues(); |
| renderRepos(); |
| setupEventListeners(); |
| setupMobileMenu(); |
| showToast('🎉 مرحباً بك في Auto-Guardian!', 'success'); |
| }); |
| |
| |
| function setupMobileMenu() { |
| const mobileMenuBtn = document.getElementById('mobileMenuBtn'); |
| if (mobileMenuBtn) { |
| |
| const checkScreenSize = () => { |
| if (window.innerWidth <= 992) { |
| mobileMenuBtn.style.display = 'flex'; |
| } else { |
| mobileMenuBtn.style.display = 'none'; |
| closeMobileMenu(); |
| } |
| }; |
| |
| checkScreenSize(); |
| window.addEventListener('resize', checkScreenSize); |
| } |
| } |
| |
| |
| function toggleMobileMenu() { |
| const sidebar = document.getElementById('sidebar'); |
| const overlay = document.getElementById('sidebarOverlay'); |
| |
| if (sidebar && overlay) { |
| sidebar.classList.toggle('active'); |
| overlay.classList.toggle('active'); |
| } |
| } |
| |
| |
| function closeMobileMenu() { |
| const sidebar = document.getElementById('sidebar'); |
| const overlay = document.getElementById('sidebarOverlay'); |
| |
| if (sidebar) { |
| sidebar.classList.remove('active'); |
| } |
| if (overlay) { |
| overlay.classList.remove('active'); |
| } |
| } |
| |
| |
| function loadSettings() { |
| const saved = localStorage.getItem('autoGuardianSettings'); |
| if (saved) { |
| settings = JSON.parse(saved); |
| } |
| |
| |
| document.getElementById('settingUsername').value = settings.username || ''; |
| document.getElementById('settingEmail').value = settings.email || ''; |
| document.getElementById('settingLanguage').value = settings.language || 'ar'; |
| document.getElementById('settingTheme').value = settings.theme || 'light'; |
| updateToggle('toggleAutoScan', settings.autoScan); |
| updateToggle('toggleCriticalAlerts', settings.criticalAlerts); |
| updateToggle('toggleAutoFix', settings.autoFix); |
| } |
| |
| |
| function saveSettings() { |
| settings.username = document.getElementById('settingUsername').value; |
| settings.email = document.getElementById('settingEmail').value; |
| settings.language = document.getElementById('settingLanguage').value; |
| settings.theme = document.getElementById('settingTheme').value; |
| |
| localStorage.setItem('autoGuardianSettings', JSON.stringify(settings)); |
| closeSettings(); |
| showToast('✅ تم حفظ الإعدادات بنجاح!', 'success'); |
| } |
| |
| |
| function updateToggle(id, value) { |
| const toggle = document.getElementById(id); |
| if (value) { |
| toggle.classList.add('active'); |
| } else { |
| toggle.classList.remove('active'); |
| } |
| } |
| |
| |
| function toggleSetting(setting) { |
| settings[setting] = !settings[setting]; |
| updateToggle('toggle' + setting.charAt(0).toUpperCase() + setting.slice(1), settings[setting]); |
| showToast(`⚙️ تم ${settings[setting] ? 'تفعيل' : 'تعطيل'} ${setting}`, 'info'); |
| } |
| |
| |
| function loadData() { |
| currentData.issues = sampleIssues; |
| currentData.repos = sampleRepos; |
| |
| |
| currentData.threats = Math.floor(Math.random() * 2000) + 500; |
| currentData.openIssues = Math.floor(Math.random() * 30) + 10; |
| currentData.responseTime = (Math.random() * 0.5 + 0.1).toFixed(1); |
| |
| updateStatsUI(); |
| } |
| |
| |
| function updateStatsUI() { |
| document.getElementById('statThreats').textContent = currentData.threats.toLocaleString(); |
| document.getElementById('statSuccess').textContent = currentData.successRate + '%'; |
| document.getElementById('statOpen').textContent = currentData.openIssues; |
| document.getElementById('statResponse').textContent = currentData.responseTime + 's'; |
| |
| |
| const critical = currentData.issues.filter(i => i.severity === 'critical').length; |
| const warning = currentData.issues.filter(i => i.severity === 'warning').length; |
| const info = currentData.issues.filter(i => i.severity === 'info').length; |
| const success = currentData.issues.filter(i => i.severity === 'success').length; |
| |
| document.getElementById('legendCritical').textContent = critical; |
| document.getElementById('legendHigh').textContent = warning; |
| document.getElementById('legendMedium').textContent = info; |
| document.getElementById('legendLow').textContent = success; |
| document.getElementById('donutTotal').textContent = currentData.issues.length; |
| } |
| |
| |
| function renderIssues(issues = currentData.issues) { |
| const container = document.getElementById('issuesList'); |
| container.innerHTML = ''; |
| |
| issues.forEach(issue => { |
| const severityClass = issue.severity === 'critical' ? 'badge-critical' : |
| issue.severity === 'warning' ? 'badge-warning' : |
| issue.severity === 'info' ? 'badge-info' : 'badge-success'; |
| |
| const severityLabel = issue.severity === 'critical' ? 'حرجة' : |
| issue.severity === 'warning' ? 'عالية' : |
| issue.severity === 'info' ? 'متوسطة' : 'تم الإصلاح'; |
| |
| const iconSvg = issue.severity === 'critical' ? |
| '<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/></svg>' : |
| issue.severity === 'warning' ? |
| '<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>' : |
| issue.severity === 'success' ? |
| '<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>' : |
| '<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>'; |
| |
| const html = ` |
| <div class="issue-item" onclick="showIssueDetails(${issue.id})"> |
| <div class="issue-icon" style="background: rgba(${issue.severity === 'critical' ? '239, 68, 68' : issue.severity === 'warning' ? '245, 158, 11' : issue.severity === 'success' ? '16, 185, 129' : '59, 130, 246'}, 0.1); color: ${issue.severity === 'critical' ? '#EF4444' : issue.severity === 'warning' ? '#F59E0B' : issue.severity === 'success' ? '#10B981' : '#3B82F6'};"> |
| ${iconSvg} |
| </div> |
| <div class="issue-content"> |
| <div class="issue-title">${issue.title}</div> |
| <div class="issue-meta">${issue.file} • ${issue.time}</div> |
| </div> |
| <span class="issue-badge ${severityClass}">${severityLabel}</span> |
| </div> |
| `; |
| container.innerHTML += html; |
| }); |
| } |
| |
| |
| function renderRepos(repos = currentData.repos) { |
| const container = document.getElementById('reposList'); |
| container.innerHTML = ''; |
| |
| repos.forEach(repo => { |
| const statusClass = repo.status === 'active' ? 'active' : repo.status === 'warning' ? 'warning' : 'error'; |
| const statusLabel = repo.status === 'active' ? 'نشط' : repo.status === 'warning' ? 'يحتاج مراجعة' : 'مشاكل'; |
| const statusColor = repo.status === 'active' ? '#10B981' : repo.status === 'warning' ? '#F59E0B' : '#EF4444'; |
| |
| const html = ` |
| <div class="repo-item"> |
| <div class="repo-icon"> |
| <svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"/> |
| </svg> |
| </div> |
| <div class="repo-content"> |
| <div class="repo-name">${repo.name}</div> |
| <div class="repo-stats"> |
| <span>⭐ ${repo.stars}</span> |
| <span>🔀 ${repo.pullRequests}</span> |
| <span>🐛 ${repo.bugs}</span> |
| </div> |
| </div> |
| <div class="repo-status"> |
| <span class="status-dot ${statusClass}"></span> |
| <span style="color: ${statusColor};">${statusLabel}</span> |
| </div> |
| </div> |
| `; |
| container.innerHTML += html; |
| }); |
| } |
| |
| |
| function filterIssues(type) { |
| let filtered = currentData.issues; |
| |
| if (type === 'critical') { |
| filtered = currentData.issues.filter(i => i.severity === 'critical'); |
| showToast(`🔍 عرض ${filtered.length} مشكلة حرجة`, 'info'); |
| } else if (type === 'open') { |
| filtered = currentData.issues.filter(i => i.severity !== 'success'); |
| showToast(`🔍 عرض ${filtered.length} مشكلة مفتوحة`, 'info'); |
| } else if (type === 'all') { |
| showToast(`🔍 عرض ${filtered.length} مشكلة`, 'info'); |
| } |
| |
| renderIssues(filtered); |
| } |
| |
| |
| function showIssueDetails(id) { |
| const issue = currentData.issues.find(i => i.id === id); |
| if (issue) { |
| showToast(`📋 ${issue.title} - ${issue.file}`, 'info'); |
| } |
| } |
| |
| |
| function changePeriod(period) { |
| |
| document.querySelectorAll('.chart-tab').forEach(tab => { |
| tab.classList.remove('active'); |
| if (tab.dataset.period === period) { |
| tab.classList.add('active'); |
| } |
| }); |
| |
| |
| showToast(`📊 عرض بيانات ${period === 'day' ? '24 ساعة' : period === 'week' ? 'أسبوع' : 'شهر'}`, 'info'); |
| |
| |
| const randomFactor = period === 'day' ? 1 : period === 'week' ? 7 : 30; |
| currentData.threats = Math.floor(Math.random() * 2000 * randomFactor) + 500; |
| updateStatsUI(); |
| } |
| |
| |
| function setupEventListeners() { |
| |
| document.querySelectorAll('.nav-item').forEach(item => { |
| item.addEventListener('click', function() { |
| const view = this.dataset.view; |
| |
| document.querySelectorAll('.nav-item').forEach(i => i.classList.remove('active')); |
| this.classList.add('active'); |
| |
| |
| closeMobileMenu(); |
| |
| if (view === 'settings') { |
| openSettings(); |
| } else if (view === 'help') { |
| showToast('📖 المساعدة: استخدم القائمة للتنقل بين الأقسام', 'info'); |
| } else { |
| showToast(`📂 الانتقال إلى ${this.querySelector('span').textContent}`, 'info'); |
| } |
| }); |
| }); |
| |
| |
| const searchInput = document.getElementById('searchInput'); |
| const searchResults = document.getElementById('searchResults'); |
| |
| searchInput.addEventListener('input', function() { |
| const query = this.value.toLowerCase(); |
| |
| if (query.length < 2) { |
| searchResults.classList.remove('active'); |
| return; |
| } |
| |
| |
| const results = []; |
| |
| currentData.issues.forEach(issue => { |
| if (issue.title.toLowerCase().includes(query) || issue.file.toLowerCase().includes(query)) { |
| results.push({ type: 'issue', title: issue.title, subtitle: issue.file }); |
| } |
| }); |
| |
| currentData.repos.forEach(repo => { |
| if (repo.name.toLowerCase().includes(query)) { |
| results.push({ type: 'repo', title: repo.name, subtitle: `⭐ ${repo.stars} | 🔀 ${repo.pullRequests}` }); |
| } |
| }); |
| |
| if (results.length > 0) { |
| searchResults.innerHTML = results.map(r => ` |
| <div class="search-result-item"> |
| <div style="font-weight: 500;">${r.title}</div> |
| <div style="font-size: 12px; color: var(--text-muted);">${r.subtitle}</div> |
| </div> |
| `).join(''); |
| searchResults.classList.add('active'); |
| } else { |
| searchResults.innerHTML = '<div class="search-result-item">لا توجد نتائج</div>'; |
| searchResults.classList.add('active'); |
| } |
| }); |
| |
| searchInput.addEventListener('blur', function() { |
| setTimeout(() => { |
| searchResults.classList.remove('active'); |
| }, 200); |
| }); |
| |
| searchInput.addEventListener('focus', function() { |
| if (this.value.length >= 2) { |
| searchResults.classList.add('active'); |
| } |
| }); |
| |
| |
| document.getElementById('notificationBtn').addEventListener('click', function() { |
| showToast('🔔 الإشعارات: 5 إشعارات جديدة', 'info'); |
| document.getElementById('notificationBadge').textContent = '0'; |
| }); |
| } |
| |
| |
| function openSettings() { |
| document.getElementById('settingsPanel').classList.add('active'); |
| } |
| |
| function closeSettings() { |
| document.getElementById('settingsPanel').classList.remove('active'); |
| } |
| |
| |
| function showToast(message, type = 'info') { |
| const container = document.getElementById('toastContainer'); |
| const toast = document.createElement('div'); |
| toast.className = `toast ${type}`; |
| toast.innerHTML = message; |
| container.appendChild(toast); |
| |
| setTimeout(() => { |
| toast.remove(); |
| }, 3000); |
| } |
| |
| |
| document.getElementById('settingsPanel').addEventListener('click', function(e) { |
| if (e.target === this) { |
| closeSettings(); |
| } |
| }); |
| </script> |
| </body> |
| </html> |
|
|