Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| # List of apps with added Google Drive input links | |
| apps = [ | |
| { | |
| "name": "Auto DPR Generator", | |
| "url": "https://huggingface.co/spaces/Rammohan0504/DPR-5", | |
| "description": "Generates detailed progress reports based on uploaded site images, streamlining documentation.", | |
| "input": "inputs DPR", | |
| "drive_url": "https://drive.google.com/drive/folders/1w3FHuP6HOlKDur_r5lcnM8iXqBKdFors?usp=sharing" | |
| }, | |
| { | |
| "name": "AI Based Work Progress Verifier", | |
| "url": "https://huggingface.co/spaces/Rekham1110/Construction_Project1", | |
| "description": "Automatically detects construction milestones from site images and updates Salesforce with completion percentages and tags.", | |
| "input": "Work Progress Verifier", | |
| "drive_url": "https://drive.google.com/drive/folders/106UNEiyLKQu1aZfTFyXACdYY-_BYJlEg?usp=sharing" | |
| }, | |
| { | |
| "name": "Safety Violation CCTV AI Full", | |
| "url": "https://huggingface.co/spaces/PrashanthB461/Safety_Violation_CCTV_AI", | |
| "description": "Real-time detection of safety violations like missing helmets or unauthorized access, with alerts via Salesforce dashboard.", | |
| "input": "Safety Violation", | |
| "drive_url": "https://drive.google.com/drive/folders/1SfJWnUPU7lxSkPrAYiu4bqRFFl-cvChs?usp=sharing" | |
| }, | |
| { | |
| "name": "Material Reconciliation", | |
| "url": "https://huggingface.co/spaces/VijayPulmamidi/MaterialReconciliationAI", | |
| "description": "Tracks materials from purchase to usage, preventing waste, theft, or mismanagement.", | |
| "input": "materialreconciliation", | |
| "drive_url": "https://drive.google.com/drive/folders/1CFOC32FqxPhjLMUdPzUjH76uVSvtnbHL?usp=sharing" | |
| }, | |
| { | |
| "name": "Material Estimator", | |
| "url": "https://kushalmanda-yolov5-blueprint-analysis.hf.space", | |
| "description": "Provides accurate material estimations for construction projects based on blueprints and inputs.", | |
| "input": "material estimator", | |
| "drive_url": "https://drive.google.com/drive/folders/1WMWiqk7sw5Nn7YE9m0TFWcEvMY5Bje-A?usp=sharing" | |
| }, | |
| { | |
| "name": "AI Coach Site Supervisor", | |
| "url": "https://huggingface.co/spaces/geethareddy/geethaAICoach3", | |
| "description": "Generates daily checklists, milestone-based focus suggestions, and reflection logs for site supervisors.", | |
| "input": "AI Coach Site Supervisor", | |
| "drive_url": "https://drive.google.com/drive/folders/1M_IvEL3eezcIGlDMwOeyMubPIYOeWSGm?usp=sharing" | |
| }, | |
| { | |
| "name": "Smart Finishing Material Estimator", | |
| "url": "https://huggingface.co/spaces/himabindug212/estimation_material", | |
| "description": "Estimates quantities of finishing materials like tiles, paint, and panels with auto-calculated results.", | |
| "input": "Smart Finisher Material Estimator", | |
| "drive_url": "https://drive.google.com/drive/folders/167c5Ej-O1Hcl0UdXMmlMAbzrOOwllWnc?usp=sharing" | |
| }, | |
| { | |
| "name": "Labour Attendance Analyzer", | |
| "url": "https://huggingface.co/spaces/lavanya121/attendance-forecasting_121", | |
| "description": "Monitors labour attendance, identifies shortage risks, and suggests actionable solutions.", | |
| "input": "Labour Attendance", | |
| "drive_url": "https://drive.google.com/drive/folders/1sanCj7li9wGlX_VPJmIjdpPyOR-WQrmX?usp=sharing" | |
| }, | |
| { | |
| "name": "AI Estimator Daily Requirements", | |
| "url": "https://huggingface.co/spaces/Naveensai/Construction-Forecast-App", | |
| "description": "Forecasts daily labour and material requirements for efficient construction site management.", | |
| "input": "AI Estimator Daily Requirements", | |
| "drive_url": "https://drive.google.com/drive/folders/1fe3Bu0cPjMCTsQDaqBRI7TkqSs9105zP?usp=sharing" | |
| }, | |
| ] | |
| # Function to generate HTML content | |
| def display_apps(search_query="", filter_input="All"): | |
| # Filter apps based on search query and input category | |
| filtered_apps = apps | |
| if search_query: | |
| filtered_apps = [ | |
| app for app in filtered_apps | |
| if search_query.lower() in app["name"].lower() or search_query.lower() in app["input"].lower() | |
| ] | |
| if filter_input != "All": | |
| filtered_apps = [app for app in filtered_apps if app["input"] == filter_input] | |
| # Generate HTML with embedded CSS and JavaScript | |
| html_content = """ | |
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet"> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet"> | |
| <style> | |
| body { | |
| font-family: 'Inter', sans-serif; | |
| background: linear-gradient(135deg, #f3f4f6, #e5e7eb); | |
| } | |
| .card { | |
| transition: transform 0.3s ease, box-shadow 0.3s ease; | |
| margin-bottom: 20px; | |
| } | |
| .card:hover { | |
| transform: translateY(-5px); | |
| box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1); | |
| } | |
| .search-input, .filter-select { | |
| transition: border-color 0.3s ease, box-shadow 0.3s ease; | |
| } | |
| .search-input:focus, .filter-select:focus { | |
| border-color: #2563eb; | |
| box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1); | |
| } | |
| .header { | |
| animation: fadeIn 1s ease-in-out; | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(-20px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| .button-container { | |
| display: flex; | |
| justify-content: center; | |
| gap: 10px; | |
| } | |
| .launch-button, .drive-button { | |
| background-color: transparent; | |
| color: #2563eb; | |
| border: 1px solid #2563eb; | |
| padding: 5px 15px; | |
| border-radius: 5px; | |
| text-decoration: none; | |
| transition: color 0.3s ease, border-color 0.3s ease; | |
| } | |
| .launch-button:hover, .drive-button:hover { | |
| color: #1d4ed8; | |
| border-color: #1d4ed8; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="min-h-screen py-12 px-4 sm:px-6 lg:px-8"> | |
| <div class="max-w-7xl mx-auto"> | |
| <div class="text-center mb-12 header"> | |
| <h1 class="text-4xl font-bold text-gray-900">SMARTLAB APPS</h1> | |
| </div> | |
| <div id="apps-grid" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6"> | |
| """ | |
| for app in filtered_apps: | |
| html_content += f""" | |
| <div class="card bg-white rounded-xl shadow-lg p-6"> | |
| <h2 class="text-xl font-semibold text-blue-600 mb-3">{app['name']}</h2> | |
| <p class="text-gray-600 mb-4">{app['description']}</p> | |
| <p class="text-gray-500 italic mb-4"><span class="font-medium">Category:</span> {app['input']}</p> | |
| <div class="button-container"> | |
| <a href="{app['url']}" target="_blank" class="launch-button"> | |
| Launch App | |
| </a> | |
| <a href="{app['drive_url']}" target="_blank" class="drive-button"> | |
| View Input Data | |
| </a> | |
| </div> | |
| </div> | |
| """ | |
| html_content += """ | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', () => { | |
| const searchInput = document.getElementById('search-input'); | |
| const filterInput = document.getElementById('filter-input'); | |
| const appsGrid = document.getElementById('apps-grid'); | |
| function renderApps() { | |
| const searchQuery = searchInput ? searchInput.value.toLowerCase() : ''; | |
| const filterValue = filterInput ? filterInput.value : 'All'; | |
| let filteredApps = """ + str(apps).replace("'", '"') + """; | |
| if (searchQuery) { | |
| filteredApps = filteredApps.filter(app => | |
| app.name.toLowerCase().includes(searchQuery) || | |
| app.input.toLowerCase().includes(searchQuery) | |
| ); | |
| } | |
| if (filterValue !== "All") { | |
| filteredApps = filteredApps.filter(app => app.input === filterValue); | |
| } | |
| appsGrid.innerHTML = filteredApps.length ? filteredApps.map(app => ` | |
| <div class="card bg-white rounded-xl shadow-lg p-6"> | |
| <h2 class="text-xl font-semibold text-blue-600 mb-3">\${app.name}</h2> | |
| <p class="text-gray-600 mb-4">\${app.description}</p> | |
| <p class="text-gray-500 italic mb-4"><span class="font-medium">Category:</span> \${app.input}</p> | |
| <div class="button-container"> | |
| <a href="\${app.url}" target="_blank" class="launch-button"> | |
| Launch App | |
| </a> | |
| <a href="\${app.drive_url}" target="_blank" class="drive-button"> | |
| View Input Data | |
| </a> | |
| </div> | |
| </div> | |
| `).join('') : '<p class="text-center text-gray-600 col-span-full">No apps found matching your criteria.</p>'; | |
| } | |
| if (searchInput && filterInput) { | |
| searchInput.addEventListener('input', renderApps); | |
| filterInput.addEventListener('change', renderApps); | |
| renderApps(); | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> | |
| """ | |
| return html_content | |
| # Gradio interface | |
| with gr.Blocks(title="SMARTLAB APPS") as demo: | |
| output = gr.HTML(display_apps("", "All")) | |
| demo.launch() |