about summary refs log tree commit diff stats
path: root/html/file-system/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'html/file-system/index.html')
-rw-r--r--html/file-system/index.html297
1 files changed, 297 insertions, 0 deletions
diff --git a/html/file-system/index.html b/html/file-system/index.html
new file mode 100644
index 0000000..89e05b8
--- /dev/null
+++ b/html/file-system/index.html
@@ -0,0 +1,297 @@
+<!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>
\ No newline at end of file