refactor: Modularize UI components and utilities

- Extract UI components into separate JS files
- Centralize configuration values in config.js
- Introduce a dedicated logger module
- Improve file tree drag-and-drop and undo functionality
- Refactor modal handling to a single manager
- Add URL routing support for SPA navigation
- Implement view mode for read-only access
This commit is contained in:
Mahmoud-Emad
2025-10-26 15:42:15 +03:00
parent 23a24d42e2
commit 0ed6bcf1f2
34 changed files with 4136 additions and 940 deletions

View File

@@ -0,0 +1,100 @@
/**
* Collection Selector Module
* Manages the collection dropdown selector and persistence
*/
class CollectionSelector {
constructor(selectId, webdavClient) {
this.select = document.getElementById(selectId);
this.webdavClient = webdavClient;
this.onChange = null;
this.storageKey = Config.STORAGE_KEYS.SELECTED_COLLECTION;
}
/**
* Load collections from WebDAV and populate the selector
*/
async load() {
try {
const collections = await this.webdavClient.getCollections();
this.select.innerHTML = '';
collections.forEach(collection => {
const option = document.createElement('option');
option.value = collection;
option.textContent = collection;
this.select.appendChild(option);
});
// Try to restore previously selected collection from localStorage
const savedCollection = localStorage.getItem(this.storageKey);
let collectionToSelect = collections[0]; // Default to first
if (savedCollection && collections.includes(savedCollection)) {
collectionToSelect = savedCollection;
}
if (collections.length > 0) {
this.select.value = collectionToSelect;
this.webdavClient.setCollection(collectionToSelect);
if (this.onChange) {
this.onChange(collectionToSelect);
}
}
// Add change listener
this.select.addEventListener('change', () => {
const collection = this.select.value;
// Save to localStorage
localStorage.setItem(this.storageKey, collection);
this.webdavClient.setCollection(collection);
Logger.info(`Collection changed to: ${collection}`);
if (this.onChange) {
this.onChange(collection);
}
});
Logger.debug(`Loaded ${collections.length} collections`);
} catch (error) {
Logger.error('Failed to load collections:', error);
if (window.showNotification) {
window.showNotification('Failed to load collections', 'error');
}
}
}
/**
* Get the currently selected collection
* @returns {string} The collection name
*/
getCurrentCollection() {
return this.select.value;
}
/**
* Set the collection to a specific value
* @param {string} collection - The collection name to set
*/
async setCollection(collection) {
const collections = Array.from(this.select.options).map(opt => opt.value);
if (collections.includes(collection)) {
this.select.value = collection;
localStorage.setItem(this.storageKey, collection);
this.webdavClient.setCollection(collection);
Logger.info(`Collection set to: ${collection}`);
if (this.onChange) {
this.onChange(collection);
}
} else {
Logger.warn(`Collection "${collection}" not found in available collections`);
}
}
}
// Make CollectionSelector globally available
window.CollectionSelector = CollectionSelector;