add file list
This commit is contained in:
parent
beac4c4d4d
commit
d60cb8fbe2
10 changed files with 256 additions and 12 deletions
|
|
@ -8,7 +8,9 @@ secret = "e93865c991358ff7a14f9781fa33ba4f28c33bb8d1cf3490ce6fd68521513536"
|
|||
|
||||
[collabora]
|
||||
url = "https://loolwsd.deblan.org"
|
||||
budget_file = "_data/test.ods"
|
||||
|
||||
[file]
|
||||
path = "./_data/"
|
||||
|
||||
[log]
|
||||
; level = "debug"
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@ type collabora struct {
|
|||
BudgetFile string
|
||||
}
|
||||
|
||||
type file struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
func (c *collabora) HostingDiscoveryUrl() string {
|
||||
return fmt.Sprintf("%s/hosting/discovery", c.Url)
|
||||
}
|
||||
|
|
@ -40,6 +44,7 @@ type Config struct {
|
|||
Security security
|
||||
Server server
|
||||
Collabora collabora
|
||||
File file
|
||||
}
|
||||
|
||||
var config *Config
|
||||
|
|
@ -66,5 +71,5 @@ func (c *Config) Load(file string) {
|
|||
config.Server.Port, _ = cfg.Section("server").Key("port").Int()
|
||||
config.Server.BaseUrl = cfg.Section("server").Key("base_url").String()
|
||||
config.Collabora.Url = cfg.Section("collabora").Key("url").String()
|
||||
config.Collabora.BudgetFile = cfg.Section("collabora").Key("budget_file").String()
|
||||
config.File.Path = cfg.Section("file").Key("path").String()
|
||||
}
|
||||
|
|
|
|||
103
file/manager.go
Normal file
103
file/manager.go
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
package file
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
"os"
|
||||
|
||||
"github.com/gabriel-vasile/mimetype"
|
||||
)
|
||||
|
||||
type File struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
Size int64 `json:"size"`
|
||||
Type string `json:"type"`
|
||||
Extension string `json:"extension"`
|
||||
}
|
||||
|
||||
type Tree struct {
|
||||
Name string `json:"name"`
|
||||
Directories []Tree `json:"directories"`
|
||||
Path string `json:"path"`
|
||||
Files []File `json:"files"`
|
||||
IsRoot bool `json:"is_root"`
|
||||
}
|
||||
|
||||
func getFileId(path string) string {
|
||||
hash := sha256.New()
|
||||
hash.Write([]byte(path))
|
||||
hashBytes := hash.Sum(nil)
|
||||
bInt := new(big.Int).SetBytes(hashBytes)
|
||||
|
||||
return fmt.Sprintf("%d", int(math.Abs(float64(bInt.Int64()))))
|
||||
}
|
||||
|
||||
func GetTree(name, path string) Tree {
|
||||
tree := Tree{
|
||||
Name: name,
|
||||
Directories: []Tree{},
|
||||
Path: path,
|
||||
Files: []File{},
|
||||
IsRoot: name == "",
|
||||
}
|
||||
entries, err := os.ReadDir(path)
|
||||
|
||||
if err != nil {
|
||||
return tree
|
||||
}
|
||||
|
||||
for _, e := range entries {
|
||||
if e.IsDir() {
|
||||
tree.Directories = append(tree.Directories, GetTree(e.Name(), path+"/"+e.Name()))
|
||||
} else {
|
||||
p := path + "/" + e.Name()
|
||||
fi, _ := os.Stat(p)
|
||||
mtype, _ := mimetype.DetectFile(p)
|
||||
|
||||
tree.Files = append(tree.Files, File{
|
||||
Id: getFileId(p),
|
||||
Name: e.Name(),
|
||||
Path: p,
|
||||
Size: fi.Size(),
|
||||
Type: mtype.Extension(),
|
||||
Extension: mtype.Extension(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return tree
|
||||
}
|
||||
|
||||
func GetFiles(files *[]File, path string) *[]File {
|
||||
entries, err := os.ReadDir(path)
|
||||
|
||||
if err != nil {
|
||||
return files
|
||||
}
|
||||
|
||||
for _, e := range entries {
|
||||
p := path + "/" + e.Name()
|
||||
|
||||
if e.IsDir() {
|
||||
GetFiles(files, p)
|
||||
} else {
|
||||
fi, _ := os.Stat(p)
|
||||
mtype, _ := mimetype.DetectFile(p)
|
||||
|
||||
*files = append(*files, File{
|
||||
Id: getFileId(p),
|
||||
Name: e.Name(),
|
||||
Path: p,
|
||||
Size: fi.Size(),
|
||||
Type: mtype.Extension(),
|
||||
Extension: mtype.Extension(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return files
|
||||
}
|
||||
|
|
@ -1,9 +1,67 @@
|
|||
<template>
|
||||
<div>
|
||||
<iframe src="/collabora" id="collabora"></iframe>
|
||||
<div v-if="tree !== null && fileId === null" class="w-100">
|
||||
<div v-if="!tree.is_root" class="p-3 border-bottom cursor" @click="cd(tree.parent)">
|
||||
<span class="text-warning">
|
||||
<i class="fa-solid fa-folder me-2"></i>
|
||||
</span>
|
||||
..
|
||||
</div>
|
||||
<div v-for="item in tree.directories" class="p-3 border-bottom cursor" @click="cd(item)">
|
||||
<span class="text-warning">
|
||||
<i class="fa-solid fa-folder me-2"></i>
|
||||
</span>
|
||||
|
||||
{{ item.name }}
|
||||
</div>
|
||||
<div v-for="item in tree.files" class="p-3 border-bottom">
|
||||
<div v-if="item.extension === '.ods'" class="cursor" @click="fileId = item.id">
|
||||
<span class="text-success">
|
||||
<i class="fa-solid fa-file-lines"></i>
|
||||
</span>
|
||||
{{ item.name }}
|
||||
</div>
|
||||
<div v-else class="text-secondary">
|
||||
<i class="fa-regular fa-file"></i>
|
||||
{{ item.name }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="fileId !== null" class="w-100">
|
||||
<div class="text-end cursor p-2" @click="fileId = null">
|
||||
<i class="fa-solid fa-xmark"></i>
|
||||
</div>
|
||||
<iframe :src="'/collabora/' + fileId" id="collabora"></iframe>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue"
|
||||
import { ref, onMounted, watch } from 'vue'
|
||||
|
||||
const tree = ref(null)
|
||||
const parent = ref(null)
|
||||
const fileId = ref(null)
|
||||
|
||||
const cd = (directory) => {
|
||||
tree.value = directory
|
||||
}
|
||||
|
||||
const withParents = (tree) => {
|
||||
tree.directories.forEach((subTree, key) => {
|
||||
tree.directories[key].parent = tree
|
||||
tree.directories[key] = withParents(tree.directories[key])
|
||||
})
|
||||
|
||||
return tree
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetch('/api/files')
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
tree.value = withParents(data)
|
||||
console.log(tree.value)
|
||||
})
|
||||
})
|
||||
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ $nav-size-sm: 50px;
|
|||
|
||||
@media screen and (max-width: 980px) {
|
||||
#collabora {
|
||||
height: calc(100vh - 70px);
|
||||
height: calc(100vh - 100px);
|
||||
}
|
||||
|
||||
#app-name {
|
||||
|
|
|
|||
2
go.mod
2
go.mod
|
|
@ -18,7 +18,7 @@ require (
|
|||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
||||
github.com/daaku/go.zipexe v1.0.2 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.5 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator v9.31.0+incompatible // indirect
|
||||
|
|
|
|||
2
go.sum
2
go.sum
|
|
@ -21,6 +21,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||
github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=
|
||||
github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/labstack/echo/v4"
|
||||
"gitnet.fr/deblan/budget/config"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
f "gitnet.fr/deblan/budget/file"
|
||||
"gitnet.fr/deblan/budget/web/view"
|
||||
tpl "gitnet.fr/deblan/budget/web/view/template/collabora"
|
||||
)
|
||||
|
|
@ -45,7 +46,7 @@ func New(e *echo.Echo) *Controller {
|
|||
Token: getToken(),
|
||||
}
|
||||
|
||||
e.GET("/collabora", c.Iframe)
|
||||
e.GET("/collabora/:id", c.Iframe)
|
||||
e.GET("/wopi/:id", c.Info)
|
||||
e.GET("/wopi/:id/contents", c.WopiContentGet)
|
||||
e.POST("/wopi/:id/contents", c.WopiContentPost)
|
||||
|
|
@ -77,7 +78,7 @@ func (ctrl *Controller) Iframe(c echo.Context) error {
|
|||
wopiSrc := fmt.Sprintf(
|
||||
"%s%s",
|
||||
config.Get().Server.BaseUrl,
|
||||
"/wopi/1",
|
||||
"/wopi/"+c.Param("id"),
|
||||
)
|
||||
|
||||
url := items[1] + "WOPISrc=" + wopiSrc
|
||||
|
|
@ -90,7 +91,21 @@ func (ctrl *Controller) Info(c echo.Context) error {
|
|||
return c.JSON(403, nil)
|
||||
}
|
||||
|
||||
fi, _ := os.Stat(config.Get().Collabora.BudgetFile)
|
||||
var file string
|
||||
files := []f.File{}
|
||||
f.GetFiles(&files, config.Get().File.Path)
|
||||
|
||||
for _, f := range files {
|
||||
if f.Id == c.Param("id") {
|
||||
file = f.Path
|
||||
}
|
||||
}
|
||||
|
||||
if file == "" {
|
||||
return c.JSON(404, "File not found")
|
||||
}
|
||||
|
||||
fi, _ := os.Stat(file)
|
||||
|
||||
type res struct {
|
||||
BaseFileName string
|
||||
|
|
@ -112,7 +127,21 @@ func (ctrl *Controller) WopiContentGet(c echo.Context) error {
|
|||
return c.JSON(403, nil)
|
||||
}
|
||||
|
||||
content, _ := os.ReadFile(config.Get().Collabora.BudgetFile)
|
||||
var file string
|
||||
files := []f.File{}
|
||||
f.GetFiles(&files, config.Get().File.Path)
|
||||
|
||||
for _, f := range files {
|
||||
if f.Id == c.Param("id") {
|
||||
file = f.Path
|
||||
}
|
||||
}
|
||||
|
||||
if file == "" {
|
||||
return c.JSON(404, "File not found")
|
||||
}
|
||||
|
||||
content, _ := os.ReadFile(file)
|
||||
|
||||
return c.Blob(200, "application/vnd.oasis.opendocument.spreadsheet", content)
|
||||
}
|
||||
|
|
@ -122,9 +151,23 @@ func (ctrl *Controller) WopiContentPost(c echo.Context) error {
|
|||
return c.JSON(403, nil)
|
||||
}
|
||||
|
||||
var file string
|
||||
files := []f.File{}
|
||||
f.GetFiles(&files, config.Get().File.Path)
|
||||
|
||||
for _, f := range files {
|
||||
if f.Id == c.Param("id") {
|
||||
file = f.Path
|
||||
}
|
||||
}
|
||||
|
||||
if file == "" {
|
||||
return c.JSON(404, "File not found")
|
||||
}
|
||||
|
||||
data, _ := ioutil.ReadAll(c.Request().Body)
|
||||
|
||||
err := os.WriteFile(config.Get().Collabora.BudgetFile, data, 0600)
|
||||
err := os.WriteFile(file, data, 0600)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
29
web/controller/file/controller.go
Normal file
29
web/controller/file/controller.go
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package file
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitnet.fr/deblan/budget/config"
|
||||
"gitnet.fr/deblan/budget/database/model"
|
||||
f "gitnet.fr/deblan/budget/file"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
}
|
||||
|
||||
func New(e *echo.Echo) *Controller {
|
||||
c := Controller{}
|
||||
|
||||
e.GET("/api/files", c.Files)
|
||||
|
||||
return &c
|
||||
}
|
||||
|
||||
func (ctrl *Controller) Files(c echo.Context) error {
|
||||
if nil == model.LoadSessionUser(c) {
|
||||
return c.Redirect(302, "/login")
|
||||
}
|
||||
|
||||
tree := f.GetTree("", config.Get().File.Path)
|
||||
|
||||
return c.JSON(200, tree)
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"gitnet.fr/deblan/budget/web/controller/bank_account"
|
||||
"gitnet.fr/deblan/budget/web/controller/category"
|
||||
"gitnet.fr/deblan/budget/web/controller/collabora"
|
||||
"gitnet.fr/deblan/budget/web/controller/file"
|
||||
"gitnet.fr/deblan/budget/web/controller/saving_account"
|
||||
"gitnet.fr/deblan/budget/web/controller/transaction"
|
||||
"gitnet.fr/deblan/budget/web/controller/user"
|
||||
|
|
@ -21,4 +22,5 @@ func RegisterControllers(e *echo.Echo) {
|
|||
category.New(e)
|
||||
transaction.New(e)
|
||||
collabora.New(e)
|
||||
file.New(e)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue