diff --git a/backend/app/database/myp.db-shm b/backend/app/database/myp.db-shm index 65f48adf..0d6d9579 100644 Binary files a/backend/app/database/myp.db-shm and b/backend/app/database/myp.db-shm differ diff --git a/backend/app/database/myp.db-wal b/backend/app/database/myp.db-wal index e9cfb2dc..d6e95d8e 100644 Binary files a/backend/app/database/myp.db-wal and b/backend/app/database/myp.db-wal differ diff --git a/backend/app/static/js/advanced-components.js b/backend/app/static/js/advanced-components.js index 0519ecba..c0b75864 100644 --- a/backend/app/static/js/advanced-components.js +++ b/backend/app/static/js/advanced-components.js @@ -1 +1,752 @@ - \ No newline at end of file +/** + * MYP Platform Advanced UI Components + * Erweiterte Komponenten: Progress-Bars, File-Upload, Datepicker + * Version: 2.0.0 + */ + +(function() { + 'use strict'; + + // Namespace erweitern + window.MYP = window.MYP || {}; + window.MYP.Advanced = window.MYP.Advanced || {}; + + /** + * Progress Bar Component + */ + class ProgressBar { + constructor(container, options = {}) { + this.container = typeof container === 'string' ? document.querySelector(container) : container; + this.options = { + value: 0, + max: 100, + showLabel: true, + showPercentage: true, + animated: true, + color: 'blue', + size: 'md', + striped: false, + ...options + }; + + this.currentValue = this.options.value; + this.init(); + } + + init() { + if (!this.container) { + console.error('ProgressBar: Container nicht gefunden'); + return; + } + + this.render(); + } + + render() { + const percentage = Math.round((this.currentValue / this.options.max) * 100); + const sizeClass = this.getSizeClass(); + const colorClass = this.getColorClass(); + + this.container.innerHTML = ` +
+ `; + } + + getSizeClass() { + const sizes = { + 'sm': 'h-2', + 'md': 'h-3', + 'lg': 'h-4', + 'xl': 'h-6' + }; + return sizes[this.options.size] || sizes.md; + } + + getColorClass() { + const colors = { + 'blue': 'bg-blue-500', + 'green': 'bg-green-500', + 'red': 'bg-red-500', + 'yellow': 'bg-yellow-500', + 'purple': 'bg-purple-500', + 'indigo': 'bg-indigo-500' + }; + return colors[this.options.color] || colors.blue; + } + + setValue(value, animate = true) { + const oldValue = this.currentValue; + this.currentValue = Math.max(0, Math.min(this.options.max, value)); + + if (animate) { + this.animateToValue(oldValue, this.currentValue); + } else { + this.render(); + } + } + + animateToValue(from, to) { + const duration = 500; // ms + const steps = 60; + const stepValue = (to - from) / steps; + let currentStep = 0; + + const animate = () => { + if (currentStep < steps) { + this.currentValue = from + (stepValue * currentStep); + this.render(); + currentStep++; + requestAnimationFrame(animate); + } else { + this.currentValue = to; + this.render(); + } + }; + + animate(); + } + + increment(amount = 1) { + this.setValue(this.currentValue + amount); + } + + decrement(amount = 1) { + this.setValue(this.currentValue - amount); + } + + reset() { + this.setValue(0); + } + + complete() { + this.setValue(this.options.max); + } + } + + /** + * Advanced File Upload Component + */ + class FileUpload { + constructor(container, options = {}) { + this.container = typeof container === 'string' ? document.querySelector(container) : container; + this.options = { + multiple: false, + accept: '*/*', + maxSize: 50 * 1024 * 1024, // 50MB + maxFiles: 10, + dragDrop: true, + showProgress: true, + showPreview: true, + uploadUrl: '/api/upload', + chunkSize: 1024 * 1024, // 1MB chunks + ...options + }; + + this.files = []; + this.uploads = new Map(); + this.init(); + } + + init() { + if (!this.container) { + console.error('FileUpload: Container nicht gefunden'); + return; + } + + this.render(); + this.setupEventListeners(); + } + + render() { + this.container.innerHTML = ` ++ ${fileData.name} +
+ ++ ${this.formatFileSize(fileData.size)} • ${this.getStatusText(fileData.status)} +
+ + ${this.options.showProgress && fileData.status === 'uploading' ? ` +${fileData.error}
+ ` : ''} +