Compare commits

...

8 Commits

10 changed files with 331 additions and 91 deletions

View File

@ -3,7 +3,9 @@ package finder
import ( import (
"net/http" "net/http"
"personalwebsite/apps" "personalwebsite/apps"
"personalwebsite/wde"
"personalwebsite/webfilesystem" "personalwebsite/webfilesystem"
"strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
@ -34,6 +36,78 @@ func (f *FinderApplication) Render(isMobile bool) gin.H {
return gin.H{} return gin.H{}
} }
func (f *FinderApplication) RenderContextMenu(context string, data string) gin.H {
islands := [][]wde.ContexMenuRow{} //FIXME
switch context {
case "FileTileView":
islands = [][]wde.ContexMenuRow{
{
{
Label: "Get Info",
Action: strings.Join([]string{"getInfo"}[:], ","),
},
},
{
{
Label: "New Directory",
Action: strings.Join([]string{"newDir"}[:], ","),
},
},
}
case "directory":
islands = [][]wde.ContexMenuRow{
{
{
Label: "Test",
Action: strings.Join([]string{""}[:], ","),
},
{
Label: "Delete",
Action: strings.Join([]string{""}[:], ","),
},
},
{
{
Label: "Get Info",
Action: strings.Join([]string{""}[:], ","),
},
},
}
default:
islands = [][]wde.ContexMenuRow{
{
{
Label: "temp Menu 1",
Action: strings.Join([]string{""}[:], ","),
},
{
Label: "temp Menu 2",
Action: strings.Join([]string{""}[:], ","),
},
{
Label: "temp Menu 3",
Action: strings.Join([]string{""}[:], ","),
},
{
Label: "temp Menu 4",
Action: strings.Join([]string{""}[:], ","),
},
},
}
}
islands = append(islands, []wde.ContexMenuRow{
{
Label: "Delete File",
Action: strings.Join([]string{"deleteFile"}[:], ";"),
},
})
return gin.H{
"Islands": islands,
}
}
func (f *FinderApplication) Routes(routes *gin.RouterGroup) { func (f *FinderApplication) Routes(routes *gin.RouterGroup) {
routes.GET("render", func(ctx *gin.Context) { routes.GET("render", func(ctx *gin.Context) {
isMobileParam := ctx.Query("isMobile") isMobileParam := ctx.Query("isMobile")
@ -61,7 +135,11 @@ func (f *FinderApplication) Routes(routes *gin.RouterGroup) {
} }
ctx.HTML(http.StatusOK, "finder/desktop.tmpl", gin.H{}) ctx.HTML(http.StatusOK, "finder/desktop.tmpl", gin.H{})
}) })
routes.GET("contextMenu", func(ctx *gin.Context) { routes.GET("contextMenu", func(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "wde-widgets/context-menu.tmpl", gin.H{}) context := ctx.Query("context")
data := ctx.Query("data")
ginH := f.RenderContextMenu(context, data)
ctx.HTML(http.StatusOK, "wde-widgets/context-menu.tmpl", ginH)
}) })
} }

32
main.go
View File

