diff --git a/ansible-docs.html b/ansible-docs.html index bc80961..b23226e 100644 --- a/ansible-docs.html +++ b/ansible-docs.html @@ -1,10 +1,6 @@ - Ansible Sandbox Documentation | Argobox @@ -44,7 +40,6 @@ --card-hover-bg: rgba(30, 41, 59, 0.95); --card-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.3); --transition-normal: 0.3s ease; - --glass-effect: blur(10px); } * { @@ -63,255 +58,333 @@ radial-gradient(circle at 75% 60%, rgba(14, 165, 233, 0.1) 0%, transparent 50%); } - .navbar { - background-color: rgba(15, 23, 42, 0.9); - backdrop-filter: var(--glass-effect); - -webkit-backdrop-filter: var(--glass-effect); + .docs-container { + display: flex; + min-height: 100vh; + } + + .sidebar { + width: 280px; + background-color: var(--sidebar-bg); + border-right: 1px solid var(--border); position: fixed; top: 0; left: 0; - right: 0; - z-index: 1000; - padding: 1.25rem 0; + height: 100vh; + overflow-y: auto; + scrollbar-width: thin; + scrollbar-color: var(--border) transparent; + padding: 2rem 0; + z-index: 10; + } + + .sidebar::-webkit-scrollbar { + width: 6px; + } + + .sidebar::-webkit-scrollbar-track { + background: transparent; + } + + .sidebar::-webkit-scrollbar-thumb { + background-color: var(--border); + border-radius: 3px; + } + + .sidebar-header { + padding: 0 1.5rem; + margin-bottom: 2rem; + } + + .sidebar-title { + font-size: 1.25rem; + font-weight: 600; + margin-bottom: 0.5rem; + } + + .back-link { + display: flex; + align-items: center; + gap: 0.5rem; + color: var(--accent); + font-weight: 500; + font-size: 0.9rem; + padding: 0.5rem 0; + transition: all var(--transition-normal); + } + + .back-link:hover { + color: var(--accent-darker); + transform: translateX(-3px); + } + + .sidebar-section { + margin-bottom: 1.5rem; + } + + .sidebar-section-title { + font-weight: 600; + font-size: 0.85rem; + text-transform: uppercase; + color: var(--text-secondary); + letter-spacing: 0.05em; + padding: 0 1.5rem; + margin-bottom: 0.75rem; + } + + .sidebar-nav { + list-style: none; + } + + .sidebar-nav-item { + transition: all var(--transition-normal); + } + + .sidebar-nav-link { + display: block; + padding: 0.5rem 1.5rem; + color: var(--text-secondary); + text-decoration: none; + transition: all var(--transition-normal); + position: relative; + font-size: 0.95rem; + } + + .sidebar-nav-link:hover { + color: var(--text-primary); + background-color: rgba(255, 255, 255, 0.05); + } + + .sidebar-nav-link.active { + color: var(--accent); + background-color: rgba(59, 130, 246, 0.1); + } + + .sidebar-nav-link.active::before { + content: ''; + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 3px; + background: var(--accent-gradient); + } + + .main-content { + flex: 1; + margin-left: 280px; + padding: 3rem; + max-width: 1000px; + } + + .docs-header { + margin-bottom: 3rem; + } + + .docs-title { + font-size: 2.5rem; + font-weight: 700; + margin-bottom: 1rem; + } + + .docs-subtitle { + color: var(--text-secondary); + font-size: 1.2rem; + } + + .docs-section { + margin-bottom: 3rem; + scroll-margin-top: 2rem; + } + + .docs-section-title { + font-size: 1.75rem; + font-weight: 600; + margin-bottom: 1.5rem; + color: var(--text-primary); + position: relative; + padding-bottom: 0.75rem; border-bottom: 1px solid var(--border); } - .navbar .container { - display: flex; - justify-content: space-between; - align-items: center; - max-width: 1400px; - margin: 0 auto; - padding: 0 1.5rem; + .docs-subsection { + margin-bottom: 2rem; } - .logo a { - color: var(--text-primary); - text-decoration: none; - display: flex; - align-items: center; - gap: 0.25rem; - } - - .logo-text { - background: var(--accent-gradient); - -webkit-background-clip: text; - background-clip: text; - color: transparent; - font-size: 1.5rem; + .docs-subsection-title { + font-size: 1.25rem; font-weight: 600; - } - - .logo-dot { - color: var(--text-secondary); - font-size: 1.5rem; - font-weight: 600; - } - - .nav-menu { - display: flex; - gap: 2.5rem; - } - - .nav-link { - color: var(--text-secondary); - text-decoration: none; - font-size: 0.95rem; - font-weight: 500; - transition: all var(--transition-normal); - position: relative; - } - - .nav-link.active, - .nav-link:hover { + margin-bottom: 1rem; color: var(--accent); } - .nav-buttons { - display: flex; - align-items: center; - gap: 1.25rem; + .docs-text { + color: var(--text-secondary); + margin-bottom: 1.5rem; } - .dashboard-link { - display: flex; - align-items: center; - gap: 0.75rem; - padding: 0.625rem 1.25rem; - font-size: 0.95rem; - font-weight: 500; - color: var(--text-primary); - background-color: rgba(59, 130, 246, 0.1); - border: 1px solid rgba(59, 130, 246, 0.2); + .docs-list { + list-style-type: disc; + margin-left: 1.5rem; + margin-bottom: 1.5rem; + color: var(--text-secondary); + } + + .docs-list li { + margin-bottom: 0.5rem; + } + + .docs-code { + font-family: 'JetBrains Mono', monospace; + background-color: var(--sidebar-bg); + padding: 1.5rem; border-radius: 0.5rem; + overflow-x: auto; + margin-bottom: 1.5rem; + border: 1px solid var(--border); + font-size: 0.9rem; + line-height: 1.5; + } + + .docs-code pre { + margin: 0; + } + + .docs-table { + width: 100%; + border-collapse: collapse; + margin-bottom: 1.5rem; + } + + .docs-table th { + text-align: left; + padding: 0.75rem 1rem; + background-color: var(--sidebar-bg); + color: var(--text-primary); + font-weight: 600; + border-bottom: 2px solid var(--border); + } + + .docs-table td { + padding: 0.75rem 1rem; + border-bottom: 1px solid var(--border); + color: var(--text-secondary); + } + + .docs-note { + background-color: rgba(59, 130, 246, 0.1); + border-left: 4px solid var(--accent); + padding: 1rem 1.5rem; + border-radius: 0 0.5rem 0.5rem 0; + margin-bottom: 1.5rem; + } + + .docs-note-title { + font-weight: 600; + color: var(--accent); + display: flex; + align-items: center; + gap: 0.5rem; + margin-bottom: 0.5rem; + } + + .docs-warning { + background-color: rgba(245, 158, 11, 0.1); + border-left: 4px solid var(--warning); + padding: 1rem 1.5rem; + border-radius: 0 0.5rem 0.5rem 0; + margin-bottom: 1.5rem; + } + + .docs-warning-title { + font-weight: 600; + color: var(--warning); + display: flex; + align-items: center; + gap: 0.5rem; + margin-bottom: 0.5rem; + } + + .docs-button { + display: inline-flex; + align-items: center; + gap: 0.5rem; + background-color: var(--accent); + color: white; + padding: 0.75rem 1.25rem; + border-radius: 0.5rem; + font-weight: 500; text-decoration: none; transition: all var(--transition-normal); + margin-bottom: 1.5rem; } - .dashboard-link:hover { + .docs-button:hover { background-color: var(--accent-darker); + transform: translateY(-2px); + box-shadow: var(--card-shadow); } - .navbar .menu-toggle { - background: none; - border: none; - color: var(--text-primary); - font-size: 1.5rem; - cursor: pointer; - } - - .navbar .menu-toggle i { - transition: transform var(--transition-normal); - } - - .navbar .nav-menu.show { - display: block; - } - - .footer { - background-color: var(--secondary-bg); - padding: 2rem; - color: var(--text-secondary); + .docs-footer { border-top: 1px solid var(--border); - } - - .footer .container { - display: flex; - flex-direction: column; - align-items: center; - gap: 1rem; - } - - .footer .footer-content { - display: flex; - justify-content: space-between; - align-items: center; - width: 100%; - } - - .footer .footer-logo { - display: flex; - align-items: center; - } - - .footer .footer-logo .logo-text { - font-size: 1.5rem; - font-weight: 700; - color: var(--accent); - } - - .footer .footer-logo .logo-dot { - font-size: 1.5rem; - font-weight: 700; - color: var(--text-primary); - } - - .footer .footer-links { - display: flex; - gap: 1rem; - } - - .footer .footer-links a { + margin-top: 3rem; + padding-top: 2rem; color: var(--text-secondary); - text-decoration: none; font-size: 0.9rem; - transition: color var(--transition-normal); } - .footer .footer-links a:hover { - color: var(--accent); - } - - .footer .footer-social { - display: flex; - gap: 1rem; - } - - .footer .footer-social a { - color: var(--text-secondary); - font-size: 1.2rem; - transition: color var(--transition-normal); - } - - .footer .footer-social a:hover { - color: var(--accent); - } - - .footer .footer-bottom { - text-align: center; - font-size: 0.9rem; + .mobile-menu-toggle { + display: none; + position: fixed; + bottom: 1.5rem; + right: 1.5rem; + background: var(--accent-gradient); + color: white; + width: 50px; + height: 50px; + border-radius: 50%; + border: none; + cursor: pointer; + display: none; + position: fixed; + bottom: 1.5rem; + right: 1.5rem; + background: var(--accent-gradient); + color: white; + width: 50px; + height: 50px; + border-radius: 50%; + border: none; + cursor: pointer; + font-size: 1.5rem; + align-items: center; + justify-content: center; + z-index: 20; + box-shadow: var(--card-shadow); } @media (max-width: 992px) { - .navbar .nav-menu { - display: none; - flex-direction: column; - gap: 0.5rem; - background-color: var(--secondary-bg); - position: absolute; - top: 100%; - right: 0; - width: 200px; - padding: 1rem; - border: 1px solid var(--border); - border-radius: 0.5rem; + .sidebar { + transform: translateX(-100%); + transition: transform var(--transition-normal); } - .navbar .nav-menu.show { + .sidebar.active { + transform: translateX(0); + } + + .main-content { + margin-left: 0; + padding: 2rem 1.5rem; + } + + .mobile-menu-toggle { display: flex; } } - - - - - - - -
-
- -

Under Construction

-

This page is currently being developed. Some features may not be fully functional.

-
-
-
- - - - + @@ -882,23 +934,6 @@ web-server/ } }); }); - - // Add mobile menu toggle functionality - const menuToggleNav = document.querySelector('.menu-toggle'); - const navMenu = document.querySelector('.nav-menu'); - - menuToggleNav.addEventListener('click', function() { - navMenu.classList.toggle('show'); - const icon = menuToggleNav.querySelector('i'); - - if (navMenu.classList.contains('show')) { - icon.classList.remove('fa-bars'); - icon.classList.add('fa-times'); - } else { - icon.classList.remove('fa-times'); - icon.classList.add('fa-bars'); - } - }); }); diff --git a/ansible-sandbox.html b/ansible-sandbox.html index f086a93..a4179a3 100644 --- a/ansible-sandbox.html +++ b/ansible-sandbox.html @@ -1,26 +1,25 @@ - - - Argobox | Ansible Sandbox + + ArgoBox | Ansible Sandbox - + + + + - + @@ -1436,100 +1403,1117 @@ ArgoBox.com + -
- -
-

Under Construction

-

This page is still being developed. Check back soon for updates!

+ + + + +
+
+ +
+ Simulation Mode + + Active
-
-
-

Ansible Sandbox

-

Deploy infrastructure with Ansible playbooks in an isolated environment.

- -
-
-
Code
-
Output
-
Status
+ +
+
+ +
+
+

Ansible Sandbox is Currently Offline

+

The Ansible Sandbox environment is currently in simulation mode. You can explore the interface, but actual deployments are not available at this time. We're working to bring the full functionality online soon.

-
-
-
-

Ansible Playbook Editor

-

Edit your playbook here...

+
+
+

Ansible Sandbox

+
+ + +
+ +
+
+
+
+

Web Server Deployment

+ Basic +
+

+ Deploy a Nginx web server with a sample website in a controlled environment. +

+
+
+ + Runtime: ~3 min +
+
+ + 1 VM +
+
+
+ +
+
+

Docker Compose Stack

+ Intermediate +
+

+ Deploy a multi-container application using Docker Compose with automatic configuration. +

+
+
+ + Runtime: ~5 min +
+
+ + 1 VM +
+
+
+ +
+
+

K3s Kubernetes Cluster

+ Advanced +
+

+ Deploy a lightweight Kubernetes cluster with basic services and sample application. +

+
+
+ + Runtime: ~8 min +
+
+ + 3 VMs +
+
+
+ +
+
+

LAMP Stack

+ Intermediate +
+

+ Deploy a Linux, Apache, MySQL, and PHP stack with a sample application. +

+
+
+ + Runtime: ~4 min +
+
+ + 1 VM +
+
+
+ +
+
+

Security Hardening

+ Advanced +
+

+ Apply security best practices to a Linux server including firewall, SSH hardening, and more. +

+
+
+ + Runtime: ~6 min +
+
+ + 1 VM +
+
-
-

Deployment Output

-

Output will appear here when you deploy...

+
+
+
+
+ + Web Server Deployment +
+
+
Playbook
+
Configuration
+
Output
+
VM Status
+
View
- -
-

Deployment Status

-
-
- Ready to deploy -
-
-
Sandbox environment ready
-
-
-
+
+
+
+
+
+ 1 + --- +
+
+ 2 + # Web Server Deployment Playbook +
+
+ 3 + # This playbook installs and configures a basic Nginx web server +
+
+ 4 + +
+
+ 5 + - name: Deploy Web Server +
+
+ 6 + hosts: all +
+
+ 7 + become: yes +
+
+ 8 + vars: +
+
+ 9 + web_domain: example.local +
+
+ 10 + web_root: /var/www/html +
+
+ 11 + enable_https: false +
+
+ 12 + web_color: blue +
+
+ 13 + +
+
+ 14 + tasks: +
+
+ 15 + - name: Update apt cache +
+
+ 16 + apt: +
+
+ 17 + update_cache: yes +
+
+ 18 + cache_valid_time: 3600 +
+
+ 19 + +
+
+ 20 + - name: Install Nginx and required packages +
+
+ 21 + apt: +
+
+ 22 + name: +
+
+ 23 + - nginx +
+
+ 24 + - curl +
+
+ 25 + state: present +
+
+ 26 + +
+
+ 27 + - name: Create web root directory +
+
+ 28 + file: +
+
+ 29 + path: "{{ web_root }}" +
+
+ 30 + state: directory +
+
+ 31 + mode: '0755' +
+
+ 32 + +
+
+ 33 + - name: Create sample website +
+
+ 34 + template: +
+
+ 35 + src: templates/index.html.j2 +
+
+ 36 + dest: "{{ web_root }}/index.html" +
+
+ 37 + mode: '0644' +
+
+ 38 + +
+
+ 39 + - name: Configure Nginx virtual host +
+
+ 40 + template: +
+
+ 41 + src: templates/nginx.conf.j2 +
+
+ 42 + dest: /etc/nginx/sites-available/{{ web_domain }} +
+
+ 43 + notify: restart nginx +
+
+ 44 + +
+
+ 45 + - name: Enable Nginx virtual host +
+
+ 46 + file: +
+
+ 47 + src: /etc/nginx/sites-available/{{ web_domain }} +
+
+ 48 + dest: /etc/nginx/sites-enabled/{{ web_domain }} +
+
+ 49 + state: link +
+
+ 50 + notify: restart nginx +
+
+ 51 + +
+
+ 52 + - name: Start Nginx +
+
+ 53 + service: +
+
+ 54 + name: nginx +
+
+ 55 + state: started +
+
+ 56 + enabled: yes +
+
+ 57 + +
+
+ 58 + handlers: +
+
+ 59 + - name: restart nginx +
+
+ 60 + service: +
+
+ 61 + name: nginx +
+
+ 62 + state: restarted +
+
+
+ +
+
+
+ + +
Domain name for the Nginx virtual host.
+
+ +
+ + +
Directory path where website files will be stored.
+
+ +
+ +
+ +
+ +
+ + +
Color theme for the sample website.
+
+ +
+ + +
Operating system for the virtual machine.
+
+ +
+ + +
Resource allocation for the virtual machine.
+
+
+
+ +
+
+PLAY [Deploy Web Server] *************************************************** + +TASK [Gathering Facts] ***************************************************** +ok: [webserver] + +TASK [Update apt cache] **************************************************** +ok: [webserver] + +TASK [Install Nginx and required packages] ******************************** +ok: [webserver] + +TASK [Create web root directory] ******************************************* +ok: [webserver] + +TASK [Create sample website] *********************************************** +changed: [webserver] + +TASK [Configure Nginx virtual host] **************************************** +changed: [webserver] + +TASK [Enable Nginx virtual host] ******************************************* +changed: [webserver] + +TASK [Start Nginx] ********************************************************* +ok: [webserver] + +RUNNING HANDLER [restart nginx] ******************************************** +changed: [webserver] + +PLAY RECAP ***************************************************************** +webserver : ok=9 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 + +VERIFICATION ************************************************************** +Testing website availability... +Website is accessible at: http://192.168.122.10 +Website deployed successfully! +
+
+ +
+
+
+
+ +
+
+
webserver (Ubuntu 22.04 LTS)
+
1 vCPU, 1GB RAM, 20GB Storage
+
+
+
+
+
Running
+
+ +
+
Sandbox environment active for 15 more minutes
+
+
+
+
+
+
+ + +
+ +
+
+
+

Deployed Web Server

+

Your Nginx web server has been successfully deployed and is now running

+
+
+
+
+
+
CPU Usage
+
15%
+
+
+
+
+
59MB / 1GB
+
+
+
+
Memory Usage
+
23%
+
+
+
+
+
241MB / 1GB
+
+
+
+
Disk Usage
+
8%
+
+
+
+
+
1.6GB / 20GB
+
+
+ +
+
+
+
+
+
+
+
+ + http://192.168.122.10 +
+
+
+ +
Welcome to nginx!
+
Deployed with Ansible automation
+

If you see this page, the nginx web server is successfully installed and working.

+
+
+
+
+ + + +
+
+
+ + +
+
+
+

Deployed Docker Compose Stack

+

Your multi-container application has been successfully deployed with Docker Compose

+
+
+

Running Containers (4)

+
+
+
+ +
+
app-nodejs
+
Running
+
:3000→3000/tcp
+
+
+
+ +
+
app-db
+
Running
+
:5432→5432/tcp
+
+
+
+ +
+
app-nginx
+
Running
+
:80→80/tcp
+
+
+
+ +
+
app-redis
+
Running
+
:6379→6379/tcp
+
+
+ +

Container Networks

+
+
+
+ +
+
app-network
+
bridge
+
+
+
+
+ + + +
+
+
+ + +
+
+
+

K3s Kubernetes Cluster

+

Your lightweight Kubernetes cluster has been successfully deployed

+
+
+
+
+

Cluster Nodes

+
+
+
k3s-master
+
Ready
+
control-plane
+
v1.25.9+k3s1
+
+
+
k3s-worker-1
+
Ready
+
worker
+
v1.25.9+k3s1
+
+
+
k3s-worker-2
+
Ready
+
worker
+
v1.25.9+k3s1
+
+
+
+ +
+

Namespaces

+
+
+
default
+
Active
+
5m
+
+
+
kube-system
+
Active
+
5m
+
+
+
kube-public
+
Active
+
5m
+
+
+
kube-node-lease
+
Active
+
5m
+
+
+
+ +
+

Workloads

+
+
+
traefik-78bcf47b8b-z4nx6
+
1/1
+
Pod
+
4m
+
+
+
metrics-server-7d7f69dc4f-9rkcj
+
1/1
+
Pod
+
4m
+
+
+
local-path-provisioner
+
1/1
+
Pod
+
4m
+
+
+
+
+
+
+ + + +
+
+
+ + +
+
+
+

Deployed LAMP Stack

+

Your Linux, Apache, MySQL, and PHP stack has been successfully deployed

+
+
+

LAMP Stack Components

+
+
+
+ +
+
+
Apache Web Server
+
+ Version: 2.4.52 • Status: Running • Port: 80 +
+
+
+
+
+ +
+
+
MySQL Database
+
+ Version: 8.0.28 • Status: Running • Port: 3306 +
+
+
+
+
+ +
+
+
PHP
+
+ Version: 8.1.2 • Status: Running • Extensions: 20 +
+
+
+
+ +

PHP Configuration

+
+
PHP Information
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PHP Version8.1.2-1ubuntu2.14
SystemLinux lamp-server 5.15.0-70-generic #77-Ubuntu SMP
Server APIApache 2.0 Handler
Virtual Directory Supportenabled
Configuration File/etc/php/8.1/apache2/php.ini
Max Execution Time30 seconds
Memory Limit128M
+
+
+
+
+ + + +
+
+
+ + +
+
+
+

Security Hardened Server

+

Your server has been successfully hardened with multiple security configurations

- -
- - -
-
+
+
+
+

System Security Verification

+
+
+ +
+
+
Updated Packages
+
All system packages are updated to latest secure versions
+
+
Passed
+
+
+
+ +
+
+
SSH Hardening
+
Password authentication disabled, key-based auth only
+
+
Passed
+
+
+
+ +
+
+
Firewall Configuration
+
UFW enabled with proper rule configuration
+
+
Passed
+
-
+
+
+ + + +
+
+
+
+
+
+
+
+ Ready to deploy +
+
+ + +
+
+
+
+
+ + +
+
+ + + \ No newline at end of file diff --git a/dashboard.html b/dashboard.html index 10090ca..b0e2b20 100644 --- a/dashboard.html +++ b/dashboard.html @@ -989,6 +989,220 @@ grid-template-columns: 1fr; } } + + /* Simulation toggle */ + .simulation-toggle { + display: flex; + align-items: center; + gap: 0.75rem; + margin-left: 1rem; + } + + .toggle-switch { + position: relative; + display: inline-block; + width: 46px; + height: 24px; + } + + .toggle-switch input { + opacity: 0; + width: 0; + height: 0; + } + + .toggle-slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(148, 163, 184, 0.2); + transition: .4s; + border-radius: 24px; + } + + .toggle-slider:before { + position: absolute; + content: ""; + height: 18px; + width: 18px; + left: 3px; + bottom: 3px; + background-color: var(--text-secondary); + transition: .4s; + border-radius: 50%; + } + + input:checked + .toggle-slider { + background-color: rgba(59, 130, 246, 0.3); + } + + input:checked + .toggle-slider:before { + transform: translateX(22px); + background-color: var(--accent); + } + + .toggle-label { + font-size: 0.85rem; + color: var(--text-secondary); + font-weight: 500; + } + + .toggle-status { + font-weight: 600; + color: var(--text-secondary); + } + + /* Status indicators - including offline state */ + .live-indicator.offline { + background-color: var(--error); + } + + .live-indicator.offline::after { + background-color: var(--error); + } + + .live-indicator-label.offline { + background-color: rgba(239, 68, 68, 0.1); + color: var(--error); + } + + /* Popup styles for settings and alerts */ + .popup-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(15, 23, 42, 0.8); + backdrop-filter: blur(5px); + -webkit-backdrop-filter: blur(5px); + z-index: 1001; + display: none; + align-items: center; + justify-content: center; + } + + .popup-container { + background-color: var(--secondary-bg); + border-radius: 0.75rem; + box-shadow: var(--card-shadow); + width: 90%; + max-width: 500px; + max-height: 90vh; + overflow-y: auto; + } + + .popup-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1.25rem 1.5rem; + border-bottom: 1px solid var(--border); + } + + .popup-title { + font-size: 1.25rem; + font-weight: 600; + } + + .popup-close { + font-size: 1.5rem; + cursor: pointer; + color: var(--text-secondary); + transition: color var(--transition-normal); + } + + .popup-close:hover { + color: var(--text-primary); + } + + .popup-content { + padding: 1.5rem; + } + + /* Settings popup */ + .settings-section { + margin-bottom: 1.5rem; + } + + .settings-section:last-child { + margin-bottom: 0; + } + + .settings-title { + font-size: 1rem; + font-weight: 600; + margin-bottom: 1rem; + color: var(--text-primary); + } + + .settings-option { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0.75rem 0; + border-bottom: 1px solid var(--border); + } + + .settings-option:last-child { + border-bottom: none; + } + + .settings-label { + font-size: 0.95rem; + color: var(--text-secondary); + } + + /* Alerts popup */ + .alert-list { + display: flex; + flex-direction: column; + gap: 1rem; + } + + .alert-item { + background-color: rgba(30, 41, 59, 0.5); + border-radius: 0.5rem; + padding: 1rem; + border-left: 3px solid var(--accent); + } + + .alert-item.error { + border-left-color: var(--error); + } + + .alert-item.warning { + border-left-color: var(--warning); + } + + .alert-item.success { + border-left-color: var(--success); + } + + .alert-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 0.5rem; + } + + .alert-title { + font-weight: 600; + font-size: 0.95rem; + } + + .alert-time { + font-size: 0.8rem; + color: var(--text-secondary); + } + + .alert-message { + font-size: 0.9rem; + color: var(--text-secondary); + } @@ -1030,18 +1244,26 @@ Live
+
+ Simulation Mode: + + Inactive +
- - - @@ -1386,6 +1608,144 @@
+ + + + + +
@@ -1466,12 +1826,72 @@ }); // Refresh button functionality - const refreshBtn = document.querySelector('.dashboard-btn'); + const refreshBtn = document.getElementById('refresh-btn'); refreshBtn.addEventListener('click', function() { simulateRefresh(); }); + // Initialize simulation toggle + const toggleInput = document.getElementById('simulation-toggle'); + const toggleStatus = document.querySelector('.toggle-status'); + const liveIndicator = document.querySelector('.live-dot'); + const liveLabel = document.querySelector('.live-indicator-label'); + + toggleInput.addEventListener('change', function() { + if(this.checked) { + toggleStatus.textContent = 'Active'; + document.body.classList.add('simulation-mode'); + liveIndicator.classList.add('offline'); + liveLabel.classList.add('offline'); + liveLabel.querySelector('span:last-child').textContent = 'Offline'; + } else { + toggleStatus.textContent = 'Inactive'; + document.body.classList.remove('simulation-mode'); + liveIndicator.classList.remove('offline'); + liveLabel.classList.remove('offline'); + liveLabel.querySelector('span:last-child').textContent = 'Live'; + } + }); + + // Initialize simulation as active by default for demonstration + toggleInput.checked = true; + toggleInput.dispatchEvent(new Event('change')); + + // Set up settings and alerts popup functionality + const settingsBtn = document.getElementById('settings-btn'); + const alertsBtn = document.getElementById('alerts-btn'); + const settingsPopup = document.getElementById('settings-popup'); + const alertsPopup = document.getElementById('alerts-popup'); + const closeSettings = document.getElementById('close-settings'); + const closeAlerts = document.getElementById('close-alerts'); + + settingsBtn.addEventListener('click', function() { + settingsPopup.style.display = 'flex'; + }); + + alertsBtn.addEventListener('click', function() { + alertsPopup.style.display = 'flex'; + }); + + closeSettings.addEventListener('click', function() { + settingsPopup.style.display = 'none'; + }); + + closeAlerts.addEventListener('click', function() { + alertsPopup.style.display = 'none'; + }); + + // Close popups when clicking outside + window.addEventListener('click', function(e) { + if (e.target === settingsPopup) { + settingsPopup.style.display = 'none'; + } + if (e.target === alertsPopup) { + alertsPopup.style.display = 'none'; + } + }); + // Set up simulation of real-time data function simulateRefresh() { // Update metrics with random variations @@ -1481,7 +1901,7 @@ updateOverviewCard('Network', 15, 40); // Update last refresh time - document.getElementById('last-refresh').textContent = 'Just now'; + document.querySelector('.services-refresh span').textContent = 'Last updated: Just now'; // Add a new log entry addLogEntry(); @@ -1523,8 +1943,11 @@ function addLogEntry() { const logsContent = document.querySelector('.logs-content'); + + // Get current time in MST (UTC-7) const now = new Date(); - const timeString = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`; + const mstTime = new Date(now.getTime() - (7 * 60 * 60 * 1000)); // Convert to MST + const timeString = `${mstTime.getHours().toString().padStart(2, '0')}:${mstTime.getMinutes().toString().padStart(2, '0')}:${mstTime.getSeconds().toString().padStart(2, '0')}`; const logTypes = ['info', 'success', 'warning', 'error']; const logType = logTypes[Math.floor(Math.random() * logTypes.length)]; @@ -1537,7 +1960,13 @@ 'Disk space cleanup completed', 'User session timeout', 'API rate limit approaching', - 'Security scan completed' + 'Security scan completed', + 'Database connection pool refreshed', + 'Cache invalidation triggered', + 'SSL certificate validity verified', + 'User authentication succeeded', + 'Scheduled task executed', + 'Configuration updated' ]; const logMessage = logMessages[Math.floor(Math.random() * logMessages.length)]; @@ -1551,15 +1980,96 @@ `; logsContent.insertBefore(logEntry, logsContent.firstChild); + + // Keep only the last 20 log entries + const allEntries = logsContent.querySelectorAll('.log-entry'); + if (allEntries.length > 20) { + for (let i = 20; i < allEntries.length; i++) { + logsContent.removeChild(allEntries[i]); + } + } } // Mobile menu toggle const menuToggle = document.querySelector('.menu-toggle'); const navMenu = document.querySelector('.nav-menu'); - menuToggle.addEventListener('click', function() { - navMenu.classList.toggle('active'); - }); + if (menuToggle && navMenu) { + menuToggle.addEventListener('click', function() { + navMenu.classList.toggle('active'); + }); + } + + // Generate initial log entries with timestamps ranging from 30-40 minutes ago to now + function generateInitialLogs() { + const logsContent = document.querySelector('.logs-content'); + if (!logsContent) return; + + // Clear existing logs + logsContent.innerHTML = ''; + + // Get current time in MST + const now = new Date(); + const mstNow = new Date(now.getTime() - (7 * 60 * 60 * 1000)); // Convert to MST + + // Generate entries from 40 minutes ago to now + for (let i = 0; i < 15; i++) { + const minutesAgo = Math.floor(Math.random() * 40) + 1; // 1-40 minutes ago + const logTime = new Date(mstNow.getTime() - (minutesAgo * 60 * 1000)); + const timeString = `${logTime.getHours().toString().padStart(2, '0')}:${logTime.getMinutes().toString().padStart(2, '0')}:${logTime.getSeconds().toString().padStart(2, '0')}`; + + const logTypes = ['info', 'success', 'warning', 'error']; + const logType = logTypes[Math.floor(Math.random() * logTypes.length)]; + + const logMessages = [ + 'System health check completed', + 'Container restarted automatically', + 'Network traffic spike detected', + 'Backup process initiated', + 'Disk space cleanup completed', + 'User session timeout', + 'API rate limit approaching', + 'Security scan completed', + 'Database connection pool refreshed', + 'Cache invalidation triggered', + 'SSL certificate validity verified', + 'User authentication succeeded', + 'Scheduled task executed', + 'Configuration updated' + ]; + + const logMessage = logMessages[Math.floor(Math.random() * logMessages.length)]; + + const logEntry = document.createElement('div'); + logEntry.className = 'log-entry'; + logEntry.innerHTML = ` + ${timeString} + ${logType.toUpperCase()} + ${logMessage} + `; + + // Sort logs by time (most recent at the top) + if (logsContent.children.length === 0) { + logsContent.appendChild(logEntry); + } else { + let inserted = false; + for (let j = 0; j < logsContent.children.length; j++) { + const existingTime = logsContent.children[j].querySelector('.log-time').textContent; + if (timeString > existingTime) { + logsContent.insertBefore(logEntry, logsContent.children[j]); + inserted = true; + break; + } + } + if (!inserted) { + logsContent.appendChild(logEntry); + } + } + } + } + + // Generate initial logs + generateInitialLogs(); // Auto refresh every 60 seconds setInterval(function() { diff --git a/index.html b/index.html index 8faa435..6330176 100644 --- a/index.html +++ b/index.html @@ -111,9 +111,10 @@
-
+
- Public + Offline
@@ -894,7 +895,7 @@

