diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..86374ecc --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +root/* \ No newline at end of file diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 46e02398..c1392723 --- a/README.md +++ b/README.md @@ -1,60 +1,33 @@ `#html` `#css` `#js` `#php` `#master-in-software-development` -# PHP Local FileSystem explorer - -

- Version -

- ->In this project you will have to create a system file explorer that allows the user to navigate, create directories and upload files in the same way as he would in his usual operating system. - ->The file explorer is a tool that allows you to directly view and manipulate the files and directories associated with a path, so you must take into account from which path the user starts and which path they can access. - - -## Index - -- [Requirements](#requirements) -- [Repository](#repository) -- [Technologies used](#technologies-used) -- [Project delivery](#project-delivery) -- [Resources](#resources) - -## Requirements - -- You cannot use file third-party libraries -- You will not be able to use global variables in PHP. -- You must use GIT -- You must use the PHP > v8 -- Create a clear and orderly directory structure -- Both the code and the comments must be written in English -- Use the camelCase code style to define variables and functions -- In the case of using HTML, never use inline styles -- In the case of using different programming languages ​​always define the implementation in separate terms -- Remember that it is important to divide the tasks into several sub-tasks so that in this way you can associate each particular step of the construction with a specific commit -- You should try as much as possible that the commits and the planned tasks are the same -Delete files that are not used or are not necessary to evaluate the project - -## Repository - -First of all you must fork this project into your GitHub account. - -To create a fork on GitHub is as easy as clicking the “fork” button on the repository page. - -Fork on GitHub - -## Technologies used - -\* HTML - -\* CSS - -\* JS - -\* PHP - -## Resources - -- [File system](https://es.wikipedia.org/wiki/Administrador_de_archivos) -- [PHP FileSystem W3C](https://www.w3schools.com/php/php_ref_filesystem.asp) -- [PHP FileSystem Oficial](https://www.php.net/manual/es/book.filesystem.php) -- [README Guidelines Example](https://gist.github.com/PurpleBooth/109311bb0361f32d87a2) +# PHP Local FileSystem-X-Plorer + +## Wireframes +![This is an image](/assets/wireframes/wireframe.png) +![This is an image](/assets/wireframes/wireframe-1.png) +![This is an image](/assets/wireframes/wireframe-2.png) +![This is an image](/assets/wireframes/use-case-diagram.png) +## Final product +![This is an image](/assets/wireframes/landscape.png) +![This is an image](/assets/wireframes/mobile.png) + +## Requriments + +- [PHP] 8. + + +## Installing +Clone repository: +``` +git clone https://github.com/DTPF/filesystem-explorer.git +``` +Create root directory to save files: +``` +mkdir root +``` +Grant permissions if it necessary (Mac and Linux) in root directory: +``` +sudo chmod -R 777 root +``` + +[PHP]: \ No newline at end of file diff --git a/assets/css/index.css b/assets/css/index.css new file mode 100755 index 00000000..5c3459a0 --- /dev/null +++ b/assets/css/index.css @@ -0,0 +1,662 @@ +/*+++++++++++++++++++++++++++ ROOT +++++++++++++++++++++++++++++*/ +:root { + --color-primary: #4285f4; + --color-secondary: rgb(240, 240, 240); + --bg--primary: #4285f4; + --bg--secondary: #f4b400; + --bg--green: #0f9d58; +} + +::-webkit-scrollbar { + width: 5px; +} + +::-webkit-scrollbar-track { + background: rgb(237, 237, 237); +} + +::-webkit-scrollbar-thumb { + background: rgb(222, 222, 222); +} + +* { + margin: 0; + padding: 0; + font-family: "Montserrat", sans-serif; +} + +body { + width: 100%; + height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + overflow-y: hidden; +} + +/*+++++++++++++++++++++++++++ HEADER +++++++++++++++++++++++++++++*/ +header { + height: 10%; + width: 80%; + display: flex; + align-items: center; + justify-content: center; + color: var(--color-secondary); + border-bottom: 1px solid rgb(222, 222, 222); +} + +nav { + width: 100%; + height: 30%; + padding: 15px; + padding-left: 50px; + padding-right: 50px; + display: flex; + align-items: center; + justify-content: space-between; +} + +nav * { + width: 25%; +} + +nav p { + color: grey; + font-size: 1.25em; + pointer-events: none; +} + +span { + font-weight: bolder; +} + +.search-input-group { + display: flex; + align-items: center; + justify-content: space-between; + position: relative; +} + +.search-input-group img { + position: absolute; + right: 10px; + width: 25px; + cursor: pointer; +} + +nav input { + border-radius: 25px; + width: 100%; + outline: none; + border: none; + border: 1px solid grey; + padding: 10px; +} + +/*+++++++++++++++++++++++++++ MAIN +++++++++++++++++++++++++++++*/ +main { + width: 70%; + height: 85%; + position: relative; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, 200px)); + grid-template-rows: repeat(auto-fill, minmax(200px, 200px)); + justify-content: center; + align-content: flex-start; + overflow-y: auto; + overflow-x: hidden; +} + +/* bread crumbs */ + +.bread-crumbs-container { + position: fixed; + padding: 7.5px; + background-color: var(--bg--green); + border-radius: 25px; + left: 10vw; + margin-top: 15px; + color: var(--color-secondary); + font-size: 0.85em; + z-index: 999; +} + +.bread-crumbs-container a:last-child { + text-decoration: underline; +} + +.bread-crumbs-container * { + cursor: pointer; + font-size: 1.15em; + margin: 2px; + margin-left: 5px; + padding-right: 5px; + border-right: 1px solid white; + user-select: none; +} + +.bread-crumbs-container a:first-child { + display: none; +} +.bread-crumbs-container a:last-child { + border: none; +} + +/* bread crumbs */ + +aside { + height: 20vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-around; + position: fixed; + top: 20vh; + left: 2.5vw; + z-index: 999; + color: grey; +} + +aside p { + width: 100%; + padding-top: 10px; + padding-bottom: 10px; +} + +aside p:first-child { + border-top: 1px solid rgb(199, 199, 199); +} + +aside p:nth-child(2n) { + border-bottom: 1px solid rgb(199, 199, 199); + padding-top: 0px; + transition-duration: 0.2s; +} + +aside p:nth-child(2n-1) { + color: rgb(70, 70, 70); +} + +.file-details-container { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: space-between; +} + +.file-details-container-items { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: space-between; +} + +.file-content-container { + height: 65%; + width: 100%; + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: space-between; + margin-bottom: 10px; +} + +.file-content-container div { + width: 100%; + height: 90%; + border: 1px solid grey; +} + +.empty-root-folder-alert { + width: 70%; + height: 40%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-around; + margin: auto; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + border: 3px solid var(--bg--primary); + border-radius: 15px; + padding: 15px; +} + +.create-folder-btn, +.upload-file-btn { + width: 50px; + cursor: pointer; + transition-duration: 0.3s; +} +.create-folder-btn:hover, +.upload-file-btn:hover { + transform: scale(1.05); +} + +.empty-root-folder-alert p { + line-height: 1.5em; + width: 60%; + text-align: center; + font-size: 2em; +} + +.empty-root-btns-container { + width: 30%; + display: flex; + align-items: center; + justify-content: space-between; +} + +.btns-container { + height: 30vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-around; + position: fixed; + top: 15vh; + right: 2.5vw; + z-index: 999; +} + +.btns-container img { + margin: 10px; +} + +.folder-container, +.file-container { + margin-top: 30px; + height: 150px; + width: 150px; + background: linear-gradient( + 180deg, + rgba(255, 255, 255, 1) 55%, + rgba(66, 133, 244, 1) 55% + ); + color: var(--color-secondary); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + /* transition-duration: 0.3s; */ + perspective: 100px; +} + +.folder-container p, +.file-container p { + font-size: 0.9em; + padding-top: 5px; +} + +.folder, +.file { + height: 50%; + width: 50%; + cursor: pointer; +} + +.folder { + background-image: url("../fileIcons/folderIcon.png"); + background-size: contain; + background-repeat: no-repeat; + background-position: center; + transition-duration: 0.3s; +} + +.folder:hover, +.file:hover { + transform: scale(1.05) rotateY(10deg); +} + +.folder-name, +.file-container p { + cursor: pointer; +} + +.menu { + height: 175px; + width: 175px; + border: none; + position: absolute; + z-index: 999; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-between; + flex-wrap: wrap; + border-radius: 15px; + opacity: 0; + transition-duration: 0.3s; +} + +.menu img { + cursor: pointer; + width: 40%; + height: 40%; + background: rgba(255, 255, 255, 0.75); + border: 3px solid rgba(128, 128, 128, 0.7); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + transition-duration: 0.3s; +} + +.menu img:hover { + transform: rotate(5deg); +} + +.confirmation-modal { + max-height: 200px; + max-width: 350px; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + margin: auto; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 25px; + border: 2px solid var(--bg--primary); + background-color: white; + border-radius: 15px; + box-shadow: 14px 15px 26px -9px rgba(0, 0, 0, 0.75); +} + +.confirmation-modal p { + font-size: 1.5em; +} + +.confirmation-btn-container { + height: 60px; + width: 60%; + display: flex; + align-items: center; + justify-content: space-between; +} + +.confirmation-btn-container img { + height: 100%; + cursor: pointer; +} + +.rename-input { + color: rgb(65, 65, 65); + text-align: center; + width: 70%; + border: none; + outline: none; + padding: 2px; + border-radius: 15px; + margin-top: 15px; +} + +.file { + background-size: contain; + background-repeat: no-repeat; + background-position: center; + transition-duration: 0.3s; +} + +.preview-modal { + height: 80vh; + width: 70vw; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + margin: auto; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 25px; + /* border: 2px solid var(--bg--primary); */ + background-color: white; + border-radius: 5px; + box-shadow: 14px 15px 26px -9px rgba(0, 0, 0, 0.75); + opacity: 0; + transition-duration: 0.3s; + z-index: 99999999999; +} + +.preview-container { + height: 80%; + width: 80%; + /* border: 1px solid rgb(218, 218, 218); */ + overflow-y: auto; + display: flex; + align-items: center; + justify-content: center; +} + +.preview-container img { + height: 80%; +} + +.close-preview-modal-btn { + cursor: pointer; + height: 25px; + position: absolute; + padding: 25px; + top: 0; + right: 0; +} + +.jpg { + background-image: url("../fileIcons/jpg.png"); +} + +.doc { + background-image: url("../fileIcons/doc.png"); +} + +.csv { + background-image: url("../fileIcons/csv.png"); +} + +.png { + background-image: url("../fileIcons/png.png"); +} + +.txt { + background-image: url("../fileIcons/txt.png"); +} + +.ppt { + background-image: url("../fileIcons/ppt.png"); +} + +.odt { + background-image: url("../fileIcons/odt.png"); +} + +.pdf { + background-image: url("../fileIcons/pdf.png"); +} + +.zip { + background-image: url("../fileIcons/zip.png"); +} + +.rar { + background-image: url("../fileIcons/rar.png"); +} + +.exe { + background-image: url("../fileIcons/exe.png"); +} + +.svg { + background-image: url("../fileIcons/svg.png"); +} + +.mp3 { + background-image: url("../fileIcons/mp3.png"); +} + +.mp4 { + background-image: url("../fileIcons/mp4.png"); +} + +.hidden { + display: none; +} + +.video { + width: 80%; +} + +.preview-container { + display: flex; + align-items: flex-start; + justify-content: center; +} + +.preview-text-container { + margin-top: 25px; +} + +.selected { + border-bottom: 3px solid rgb(49, 141, 49); +} + +@media (max-width: 768px) { + nav { + padding: 0; + width: 100%; + } + + .size-nav-text { + display: none; + } + + .search-input-group { + width: 30vw; + } + + .search-input-group img { + width: 15px; + } + nav p { + font-size: 1em; + } + + .bread-crumbs-container { + margin-top: 5px; + padding: 5px; + } + + .bread-crumbs-container a { + font-size: 0.75em; + } + main { + display: grid; + grid-template-columns: 1fr 1fr; + height: 65vh; + width: 80%; + justify-content: center; + } + + .file-container, + .folder-container { + width: 140px; + height: 140px; + } + + aside { + height: auto; + width: 90%; + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-around; + position: fixed; + margin: auto; + left: 0; + right: 0; + top: auto; + bottom: 0; + left: 2.5vw; + z-index: 999; + color: grey; + } + + .file-details-container { + width: 100%; + height: 100%; + display: flex; + flex-direction: row; + align-items: flex-start; + justify-content: space-between; + flex-wrap: wrap; + } + + .file-details-container-items { + width: 100%; + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + } + + aside p:first-child { + border-top: 1px solid rgba(199, 199, 199, 0); + } + + aside p:nth-child(2n) { + border-bottom: 1px solid rgba(199, 199, 199, 0); + padding-top: 10px; + transition-duration: 0.2s; + } + + aside p:nth-child(2n-1) { + color: rgb(70, 70, 70); + } + + .file-details-container-items p { + font-size: 0.65em; + } + + .btns-container { + height: 10vh; + width: 60%; + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-around; + position: fixed; + margin: auto; + top: auto; + right: 0; + left: 0; + bottom: 15vh; + right: 2.5vw; + z-index: 999; + } + + .btns-container img { + margin: 10px; + width: 30px; + } + + .preview-modal { + height: 70vh; + width: 90vw; + } + + .empty-root-folder-alert p { + font-size: 1.25em; + } +} diff --git a/assets/fileIcons/ModalCheckIcon.png b/assets/fileIcons/ModalCheckIcon.png new file mode 100644 index 00000000..8f8a19a0 Binary files /dev/null and b/assets/fileIcons/ModalCheckIcon.png differ diff --git a/assets/fileIcons/ModalDismissIcon.png b/assets/fileIcons/ModalDismissIcon.png new file mode 100644 index 00000000..5f307307 Binary files /dev/null and b/assets/fileIcons/ModalDismissIcon.png differ diff --git a/assets/fileIcons/csv.png b/assets/fileIcons/csv.png new file mode 100755 index 00000000..b4b1f026 Binary files /dev/null and b/assets/fileIcons/csv.png differ diff --git a/assets/fileIcons/deleteIcon.png b/assets/fileIcons/deleteIcon.png new file mode 100644 index 00000000..3883a381 Binary files /dev/null and b/assets/fileIcons/deleteIcon.png differ diff --git a/assets/fileIcons/doc.png b/assets/fileIcons/doc.png new file mode 100755 index 00000000..2f30604b Binary files /dev/null and b/assets/fileIcons/doc.png differ diff --git a/assets/fileIcons/exe.png b/assets/fileIcons/exe.png new file mode 100644 index 00000000..16825a9f Binary files /dev/null and b/assets/fileIcons/exe.png differ diff --git a/assets/fileIcons/folderIcon.png b/assets/fileIcons/folderIcon.png new file mode 100755 index 00000000..6f203475 Binary files /dev/null and b/assets/fileIcons/folderIcon.png differ diff --git a/assets/fileIcons/infoIcon.png b/assets/fileIcons/infoIcon.png new file mode 100644 index 00000000..a4624765 Binary files /dev/null and b/assets/fileIcons/infoIcon.png differ diff --git a/assets/fileIcons/jpg.png b/assets/fileIcons/jpg.png new file mode 100755 index 00000000..f8074f6e Binary files /dev/null and b/assets/fileIcons/jpg.png differ diff --git a/assets/fileIcons/mp3.png b/assets/fileIcons/mp3.png new file mode 100755 index 00000000..93e53ea0 Binary files /dev/null and b/assets/fileIcons/mp3.png differ diff --git a/assets/fileIcons/mp4.png b/assets/fileIcons/mp4.png new file mode 100644 index 00000000..1fa1a798 Binary files /dev/null and b/assets/fileIcons/mp4.png differ diff --git a/assets/fileIcons/noFolderIcon.png b/assets/fileIcons/noFolderIcon.png new file mode 100644 index 00000000..d2ba57fe Binary files /dev/null and b/assets/fileIcons/noFolderIcon.png differ diff --git a/assets/fileIcons/odt.png b/assets/fileIcons/odt.png new file mode 100644 index 00000000..ea9b7178 Binary files /dev/null and b/assets/fileIcons/odt.png differ diff --git a/assets/fileIcons/pdf.png b/assets/fileIcons/pdf.png new file mode 100755 index 00000000..5196ca46 Binary files /dev/null and b/assets/fileIcons/pdf.png differ diff --git a/assets/fileIcons/png.png b/assets/fileIcons/png.png new file mode 100755 index 00000000..c6babf18 Binary files /dev/null and b/assets/fileIcons/png.png differ diff --git a/assets/fileIcons/ppt.png b/assets/fileIcons/ppt.png new file mode 100755 index 00000000..05b9031e Binary files /dev/null and b/assets/fileIcons/ppt.png differ diff --git a/assets/fileIcons/rar.png b/assets/fileIcons/rar.png new file mode 100644 index 00000000..fae46ddc Binary files /dev/null and b/assets/fileIcons/rar.png differ diff --git a/assets/fileIcons/renameIcon.png b/assets/fileIcons/renameIcon.png new file mode 100644 index 00000000..8b95766e Binary files /dev/null and b/assets/fileIcons/renameIcon.png differ diff --git a/assets/fileIcons/search.png b/assets/fileIcons/search.png new file mode 100644 index 00000000..fbbed784 Binary files /dev/null and b/assets/fileIcons/search.png differ diff --git a/assets/fileIcons/svg.png b/assets/fileIcons/svg.png new file mode 100755 index 00000000..24ed6e02 Binary files /dev/null and b/assets/fileIcons/svg.png differ diff --git a/assets/fileIcons/trashIcon.png b/assets/fileIcons/trashIcon.png new file mode 100644 index 00000000..0873a61b Binary files /dev/null and b/assets/fileIcons/trashIcon.png differ diff --git a/assets/fileIcons/txt.png b/assets/fileIcons/txt.png new file mode 100755 index 00000000..b95f2f75 Binary files /dev/null and b/assets/fileIcons/txt.png differ diff --git a/assets/fileIcons/uploadIcon.png b/assets/fileIcons/uploadIcon.png new file mode 100644 index 00000000..4a2f18fc Binary files /dev/null and b/assets/fileIcons/uploadIcon.png differ diff --git a/assets/fileIcons/zip.png b/assets/fileIcons/zip.png new file mode 100755 index 00000000..12093018 Binary files /dev/null and b/assets/fileIcons/zip.png differ diff --git a/assets/js/index.js b/assets/js/index.js new file mode 100755 index 00000000..c905ec02 --- /dev/null +++ b/assets/js/index.js @@ -0,0 +1,446 @@ +const createFolderBtn = document.querySelectorAll(".create-folder-btn"); +const filesAndFoldersContainer = document.getElementsByTagName("main")[0]; +const noFilerOrFoldersAlert = document.querySelector( + ".empty-root-folder-alert" +); +const btnsContainer = document.querySelectorAll(".btns-container"); +const menu = document.querySelector(".menu"); +const deleteBtn = document.querySelector("#delete-btn"); +const renameBtn = document.querySelector("#renameBtn"); +const uploadFileBtn = document.querySelectorAll(".upload-file-btn"); +const uploadInput = document.getElementById("upload-input"); +const infoBtn = document.querySelector("#infoBtn"); +const confirmationModal = document.querySelector("#confirmationModal"); +const checkBtn = document.querySelector("#checkBtn"); +const dismissBtn = document.querySelector("#dismissBtn"); +const previewModal = document.querySelector("#previewModal"); +const closePreviewModal = document.querySelector("#closePreviewModal"); +const viewMoreBtn = document.querySelector("#viewMoreBtn"); +const previewContainer = document.querySelector(".preview-container"); + +const infoName = document.querySelector("#infoName"); +const infoType = document.querySelector("#infoType"); +const infoSize = document.querySelector("#infoSize"); +const infoUpdate = document.querySelector("#infoUpdate"); +const infoCreation = document.querySelector("#infoCreation"); + +const searchInputBtn = document.querySelector("#searchInputBtn"); +const searchInput = document.querySelector("#searchInput"); + +let pathToDelete; +let currentFolder; + +for (let btn of createFolderBtn) { + btn.addEventListener("click", (e) => createFolder(e)); +} + +for (let btn of uploadFileBtn) { + btn.addEventListener("click", uploadFile); +} + +document.body.addEventListener("click", closeMenu); +deleteBtn.addEventListener("click", toggleConfirmationVisibility); +dismissBtn.addEventListener("click", toggleConfirmationVisibility); +checkBtn.addEventListener("click", deleteDir); +renameBtn.addEventListener("click", renameDirFromMenu); +uploadInput.addEventListener("change", submitUploadForm); +closePreviewModal.addEventListener("click", togglePreviewModalVisibility); +closePreviewModal.addEventListener("click", stopMusicOrVideo); +searchInputBtn.addEventListener("click", search); + +function createFolder(e) { + currentDirectory = "." + e.target.getAttribute("path"); + filePath = e.target.getAttribute("path"); + fetch( + `./modules/createFolder.php?path=${currentDirectory}&filepath=${filePath}`, + { + method: "GET", + } + ) + .then((response) => response.json()) + .then((data) => { + if (data.ok) { + const folder = document.createElement("div"); + + folder.classList.add("folder-container"); + folder.innerHTML = `
+

${data.dir}

`; + filesAndFoldersContainer.insertAdjacentElement("afterbegin", folder); + noFilerOrFoldersAlert + ? (noFilerOrFoldersAlert.style.display = "none") + : null; + + for (let btnContainer of btnsContainer) { + btnContainer.style.display = "flex"; + } + } + }) + .catch((err) => console.log("Request: ", err)); +} + +function openRenameFolderInput(event) { + let folderName = event.target; + selectItem(folderName); + + let text = event.target.innerText; + let folderContainer = folderName.parentElement; + let input = document.createElement("input"); + + input.classList.add("rename-input"); + input.type = "text"; + input.value = text; + input.classList.add("rename-input"); + input.addEventListener("focusout", rename); + folderContainer.removeChild(folderName); + folderContainer.appendChild(input); + input.focus(); + input.select(); +} + +function navigateToFolder(event) { + let path = event.target.getAttribute("path"); + + fetch(`./modules/savePathToSession.php?path=${path}`, { + method: "GET", + }) + .then((response) => response.json()) + .then((data) => { + if (data.ok) { + currentDirectory = data.path; + filesAndFoldersContainer.innerHTML = ""; + window.location.href = "./index.php"; + } + }) + .catch((err) => console.log("Request: ", err)); +} + +function rename(e) { + let newText = e.target.value; + let folder = e.target.parentElement.children[0]; + let path = folder.getAttribute("path"); + + fetch(`./modules/renameFolder.php?path=${path}&text=${newText}`, { + method: "GET", + }) + .then((response) => response.json()) + .then((data) => { + if (data.ok) { + let folderContainer = folder.parentElement; + let input = folderContainer.children[1]; + + let folderName = document.createElement("p"); + folderName.innerText = input.value; + folderName.addEventListener("click", openRenameFolderInput); + + folderContainer.removeChild(input); + folderContainer.appendChild(folderName); + + folder.setAttribute("path", data.newPath); + } + }) + .catch((err) => console.log("Request: ", err)); +} + +function openMenu(event) { + pathToDelete = event.target.getAttribute("path"); + currentFolder = event.target; + selectItem(event.target); + + menu.classList.remove("hidden"); + menu.style.left = event.pageX - 10 + "px"; + menu.style.top = event.pageY - 10 + "px"; + + setTimeout(() => { + menu.style.opacity = 1; + }, 10); +} + +function closeMenu() { + menu.style.opacity = 0; + + setTimeout(() => { + menu.classList.add("hidden"); + }, 300); +} + +function toggleConfirmationVisibility() { + confirmationModal.classList.toggle("hidden"); +} + +function deleteDir() { + fetch(`./modules/deleteDir.php?path=${pathToDelete}`, { + method: "GET", + }) + .then((response) => response.json()) + .then((data) => { + if (data.ok) { + filesAndFoldersContainer.removeChild(currentFolder.parentElement); + } + }) + .catch((err) => console.log("Request: ", err)); + + confirmationModal.classList.add("hidden"); +} + +function renameDirFromMenu() { + let folderName = currentFolder.parentElement.children[1]; + let text = folderName.innerText; + let folderContainer = currentFolder.parentElement; + let input = document.createElement("input"); + + input.classList.add("rename-input"); + input.type = "text"; + input.value = text; + input.classList.add("rename-input"); + input.addEventListener("focusout", rename); + + folderContainer.removeChild(folderName); + folderContainer.appendChild(input); + + input.focus(); + input.select(); +} + +function uploadFile() { + uploadInput.click(); +} + +function submitUploadForm(e) { + let file = e.target.files[0]; + const form_data = new FormData(); + + form_data.append("file", file); + + fetch(`./modules/uploadFiles.php`, { + method: "POST", + body: form_data, + }) + .then((response) => response.json()) + .then((data) => { + let file = document.createElement("div"); + file.classList.add("file-container"); + + let fileImg = document.createElement("div"); + fileImg.classList.add("file"); + fileImg.classList.add(data.extension.toLowerCase()); + fileImg.setAttribute("path", data.path); + file.addEventListener("contextmenu", (e) => openMenu(e)); + file.addEventListener("click", printInfo); + file.addEventListener("dblclick", togglePreviewModalVisibility); + + let fileName = document.createElement("p"); + fileName.classList.add("folder-name"); + fileName.addEventListener("click", openRenameFolderInput); + fileName.innerText = data.fileName; + + file.appendChild(fileImg); + file.appendChild(fileName); + + filesAndFoldersContainer.appendChild(file); + noFilerOrFoldersAlert.classList.add("hidden"); + for (let btnContainer of btnsContainer) { + btnContainer.style.display = "flex"; + } + }) + .catch((err) => console.log("Request: ", err)); +} + +function printInfo(event) { + let path = event.target.getAttribute("path"); + + selectItem(event.target); + + fetch(`./modules/getInfo.php?path=${path}`, { + method: "GET", + }) + .then((response) => response.json()) + .then((data) => { + infoName.innerText = data.name; + infoType.innerText = data.type; + infoSize.innerText = data.size; + infoUpdate.innerText = data.lastUpdateDate; + infoCreation.innerText = data.creationDate; + + infoName.style.color = "#4285f4"; + infoType.style.color = "#4285f4"; + infoSize.style.color = "#4285f4"; + infoUpdate.style.color = "#4285f4"; + infoCreation.style.color = "#4285f4"; + + setTimeout(() => { + infoName.style.color = "grey"; + infoType.style.color = "grey"; + infoSize.style.color = "grey"; + infoUpdate.style.color = "grey"; + infoCreation.style.color = "grey"; + }, 200); + }) + .catch((err) => console.log("Request: ", err)); +} + +function togglePreviewModalVisibility(event) { + previewContainer.innerHTML = ""; + let currentFile = event.target.getAttribute("path"); + previewModal.classList.toggle("hidden"); + + if (!previewModal.classList.contains("hidden")) { + setTimeout(() => { + previewModal.style.opacity = 1; + }, 10); + } else { + previewModal.style.opacity = 0; + } + + let splittedPath = currentFile?.split("."); + let extension = + splittedPath && splittedPath[splittedPath.length - 1].toLowerCase(); + + switch (extension) { + case "png": + previewContainer.innerHTML = ` + + `; + break; + case "jpg": + previewContainer.innerHTML = ` + + `; + break; + case "svg": + previewContainer.innerHTML = ` + + `; + break; + case "mp3": + previewContainer.innerHTML = ` + + `; + break; + case "mp4": + previewContainer.innerHTML = ` + + `; + break; + case "pdf": + previewContainer.innerHTML = ` + + `; + break; + case "txt": + readFile(currentFile); + break; + default: + previewContainer.innerHTML = ` +

Can not preview this file

+ `; + break; + } +} + +function stopMusicOrVideo() { + const player = document.querySelector("#player"); + + if (player) { + player.pause(); + player.currentTime = 0; + } +} + +function readFile(path) { + fetch(`./modules/readTextFile.php?path=${path}`, { + method: "GET", + }) + .then((response) => response.json()) + .then((data) => { + let previewTextContainer = document.createElement("div"); + previewTextContainer.classList.add("preview-text-container"); + + for (let line of data.text) { + previewTextContainer.innerHTML += `

${line}

`; + } + previewContainer.appendChild(previewTextContainer); + }) + .catch((err) => console.log("Request: ", err)); +} + +function selectItem(item) { + let folders = document.getElementsByClassName("folder"); + let files = document.getElementsByClassName("file"); + + for (let folder of folders) { + folder.parentElement.classList.remove("selected"); + } + for (let file of files) { + file.parentElement.classList.remove("selected"); + } + + item.parentElement.classList.add("selected"); +} + +function search() { + let inputValue = searchInput.value; + + if (inputValue.length === 0) return; + + fetch(`./modules/search.php?search=${inputValue}`, { + method: "GET", + }) + .then((response) => response.json()) + .then((data) => { + let folders = data.folders; + let files = data.files; + + let breadCrumbs = document.querySelector(".bread-crumbs-container"); + filesAndFoldersContainer.innerHTML = ""; + filesAndFoldersContainer.appendChild(breadCrumbs); + + files.forEach((file) => { + let fileContainer = document.createElement("div"); + fileContainer.classList.add("file-container"); + + let splittedFile = file.split("."); + let extension = splittedFile[splittedFile.length - 1].toLowerCase(); + let path = + "." + + splittedFile[splittedFile.length - 2] + + "." + + splittedFile[splittedFile.length - 1]; + let splittedPath = path.split("/"); + let fileName = splittedPath[splittedPath.length - 1]; + let fileNameWithoutExtension = fileName.split("."); + fileNameWithoutExtension = + fileNameWithoutExtension[fileNameWithoutExtension.length - 2]; + + fileContainer.innerHTML = ` +
+

${fileNameWithoutExtension}.${extension}

+ `; + filesAndFoldersContainer.appendChild(fileContainer); + }); + + folders.forEach((folder) => { + let folderContainer = document.createElement("div"); + folderContainer.classList.add("folder-container"); + + let splittedfolder = folder.split("."); + let path = "." + splittedfolder[splittedfolder.length - 1]; + let splittedPath = path.split("/"); + let folderName = splittedPath[splittedPath.length - 1]; + + folderContainer.innerHTML = ` +
+

${folderName}

+ `; + filesAndFoldersContainer.appendChild(folderContainer); + }); + }) + .catch((err) => console.log("Request: ", err)); +} diff --git a/assets/wireframes/landscape.png b/assets/wireframes/landscape.png new file mode 100644 index 00000000..f9448260 Binary files /dev/null and b/assets/wireframes/landscape.png differ diff --git a/assets/wireframes/mobile.png b/assets/wireframes/mobile.png new file mode 100644 index 00000000..087f10f9 Binary files /dev/null and b/assets/wireframes/mobile.png differ diff --git a/assets/wireframes/use-case-diagram.png b/assets/wireframes/use-case-diagram.png new file mode 100644 index 00000000..9e353fd9 Binary files /dev/null and b/assets/wireframes/use-case-diagram.png differ diff --git a/assets/wireframes/wireframe-1.png b/assets/wireframes/wireframe-1.png new file mode 100644 index 00000000..e8bca2a2 Binary files /dev/null and b/assets/wireframes/wireframe-1.png differ diff --git a/assets/wireframes/wireframe-2.png b/assets/wireframes/wireframe-2.png new file mode 100644 index 00000000..9a0833d1 Binary files /dev/null and b/assets/wireframes/wireframe-2.png differ diff --git a/assets/wireframes/wireframe.png b/assets/wireframes/wireframe.png new file mode 100644 index 00000000..dd36bf39 Binary files /dev/null and b/assets/wireframes/wireframe.png differ diff --git a/index.php b/index.php new file mode 100755 index 00000000..c2b1401c --- /dev/null +++ b/index.php @@ -0,0 +1,76 @@ + + + + + + + + + + PHP - File System Explorer + + + + + + + + +
+ +
+ +
+ +
+ + + + + + + + + +
+ +
+ + + \ No newline at end of file diff --git a/modules/breadCrumbs.php b/modules/breadCrumbs.php new file mode 100644 index 00000000..7ace009a --- /dev/null +++ b/modules/breadCrumbs.php @@ -0,0 +1,23 @@ +"; + echo '

./root

'; + echo ""; + } else { + $breadCrumbs = explode("/", $_SESSION['curr_path']); + $initialRoute = ''; + + echo ""; + } +} diff --git a/modules/config.php b/modules/config.php new file mode 100644 index 00000000..d1919bff --- /dev/null +++ b/modules/config.php @@ -0,0 +1,4 @@ + 0) { + mkdir($currentPath . '/newFolder(' . $counts + 1 . ')', 0777, false); + $dir = preg_replace('/\\.[^.\\s]{3,4}$/', '', basename($currentPath . '/newFolder(' . $counts + 1 . ')')); + + echo json_encode([ + "ok" => true, + "dir" => $dir, + "path" => $filePath . '/newFolder(' . $counts + 1 . ')' + ]); + } else { + mkdir("$currentPath/newFolder", 0777, false); + $dir = preg_replace('/\\.[^.\\s]{3,4}$/', '', basename("$currentPath/newFolder")); + + echo json_encode([ + "ok" => true, + "dir" => $dir, + "path" => $filePath . '/newFolder' + ]); + } +} +createFolder(); diff --git a/modules/deleteDir.php b/modules/deleteDir.php new file mode 100644 index 00000000..a4545772 --- /dev/null +++ b/modules/deleteDir.php @@ -0,0 +1,24 @@ + true]); diff --git a/modules/getFilesAndFolders.php b/modules/getFilesAndFolders.php new file mode 100755 index 00000000..856dae9c --- /dev/null +++ b/modules/getFilesAndFolders.php @@ -0,0 +1,57 @@ + +

Oops, it seems you have not created any folder or uploaded any file...

+
+ + +
+ + + "; + } else { + echo " +
+ + +
"; + } + + foreach ($all as $ff) { + if (is_file($ff)) { + $file = preg_replace('/\\.[^.\\s]{3,4}$/', '', basename($ff)); + $extension = strtolower($ff[-3] . $ff[-2] . $ff[-1]); + + echo "
+
+

$file

+
"; + } + + if (is_dir($ff)) { + $dir = preg_replace('/\\.[^.\\s]{3,4}$/', '', basename($ff)); + $path = $directory . "/" . $dir; + + echo " +
+
+

$dir

+
"; + } + } +} diff --git a/modules/getInfo.php b/modules/getInfo.php new file mode 100644 index 00000000..22b9c9f3 --- /dev/null +++ b/modules/getInfo.php @@ -0,0 +1,65 @@ + true, + "name" => $name, + "type" => $type, + "size" => $size, + "lastUpdateDate" => $lastUpdateDate, + "creationDate" => $creationDate + ]); +} + +getInfo($pathToff); + +function getSize($path) +{ + $bytestotal = 0; + $path = realpath($path); + + if ($path !== false && $path != '' && file_exists($path)) { + foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS)) as $object) { + $bytestotal += $object->getSize(); + } + } + + if ($bytestotal < 1000) { + $bytestotal = round($bytestotal, 1) . "Kb"; + return $bytestotal; + } else { + $bytestotal = round($bytestotal / 1000, 1) . "Mb"; + return $bytestotal; + } +} diff --git a/modules/getInitialInfo.php b/modules/getInitialInfo.php new file mode 100644 index 00000000..a02e3289 --- /dev/null +++ b/modules/getInitialInfo.php @@ -0,0 +1,57 @@ + +
+

Name

+

$name

+

Extension

+

$type

+

Size

+

$size

+

Last update

+

$lastUpdateDate

+

Created

+

$creationDate

+
+ "; + } +} + +getInfo($pathToff); + +function getSize($path) +{ + $bytestotal = 0; + $path = realpath($path); + if ($path !== false && $path != '' && file_exists($path)) { + foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS)) as $object) { + $bytestotal += $object->getSize(); + } + } + return $bytestotal; +} diff --git a/modules/readTextFile.php b/modules/readTextFile.php new file mode 100644 index 00000000..3f81fe78 --- /dev/null +++ b/modules/readTextFile.php @@ -0,0 +1,15 @@ + $lines]); diff --git a/modules/renameFolder.php b/modules/renameFolder.php new file mode 100755 index 00000000..ff30fc53 --- /dev/null +++ b/modules/renameFolder.php @@ -0,0 +1,29 @@ + true, + "newPath" => $newPath . "." . $extension, + "path" => $path + ]); + +} else { + rename("." . $path, "." . $newPath); + + echo json_encode([ + "ok" => true, + "newPath" => $newPath, + "path" => $path + ]); +} diff --git a/modules/savePathToSession.php b/modules/savePathToSession.php new file mode 100755 index 00000000..e7294145 --- /dev/null +++ b/modules/savePathToSession.php @@ -0,0 +1,16 @@ + true, + "path" => $path +]); diff --git a/modules/search.php b/modules/search.php new file mode 100644 index 00000000..1932c38b --- /dev/null +++ b/modules/search.php @@ -0,0 +1,36 @@ + true, + 'folders' => $foldersArray, + 'files' => $filesArray +]); diff --git a/modules/uploadFiles.php b/modules/uploadFiles.php new file mode 100644 index 00000000..f9628c15 --- /dev/null +++ b/modules/uploadFiles.php @@ -0,0 +1,23 @@ + $extension, + "fileName" => $_FILES['file']['name'], + "path" => $attributePath . '/' . $newFileName + ]); +}