infinite-agents-public/src_infinite/ui_hybrid_15.html

946 lines
28 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Industrial File Manager - Hybrid UI Component</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Roboto Mono', monospace;
background: #0a0a0a;
color: #e0e0e0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
overflow: hidden;
position: relative;
}
/* Industrial Grid Background */
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image:
linear-gradient(rgba(255,165,0,0.05) 1px, transparent 1px),
linear-gradient(90deg, rgba(255,165,0,0.05) 1px, transparent 1px);
background-size: 50px 50px;
pointer-events: none;
animation: gridShift 20s linear infinite;
}
@keyframes gridShift {
0% { transform: translate(0, 0); }
100% { transform: translate(50px, 50px); }
}
/* Main Container */
.file-manager {
width: 90%;
max-width: 1200px;
height: 80vh;
background: linear-gradient(135deg, #1a1a1a 0%, #2d2d2d 100%);
border: 2px solid #ff6600;
border-radius: 0;
position: relative;
display: grid;
grid-template-columns: 1fr 2fr 1fr;
gap: 2px;
box-shadow:
0 0 50px rgba(255,102,0,0.3),
inset 0 0 100px rgba(255,102,0,0.1);
overflow: hidden;
}
/* Industrial Corner Brackets */
.file-manager::before,
.file-manager::after,
.corner-bracket-top,
.corner-bracket-bottom {
content: '';
position: absolute;
width: 30px;
height: 30px;
border: 3px solid #ff6600;
z-index: 10;
}
.file-manager::before {
top: -5px;
left: -5px;
border-right: none;
border-bottom: none;
}
.file-manager::after {
top: -5px;
right: -5px;
border-left: none;
border-bottom: none;
}
.corner-bracket-top {
bottom: -5px;
left: -5px;
border-right: none;
border-top: none;
}
.corner-bracket-bottom {
bottom: -5px;
right: -5px;
border-left: none;
border-top: none;
}
/* Panel Styles */
.panel {
background: #1a1a1a;
border: 1px solid #333;
position: relative;
overflow: hidden;
}
.panel-header {
background: linear-gradient(90deg, #2a2a2a 0%, #3a3a3a 100%);
padding: 15px;
border-bottom: 2px solid #ff6600;
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
}
.panel-header::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 2px;
background: linear-gradient(90deg, transparent, #ff6600, transparent);
animation: scanLine 3s linear infinite;
}
@keyframes scanLine {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
.panel-title {
font-size: 14px;
text-transform: uppercase;
letter-spacing: 2px;
color: #ff6600;
font-weight: 700;
}
/* Left Panel - File Browser */
.file-browser {
grid-column: 1;
display: flex;
flex-direction: column;
}
.file-list {
flex: 1;
overflow-y: auto;
padding: 10px;
}
.file-item {
background: #222;
border: 1px solid #444;
padding: 12px;
margin-bottom: 8px;
cursor: pointer;
transition: all 0.3s;
position: relative;
overflow: hidden;
}
.file-item::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,102,0,0.3), transparent);
transition: left 0.5s;
}
.file-item:hover::before {
left: 100%;
}
.file-item:hover {
border-color: #ff6600;
transform: translateX(5px);
box-shadow: -5px 0 10px rgba(255,102,0,0.3);
}
.file-item.active {
background: #333;
border-color: #ff6600;
box-shadow: inset 0 0 20px rgba(255,102,0,0.2);
}
.file-icon {
display: inline-block;
width: 20px;
height: 20px;
margin-right: 10px;
background: #ff6600;
clip-path: polygon(0 0, 80% 0, 100% 20%, 100% 100%, 0 100%);
}
.file-name {
font-size: 12px;
color: #ccc;
}
.file-size {
font-size: 10px;
color: #666;
float: right;
}
/* Center Panel - Upload Zone */
.upload-zone {
grid-column: 2;
display: flex;
flex-direction: column;
}
.drop-area {
flex: 1;
margin: 20px;
border: 3px dashed #666;
background: #0f0f0f;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: relative;
overflow: hidden;
transition: all 0.3s;
}
.drop-area.dragover {
border-color: #ff6600;
background: #1a1a1a;
box-shadow: inset 0 0 50px rgba(255,102,0,0.2);
}
.drop-area::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 200%;
height: 200%;
background: conic-gradient(
from 0deg,
transparent 0deg,
rgba(255,102,0,0.1) 90deg,
transparent 180deg
);
transform: translate(-50%, -50%);
animation: radar 4s linear infinite;
opacity: 0.5;
}
@keyframes radar {
0% { transform: translate(-50%, -50%) rotate(0deg); }
100% { transform: translate(-50%, -50%) rotate(360deg); }
}
.upload-icon {
width: 80px;
height: 80px;
margin-bottom: 20px;
position: relative;
z-index: 1;
}
.gear {
width: 100%;
height: 100%;
border: 3px solid #ff6600;
border-radius: 50%;
position: relative;
animation: gearRotate 10s linear infinite;
}
.gear::before,
.gear::after {
content: '';
position: absolute;
background: #ff6600;
}
.gear::before {
width: 30%;
height: 30%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 50%;
}
.gear::after {
width: 100%;
height: 100%;
top: 0;
left: 0;
background: repeating-conic-gradient(
from 0deg,
#ff6600 0deg 20deg,
transparent 20deg 40deg
);
-webkit-mask: radial-gradient(circle at center, transparent 30%, black 30%, black 40%, transparent 40%);
mask: radial-gradient(circle at center, transparent 30%, black 30%, black 40%, transparent 40%);
}
@keyframes gearRotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.upload-text {
font-size: 16px;
color: #ccc;
text-align: center;
z-index: 1;
}
.upload-subtext {
font-size: 12px;
color: #666;
margin-top: 10px;
}
/* Progress Bars Container */
.progress-container {
padding: 20px;
max-height: 200px;
overflow-y: auto;
}
.progress-item {
background: #1a1a1a;
border: 1px solid #333;
padding: 15px;
margin-bottom: 10px;
position: relative;
overflow: hidden;
}
.progress-header {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
}
.progress-filename {
font-size: 12px;
color: #ff6600;
}
.progress-percent {
font-size: 12px;
color: #ccc;
font-weight: bold;
}
.progress-bar {
height: 10px;
background: #0a0a0a;
border: 1px solid #444;
position: relative;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #ff6600 0%, #ff8800 100%);
width: 0%;
transition: width 0.3s;
position: relative;
}
.progress-fill::after {
content: '';
position: absolute;
top: 0;
right: 0;
width: 20px;
height: 100%;
background: white;
opacity: 0.5;
animation: progressPulse 1s ease-in-out infinite;
}
@keyframes progressPulse {
0%, 100% { opacity: 0.5; }
50% { opacity: 1; }
}
/* Right Panel - Preview & Validation */
.preview-panel {
grid-column: 3;
display: flex;
flex-direction: column;
}
.preview-area {
flex: 1;
padding: 20px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.preview-content {
width: 100%;
height: 100%;
background: #0f0f0f;
border: 2px solid #333;
display: flex;
align-items: center;
justify-content: center;
position: relative;
overflow: hidden;
}
.preview-image {
max-width: 100%;
max-height: 100%;
object-fit: contain;
}
.preview-placeholder {
text-align: center;
color: #666;
}
.preview-icon {
font-size: 48px;
margin-bottom: 10px;
color: #444;
}
/* Validation Section */
.validation-section {
padding: 20px;
border-top: 2px solid #333;
}
.validation-item {
display: flex;
align-items: center;
margin-bottom: 10px;
padding: 8px;
background: #1a1a1a;
border: 1px solid #333;
transition: all 0.3s;
}
.validation-item.valid {
border-color: #00ff00;
box-shadow: inset 0 0 10px rgba(0,255,0,0.1);
}
.validation-item.invalid {
border-color: #ff0000;
box-shadow: inset 0 0 10px rgba(255,0,0,0.1);
}
.validation-icon {
width: 20px;
height: 20px;
margin-right: 10px;
display: flex;
align-items: center;
justify-content: center;
}
.validation-icon::before {
content: '⚙';
font-size: 16px;
color: #666;
animation: validationSpin 2s linear infinite;
}
.validation-item.valid .validation-icon::before {
content: '✓';
color: #00ff00;
animation: none;
}
.validation-item.invalid .validation-icon::before {
content: '✗';
color: #ff0000;
animation: none;
}
@keyframes validationSpin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.validation-text {
font-size: 12px;
color: #ccc;
}
/* Status Bar */
.status-bar {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 30px;
background: #1a1a1a;
border-top: 2px solid #ff6600;
display: flex;
align-items: center;
padding: 0 20px;
font-size: 11px;
color: #666;
}
.status-indicator {
width: 8px;
height: 8px;
background: #00ff00;
border-radius: 50%;
margin-right: 10px;
animation: statusPulse 2s ease-in-out infinite;
}
@keyframes statusPulse {
0%, 100% { opacity: 0.5; }
50% { opacity: 1; }
}
/* File Input */
#fileInput {
display: none;
}
/* Scrollbar Styling */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: #0a0a0a;
border: 1px solid #333;
}
::-webkit-scrollbar-thumb {
background: #ff6600;
border: 1px solid #333;
}
::-webkit-scrollbar-thumb:hover {
background: #ff8800;
}
/* Responsive */
@media (max-width: 768px) {
.file-manager {
grid-template-columns: 1fr;
grid-template-rows: 1fr 2fr 1fr;
height: 90vh;
}
.file-browser,
.upload-zone,
.preview-panel {
grid-column: 1;
}
}
</style>
</head>
<body>
<div class="corner-bracket-top"></div>
<div class="corner-bracket-bottom"></div>
<div class="file-manager">
<!-- Left Panel - File Browser -->
<div class="panel file-browser">
<div class="panel-header">
<div class="panel-title">FILE DIRECTORY</div>
<div style="font-size: 10px; color: #666;">SYSTEM://LOCAL</div>
</div>
<div class="file-list" id="fileList">
<!-- Files will be added here -->
</div>
</div>
<!-- Center Panel - Upload Zone -->
<div class="panel upload-zone">
<div class="panel-header">
<div class="panel-title">UPLOAD INTERFACE</div>
<div style="font-size: 10px; color: #666;">DRAG & DROP ENABLED</div>
</div>
<div class="drop-area" id="dropArea">
<div class="upload-icon">
<div class="gear"></div>
</div>
<div class="upload-text">DROP FILES HERE</div>
<div class="upload-subtext">or click to browse</div>
</div>
<div class="progress-container" id="progressContainer">
<!-- Progress bars will be added here -->
</div>
</div>
<!-- Right Panel - Preview & Validation -->
<div class="panel preview-panel">
<div class="panel-header">
<div class="panel-title">PREVIEW & VALIDATION</div>
<div style="font-size: 10px; color: #666;">ANALYSIS MODULE</div>
</div>
<div class="preview-area">
<div class="preview-content" id="previewContent">
<div class="preview-placeholder">
<div class="preview-icon"></div>
<div>No file selected</div>
</div>
</div>
</div>
<div class="validation-section" id="validationSection">
<div class="validation-item" id="validationType">
<div class="validation-icon"></div>
<div class="validation-text">File Type: Waiting...</div>
</div>
<div class="validation-item" id="validationSize">
<div class="validation-icon"></div>
<div class="validation-text">File Size: Waiting...</div>
</div>
<div class="validation-item" id="validationFormat">
<div class="validation-icon"></div>
<div class="validation-text">Format Check: Waiting...</div>
</div>
</div>
</div>
<!-- Status Bar -->
<div class="status-bar">
<div class="status-indicator"></div>
<div id="statusText">SYSTEM READY - AWAITING INPUT</div>
</div>
</div>
<input type="file" id="fileInput" multiple>
<script>
// File Manager State
const fileManager = {
files: [],
selectedFile: null,
uploads: new Map()
};
// Elements
const dropArea = document.getElementById('dropArea');
const fileInput = document.getElementById('fileInput');
const fileList = document.getElementById('fileList');
const progressContainer = document.getElementById('progressContainer');
const previewContent = document.getElementById('previewContent');
const validationSection = document.getElementById('validationSection');
const statusText = document.getElementById('statusText');
// Drag and Drop Events
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropArea.addEventListener(eventName, preventDefaults, false);
document.body.addEventListener(eventName, preventDefaults, false);
});
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
['dragenter', 'dragover'].forEach(eventName => {
dropArea.addEventListener(eventName, highlight, false);
});
['dragleave', 'drop'].forEach(eventName => {
dropArea.addEventListener(eventName, unhighlight, false);
});
function highlight(e) {
dropArea.classList.add('dragover');
}
function unhighlight(e) {
dropArea.classList.remove('dragover');
}
// Handle Drop
dropArea.addEventListener('drop', handleDrop, false);
dropArea.addEventListener('click', () => fileInput.click());
fileInput.addEventListener('change', handleFileSelect);
function handleDrop(e) {
const dt = e.dataTransfer;
const files = dt.files;
handleFiles([...files]);
}
function handleFileSelect(e) {
const files = e.target.files;
handleFiles([...files]);
}
function handleFiles(files) {
files.forEach(uploadFile);
updateStatus(`PROCESSING ${files.length} FILE(S)`);
}
function uploadFile(file) {
const id = Date.now() + Math.random();
// Add to file manager
fileManager.files.push({
id,
name: file.name,
size: file.size,
type: file.type,
file: file,
progress: 0
});
// Create progress item
const progressItem = createProgressItem(file.name, id);
progressContainer.appendChild(progressItem);
// Simulate upload
simulateUpload(id, file);
// Add to file list
addToFileList(id, file);
}
function createProgressItem(filename, id) {
const item = document.createElement('div');
item.className = 'progress-item';
item.id = `progress-${id}`;
item.innerHTML = `
<div class="progress-header">
<div class="progress-filename">${filename}</div>
<div class="progress-percent">0%</div>
</div>
<div class="progress-bar">
<div class="progress-fill"></div>
</div>
`;
return item;
}
function simulateUpload(id, file) {
let progress = 0;
const interval = setInterval(() => {
progress += Math.random() * 15;
if (progress > 100) {
progress = 100;
clearInterval(interval);
setTimeout(() => {
const progressItem = document.getElementById(`progress-${id}`);
if (progressItem) {
progressItem.style.opacity = '0';
setTimeout(() => progressItem.remove(), 300);
}
}, 1000);
}
updateProgress(id, progress);
}, 200);
}
function updateProgress(id, progress) {
const fileData = fileManager.files.find(f => f.id === id);
if (fileData) {
fileData.progress = progress;
}
const progressItem = document.getElementById(`progress-${id}`);
if (progressItem) {
const fill = progressItem.querySelector('.progress-fill');
const percent = progressItem.querySelector('.progress-percent');
fill.style.width = `${progress}%`;
percent.textContent = `${Math.round(progress)}%`;
}
}
function addToFileList(id, file) {
const fileItem = document.createElement('div');
fileItem.className = 'file-item';
fileItem.dataset.id = id;
fileItem.innerHTML = `
<span class="file-icon"></span>
<span class="file-name">${file.name}</span>
<span class="file-size">${formatFileSize(file.size)}</span>
`;
fileItem.addEventListener('click', () => selectFile(id));
fileList.appendChild(fileItem);
}
function selectFile(id) {
// Update selected state
document.querySelectorAll('.file-item').forEach(item => {
item.classList.remove('active');
});
const fileItem = document.querySelector(`[data-id="${id}"]`);
if (fileItem) {
fileItem.classList.add('active');
}
// Get file data
const fileData = fileManager.files.find(f => f.id === id);
if (fileData) {
fileManager.selectedFile = fileData;
showPreview(fileData);
validateFile(fileData);
updateStatus(`SELECTED: ${fileData.name}`);
}
}
function showPreview(fileData) {
const file = fileData.file;
if (file.type.startsWith('image/')) {
const reader = new FileReader();
reader.onload = (e) => {
previewContent.innerHTML = `<img src="${e.target.result}" class="preview-image" alt="${file.name}">`;
};
reader.readAsDataURL(file);
} else if (file.type.startsWith('text/')) {
const reader = new FileReader();
reader.onload = (e) => {
const text = e.target.result.substring(0, 1000);
previewContent.innerHTML = `
<div style="padding: 20px; font-size: 12px; color: #ccc; white-space: pre-wrap; overflow: auto; width: 100%; height: 100%;">
${text}${e.target.result.length > 1000 ? '...' : ''}
</div>
`;
};
reader.readAsText(file);
} else {
previewContent.innerHTML = `
<div class="preview-placeholder">
<div class="preview-icon">📄</div>
<div>${file.name}</div>
<div style="font-size: 12px; color: #666; margin-top: 10px;">${file.type || 'Unknown type'}</div>
</div>
`;
}
}
function validateFile(fileData) {
const file = fileData.file;
const validations = {
type: document.getElementById('validationType'),
size: document.getElementById('validationSize'),
format: document.getElementById('validationFormat')
};
// Reset validations
Object.values(validations).forEach(v => {
v.classList.remove('valid', 'invalid');
});
// Validate after delay (simulate processing)
setTimeout(() => {
// File type validation
const allowedTypes = ['image/', 'text/', 'application/pdf'];
const isValidType = allowedTypes.some(type => file.type.startsWith(type));
validations.type.classList.add(isValidType ? 'valid' : 'invalid');
validations.type.querySelector('.validation-text').textContent =
`File Type: ${file.type || 'Unknown'} ${isValidType ? '✓' : '✗'}`;
// File size validation (max 10MB)
const maxSize = 10 * 1024 * 1024;
const isValidSize = file.size <= maxSize;
validations.size.classList.add(isValidSize ? 'valid' : 'invalid');
validations.size.querySelector('.validation-text').textContent =
`File Size: ${formatFileSize(file.size)} ${isValidSize ? '✓' : '✗'}`;
// Format validation
const hasExtension = file.name.includes('.');
validations.format.classList.add(hasExtension ? 'valid' : 'invalid');
validations.format.querySelector('.validation-text').textContent =
`Format Check: ${hasExtension ? 'Valid extension' : 'No extension'} ${hasExtension ? '✓' : '✗'}`;
}, 500);
}
function formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
function updateStatus(message) {
statusText.textContent = message.toUpperCase();
}
// Add some demo files
setTimeout(() => {
const demoFiles = [
{ name: 'system.config', size: 2048, type: 'text/plain' },
{ name: 'blueprint.pdf', size: 1048576, type: 'application/pdf' },
{ name: 'component.png', size: 524288, type: 'image/png' }
];
demoFiles.forEach((demo, index) => {
const id = `demo-${index}`;
const fakeFile = new File([''], demo.name, { type: demo.type });
fileManager.files.push({
id,
name: demo.name,
size: demo.size,
type: demo.type,
file: fakeFile,
progress: 100
});
const fileItem = document.createElement('div');
fileItem.className = 'file-item';
fileItem.dataset.id = id;
fileItem.innerHTML = `
<span class="file-icon"></span>
<span class="file-name">${demo.name}</span>
<span class="file-size">${formatFileSize(demo.size)}</span>
`;
fileItem.addEventListener('click', () => selectFile(id));
fileList.appendChild(fileItem);
});
updateStatus('SYSTEM READY - 3 FILES LOADED');
}, 1000);
</script>
</body>
</html>