diff --git a/styles.css b/styles.css index 50f8984..931f050 100644 --- a/styles.css +++ b/styles.css @@ -2759,137 +2759,140 @@ section { } /* Enhanced Mobile Optimizations */ -@media (max-width: 480px) { - section { - padding: 3rem 0; +@media (max-width: 768px) { + /* Improve readability on mobile */ + body { + font-size: 16px; + } + + /* Make buttons more tappable */ + .btn, .nav-link, .service-item, .tech-card, .project-card { + padding: 0.8rem; } - .section-title { - font-size: 1.75rem; - } - - .section-description { - font-size: 0.95rem; - } - - .container { - padding: 0 1rem; - } - - /* Architecture section mobile optimization */ - .architecture-diagram { - flex-direction: column; - } - - .diagram-wrapper { - width: 100%; + /* Better spacing for section headers on mobile */ + .section-header { margin-bottom: 2rem; } - .architecture-details { - width: 100%; + .section-title { + font-size: 1.8rem; } - /* Improved mobile tech grid */ - .tech-grid { + /* Improved hero section for mobile */ + .hero { + padding: 6rem 0 3rem; + } + + .hero-title { + font-size: 2rem; + line-height: 1.3; + } + + .hero-description { + font-size: 1rem; + margin-bottom: 1.5rem; + } + + .cta-buttons { + flex-wrap: wrap; + gap: 1rem; + } + + /* Improved card layouts for touch */ + .tech-grid, .services-grid, .projects-grid, .dashboard-grid { grid-template-columns: 1fr; + gap: 1rem; } - .tech-card { - padding: 1.5rem; + .tech-card, .service-item, .project-card { + padding: 1.25rem; } - /* Services optimization */ - .services-grid { - grid-template-columns: 1fr; - } - - .service-items { - grid-template-columns: 1fr; - } - - /* Contact form mobile friendly */ - .contact-grid { - grid-template-columns: 1fr; - } - - .contact-form { - padding: 1.5rem; - } - - /* Top links mobile optimization */ - .top-links { - padding: 0.5rem 1rem; - justify-content: center; - } - - .laforceit-link, .signin-button { - font-size: 0.85rem; - } - - /* Projects section mobile */ - .projects-grid { - grid-template-columns: 1fr; - } - - /* Dashboard section mobile */ - .dashboard-grid { - grid-template-columns: 1fr; - } -} - -/* Touch-friendly adjustments */ -@media (hover: none) { - .btn:hover::before { - display: none; - } - - .btn:active { - transform: scale(0.98); - } - - .service-item, .tech-card, .project-card, .dashboard-card { - transition: transform 0.2s ease; + /* Enhanced tap targets for touch */ + .service-item, .tech-card, .project-card, .dashboard-card, .footer-link { + transition: transform 0.2s ease, box-shadow 0.2s ease; } .service-item:active, .tech-card:active, .project-card:active, .dashboard-card:active { transform: scale(0.98); } - - .nav-link:active::after { - width: 100%; - } } -/* Improved scrolling for mobile */ -@media (max-width: 768px) { - html { - scroll-padding-top: var(--mobile-nav-height); +/* Tablet-specific optimizations */ +@media (min-width: 481px) and (max-width: 1024px) { + /* Two-column layouts for tablets */ + .tech-grid, .services-grid, .projects-grid { + grid-template-columns: repeat(2, 1fr); } - /* Handle form inputs better on mobile */ - input, textarea, select, button { - font-size: 16px !important; /* Prevents zoom on focus in iOS */ + /* Balanced spacing for tablets */ + section { + padding: 4rem 0; } - /* Optimized footer for mobile */ - .footer-content { - flex-direction: column; - } - - .footer-info { - margin-bottom: 2rem; - text-align: center; - width: 100%; - } - - .footer-links { - width: 100%; - grid-template-columns: 1fr; + /* Hero layout adjustments */ + .hero-content { gap: 2rem; } - .footer-links-column { - text-align: center; + /* Architecture diagram adjustments */ + .architecture-diagram { + flex-direction: column; + } + + /* Footer improvements */ + .footer-content { + flex-wrap: wrap; + } +} + +/* Phone-specific optimizations */ +@media (max-width: 480px) { + .hero-stats { + grid-template-columns: repeat(2, 1fr); + gap: 1rem; + } + + .stat-item { + padding: 0.75rem; + } + + .stat-value { + font-size: 1.25rem; + } + + /* Single column layouts for phones */ + .contact-grid, .architecture-details { + grid-template-columns: 1fr; + } + + /* Improved form elements for touch */ + input, textarea, button { + font-size: 16px; /* Prevents zoom on input focus on iOS */ + padding: 0.8rem; + } + + /* Navbar adjustments */ + .navbar .container { + padding: 0 1rem; + } +} + +/* Touch optimizations */ +@media (hover: none) { + /* Disable hover effects on touch devices */ + .btn::before, .service-item:hover, .tech-card:hover { + transform: none; + } + + /* Use active states instead */ + .btn:active, .nav-link:active, .service-item:active { + opacity: 0.8; + } + + /* Larger tap targets */ + .nav-link, .footer-link, .dashboard-link { + padding: 0.6rem; } } \ No newline at end of file