infinite-agents-public/src_group/ui_hybrid_3/script.js

481 lines
18 KiB
JavaScript

// DATACOM-3000 Data Explorer JavaScript Module
class DataExplorer {
constructor() {
this.data = [];
this.filteredData = [];
this.sortColumn = 'id';
this.sortDirection = 'asc';
this.selectedRow = null;
this.columns = ['id', 'name', 'type', 'size', 'modified'];
this.init();
}
init() {
this.bindEvents();
this.generateMockData();
this.updateDisplay();
this.startSystemClock();
this.simulateMemoryUsage();
}
bindEvents() {
// Search filter
const searchInput = document.getElementById('search-filter');
searchInput.addEventListener('input', (e) => this.handleSearch(e.target.value));
// Sort controls
const sortSelector = document.getElementById('sort-selector');
sortSelector.addEventListener('change', (e) => this.handleSort(e.target.value));
const sortDirection = document.querySelector('.sort-direction');
sortDirection.addEventListener('click', () => this.toggleSortDirection());
// Action buttons
document.querySelectorAll('.action-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
const action = e.currentTarget.dataset.action;
this.handleAction(action);
});
});
// Column headers for sorting
document.querySelectorAll('.column-header').forEach(header => {
header.addEventListener('click', (e) => {
if (!e.target.classList.contains('resize-handle')) {
const column = header.dataset.column;
this.handleSort(column);
}
});
});
// Column resizing
this.initColumnResizing();
// Preview close button
const previewClose = document.querySelector('.preview-close');
previewClose.addEventListener('click', () => this.closePreview());
// Command input
const commandInput = document.querySelector('.command-input');
commandInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
this.executeCommand(e.target.value);
e.target.value = '';
}
});
}
generateMockData() {
const fileTypes = ['DAT', 'TXT', 'BIN', 'LOG', 'CFG', 'SYS', 'EXE', 'BAT'];
const names = [
'SYSTEM', 'CONFIG', 'DATA', 'BACKUP', 'ARCHIVE', 'TEMP',
'CACHE', 'INDEX', 'DATABASE', 'REPORT', 'LOG', 'USER'
];
for (let i = 1; i <= 50; i++) {
const type = fileTypes[Math.floor(Math.random() * fileTypes.length)];
const name = names[Math.floor(Math.random() * names.length)];
const size = Math.floor(Math.random() * 999999) + 1;
const date = new Date(Date.now() - Math.floor(Math.random() * 31536000000));
this.data.push({
id: String(i).padStart(4, '0'),
name: `${name}_${String(i).padStart(2, '0')}.${type}`,
type: type,
size: this.formatSize(size),
sizeBytes: size,
modified: this.formatDate(date),
modifiedTimestamp: date.getTime(),
rawData: this.generatePreviewData(type)
});
}
this.filteredData = [...this.data];
}
generatePreviewData(type) {
const previews = {
'DAT': '00000000 48 45 58 20 44 55 4D 50 20 44 41 54 41 20 46 49 |HEX DUMP DATA FI|\n00000010 4C 45 20 46 4F 52 20 50 52 45 56 49 45 57 20 4F |LE FOR PREVIEW O|\n00000020 4E 4C 59 20 2D 20 4E 4F 54 20 41 43 54 55 41 4C |NLY - NOT ACTUAL|',
'TXT': 'PLAINTEXT DOCUMENT\n==================\nLorem ipsum dolor sit amet, consectetur adipiscing elit.\nSed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n\n[END OF FILE]',
'BIN': '01001000 01000101 01001100 01001100 01001111\n01010111 01001111 01010010 01001100 01000100\n00100001 00100000 00110010 00110000 00110010\n00110100 00100000 01000010 01001001 01001110',
'LOG': '[1990-01-01 00:00:00] SYSTEM INITIALIZED\n[1990-01-01 00:00:01] MEMORY CHECK... OK\n[1990-01-01 00:00:02] DISK CHECK... OK\n[1990-01-01 00:00:03] NETWORK CHECK... OK\n[1990-01-01 00:00:04] READY FOR OPERATION',
'CFG': 'SYSTEM.MEMORY=640K\nSYSTEM.DISK=40MB\nSYSTEM.CPU=80486\nSYSTEM.SPEED=33MHZ\nSYSTEM.CACHE=ENABLED\nSYSTEM.SOUND=BEEPER',
'SYS': 'SYSTEM FILE - PROTECTED\n\nACCESS DENIED\n\nAUTHORIZATION REQUIRED',
'EXE': 'EXECUTABLE FILE HEADER\n=====================\nMAGIC NUMBER: 4D5A\nBYTES ON LAST PAGE: 0090\nPAGES IN FILE: 0003\nRELOCATIONS: 0000\nHEADER SIZE: 0004',
'BAT': '@ECHO OFF\nCLS\nECHO BATCH FILE PREVIEW\nECHO ==================\nPAUSE\nEXIT'
};
return previews[type] || 'UNKNOWN FILE TYPE';
}
formatSize(bytes) {
if (bytes < 1024) return `${bytes}B`;
if (bytes < 1048576) return `${Math.floor(bytes / 1024)}K`;
return `${(bytes / 1048576).toFixed(1)}M`;
}
formatDate(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}`;
}
handleSearch(query) {
if (!query) {
this.filteredData = [...this.data];
} else {
const searchTerm = query.toLowerCase();
this.filteredData = this.data.filter(item =>
item.name.toLowerCase().includes(searchTerm) ||
item.type.toLowerCase().includes(searchTerm) ||
item.id.includes(searchTerm)
);
}
this.updateDisplay();
}
handleSort(column) {
if (this.sortColumn === column) {
this.toggleSortDirection();
} else {
this.sortColumn = column;
this.sortDirection = 'asc';
document.querySelector('.sort-direction').textContent = '▲';
}
this.sortData();
this.updateDisplay();
}
toggleSortDirection() {
this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc';
const directionBtn = document.querySelector('.sort-direction');
directionBtn.textContent = this.sortDirection === 'asc' ? '▲' : '▼';
this.sortData();
this.updateDisplay();
}
sortData() {
this.filteredData.sort((a, b) => {
let valueA, valueB;
switch (this.sortColumn) {
case 'size':
valueA = a.sizeBytes;
valueB = b.sizeBytes;
break;
case 'date':
case 'modified':
valueA = a.modifiedTimestamp;
valueB = b.modifiedTimestamp;
break;
default:
valueA = a[this.sortColumn];
valueB = b[this.sortColumn];
}
if (valueA < valueB) return this.sortDirection === 'asc' ? -1 : 1;
if (valueA > valueB) return this.sortDirection === 'asc' ? 1 : -1;
return 0;
});
}
handleAction(action) {
switch (action) {
case 'import':
this.showMessage('IMPORT FUNCTION NOT IMPLEMENTED');
this.simulateImport();
break;
case 'export':
this.exportData();
break;
case 'refresh':
this.refreshData();
break;
}
}
simulateImport() {
// Simulate file import
setTimeout(() => {
const newItem = {
id: String(this.data.length + 1).padStart(4, '0'),
name: `IMPORT_${Date.now()}.DAT`,
type: 'DAT',
size: this.formatSize(Math.floor(Math.random() * 99999) + 1000),
sizeBytes: Math.floor(Math.random() * 99999) + 1000,
modified: this.formatDate(new Date()),
modifiedTimestamp: Date.now(),
rawData: 'IMPORTED DATA FILE\n================\n[DATA IMPORTED SUCCESSFULLY]'
};
this.data.push(newItem);
this.filteredData = [...this.data];
this.updateDisplay();
this.showMessage('IMPORT COMPLETE: 1 FILE ADDED');
}, 1000);
}
exportData() {
const exportText = this.filteredData.map(item =>
`${item.id},${item.name},${item.type},${item.size},${item.modified}`
).join('\n');
const header = 'ID,NAME,TYPE,SIZE,MODIFIED\n';
const fullExport = header + exportText;
// Create download
const blob = new Blob([fullExport], { type: 'text/csv' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `DATACOM_EXPORT_${Date.now()}.CSV`;
a.click();
URL.revokeObjectURL(url);
this.showMessage(`EXPORT COMPLETE: ${this.filteredData.length} RECORDS`);
}
refreshData() {
// Simulate refresh animation
const tbody = document.getElementById('data-tbody');
tbody.style.opacity = '0.5';
setTimeout(() => {
tbody.style.opacity = '1';
this.updateDisplay();
this.showMessage('DATA REFRESHED');
}, 500);
}
updateDisplay() {
const tbody = document.getElementById('data-tbody');
tbody.innerHTML = '';
this.filteredData.forEach((item, index) => {
const row = document.createElement('tr');
row.setAttribute('role', 'row');
row.dataset.index = index;
row.innerHTML = `
<td role="gridcell">${item.id}</td>
<td role="gridcell">${item.name}</td>
<td role="gridcell">${item.type}</td>
<td role="gridcell">${item.size}</td>
<td role="gridcell">${item.modified}</td>
<td role="gridcell">
<button class="preview-btn" data-index="${index}">▶</button>
</td>
`;
row.addEventListener('click', (e) => {
if (!e.target.classList.contains('preview-btn')) {
this.selectRow(row, item);
}
});
tbody.appendChild(row);
});
// Bind preview buttons
document.querySelectorAll('.preview-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
e.stopPropagation();
const index = parseInt(btn.dataset.index);
this.showPreview(this.filteredData[index]);
});
});
// Update record count
document.getElementById('record-count').textContent = this.filteredData.length;
}
selectRow(row, item) {
// Remove previous selection
document.querySelectorAll('.data-table tbody tr').forEach(tr => {
tr.classList.remove('selected');
});
// Add selection to current row
row.classList.add('selected');
this.selectedRow = item;
}
showPreview(item) {
const previewContent = document.getElementById('preview-content');
previewContent.innerHTML = `
<div class="preview-info">
<p><span class="label">FILE:</span> ${item.name}</p>
<p><span class="label">TYPE:</span> ${item.type}</p>
<p><span class="label">SIZE:</span> ${item.size}</p>
<p><span class="label">DATE:</span> ${item.modified}</p>
</div>
<div class="preview-separator">════════════════════</div>
<pre class="preview-data">${item.rawData}</pre>
`;
// Show preview panel on mobile
const preview = document.querySelector('.data-preview');
preview.classList.add('active');
}
closePreview() {
const preview = document.querySelector('.data-preview');
preview.classList.remove('active');
}
executeCommand(command) {
const cmd = command.toUpperCase().trim();
switch (cmd) {
case 'CLS':
case 'CLEAR':
this.filteredData = [];
this.updateDisplay();
this.showMessage('SCREEN CLEARED');
break;
case 'DIR':
case 'LS':
this.showMessage(`${this.data.length} FILES IN DIRECTORY`);
break;
case 'HELP':
this.showMessage('COMMANDS: CLS, DIR, SORT, FILTER, EXIT');
break;
case 'EXIT':
this.showMessage('CANNOT EXIT - SYSTEM LOCKED');
break;
default:
if (cmd.startsWith('FILTER ')) {
const query = cmd.substring(7);
document.getElementById('search-filter').value = query;
this.handleSearch(query);
} else if (cmd.startsWith('SORT ')) {
const column = cmd.substring(5).toLowerCase();
if (this.columns.includes(column)) {
this.handleSort(column);
}
} else {
this.showMessage('UNKNOWN COMMAND - TYPE HELP');
}
}
}
showMessage(message) {
const commandInput = document.querySelector('.command-input');
const originalPlaceholder = commandInput.placeholder;
commandInput.placeholder = message;
setTimeout(() => {
commandInput.placeholder = originalPlaceholder;
}, 3000);
}
initColumnResizing() {
let isResizing = false;
let currentColumn = null;
let startX = 0;
let startWidth = 0;
document.querySelectorAll('.resize-handle').forEach(handle => {
handle.addEventListener('mousedown', (e) => {
isResizing = true;
currentColumn = handle.parentElement;
startX = e.pageX;
startWidth = currentColumn.offsetWidth;
document.body.style.cursor = 'col-resize';
e.preventDefault();
});
});
document.addEventListener('mousemove', (e) => {
if (!isResizing) return;
const width = startWidth + (e.pageX - startX);
if (width > 50) {
currentColumn.style.width = `${width}px`;
}
});
document.addEventListener('mouseup', () => {
isResizing = false;
currentColumn = null;
document.body.style.cursor = 'default';
});
}
startSystemClock() {
const updateClock = () => {
const now = new Date();
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
document.getElementById('system-time').textContent = `${hours}:${minutes}:${seconds}`;
};
updateClock();
setInterval(updateClock, 1000);
}
simulateMemoryUsage() {
const memoryBar = document.querySelector('.memory-used');
const memoryText = document.querySelector('.memory-text');
setInterval(() => {
const used = 640 + Math.floor(Math.random() * 100);
const percentage = (used / 1024) * 100;
memoryBar.style.width = `${percentage}%`;
memoryText.textContent = `${used}K/1024K`;
if (percentage > 90) {
memoryBar.style.backgroundColor = 'var(--error-red)';
} else if (percentage > 75) {
memoryBar.style.backgroundColor = 'var(--warning-yellow)';
} else {
memoryBar.style.backgroundColor = 'var(--terminal-text)';
}
}, 2000);
}
}
// Initialize on DOM ready
document.addEventListener('DOMContentLoaded', () => {
window.dataExplorer = new DataExplorer();
// Add keyboard shortcuts
document.addEventListener('keydown', (e) => {
if (e.ctrlKey || e.metaKey) {
switch (e.key) {
case 'f':
e.preventDefault();
document.getElementById('search-filter').focus();
break;
case 'e':
e.preventDefault();
window.dataExplorer.handleAction('export');
break;
case 'r':
e.preventDefault();
window.dataExplorer.handleAction('refresh');
break;
}
}
});
});
// Add some retro console messages
console.log('%c╔════════════════════════════╗', 'color: #00ff00');
console.log('%c║ DATACOM-3000 SYSTEM v2.31 ║', 'color: #00ff00');
console.log('%c║ (C) 1990 RETROTECH CORP ║', 'color: #00ff00');
console.log('%c╚════════════════════════════╝', 'color: #00ff00');
console.log('%cSYSTEM INITIALIZED', 'color: #ffb000');
console.log('%cMEMORY: 640K OK', 'color: #00ff00');
console.log('%cREADY.', 'color: #00ff00');