- {{end}}
-
- {{range $file := .Files}}
- {{ if $file.IsDir }}
-
- {{ end }}
- {{ if not $file.IsDir }}
-
- {{end}}
- {{end}}
+
diff --git a/assets/web/static/app.js b/assets/web/static/app.js
new file mode 100644
index 0000000..0af65cf
--- /dev/null
+++ b/assets/web/static/app.js
@@ -0,0 +1,88 @@
+const $ = element => document.getElementById(element);
+
+const init = event => {
+ var path = window.location.pathname;
+ var pathSplit = path.split("/");
+ var path = pathSplit.splice(1).join("/");
+ document.title = path + " | PiNAS";
+
+ getFiles(pathSplit[0], path, json => {
+ console.log(json);
+ document.getElementById("previous-dir").href = "/" + json.Prefix + "/" + json.Previous;
+ buildList(json);
+ });
+
+ $("path-header").innerText = path;
+
+ document.querySelector("body").addEventListener('contextmenu', function(ev) {
+ if (ev.target.localName == "a") {
+ ev.preventDefault();
+
+ var d = document.getElementById('context');
+ d.classList.remove("hidden");
+ d.style.position = "absolute";
+ d.style.left = ev.clientX + 'px';
+ d.style.top = ev.clientY + 'px';
+
+ }
+ return false;
+ }, false);
+
+ document.querySelector("body").addEventListener('click', function(ev) {
+ let shouldDismiss = ev.target.dataset.dismissContext == undefined && ev.target.parentElement.classList.contains("context-actions") == false && ev.target.localName != 'a';
+
+ if (ev.which == 1 && shouldDismiss) {
+ ev.preventDefault();
+
+ var d = document.getElementById('context');
+ d.classList.add("hidden");
+ return false;
+ }
+ }, false);
+}
+
+const getFiles = (prefix, path, callback) => {
+ fetch('/api/' + prefix + '/' + path)
+ .then(function (response) {
+ return response.json();
+ })
+ .then(function (jsonResult) {
+ callback(jsonResult);
+ });
+}
+
+const buildList = data => {
+ for (var i = 0; i < data.Files.length; i++) {
+ let fileItem = document.createElement('p');
+ let fileLink = document.createElement('a');
+ if (data.Files[i].IsDirectory == true) {
+ fileItem.classList.add("directory");
+ fileLink.href = "/" + data.Prefix + "/" + data.Path + "/" + data.Files[i].Name;
+ }
+ else {
+ fileItem.classList.add("file");
+ fileLink.href = "/" + data.SinglePrefix + "/" + data.Path + "/" + data.Files[i].Name;
+ }
+
+ fileLink.innerText = data.Files[i].Name;
+ fileItem.appendChild(fileLink);
+ document.getElementById("filelist").appendChild(fileItem);
+ }
+}
+
+const upload = (file, path) => {
+ var formData = new FormData();
+ formData.append("path", path);
+ formData.append("file", file);
+ fetch('/upload', { // Your POST endpoint
+ method: 'POST',
+ body: formData
+ }).then(
+ success => console.log(success) // Handle the success response object
+ ).catch(
+ error => console.log(error) // Handle the error response object
+ );
+};
+
+window.addEventListener('load', init);
+
diff --git a/assets/web/static/fileListing.js b/assets/web/static/fileListing.js
deleted file mode 100644
index d73cf61..0000000
--- a/assets/web/static/fileListing.js
+++ /dev/null
@@ -1,40 +0,0 @@
-function dragEnter(e) {
- document.getElementById("uploadoverlay").classList.remove("hidden");
-}
-
-function dragExit(e) {
- document.getElementById("uploadoverlay").classList.add("hidden");
-}
-document.addEventListener("drop", function(e) {
- var files = e.target.files || e.dataTransfer.files
- console.log(files)
- document.getElementById("uploadoverlay").classList.add("hidden");
- for (var i = 0; i <= files.length; i++) {
- upload(files[i]);
- }
-})
-
-window.addEventListener("dragover",function(e){
- e = e || event;
- e.preventDefault();
-},false);
-window.addEventListener("drop",function(e){
- e = e || event;
- e.preventDefault();
-},false);
-
-
-var upload = (file) => {
- var path = document.getElementById("path").value;
- var formData = new FormData();
- formData.append("path", path);
- formData.append("file", file);
- fetch('/upload', { // Your POST endpoint
- method: 'POST',
- body: formData
- }).then(
- success => console.log(success) // Handle the success response object
- ).catch(
- error => console.log(error) // Handle the error response object
- );
-};
\ No newline at end of file
diff --git a/assets/web/static/styles.css b/assets/web/static/styles.css
index 7054f0a..8afc72d 100644
--- a/assets/web/static/styles.css
+++ b/assets/web/static/styles.css
@@ -81,3 +81,19 @@ h1, h2, h3 {
a.back-button {
display: inline-block;
}
+
+.context-menu {
+ background-color: #ededed;
+ padding: 10px;
+}
+
+.context-actions {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.context-actions li {
+ border-bottom: 1px solid black;
+ cursor: pointer;
+}
\ No newline at end of file
diff --git a/files/files.go b/files/files.go
index 1faceb3..2394c2a 100644
--- a/files/files.go
+++ b/files/files.go
@@ -1,11 +1,12 @@
package files
import (
+ "crypto/md5"
+ "encoding/hex"
"encoding/json"
"fmt"
"github.com/gmemstr/nas/common"
"github.com/gorilla/mux"
- "html/template"
"io"
"io/ioutil"
"net/http"
@@ -20,12 +21,17 @@ type Config struct {
type Directory struct {
Path string
- Files []os.FileInfo
+ Files []FileInfo
Previous string
Prefix string
SinglePrefix string
}
+type FileInfo struct {
+ IsDirectory bool
+ Name string
+}
+
// Lists out directory using template.
func Listing(tier string) common.Handler {
@@ -62,6 +68,15 @@ func Listing(tier string) common.Handler {
}
fileDir, err := ioutil.ReadDir(path)
+ var fileList []FileInfo;
+
+ for _, file := range fileDir {
+ info := FileInfo{
+ IsDirectory: file.IsDir(),
+ Name: file.Name(),
+ }
+ fileList = append(fileList, info)
+ }
path = strings.Replace(path, storage, "", -1)
// Figure out what our previous location was.
@@ -71,19 +86,15 @@ func Listing(tier string) common.Handler {
directory := Directory{
Path: path,
- Files: fileDir,
+ Files: fileList,
Previous: previousPath,
Prefix: prefix,
SinglePrefix: singleprefix,
}
- t, err := template.ParseFiles("assets/web/listing.html")
- if err != nil {
- panic(err)
- }
-
- t.Execute(w, directory)
- return nil
+ resultJson, err := json.Marshal(directory);
+ w.Write(resultJson);
+ return nil;
}
}
@@ -155,3 +166,50 @@ func UploadFile() common.Handler {
}
}
+
+func Md5File(tier string) common.Handler {
+
+ return func(rc *common.RouterContext, w http.ResponseWriter, r *http.Request) *common.HTTPError {
+ vars := mux.Vars(r)
+ id := vars["file"]
+
+ var returnMD5String string
+
+ d, err := ioutil.ReadFile("assets/config/config.json")
+ var config Config;
+ err = json.Unmarshal(d, &config)
+ if err != nil {
+ panic(err)
+ }
+
+ // Default to hot storage
+ storage := config.HotStorage
+
+ if err != nil {
+ fmt.Println(err)
+ return nil
+ }
+ file, err := os.Open(storage + "/" + id)
+ if err != nil {
+ panic(err)
+ }
+ defer file.Close()
+
+ hash := md5.New()
+ if _, err := io.Copy(hash, file); err != nil {
+ panic(err)
+ }
+
+ //Get the 16 bytes hash
+ hashInBytes := hash.Sum(nil)[:16]
+
+ //Convert the bytes to a string
+ returnMD5String = hex.EncodeToString(hashInBytes)
+
+ w.Write([]byte(returnMD5String))
+
+
+ return nil
+ }
+
+}
diff --git a/router/router.go b/router/router.go
index 250c7bd..910c044 100644
--- a/router/router.go
+++ b/router/router.go
@@ -48,29 +48,48 @@ func Init() *mux.Router {
r.Handle("/", Handle(
rootHandler(),
)).Methods("GET")
+ r.Handle(`/files/{file:[a-zA-Z0-9=\-\/\s.,&_+]+}`, Handle(
+ fileList(),
+ )).Methods("GET")
+ r.Handle(`/files/`, Handle(
+ fileList(),
+ )).Methods("GET")
+ r.Handle(`/archive/{file:[a-zA-Z0-9=\-\/\s.,&_+]+}`, Handle(
+ fileList(),
+ )).Methods("GET")
+ r.Handle(`/archive/`, Handle(
+ fileList(),
+ )).Methods("GET")
- r.Handle("/files/", Handle(
+
+ r.Handle("/api/files/", Handle(
files.Listing("hot"),
)).Methods("GET")
- r.Handle(`/files/{file:[a-zA-Z0-9=\-\/\s.,&_+]+}`, Handle(
+ r.Handle(`/api/files/{file:[a-zA-Z0-9=\-\/\s.,&_+]+}`, Handle(
files.Listing("hot"),
)).Methods("GET")
r.Handle(`/file/{file:[a-zA-Z0-9=\-\/\s.,&_+]+}`, Handle(
files.ViewFile("hot"),
)).Methods("GET")
- r.Handle("/upload", Handle(
+ r.Handle("/api/upload", Handle(
files.UploadFile(),
)).Methods("POST")
+ r.Handle(`/api/filesmd5/{file:[a-zA-Z0-9=\-\/\s.,&_+]+}`, Handle(
+ files.Md5File("hot"),
+ )).Methods("GET")
- r.Handle("/archive/", Handle(
+ r.Handle("/api/archive/", Handle(
files.Listing("cold"),
)).Methods("GET")
- r.Handle(`/archive/{file:[a-zA-Z0-9=\-\/\s.,&_+]+}`, Handle(
+ r.Handle(`/api/archive/{file:[a-zA-Z0-9=\-\/\s.,&_+]+}`, Handle(
files.Listing("cold"),
)).Methods("GET")
r.Handle(`/archived/{file:[a-zA-Z0-9=\-\/\s.,&_+]+}`, Handle(
files.ViewFile("cold"),
)).Methods("GET")
+ r.Handle(`/api/archivemd5/{file:[a-zA-Z0-9=\-\/\s.,&_+]+}`, Handle(
+ files.Md5File("cold"),
+ )).Methods("GET")
return r
}
@@ -84,6 +103,7 @@ func rootHandler() common.Handler {
case "/":
w.Header().Set("Content-Type", "text/html")
file = "assets/web/index.html"
+
default:
return &common.HTTPError{
Message: fmt.Sprintf("%s: Not Found", r.URL.Path),
@@ -95,8 +115,11 @@ func rootHandler() common.Handler {
}
}
-func adminHandler() common.Handler {
+func fileList() common.Handler {
return func(rc *common.RouterContext, w http.ResponseWriter, r *http.Request) *common.HTTPError {
- return common.ReadAndServeFile("assets/web/admin.html", w)
+ w.Header().Set("Content-Type", "text/html")
+ file := "assets/web/listing.html"
+
+ return common.ReadAndServeFile(file, w)
}
}
\ No newline at end of file
-
- {{$prefix}}/{{$path}}
+
- {{ if eq $prefix "files" }}
+
+