about summary refs log blame commit diff stats
path: root/html/file-system/index.html
blob: 89e05b8ee6ab1ab8673eeb7eda83bfd2de946e3d (plain) (tree)
1
2
3
4
5
6




                                                                          
                                                

































                                           
                 



                                  



























                                       
                     














                                                                 
                                              



                                                  
                                           



                             

                                                                                               


        


                                                       
 
                                                                                              
 





                                                             
 
                                                       
 













                                                                  
 





                                                      

     







                                                                

                   


                                                                                            
 





                                                               
 


                                                                   
 



                                     
 





                                                     
     
  
 







                                                                            
     
  
 

                                                                                   
 

                                                              
 





                                                                                                                  


         






                                                                                      
     
  
 





                                                                                                     
     
  
 

                                                                                           
 

                                                                                                                       
 






                                                                                      
     
  
 





                                                                                                   
     
  
 






















                                                                                         
     















                                                                                                            
 
         



         
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Folders in Folders in Folders</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            background-color: beige;
            display: flex;
            flex-direction: column;
            align-items: center;
        }
        #navigation {
            display: flex;
            flex-wrap: wrap;
            justify-content: center;
            margin: 0.625em 0;
        }
        #navigation button {
            margin: 0.3125em;
            padding: 0.625em 0.9375em;
            font-size: 1em;
            flex-grow: 1;
            min-width: 7.5em;
        }
        #currentPath {
            font-weight: bold;
            margin: 0.625em 0;
        }
        ul {
            list-style-type: none;
            width: 100%;
            max-width: 37.5em;
        }
        li {
            margin: 0.3125em 0;
            cursor: pointer;
        }
        .folder {
            display: inline-block;
            padding: 0.3125em 0;
            cursor: pointer;
            font-size: 1.125em;
            color: black;
        }
        #editor {
            margin-top: 1.25em;
            width: 100%;
            max-width: 37.5em;
        }
        #editor textarea {
            width: 100%;
            height: 9.375em;
            font-size: 1em;
            padding: 0.625em;
            box-sizing: border-box;
            resize: none;
        }
        h1 {
            text-align: center;
            font-size: 1.5em;
            margin-top: 0.625em;
        }
        @media (max-width: 37.5em) {
            h1 {
                font-size: 1.25em;
            }
            #navigation button {
                font-size: 0.875em;
                padding: 0.5em 0.625em;
            }
            .folder {
                font-size: 1em;
            }
            #editor textarea {
                height: 7.5em;
                font-size: 0.875em;
            }
        }
    </style>
</head>
<body>

<div id="navigation">
    <button onclick="goToRoot()">Go to Root</button>
    <button onclick="goUp()">Go Up One Level</button>
    <button onclick="createFolderPrompt()">Create Folder</button>
    <button onclick="copyItem()">Copy</button>
    <button onclick="pasteItem()">Paste</button>
    <button onclick="deleteItem()">Delete</button>
</div>

<h1 id="currentPath">Current Folder: /</h1>

<ul id="fileSystemTree"></ul>

<div id="editor">
    <h2>Folder Content Editor</h2>
    <textarea id="folderContent" placeholder="Select a folder to edit its contents"></textarea>
</div>

<script>
const initialState = () => ({
    root: { type: 'folder', children: {}, content: '' }
});

const loadFileSystem = () => JSON.parse(localStorage.getItem('fileSystem')) || initialState();

const state = {
    fileSystem: loadFileSystem(),
    currentFolderPath: 'root',
    copiedFolderData: null, // Pastebin for the copied folder
    copiedItemPath: null
};

const clone = (obj) => JSON.parse(JSON.stringify(obj));

const updateFileSystem = (newFileSystem) => {
    state.fileSystem = newFileSystem;
    saveFileSystem(newFileSystem);
};

const getFolder = (path, fileSystem = state.fileSystem) => {
    const parts = path.split('/').filter(part => part !== 'root');
    return parts.reduce((current, part) => {
        if (!current || !current.children[part]) {
            return null;
        }
        return current.children[part];
    }, fileSystem.root);
};

const updateFolder = (fileSystem, path, updateFn) => {
    const rootCopy = clone(fileSystem);
    const folderToUpdate = getFolder(path, rootCopy);
    if (!folderToUpdate) {
        alert(`Folder not found for path: ${path}`);
        return null;
    }

    updateFn(folderToUpdate);
    return rootCopy;
};

