diff --git a/src/components/BookingDetailsModal.tsx b/src/components/BookingDetailsModal.tsx index f30c56e..b5fd328 100644 --- a/src/components/BookingDetailsModal.tsx +++ b/src/components/BookingDetailsModal.tsx @@ -7,7 +7,7 @@ import React, { useState } from 'react'; import { Booking, LabTemplate, Device, User } from '../types'; import { authFetch } from '../lib/auth'; import { - X, Calendar, Clock, UserIcon, Database, Terminal, Cpu, Play, Check, + X, Calendar, Clock, UserIcon, Database, Terminal, Play, Check, Trash2, Ban, Copy, CheckCircle, HelpCircle, HardDrive, } from 'lucide-react'; @@ -76,12 +76,7 @@ export default function BookingDetailsModal({ } } - // Developer panel tabs ('rest', 'ansible', 'terminal') - const [activeTab, setActiveTab] = useState<'rest' | 'ansible' | 'terminal'>('ansible'); const [isCopied, setIsCopied] = useState(false); - const [isSimulating, setIsSimulating] = useState(false); - const [simulationLogs, setSimulationLogs] = useState([]); - const [simStep, setSimStep] = useState(0); const startFormatted = new Date(booking.startDateTime).toLocaleString('en-US', { weekday: 'short', @@ -101,35 +96,6 @@ export default function BookingDetailsModal({ timeZoneName: 'short' }); - // Dynamic Ansible playbook string based on active nodes - const ipList = mappedDevices.map(d => d.ip); - const ansiblePlaybook = `--- -- name: Reset GhostGrid Infrastructure Post-Reservation - hosts: localhost - gather_facts: false - vars: - target_nodes: -${ipList.map(ip => ` - "${ip}"`).join('\n') || ' - "No registered targets"'} - backup_repo: "https://git.ghostgrid.io/topology-configs" - - tasks: - - name: Audit out-of-band diagnostic link states - ansible.builtin.ping: - register: ping_result - - - name: Fetch designated golden config profile - ansible.builtin.get_url: - url: "{{ backup_repo }}/golden/${booking.labId}.cfg" - dest: "/tmp/golden_${booking.id}.cfg" - - - name: Commit golden parameters & purge current stack - ansible.netcommon.net_config: - src: "/tmp/golden_${booking.id}.cfg" - replace: block - when: ping_result is succeeded -`; - - // Dynamic REST Response const mockJsonResponse = JSON.stringify({ retrievedAt: new Date().toISOString(), apiEndpoint: `/api/bookings/${booking.id}`, @@ -145,57 +111,12 @@ ${ipList.map(ip => ` - "${ip}"`).join('\n') || ' - "No registered targ } }, null, 2); - const handleCopyText = (text: string) => { - navigator.clipboard.writeText(text); + const handleCopyJson = () => { + navigator.clipboard.writeText(mockJsonResponse); setIsCopied(true); setTimeout(() => setIsCopied(false), 2000); }; - // Ansible Terminal simulation execution - const runAnsibleSimulation = () => { - if (isSimulating) return; - setIsSimulating(true); - setSimStep(1); - setSimulationLogs([ - `[ansible-playbook -i localhost] Starting playbook: "Reset GhostGrid Infrastructure"`, - `[ansible-playbook] Configured target node list: ${ipList.join(', ') || 'None'}` - ]); - - setTimeout(() => { - setSimStep(2); - setSimulationLogs(prev => [ - ...prev, - `[localhost] TASK [Audit out-of-band diagnostic link states] **********************`, - ...mappedDevices.map(d => `ok: [${d.hostname} (${d.ip})] ping_state=SUCCESS latency=1.2ms`) - ]); - }, 1000); - - setTimeout(() => { - setSimStep(3); - setSimulationLogs(prev => [ - ...prev, - `[localhost] TASK [Fetch designated golden config profile] *************************`, - `changed: [localhost] fetched golden profile for lab ID "${booking.labId}"` - ]); - }, 2200); - - setTimeout(() => { - setSimStep(4); - setSimulationLogs(prev => [ - ...prev, - `[localhost] TASK [Commit golden parameters & purge current stack] ******************`, - ...mappedDevices.map(d => `changed: [${d.hostname}] configuration synced - cache invalidated - interfaces reset`), - `PLAY RECAP *************************************************************************`, - `localhost : ok=4 changed=2 unreachable=0 failed=0` - ]); - setIsSimulating(false); - onAddLog({ - type: 'maintenance', - message: `System Worker triggered an automated Ansible Golden Reset on reservation ${booking.id} (${lab?.name || 'Unknown'}). Checked ${mappedDevices.length} hosts.` - }); - }, 3800); - }; - return (
@@ -392,115 +313,27 @@ ${ipList.map(ip => ` - "${ip}"`).join('\n') || ' - "No registered targ
)} - {/* BELOW BLOCK: Restful API & Automation Integration developer panel */} + {/* JSON REST Response panel */}
- - {/* Panel Tabs Header */} -
+
- - Developer Restful API & Ansible Integration + + GET /api/bookings/{booking.id} - -
- - - -
+ application/json
- - {/* Panel Content Box */} -
- - {/* Copy Overlay button */} - {activeTab !== 'terminal' && ( - - )} - - {activeTab === 'ansible' && ( -
-
- Use this playbook in your local cron or Ansible Tower instance to automatically sync devices post-session: -
-
-                    {ansiblePlaybook}
-                  
-
- )} - - {activeTab === 'rest' && ( -
-
- GET Endpoint: /api/bookings/{booking.id} - application/json -
-
-                    {mockJsonResponse}
-                  
-
- )} - - {activeTab === 'terminal' && ( -
-
- Manual trigger simulation to verify post-booking hardware reset tasks - -
- -
- {simulationLogs.length === 0 ? ( -

Playbook simulator offline. Press "Run Simulator" above to run the automated Ansible pipeline check on the active SQLite nodes...

- ) : ( - simulationLogs.map((logLine, lIdx) => ( -
- {logLine} -
- )) - )} -
-
- )} - +
+ +
+                {mockJsonResponse}
+              
-
diff --git a/src/components/Settings.tsx b/src/components/Settings.tsx index ca307ec..56f03d5 100644 --- a/src/components/Settings.tsx +++ b/src/components/Settings.tsx @@ -315,7 +315,7 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) { } return ( -
+
{/* Page header */}
@@ -343,6 +343,9 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
)} + {/* Integration cards: three columns on large screens */} +
+ {/* ── Microsoft Entra ID ── */}
@@ -629,6 +632,8 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
+
{/* end grid */} + {/* Save bar */}

Changes are applied after saving and a server restart.