diff --git a/resources/sys/finder/finder.js b/resources/sys/finder/finder.js index 21a4b86..82906f3 100644 --- a/resources/sys/finder/finder.js +++ b/resources/sys/finder/finder.js @@ -1,4 +1,5 @@ class Finder{ + static appId = "Finder" appId = "Finder" fileView = undefined path = "/" @@ -10,27 +11,29 @@ class Finder{ // this.appElem = appElem // WebDesktopEnvironment.RegisterApp(this) } - /** * @param {string[]} args */ async NewWindow(args){ + let newFinder = new FinderWindow() + await newFinder.Init(args) + return this.path = args[0] if (args[1] == "desktop"){ this.NewDesktop(args) return } - const params = new URLSearchParams({isMobile: WebDesktopEnvironment.isMobile}) - fetch(`/app/${this.appId}/render?` + params) + // const params = new URLSearchParams({isMobile: WebDesktopEnvironment.isMobile}) + fetch(`/app/${Finder.appId}/render?` + params) .then((response) => response.text()) .then((html) => { - let newWindow = WebDesktopEnvironment.CreateNewWindow(this.appId, 500, 350 ) + let newWindow = WebDesktopEnvironment.CreateNewWindow(Finder.appId, 500, 350 ) newWindow.innerHTML = html this.fileView = new FileView(newWindow.querySelector(".FileTileView"), (event) =>{ this.Click(event) }, (event) =>{ this.RightClick(event) }, - (event) =>{ this.FileUploading(event) }, + (event, draggedElem) =>{ this.DropEvent(event, draggedElem) }, ) this.OpenDir(this.path) @@ -61,36 +64,46 @@ class Finder{ } /** - * @param {DataTransferItemList} filesList + * @param {DragEvent} event + * @param {HTMLElement} draggedElem */ - - FileUploading(filesList){ - let formData = new FormData() - console.log(this.path) - for (let i = 0; i < filesList.length; i++) { - const element = filesList[i]; - formData.append("file", element.getAsFile()) + async DropEvent(event){ + // console.log(event.dataTransfer.getData("dropType")) + if (event.dataTransfer.getData("dropType") == "move"){ + let params = new URLSearchParams({ + sourcePath: event.dataTransfer.getData("filePath"), + targetPath: this.path + "/" + event.dataTransfer.getData("fileName"), + }) + let response = await fetch('/fs/move/?' + params) + console.log(response.status) + } else { + let formData = new FormData() + console.log(this.path) + for (let i = 0; i < event.length; i++) { + const element = event[i]; + formData.append("file", element.getAsFile()) + // console.log(formData) + } // console.log(formData) + // formData.append("photo", photo); + fetch('/fs/upload/?' + new URLSearchParams({ + parentPath: this.path, + }), + { + method: "POST", + body: formData + }) + .catch((error) => { + WebDesktopEnvironment.Alert(error); + }) } - // console.log(formData) - // formData.append("photo", photo); - fetch('/fs/upload/?' + new URLSearchParams({ - parentPath: this.path, - }), - { - method: "POST", - body: formData - }) - .catch((error) => { - WebDesktopEnvironment.Alert(error); - }) } /** * @param {string[]} args */ NewDesktop(args){ - fetch(`${window.location.origin}/application/${this.appId}/renderDesktop?` + new URLSearchParams({ + fetch(`${window.location.origin}/application/${Finder.appId}/renderDesktop?` + new URLSearchParams({ isMobile: WebDesktopEnvironment.isMobile, path: args[0] })) @@ -133,14 +146,123 @@ class Finder{ // OpenNewDir(){ // WebDesktopEnvironment.Open("finder", [this.path]) // } + /** + * @param {string} path + * @returns {boolean} + */ + static async RenderProperites(path){ + const params = new URLSearchParams({ + path: path + }) + const response = await fetch(`/application/${Finder.appId}/renderProps?` + params) + if (response.status != 200){ + WebDesktopEnvironment.Alert("Error in properties render") //TODO + return false + } + const html = response.text() + let newWindow = WebDesktopEnvironment.CreateNewWindow(Finder.appId, 350, 500 ) + newWindow.innerHTML = html + newWindow.querySelector("#closeWindowButton").addEventListener('click', function (params) { + WebDesktopEnvironment.CloseWindow(newWindow) + }) + } + + /** + * @param {string} path + * @returns {boolean} + */ + static async DeleteFile(path){ + const params = new URLSearchParams({ + path: path + }) + const response = await fetch(`/fs/delete?` + params) + if (response.status != 200){ + WebDesktopEnvironment.Alert("DELETE ERROR") //TODO + return false + } + return true + } /** - * @param {MouseEvent} event + * @param {string} path + * @returns {boolean} */ - RightClick(event){ - this.CreateContextMenu(event.target, [event.clientY, event.clientX]) + static async CreateDirectory(path){ + if (path == undefined){ + WebDesktopEnvironment.Alert("Path is undefined") + return false + } + const params = new URLSearchParams({ + path: `${path}/New Directory` + }) + const response = await fetch(`/fs/createDir?` + params) + if (response.status != 200){ + WebDesktopEnvironment.Alert("DIRCTORY CREATION ERROR") //TODO + return false + } + return true } + + + +} + + +class FinderWindow{ + CurPath = "" + fileView = undefined + windowElem = undefined + + async Init(args){ + const params = new URLSearchParams({isMobile: WebDesktopEnvironment.isMobile}) + const response = await fetch(`/app/${Finder.appId}/render?` + params) + if (response.status != 200){ + WebDesktopEnvironment.Alert("Finder ERROR TODO") //TODO + return + } + const html = await response.text() + + let newWindow = WebDesktopEnvironment.CreateNewWindow(Finder.appId, 500, 350 ) + newWindow.innerHTML = html + + this.fileView = new FileView(newWindow.querySelector(".FileTileView"), + (event) =>{ this.Click(event) }, + (event) =>{ this.RightClick(event) }, + (event, draggedElem) =>{ this.DropEvent(event, draggedElem) + }) + + newWindow.querySelector("#closeWindowButton").addEventListener('click', function (params) { + + WebDesktopEnvironment.CloseWindow(newWindow) + + }) + + newWindow.querySelector("#RootButton").addEventListener('click', () =>{ + this.RenderDir('/') + }) + + newWindow.querySelector("#HomeButton").addEventListener('click', () =>{ + this.RenderDir('/home/user') + }) + + let scrollBar = new WdeScrollBar(newWindow.querySelector(".ScrollbarPlace"), newWindow.querySelector(".FileTileView")) + + + this.windowElem = newWindow + this.RenderDir(args[0]) + } + + RenderDir(path){ + this.CurPath = path + this.fileView.OpenFolder(path) + } + + ReRenderDir(){ + this.RenderDir(this.CurPath) + } + + /** * @param {MouseEvent} event */ @@ -151,16 +273,16 @@ class Finder{ switch (fileType) { case "directory": if (fileExtension == "app"){ - WebDesktopEnvironment.Open(`${this.path}/${fileName}`, []) + WebDesktopEnvironment.Open(`${this.CurPath}/${fileName}`, []) } else{ - WebDesktopEnvironment.Open(`/Applications/Finder.app`, [`${this.path}/${fileName}`]) + WebDesktopEnvironment.Open(`/Applications/Finder.app`, [`${this.CurPath}/${fileName}`]) } break case "blog": - WebDesktopEnvironment.Open("blog-viewer", [`${this.path}/${fileName}`]) + WebDesktopEnvironment.Open("blog-viewer", [`${this.CurPath}/${fileName}`]) break case "personal-properties": - WebDesktopEnvironment.Open("personal-properties", [`${this.path}/${fileName}`]) + WebDesktopEnvironment.Open("personal-properties", [`${this.CurPath}/${fileName}`]) break // case "app": // //TODO get real id @@ -168,7 +290,7 @@ class Finder{ // break; case "jpeg": case "png": - WebDesktopEnvironment.Open("img-viewer", [this.path + "/" + fileName]) + WebDesktopEnvironment.Open("img-viewer", [this.CurPath + "/" + fileName]) break; default: // console.log("Unsupported file type") @@ -177,7 +299,18 @@ class Finder{ } } - CreateContextMenu(target, pos){ + /** + * @param {MouseEvent} event + */ + RightClick(event){ + this.CreateContextMenu(event.target, [event.clientY, event.clientX]) + } + + /** + * @param {HTMLElement} target + * @param {string[]} pos + */ + async CreateContextMenu(target, pos){ let context = "" const fileName = target.getAttribute("name") const fileType = target.getAttribute("fileType") @@ -187,101 +320,85 @@ class Finder{ } else { context = fileType } - const params = new URLSearchParams({context: context, path: `${this.path}/${fileName}`}) - fetch(`/app/${this.appId}/contextMenu?` + params) - .then((response) => response.text()) - .then((html) => { - let overlay = document.createElement("div") //TODO Move to WDE.CreateOverlay() - overlay.setAttribute('id', 'finder-context-menu-overlay') - overlay.style.position = 'absolute' - overlay.style.width = "100%" - overlay.style.height = "100%" + const params = new URLSearchParams({context: context, path: `${this.CurPath}/${fileName}`}) + const response = await fetch(`/app/${Finder.appId}/contextMenu?` + params) + if (response.status != 200){ + WebDesktopEnvironment.Alert("ERROR in Context menu TODO"); //TODO + return + } + const html = await response.text() + let overlay = document.createElement("div") //TODO Move to WDE.CreateOverlay() + overlay.setAttribute('id', 'finder-context-menu-overlay') + overlay.style.position = 'absolute' + overlay.style.width = "100%" + overlay.style.height = "100%" - let menu = document.createElement("div") - menu.setAttribute('class', 'ContextMenu WindowFrameShadow') - menu.style.position = 'absolute'; - menu.style.top = pos[0] + "px"; - menu.style.left = pos[1] + "px"; - - menu.innerHTML = html - menu.children[0].lastElementChild.remove() //FIXME Can't ommit rendering of horLine in end of menu on backend - - overlay.appendChild(menu) - document.body.appendChild(overlay) + let menu = document.createElement("div") + menu.setAttribute('class', 'ContextMenu WindowFrameShadow') + menu.style.position = 'absolute'; + menu.style.top = pos[0] + "px"; + menu.style.left = pos[1] + "px"; + + menu.innerHTML = html + menu.children[0].firstElementChild.remove() + menu.children[0].lastElementChild.remove() //FIXME Can't ommit rendering of horLine in end of menu on backend + + overlay.appendChild(menu) + document.body.appendChild(overlay) - overlay.addEventListener('click', (event) => { - if (event.target.classList.contains("Row")){ //TODO add uuid id to rows to more accurate checks?? - switch (event.target.children[0].getAttribute("action")) { - case "createDir": - fetch(`/fs/createDir?` + new URLSearchParams({ - path: `${this.path}/New Directory` - })) - .then((response) => { - console.log(response.status) - if (response.status == 200){ - this.OpenDir(this.path) - } - }) - .catch((error) => { - WebDesktopEnvironment.Alert(error); - }) + overlay.addEventListener('click', async (event) => { + if (event.target.classList.contains("Row")){ //TODO add uuid id to rows to more accurate checks?? + let res = false + switch (event.target.children[0].getAttribute("action")) { + case "createDir": + res = await Finder.CreateDirectory(`${this.CurPath}`) + console.log(res) + if (res){ + this.ReRenderDir() + } + break + case "deleteFile": + res = await Finder.DeleteFile(`${this.CurPath}/${fileName}`) + console.log(res) + if (res){ + this.ReRenderDir() + } + break + case "getInfo": + res = await Finder.RenderProperites(`${this.CurPath}/${fileName}`) + // fetch(`/application/${Finder.appId}/renderProps?` + new URLSearchParams({ + // path: `${this.CurPath}/${fileName}` + // })) + // .then((response) => { + // console.log(response) + // if (response.status == 200){ + // console.log("Success") + // return response.text(); + // } + // }) + // .then((html) =>{ + // let newWindow = WebDesktopEnvironment.CreateNewWindow(Finder.appId, 350, 500 ) + // newWindow.innerHTML = html + // newWindow.querySelector("#closeWindowButton").addEventListener('click', function (params) { + // WebDesktopEnvironment.CloseWindow(newWindow) + // }) + // }) + // .catch((error) => { + // WebDesktopEnvironment.Alert(error); + // }) + break + case "openAsDir": + WebDesktopEnvironment.Open(`/Applications/${Finder.appId}.app`,[`${this.CurPath}/${fileName}`]) break - case "deleteFile": - console.log(fileName) - // break - fetch(`/fs/delete?` + new URLSearchParams({ - path: `${this.path}/${fileName}` - })) - .then((response) => { - console.log(response.status) - if (response.status == 200){ - this.OpenDir(this.path) - - } - }) - - .catch((error) => { - WebDesktopEnvironment.Alert(error); - }) - break - case "getInfo": - fetch(`/application/${this.appId}/renderProps?` + new URLSearchParams({ - path: `${this.path}/${fileName}` - })) - .then((response) => { - console.log(response) - if (response.status == 200){ - console.log("Success") - return response.text(); - } - }) - .then((html) =>{ - let newWindow = WebDesktopEnvironment.CreateNewWindow(this.appId, 350, 500 ) - newWindow.innerHTML = html - newWindow.querySelector("#closeWindowButton").addEventListener('click', function (params) { - WebDesktopEnvironment.CloseWindow(newWindow) - }) - }) - .catch((error) => { - WebDesktopEnvironment.Alert(error); - }) - break - case "openAsDir": - WebDesktopEnvironment.Open(`/Applications/${this.appId}.app`,[`${this.path}/${fileName}`]) - break - default: - break; - } - } - overlay.remove() - }) - overlay.addEventListener('contextmenu', (event) => { - event.preventDefault(); - overlay.remove() - }) + default: + break; + } + } + overlay.remove() + }) + overlay.addEventListener('contextmenu', (event) => { + event.preventDefault(); + overlay.remove() }) - .catch((error) => { - WebDesktopEnvironment.Alert(error); - }) } -} +} \ No newline at end of file diff --git a/resources/sys/wde/file-view.css b/resources/sys/wde/file-view.css index a077da7..1956f68 100644 --- a/resources/sys/wde/file-view.css +++ b/resources/sys/wde/file-view.css @@ -7,6 +7,11 @@ /* FIXME Bug, on desktop mode top ~10 pixel are not active, like margin:10px */ } +.FileTileView.DragDropBorder{ + box-shadow: inset 0px 0px 0px 4px #9999CC; + /* background-color: blue; */ +} + .FileTileView .FlexContainer{ width: 100%; height: auto; diff --git a/resources/sys/wde/file-view.js b/resources/sys/wde/file-view.js index 4e43347..57bc881 100644 --- a/resources/sys/wde/file-view.js +++ b/resources/sys/wde/file-view.js @@ -1,4 +1,5 @@ class FileView{ + path = "" parentElem = undefined selected = [] /** @@ -35,19 +36,58 @@ class FileView{ }) if (fileUploadCallback !== undefined) { + let counter = 0 + let draggedElem = undefined + + fileViewElem.addEventListener('dragstart', (event) => { + // console.log(event.target) + // console.log(this.path) + // draggedElem = event.target + event.dataTransfer.setData("fileName", event.target.getAttribute("name")) + event.dataTransfer.setData("filePath", this.path + "/" + event.target.getAttribute("name")) + event.dataTransfer.setData("dropType", "move") + // event.dataTransfer.setData("fileName", ) + // console.log(draggedElem) + }) + fileViewElem.addEventListener('dragenter', function(event) { - // console.log("start") + event.preventDefault(); + counter++ + fileViewElem.classList.add("DragDropBorder") + // draggedElem = event.relatedTarget + + }) + + fileViewElem.addEventListener('dragend', function(event) { + // console.log(fileViewElem) + event.preventDefault(); + counter-- + if (counter === 0){ + fileViewElem.classList.remove("DragDropBorder") + } + // draggedElem = undefined + }) + + fileViewElem.addEventListener('dragleave', function(event) { + // console.log(fileViewElem) + event.preventDefault(); + counter-- + if (counter === 0){ + fileViewElem.classList.remove("DragDropBorder") + } + // draggedElem = undefined }) fileViewElem.addEventListener('dragover', function(event) { event.preventDefault(); - // console.log("over") }) fileViewElem.addEventListener("drop", (event) => { event.preventDefault(); - // console.log(event.dataTransfer.items[0]) - fileUploadCallback(event.dataTransfer.items) + // console.log(event.dataTransfer.getData("dropType")) + fileUploadCallback(event) + fileViewElem.classList.remove("DragDropBorder") + // draggedElem = undefined }) } } @@ -73,6 +113,7 @@ class FileView{ * @param {string} path */ OpenFolder(path){ + this.path = path fetch(`${window.location.origin}/system/wde/widgets/file-tile-view?path=${path}`) //TODO Move to wde func. Or Not? .then((response) => response.text()) .then((html) => { diff --git a/templates/wde-widgets/file-tile-view.tmpl b/templates/wde-widgets/file-tile-view.tmpl index 2f77f7b..c3d8dc8 100644 --- a/templates/wde-widgets/file-tile-view.tmpl +++ b/templates/wde-widgets/file-tile-view.tmpl @@ -1,7 +1,7 @@ {{ define "wde-widgets/file-tile-view.tmpl" }}
{{ range $fileTile := .Files }} -
+
{{ $fileTile.Name }}
diff --git a/webfilesystem/directory.go b/webfilesystem/directory.go index c4bb8ed..b6ad005 100644 --- a/webfilesystem/directory.go +++ b/webfilesystem/directory.go @@ -51,6 +51,7 @@ func (fs *WebFileSystem) CreateDirectory(dirPath string) (primitive.ObjectID, pr } func (fs *WebFileSystem) AppendChildToDirectory(childId primitive.ObjectID, parentId primitive.ObjectID) error { + // println(parentId) parentDirData := DirectoryData{} parentDir, err := fs.readFSDocs(parentId, &parentDirData) if err != nil { @@ -67,6 +68,28 @@ func (fs *WebFileSystem) AppendChildToDirectory(childId primitive.ObjectID, pare return nil } +func (fs *WebFileSystem) RemoveChildToDirectory(childId primitive.ObjectID, parentId primitive.ObjectID) error { + parentDirData := DirectoryData{} + parentDir, err := fs.readFSDocs(parentId, &parentDirData) + if err != nil { + return err + } + + newChildrenList := []primitive.ObjectID{} + for _, child := range parentDirData.Children { + if child != childId { + newChildrenList = append(newChildrenList, child) + } + } + parentDirData.Children = newChildrenList + + err = fs.UpdateFileData(parentDir, parentDirData) + if err != nil { + return err + } + return nil +} + func (fs *WebFileSystem) ListDir(dirPath string) ([]*FileHeader, error) { dirId, err := fs.FindFile(dirPath) if err != nil { diff --git a/webfilesystem/mongo.go b/webfilesystem/mongo.go index 0e24804..f217ab4 100644 --- a/webfilesystem/mongo.go +++ b/webfilesystem/mongo.go @@ -44,6 +44,7 @@ func (fs *WebFileSystem) removeFromMongo(fileId primitive.ObjectID) error { return errors.New("todo not implemented yet") } +//Deprecated func (fs *WebFileSystem) Validate() error { // filter := primitive.D{ // { diff --git a/webfilesystem/public.go b/webfilesystem/public.go index fd23376..72bc132 100644 --- a/webfilesystem/public.go +++ b/webfilesystem/public.go @@ -1,5 +1,7 @@ package webfilesystem +import "go.mongodb.org/mongo-driver/bson/primitive" + func (fs *WebFileSystem) Read(filePath string, fileData interface{}) (*FileHeader, error) { fileId, err := fs.FindFile(filePath) if err != nil { @@ -13,3 +15,12 @@ func (fs *WebFileSystem) Read(filePath string, fileData interface{}) (*FileHeade return fileHeader, nil } + +func (fs *WebFileSystem) ReadByObjectID(fileID primitive.ObjectID, fileData interface{}) (*FileHeader, error) { + fileHeader, err := fs.readFSDocs(fileID, fileData) + if err != nil { + return nil, err + } + + return fileHeader, nil +} diff --git a/webfilesystem/routes.go b/webfilesystem/routes.go index b51db9f..7f1fbbb 100644 --- a/webfilesystem/routes.go +++ b/webfilesystem/routes.go @@ -123,7 +123,27 @@ func (fs *WebFileSystem) Route(route *gin.RouterGroup) { }) route.GET("validate", func(ctx *gin.Context) { - err := fs.Validate() + err := fs.validate() + if err != nil { + ctx.Status(http.StatusInternalServerError) + return + } + + ctx.Status(http.StatusOK) + }) + + route.GET("move", func(ctx *gin.Context) { + sourcePath := ctx.Query("sourcePath") + if sourcePath == "" { + ctx.Status(http.StatusBadRequest) //TODO + return + } + targetPath := ctx.Query("targetPath") + if targetPath == "" { + ctx.Status(http.StatusBadRequest) //TODO + return + } + err := fs.Move(sourcePath, targetPath) if err != nil { ctx.Status(http.StatusInternalServerError) return diff --git a/webfilesystem/validate.go b/webfilesystem/validate.go new file mode 100644 index 0000000..67d015a --- /dev/null +++ b/webfilesystem/validate.go @@ -0,0 +1,58 @@ +package webfilesystem + +func (fs *WebFileSystem) validate() error { + // rootHeader, rootData, err := fs.GetRootDir() + // if err != nil { + // return err + // } + + // for _, child := range rootData.Children { + // fs.Chi + // } + // println() + // fs.Read + // filter := primitive.M{ + // "type": "directory", + // } + // cur, err := fs.webfsFilesTable.Find(fs.ctx, filter) + // if err != nil { + // return err + // } + + // directories := []FileHeader{} + // for cur.Next(fs.ctx) { + // fileHeader := FileHeader{} + // err := cur.Decode(&fileHeader) + // if err != nil { + // println(err.Error()) + // continue + // } + // directories = append(directories, fileHeader) + // } + + // allChilds := map[primitive.ObjectID{}] + // for _, dir := range directories { + // println(dir.Name) + // dirData := DirectoryData{} + // _, err := fs.ReadByObjectID(dir.MongoId, &dirData) + // if err != nil { + // println(err.Error()) + // continue + // } + + // //Check for broken links in children + // for _, dirChild := range dirData.Children { + // dirChildHeader, err := fs.ReadByObjectID(dirChild, nil) + // println(" -" + dirChildHeader.Name) + // if err != nil { + // println(err.Error()) + // continue + // } + // } + // } + return nil +} + +// func (fs *WebFileSystem) GetChildrenHeaders(directoryID primitive.ObjectID) ([]FileHeader, error) { +// fs.ReadByObjectID(directoryID, nil) +// } diff --git a/webfilesystem/webfilesystem.go b/webfilesystem/webfilesystem.go index 3c702c6..0904f6c 100644 --- a/webfilesystem/webfilesystem.go +++ b/webfilesystem/webfilesystem.go @@ -143,6 +143,49 @@ func (fs *WebFileSystem) GetRootDir() (*FileHeader, *DirectoryData, error) { return &rootDir, &rootDirData, nil } +func (fs *WebFileSystem) Move(sourcePath string, targetPath string) error { + //TODO Check about move dir to itself + //TODO if it a dir fix its parentId + //TODO Rename file if in path set new name for it + sourceFileHeader, err := fs.Read(sourcePath, nil) + if err != nil { + return err + } + sourceParentDirPath := fs.GetParentPath(sourcePath) + sourceParentDirData := DirectoryData{} + sourceParentDirHeader, err := fs.Read(sourceParentDirPath, &sourceParentDirData) + if err != nil { + return err + } + + if sourceParentDirHeader.Type != "directory" { + return errors.New("source parent object is not a directory") + } + + targetParentDirPath := fs.GetParentPath(targetPath) + targetParentDirData := DirectoryData{} + targetParentDirHeader, err := fs.Read(targetParentDirPath, &targetParentDirData) + if err != nil { + return err + } + + if targetParentDirHeader.Type != "directory" { + return errors.New("target parent object is not a directory") + } + + err = fs.RemoveChildToDirectory(sourceFileHeader.MongoId, sourceParentDirHeader.MongoId) + if err != nil { + return err + } + + err = fs.AppendChildToDirectory(sourceFileHeader.MongoId, targetParentDirHeader.MongoId) + if err != nil { + return err + } + return nil + +} + func (fs *WebFileSystem) Remove(filePath string) error { parentPath := fs.GetParentPath(filePath) parentDirId, err := fs.FindFile(parentPath)