const addFolder = (path, name, folderData, fileSystem) => {
    return updateFolder(fileSystem, path, (folder) => {
        if (folder.children[name]) {
            alert(`Folder with name "${name}" already exists.`);
            return;
        }
        folder.children[name] = folderData || { type: 'folder', children: {}, content: '' };
    });
};

const deleteFolder = (path, fileSystem) => {
    const [parentPath, folderName] = path.split(/\/([^\/]+)$/);
    return updateFolder(fileSystem, parentPath, (folder) => {
        delete folder.children[folderName];
    });
};

const saveFileSystem = (fileSystem) => {
    localStorage.setItem('fileSystem', JSON.stringify(fileSystem));
};

const goToRoot = () => {
    state.currentFolderPath = 'root';
    render();
};

const goUp = () => {
    const parts = state.currentFolderPath.split('/');
    if (parts.length > 1) {
        parts.pop();
        state.currentFolderPath = parts.join('/');
        render();
    }
};

const createFolder = (path, name) => {
    const updatedFileSystem = addFolder(path, name, null, state.fileSystem);
    if (updatedFileSystem) {
        updateFileSystem(updatedFileSystem);
        render();
    } else {
        console.error('Error creating folder', path, name);
        alert('Error creating folder');
    }
};

const deleteItem = () => {
    if (state.currentFolderPath === 'root') return alert("Can't delete the root!");

    const folderToDelete = getFolder(state.currentFolderPath);
    if (!folderToDelete) return alert("Folder not found!");

    const hasNestedFolders = Object.keys(folderToDelete.children).length > 0;

    if (hasNestedFolders) {
        const confirmDelete = confirm(`The folder contains nested folders. Do you really wanna delete them too?`);
        if (!confirmDelete) {
            return;
        }
    }

    const updatedFileSystem = deleteFolder(state.currentFolderPath, state.fileSystem);
    if (updatedFileSystem) {
        const parts = state.currentFolderPath.split('/');
        parts.pop();
        state.currentFolderPath = parts.join('/') || 'root';
        updateFileSystem(updatedFileSystem);
        render();
    }
};

const copyItem = () => {
    const folder = getFolder(state.currentFolderPath);
    if (folder) {
        state.copiedFolderData = clone(folder); // Store a deep copy of the folder
        state.copiedItemPath = state.currentFolderPath; // Store the path so that we can remove later
        // console.log('Folder copied:', state.copiedFolderData);
    }
};

const pasteItem = () => {
    if (!state.copiedItemPath || !state.copiedFolderData) return alert('No item to paste');

    const [oldPath, folderName] = state.copiedItemPath.split(/\/([^\/]+)$/);
    const updatedFileSystem = addFolder(state.currentFolderPath, folderName, state.copiedFolderData, state.fileSystem);

    if (updatedFileSystem) {
        updateFileSystem(deleteFolder(oldPath, updatedFileSystem)); // Remove original
        state.copiedFolderData = null; // Clear the copied data
        state.copiedItemPath = null;
        render();
    } else {
        alert('Error pasting item');
    }
};

const saveFolderContent = () => {
    const updatedFileSystem = updateFolder(state.fileSystem, state.currentFolderPath, (folder) => {
        folder.content = document.getElementById('folderContent').value;
    });
    if (updatedFileSystem) {
        updateFileSystem(updatedFileSystem);
    }
};

document.getElementById('folderContent').addEventListener('input', () => {
    saveFolderContent();
});

const renderFolderTree = (folder, path = 'root') => {
    const entries = Object.entries(folder.children);
    return entries.length ? entries.map(([name, item]) => `
        <li>
            <span class="folder" onclick="selectFolder('${path}/${name}')">${name}</span>
            <ul>${renderFolderTree(item, `${path}/${name}`)}</ul>
        </li>
    `).join('') : '';
};

const selectFolder = (path) => {
    const folder = getFolder(path);
    if (folder) {
        state.currentFolderPath = path;
        document.getElementById('folderContent').value = folder.content || '';
        render();
    } else {
        console.error('Folder not found', path);
        alert('Folder not found');
    }
};

const render = () => {
    if (!state.fileSystem.root) {
        console.error('File system is not initialized correctly', state.fileSystem);
        alert('File system is not initialized correctly');
        return;
    }
    document.getElementById('currentPath').textContent = state.currentFolderPath.replace('root', '') || '/';
    document.getElementById('fileSystemTree').innerHTML = renderFolderTree(state.fileSystem.root);
};

const createFolderPrompt = () => {
    const name = prompt('Enter folder name:');
    if (name) createFolder(state.currentFolderPath, name);
};

render();
</script>

</body>
</html>