Compare commits

..

8 Commits

10 changed files with 331 additions and 91 deletions

View File

@ -3,7 +3,9 @@ package finder
import (
"net/http"
"personalwebsite/apps"
"personalwebsite/wde"
"personalwebsite/webfilesystem"
"strings"
"github.com/gin-gonic/gin"
)
@ -34,6 +36,78 @@ func (f *FinderApplication) Render(isMobile bool) 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) {
routes.GET("render", func(ctx *gin.Context) {
isMobileParam := ctx.Query("isMobile")
@ -61,7 +135,11 @@ func (f *FinderApplication) Routes(routes *gin.RouterGroup) {
}
ctx.HTML(http.StatusOK, "finder/desktop.tmpl", gin.H{})
})
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 (
"context"
"errors"
"fmt"
"log"
"net/http"
"os"
@ -82,37 +81,6 @@ func main() {
appsStorage.Apps["img-viewer"] = &imgViewerApp
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")
{
libsGroup := system.Group("libs")

View File

@ -31,7 +31,9 @@ class Finder{
this.fileView = new FileView(newWindow.querySelector(".FileTileView"),
(event) =>{ this.Open(event, false) },
(event) =>{ this.RightClick(event) })
(event) =>{ this.RightClick(event) },
(event) =>{ this.FileUploading(event) },
)
this.OpenDir(this.path)
newWindow.querySelector("#BackButton").addEventListener('click', () =>{
@ -47,6 +49,7 @@ class Finder{
if (!WebDesktopEnvironment.isMobile){
// let scrollBar = new WdeScrollBar(newWindow.children[1].children[1], newWindow.children[1].children[0])// TODO to querry selector
// console.log(newWindow.querySelector("#closeWindowButton"))
newWindow.querySelector("#closeWindowButton").addEventListener('click', function (params) {
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
*/
@ -128,6 +157,17 @@ class Finder{
case "blog-page":
WebDesktopEnvironment.Open("blog-viewer", [this.path + "/" + fileName])
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":
// //TODO get real id
// WebDesktopEnvironment.Open("personal-properties", [])
@ -143,16 +183,19 @@ class Finder{
}
RightClick(event){
// console.log(event)
// console.log()
if (event.target.className="FileTileView" ||event.target.getAttribute('filetype') != ""){
this.CreateContextMenu(event.target, [event.clientY, event.clientX])
}
}
CreateContextMenu(target, pos){
let context = ""
if (target.classList.contains("FileTileView"))
{
context = "FileTileView"
}
fetch(`${window.location.origin}/application/${this.appId}/contextMenu?` + new URLSearchParams({
kek: "kek"
context: context
}))
.then((response) => response.text())
.then((html) => {
@ -161,21 +204,25 @@ class Finder{
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.backgroundColor = '#000000';
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)
overlay.addEventListener('click',(event) => {
if (event.target.className == "Row"){ //TODO add uuid id to rows to more accurate checks??
// console.log("aaaa")
if (event.target.classList.contains("Row")){ //TODO add uuid id to rows to more accurate checks??
switch (event.target.children[0].getAttribute("action")) {
default:
break;
}
}
overlay.remove()
})
@ -187,23 +234,5 @@ class Finder{
.catch((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} rightClickCallback
*/
constructor(fileViewElem, doubleClickCallback, rightClickCallback){
constructor(fileViewElem, doubleClickCallback, rightClickCallback, fileUploadCallback){
//TODO check all params
this.parentElem = fileViewElem
@ -18,8 +18,7 @@ class FileView{
}
if (event.detail === 1){
this.DeselectAll()
this.selected.push(event.target)
event.target.classList.add("Selected")
this.Select([event.target])
} else if (event.detail === 2) {
doubleClickCallback(event)
}
@ -27,8 +26,40 @@ class FileView{
fileViewElem.addEventListener('contextmenu', (event) => {
event.preventDefault();
if (event.target.classList.contains("Tile")){
this.DeselectAll()
this.Select([event.target])
}
this.Select([event.target])
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(){

View File

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

View File

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

View File

@ -1,28 +1,12 @@
{{ define "wde-widgets/context-menu.tmpl" }}
<!-- <div class="ContextMenu WindowFrameShadow"> -->
<div class="MenuContent ConvexElement">
{{ range $island := .Islands }}
{{ range $row := $island }}
<div class="Row">
<div class="Lable NoClick">Open</div>
<div class="Lable NoClick" action="{{$row.Action}}">{{ $row.Label }}</div>
</div>
{{ end }}
<div class="AdjectiveHorizontalLine"></div>
{{ end }}
</div>
<div class="Row" actionType="" action="">
<div class="Lable NoClick">Test</div>
</div>
<div class="AdjectiveHorizontalLine"></div>
<div class="Row">
<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> -->
{{ 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")
}
}
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 {

View File

@ -4,6 +4,7 @@ import (
"context"
"errors"
"net/http"
"strconv"
"strings"
"github.com/gin-gonic/gin"
@ -175,6 +176,44 @@ func (fs *WebFileSystem) GetParentPath(path string) string {
}
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) {
parentPath := ctx.Query("parentPath")
if parentPath == "" {
@ -242,6 +281,74 @@ func (fs *WebFileSystem) Route(route *gin.RouterGroup) {
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 {