leaf/examples/widget_example/index.html
2025-08-05 15:02:23 +02:00

263 lines
11 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FileBrowser Widget Example</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css" rel="stylesheet">
<script src="./uppy.min.js"></script>
<link href="./uppy.min.css" rel="stylesheet">
<style>
body {
padding: 20px;
background-color: #f8f9fa;
}
.widget-container {
border: 2px dashed #dee2e6;
border-radius: 8px;
padding: 20px;
margin: 20px 0;
background: white;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.config-panel {
background: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
margin-bottom: 20px;
}
.status-indicator {
display: inline-block;
width: 12px;
height: 12px;
border-radius: 50%;
margin-right: 8px;
}
.status-success { background-color: #28a745; }
.status-error { background-color: #dc3545; }
.status-loading { background-color: #ffc107; }
</style>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-12">
<h1 class="mb-4">
<i class="bi bi-folder2-open"></i>
FileBrowser Widget Example
</h1>
<p class="lead">This demonstrates how to embed the FileBrowser widget in your website with runtime configuration.</p>
</div>
</div>
<div class="row">
<div class="col-md-4">
<div class="config-panel">
<h4>
<i class="bi bi-gear"></i>
Configuration
</h4>
<div class="mb-3">
<label for="endpoint" class="form-label">Base Endpoint:</label>
<input type="text" id="endpoint" class="form-control" value="http://localhost:3001/files">
<div class="form-text">Backend API endpoint for file operations</div>
</div>
<div class="mb-3">
<label for="theme" class="form-label">Theme:</label>
<select id="theme" class="form-select">
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</div>
<div class="mb-3">
<label for="max-file-size" class="form-label">Max File Size (MB):</label>
<input type="number" id="max-file-size" class="form-control" value="100" min="1" max="1000">
</div>
<div class="mb-3">
<label class="form-label">Features:</label>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="show-upload" checked>
<label class="form-check-label" for="show-upload">Show Upload</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="show-download" checked>
<label class="form-check-label" for="show-download">Show Download</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="show-delete" checked>
<label class="form-check-label" for="show-delete">Show Delete</label>
</div>
</div>
<div class="mb-3">
<label for="initial-path" class="form-label">Initial Path:</label>
<input type="text" id="initial-path" class="form-control" placeholder="e.g., documents/">
</div>
<button id="recreate-widget" class="btn btn-primary w-100">
<i class="bi bi-arrow-clockwise"></i>
Apply Configuration
</button>
<div class="mt-3">
<div id="status" class="small">
<span class="status-indicator status-loading"></span>
<span id="status-text">Initializing...</span>
</div>
</div>
</div>
<div class="config-panel">
<h5>
<i class="bi bi-info-circle"></i>
Widget Info
</h5>
<div class="small">
<div><strong>Version:</strong> <span id="widget-version">Loading...</span></div>
<div><strong>Browser Compatible:</strong> <span id="browser-compat">Checking...</span></div>
<div><strong>WASM Size:</strong> ~329KB</div>
<div><strong>JS Size:</strong> ~39KB</div>
</div>
</div>
</div>
<div class="col-md-8">
<div class="widget-container">
<h3>
<i class="bi bi-hdd-stack"></i>
File Browser Widget
</h3>
<p class="text-muted mb-3">The widget will appear below once initialized:</p>
<div id="file-browser-widget"></div>
</div>
</div>
</div>
</div>
<script type="module">
import init, {
create_file_browser_widget,
create_default_config,
check_browser_compatibility,
get_version
} from './file_browser_widget.js';
let currentWidget = null;
let isInitialized = false;
function updateStatus(text, type = 'loading') {
const statusElement = document.getElementById('status-text');
const indicatorElement = document.querySelector('.status-indicator');
statusElement.textContent = text;
indicatorElement.className = `status-indicator status-${type}`;
}
async function initWidget() {
try {
updateStatus('Loading WASM module...', 'loading');
await init();
updateStatus('Checking compatibility...', 'loading');
const version = get_version();
const isCompatible = check_browser_compatibility();
document.getElementById('widget-version').textContent = version;
document.getElementById('browser-compat').textContent = isCompatible ? 'Yes ✓' : 'No ✗';
if (!isCompatible) {
updateStatus('Browser not compatible', 'error');
document.getElementById('file-browser-widget').innerHTML =
'<div class="alert alert-danger">Your browser is not compatible with this widget</div>';
return;
}
isInitialized = true;
updateStatus('Ready', 'success');
createWidget();
} catch (error) {
console.error('Failed to initialize widget:', error);
updateStatus(`Initialization failed: ${error.message}`, 'error');
document.getElementById('file-browser-widget').innerHTML =
`<div class="alert alert-danger">Failed to initialize: ${error.message}</div>`;
}
}
function createWidget() {
if (!isInitialized) {
updateStatus('Widget not initialized', 'error');
return;
}
try {
updateStatus('Creating widget...', 'loading');
// Destroy existing widget
if (currentWidget) {
currentWidget.destroy();
currentWidget = null;
}
// Clear container
const container = document.getElementById('file-browser-widget');
container.innerHTML = '';
// Get configuration from form
const config = create_default_config(document.getElementById('endpoint').value);
// Apply configuration using the corrected method names
config.setTheme(document.getElementById('theme').value);
config.setMaxFileSize(parseInt(document.getElementById('max-file-size').value) * 1024 * 1024);
config.setShowUpload(document.getElementById('show-upload').checked);
config.setShowDownload(document.getElementById('show-download').checked);
config.setShowDelete(document.getElementById('show-delete').checked);
const initialPath = document.getElementById('initial-path').value.trim();
if (initialPath) {
config.setInitialPath(initialPath);
}
// Create widget
currentWidget = create_file_browser_widget('file-browser-widget', config);
updateStatus('Widget ready', 'success');
} catch (error) {
console.error('Failed to create widget:', error);
updateStatus(`Widget creation failed: ${error.message}`, 'error');
document.getElementById('file-browser-widget').innerHTML =
`<div class="alert alert-danger">Failed to create widget: ${error.message}</div>`;
}
}
// Event listeners
document.getElementById('recreate-widget').addEventListener('click', createWidget);
// Auto-recreate on configuration changes
['endpoint', 'theme', 'max-file-size', 'show-upload', 'show-download', 'show-delete', 'initial-path'].forEach(id => {
const element = document.getElementById(id);
if (element.type === 'checkbox') {
element.addEventListener('change', () => {
if (isInitialized) createWidget();
});
} else {
element.addEventListener('input', () => {
if (isInitialized) {
clearTimeout(element.debounceTimer);
element.debounceTimer = setTimeout(createWidget, 500);
}
});
}
});
// Initialize when page loads
initWidget();
</script>
</body>
</html>