@ -3,7 +3,6 @@ package main
import ( import (
"context" "context"
"errors" "errors"
"fmt"
"log" "log"
"net/http" "net/http"
"os" "os"
@ -82,37 +81,6 @@ func main() {
appsStorage.Apps["img-viewer"] = &imgViewerApp appsStorage.Apps["img-viewer"] = &imgViewerApp
appsStorage.Apps["blog-viewer"] = blogViewerApp appsStorage.Apps["blog-viewer"] = blogViewerApp
router.POST("/upload", func(ctx *gin.Context) {
path := ctx.Query("path")
if path == "" {
ctx.JSON(http.StatusBadRequest, "TODO") //TODO json error struct
return
}
// single file
file, _ := ctx.FormFile("file")
if file == nil {
ctx.String(http.StatusBadRequest, "file is nil")
}
// generateMins := c.Param("generateMins")
// log.Println(file.Filename)
// Upload the file to specific dst.
dst := "./test-img/" + file.Filename
ctx.SaveUploadedFile(file, dst)
err := webfs.UploadFile(dst, path)
if err != nil {
ctx.String(http.StatusInternalServerError, "TODO") //TODO
return
}
// webFsCollection.CreateMiniatures("./test-img/", file.Filename)
// webfs.CreateFile(&img, "/home/user/")
ctx.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
})
system := router.Group("system") system := router.Group("system")
{ {
libsGroup := system.Group("libs") libsGroup := system.Group("libs")

View File

@ -31,7 +31,9 @@ class Finder{
this.fileView = new FileView(newWindow.querySelector(".FileTileView"), this.fileView = new FileView(newWindow.querySelector(".FileTileView"),
(event) =>{ this.Open(event, false) }, (event) =>{ this.Open(event, false) },
(event) =>{ this.RightClick(event) }) (event) =>{ this.RightClick(event) },
(event) =>{ this.FileUploading(event) },
)
this.OpenDir(this.path) this.OpenDir(this.path)
newWindow.querySelector("#BackButton").addEventListener('click', () =>{ newWindow.querySelector("#BackButton").addEventListener('click', () =>{
@ -47,6 +49,7 @@ class Finder{
if (!WebDesktopEnvironment.isMobile){ if (!WebDesktopEnvironment.isMobile){
// let scrollBar = new WdeScrollBar(newWindow.children[1].children[1], newWindow.children[1].children[0])// TODO to querry selector // let scrollBar = new WdeScrollBar(newWindow.children[1].children[1], newWindow.children[1].children[0])// TODO to querry selector
// console.log(newWindow.querySelector("#closeWindowButton")) // console.log(newWindow.querySelector("#closeWindowButton"))
newWindow.querySelector("#closeWindowButton").addEventListener('click', function (params) { newWindow.querySelector("#closeWindowButton").addEventListener('click', function (params) {
WebDesktopEnvironment.CloseWindow(newWindow) WebDesktopEnvironment.CloseWindow(newWindow)
@ -59,6 +62,32 @@ class Finder{
}) })
} }
/**
* @param {DataTransferItemList} filesList
*/
FileUploading(filesList){
let formData = new FormData()
// console.log(filesList)
for (let i = 0; i < filesList.length; i++) {
const element = filesList[i];
formData.append("file", element.getAsFile())
console.log(formData)
}
// console.log(formData)
// formData.append("photo", photo);
fetch('/fs/upload/?' + new URLSearchParams({
path: '/home/user/',
}),
{
method: "POST",
body: formData
})
.catch((error) => {
WebDesktopEnvironment.Alert(error);
})
}
/** /**
* @param {string[]} args * @param {string[]} args
*/ */
@ -128,6 +157,17 @@ class Finder{
case "blog-page": case "blog-page":
WebDesktopEnvironment.Open("blog-viewer", [this.path + "/" + fileName]) WebDesktopEnvironment.Open("blog-viewer", [this.path + "/" + fileName])
break break
case "deleteFile":
fetch(`/fs/delete` + new URLSearchParams({
path: "/home/user/" + fileName //FIXME
}))
.then((response) => {
console.log(response.status)
})
.catch((error) => {
WebDesktopEnvironment.Alert(error);
})
break
// case "app": // case "app":
// //TODO get real id // //TODO get real id
// WebDesktopEnvironment.Open("personal-properties", []) // WebDesktopEnvironment.Open("personal-properties", [])
@ -143,16 +183,19 @@ class Finder{
} }
RightClick(event){ RightClick(event){
// console.log(event) this.CreateContextMenu(event.target, [event.clientY, event.clientX])
// console.log()
if (event.target.className="FileTileView" ||event.target.getAttribute('filetype') != ""){
this.CreateContextMenu(event.target, [event.clientY, event.clientX])
}
} }
CreateContextMenu(target, pos){ CreateContextMenu(target, pos){
let context = ""
if (target.classList.contains("FileTileView"))
{
context = "FileTileView"
}
fetch(`${window.location.origin}/application/${this.appId}/contextMenu?` + new URLSearchParams({ fetch(`${window.location.origin}/application/${this.appId}/contextMenu?` + new URLSearchParams({
kek: "kek" context: context
})) }))
.then((response) => response.text()) .then((response) => response.text())
.then((html) => { .then((html) => {
@ -161,21 +204,25 @@ class Finder{
overlay.style.position = 'absolute' overlay.style.position = 'absolute'
overlay.style.width = "100%" overlay.style.width = "100%"
overlay.style.height = "100%" overlay.style.height = "100%"
let menu = document.createElement("div") let menu = document.createElement("div")
menu.setAttribute('class', 'ContextMenu WindowFrameShadow') menu.setAttribute('class', 'ContextMenu WindowFrameShadow')
menu.style.position = 'absolute'; menu.style.position = 'absolute';
// menu.style.backgroundColor = '#000000';
menu.style.top = pos[0] + "px"; menu.style.top = pos[0] + "px";
menu.style.left = pos[1] + "px"; menu.style.left = pos[1] + "px";
menu.innerHTML = html menu.innerHTML = html
menu.children[0].lastElementChild.remove() //FIXME Can't ommit rendering of horLine in end of menu on backend
overlay.appendChild(menu) overlay.appendChild(menu)
document.body.appendChild(overlay) document.body.appendChild(overlay)
overlay.addEventListener('click',(event) => { overlay.addEventListener('click',(event) => {
if (event.target.className == "Row"){ //TODO add uuid id to rows to more accurate checks?? if (event.target.classList.contains("Row")){ //TODO add uuid id to rows to more accurate checks??
// console.log("aaaa") switch (event.target.children[0].getAttribute("action")) {
default:
break;
}
} }
overlay.remove() overlay.remove()
}) })
@ -186,24 +233,6 @@ class Finder{
}) })
.catch((error) => { .catch((error) => {
WebDesktopEnvironment.Alert(error); WebDesktopEnvironment.Alert(error);
}) })
} }
// /**
// * @param {path} string
// */
// renderFileView(path){
// fetch(`${window.location.origin}/fs/list?` + new URLSearchParams({
// path: path,
// }))
// .then((response) => response.text())
// .then((html) => {
// this.fileView.innerHTML = html
// })
// .catch((error) => {
// WebDesktopEnvironment.Alert(error);
// })
// }
} }

View File

@ -6,7 +6,7 @@ class FileView{
* @param {Function} doubleClickCallback * @param {Function} doubleClickCallback
* @param {Function} rightClickCallback * @param {Function} rightClickCallback
*/ */
constructor(fileViewElem, doubleClickCallback, rightClickCallback){ constructor(fileViewElem, doubleClickCallback, rightClickCallback, fileUploadCallback){
//TODO check all params //TODO check all params
this.parentElem = fileViewElem this.parentElem = fileViewElem
@ -18,8 +18,7 @@ class FileView{
} }
if (event.detail === 1){ if (event.detail === 1){
this.DeselectAll() this.DeselectAll()
this.selected.push(event.target) this.Select([event.target])
event.target.classList.add("Selected")
} else if (event.detail === 2) { } else if (event.detail === 2) {
doubleClickCallback(event) doubleClickCallback(event)
} }
@ -27,8 +26,40 @@ class FileView{
fileViewElem.addEventListener('contextmenu', (event) => { fileViewElem.addEventListener('contextmenu', (event) => {
event.preventDefault(); event.preventDefault();
if (event.target.classList.contains("Tile")){
this.DeselectAll()
this.Select([event.target])
}
this.Select([event.target])
rightClickCallback(event) rightClickCallback(event)
}) })
if (fileUploadCallback !== undefined) {
fileViewElem.addEventListener('dragenter', function(event) {
// console.log("start")
})
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)
})
}
}
/**
* @param {[]Element} elements
*/
Select(elements){
elements.forEach(element => {
this.selected.push(element)
element.classList.add("Selected")
});
} }
DeselectAll(){ DeselectAll(){

View File

@ -4,8 +4,8 @@ document.addEventListener('DOMContentLoaded', function() {
// console.log(window.screen.width) // console.log(window.screen.width)
wde = new WebDesktopEnvironment wde = new WebDesktopEnvironment
if (!WebDesktopEnvironment.isMobile){ if (!WebDesktopEnvironment.isMobile){
// WebDesktopEnvironment.Open("finder", ["/home/user"]) WebDesktopEnvironment.Open("finder", ["/home/user"])
WebDesktopEnvironment.Open("blog-viewer", ["/home/user/blog/test-1.blog"]) // WebDesktopEnvironment.Open("blog-viewer", ["/home/user/blog/test-1.blog"])
// WebDesktopEnvironment.Open("personal-properties", ["kek"]) // WebDesktopEnvironment.Open("personal-properties", ["kek"])
} else { } else {
WebDesktopEnvironment.Open("blog-viewer", ["/home/user/blog/test-1.blog"]) WebDesktopEnvironment.Open("blog-viewer", ["/home/user/blog/test-1.blog"])

View File

@ -60,6 +60,10 @@
height: 0px; height: 0px;
} }
.AdjectiveHorizontalLine:last-child {
height: 0%;
visibility: hidden;
}
.WindowFrame .TitleBar { .WindowFrame .TitleBar {

View File

@ -1,28 +1,12 @@
{{ define "wde-widgets/context-menu.tmpl" }} {{ define "wde-widgets/context-menu.tmpl" }}
<!-- <div class="ContextMenu WindowFrameShadow"> -->
<div class="MenuContent ConvexElement"> <div class="MenuContent ConvexElement">
<div class="Row"> {{ range $island := .Islands }}
<div class="Lable NoClick">Open</div> {{ range $row := $island }}
</div> <div class="Row">
<div class="Row" actionType="" action=""> <div class="Lable NoClick" action="{{$row.Action}}">{{ $row.Label }}</div>
<div class="Lable NoClick">Test</div> </div>
</div> {{ end }}
<div class="AdjectiveHorizontalLine"></div> <div class="AdjectiveHorizontalLine"></div>
<div class="Row"> {{ end }}
<div class="Lable NoClick">Lol kek</div>
</div>
<div class="Row">
<div class="Lable NoClick">Delete this file</div>
</div>
<div class="Row">
<div class="Lable NoClick">Save to computer</div>
</div>
<div class="Row">
<div class="Lable NoClick">Pizda</div>
</div>
<div class="Row">
<div class="Lable NoClick">Azaza</div>
</div>
</div> </div>
<!-- </div> -->
{{ end }} {{ end }}

10
wde/contextmenu.go Normal file
View File

@ -0,0 +1,10 @@
package wde
type ContexMenuIsland struct {
Rows []ContexMenuRow
}
type ContexMenuRow struct {
Label string
Action string
}

View File

@ -44,6 +44,35 @@ func (fs *WebFileSystem) UploadFile(realFilepath string, path string) error {
return errors.New("this filetype not allowed") return errors.New("this filetype not allowed")
} }
}
func (fs *WebFileSystem) UploadBinaryFile(file []byte, fileName string, path string) error {
extension := fs.GetExtension(fileName)
switch extension {
case "jpg":
fallthrough
case "jpeg":
newFile := WebFSFile{
MongoId: primitive.NewObjectID(),
Name: fileName,
Type: "jpeg",
Data: file,
Icon: "",
}
err := fs.CreateFile(&newFile, path)
return err
case "png":
newFile := WebFSFile{
MongoId: primitive.NewObjectID(),
Name: fileName,
Type: "png",
Data: file,
}
err := fs.CreateFile(&newFile, path)
return err
default:
return errors.New("this filetype not allowed")
}
} }
// func (fs *WebFileSystem) CreateMiniatures(parentDir string, file string) error { // func (fs *WebFileSystem) CreateMiniatures(parentDir string, file string) error {

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"errors" "errors"
"net/http" "net/http"
"strconv"
"strings" "strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@ -175,6 +176,44 @@ func (fs *WebFileSystem) GetParentPath(path string) string {
} }
func (fs *WebFileSystem) Route(route *gin.RouterGroup) { func (fs *WebFileSystem) Route(route *gin.RouterGroup) {
route.POST("/upload", func(ctx *gin.Context) { //TODO To PUT request
// fileName := ctx.Query("fileName")
// if fileName == "" {
// ctx.JSON(http.StatusBadRequest, "TODO") //TODO json error struct
// return
// }
path := ctx.Query("path")
if path == "" {
ctx.JSON(http.StatusBadRequest, "TODO") //TODO json error struct
return
}
// single file
file, _ := ctx.FormFile("file")
if file == nil {
ctx.String(http.StatusBadRequest, "file is nil")
return
}
// generateMins := c.Param("generateMins")
// log.Println(file.Filename)
// Upload the file to specific dst.
dst := "./test-img/" + file.Filename
ctx.SaveUploadedFile(file, dst)
//TODO: Not Save to disk
err := fs.UploadFile(dst, path)
if err != nil {
ctx.String(http.StatusInternalServerError, "TODO") //TODO
return
}
// webFsCollection.CreateMiniatures("./test-img/", file.Filename)
// webfs.CreateFile(&img, "/home/user/")
ctx.Status(http.StatusCreated)
})
route.GET("writeFile", func(ctx *gin.Context) { route.GET("writeFile", func(ctx *gin.Context) {
parentPath := ctx.Query("parentPath") parentPath := ctx.Query("parentPath")
if parentPath == "" { if parentPath == "" {
@ -242,6 +281,74 @@ func (fs *WebFileSystem) Route(route *gin.RouterGroup) {
ctx.JSON(http.StatusOK, &file) ctx.JSON(http.StatusOK, &file)
}) })
route.GET("validate", func(ctx *gin.Context) {
err := fs.Validate()
if err != nil {
ctx.Status(http.StatusInternalServerError)
return
}
ctx.Status(http.StatusOK)
})
}
func (fs *WebFileSystem) Validate() error {
filter := primitive.D{
{
Key: "type",
Value: "directory",
},
}
cur, err := fs.webfsCollection.Find(context.Background(), filter)
if err != nil {
return err
}
defer cur.Close(context.Background())
directories := []*WebFSFile{}
for cur.Next(context.Background()) {
dir := &WebFSFile{}
err = cur.Decode(dir)
if err != nil {
println(err.Error())
return err
}
directories = append(directories, dir)
}
for _, d := range directories {
fs.validateDir(d)
}
return nil
}
func (fs *WebFileSystem) validateDir(dir *WebFSFile) error {
kek := dir.Data.(primitive.D).Map()["children"].(primitive.A)
_ = kek
children := []primitive.ObjectID{}
counter := 0
for _, v := range kek {
_, err := fs.ReadByObjectID(v.(primitive.ObjectID))
if err != nil {
counter++
} else {
children = append(children, v.(primitive.ObjectID))
}
}
if counter > 0 {
println(dir.Name + " broken iDs: " + strconv.Itoa(counter))
_, err := fs.webfsCollection.UpdateByID(context.Background(), dir.MongoId, bson.M{"$set": bson.M{"data.children": children}})
if err != nil {
println(err.Error())
return err
}
}
return nil
} }
type WebFSFile struct { type WebFSFile struct {