File manager mockup

This commit is contained in:
2018-07-09 23:19:16 +02:00
parent 9c7b79403e
commit 5d30b60f13
10 changed files with 138 additions and 85 deletions

View File

@@ -12,9 +12,9 @@ function createList(){
}
var url = "/api/list";
var postData = {};
var title = prompt(
"You are creating a list containing " + listfiles.length + " files.\n"
+ "What do you want to call it?", "My New Album"
@@ -29,13 +29,13 @@ function createList(){
"description": "yo",
"files": new Array()
};
for (var i = 0; i < listfiles.length; i++) {
postData.files.push({
"id": listfiles[i]
});
}
$.ajax({
url: url,
contentType: "application/json",
@@ -53,9 +53,9 @@ function listCreated(response){
+ "Your List URL: <br/>"
+ "<a href=\"/l/" + response.id + "\" target=\"_blank\" style=\"font-weight: bold;\">"+window.location.hostname+"/l/" + response.id + "</a>"
+ "</div>";
$('#uploads_queue').prepend(
$(resultString).hide().fadeIn('slow')
$(resultString).hide().fadeIn('slow').css("display", "")
);
window.open('/l/'+response.id, '_blank');
}else{
@@ -63,9 +63,9 @@ function listCreated(response){
+ "The server responded with this: <br/>"
+ response.type + ": " + response.value
+ "</div>";
$('#uploads_queue').prepend(
$(resultString).hide().fadeIn('slow')
$(resultString).hide().fadeIn('slow').css("display", "")
);
}
}
@@ -74,9 +74,9 @@ function listCreated(response){
// var fileDesc = $("#txtListDesc").val();
//
// addToList(fileId, fileDesc);
//
//
// divItems.prepend("ID: " + fileId + "<br>Description:<br>" + fileDesc + "<br><br>");
//
//
// $("#txtListId").val("");
// $("#txtListDesc").val("");
//});
//});

View File

@@ -133,14 +133,8 @@ hr{
::-webkit-scrollbar-thumb {background-color: #555;}
::-webkit-scrollbar-corner{background: transparent;}
a{
color: var(--highlight_color);
text-decoration: none;
}
a:hover{
text-decoration: underline;
color: var(--highlight_color);
}
a {color: var(--highlight_color); text-decoration: none;}
a:hover {color: var(--highlight_color); text-decoration: underline;}
.form{
margin-left: auto;
@@ -243,10 +237,13 @@ pre{
/* BUTTONS */
button,
.button,
input[type="submit"],
input[type="button"],
input[type="color"],
select{
display: inline-block;
box-sizing: border-box;
border-radius: 4px;
border: none;
margin: 2px;
@@ -254,24 +251,33 @@ select{
padding: 6px 10px 6px 10px;
box-shadow: 2px 2px 8px #000000;
font-weight: bold;
font-size: 0.85em;
line-height: 1;
text-decoration: none;
color: #FFFFFF;
outline: 0;
vertical-align: middle;
cursor: pointer;
}
button:hover,
.button:hover,
input[type="submit"]:hover,
input[type="button"]:hover,
input[type="color"]:hover,
select:hover,
button:focus,
.button:focus,
input[type="submit"]:focus,
input[type="button"]:focus,
input[type="color"]:focus,
select:focus{
color: #FFFFFF;
text-decoration: none;
box-shadow: var(--highlight_border), 2px 2px 8px #000000;
}
button:active,
.button:active,
input[type="submit"]:active,
input[type="button"]:active,
input[type="color"]:active,
@@ -291,6 +297,7 @@ option{background-color: #404040; color: #FFFFFF;}
/* TEXT FIELDS */
textarea,
.groove,
input[type="text"],
input[type="password"],
input[type="email"],

View File

@@ -3,20 +3,63 @@
<head>
{{template "meta_tags" "File Manager"}}
<script type="text/javascript">var apiEndpoint = '{{.APIEndpoint}}';</script>
<style>
.file_manager {
position: absolute;
padding: 0px 8px 0px 8px;
background-color: #252525;
box-shadow: #000000 8px 8px 50px 5px;
left:100px;
top:100px;
right: 100px;
min-width: 600px;
max-width: 1400px;
}
.file_manager > .nav_bar {
display: flex;
flex-direction: row
}
.file_manager > .nav_bar :first-child {margin-left: 5px;}
.file_manager > .nav_bar :last-child {margin-right: 5px;}
.file_manager > .nav_bar > button {flex: 0;}
.file_manager > .nav_bar > .breadcrumbs {flex: 1; margin: 1px 10px; min-width: 100px;}
.file_manager > .status_bar {text-align: left;}
.file_button {height: 40px !important;}
.file_button > img {max-height: 40px !important;}
</style>
</head>
<body>
{{template "menu" .}}
<br/>
{{range .Other.Files}}
<a class="file_button" href="/u/{{.ID}}" target="_blank">
<img src="{{$.APIEndpoint}}/file/{{.ID}}/thumbnail" alt="{{.FileName}}" />
<span style="color: var(--highlight_color);">{{.FileName}}</span>
<br/>
{{.DateUpload}}
</a>
{{end}}
<div class="file_manager">
<div class="nav_bar highlight_light border_top border_bottom">
<button></button>
<button></button>
<button style="margin-right: 16px;"></button>
<button>🏠</button>
<input class="breadcrumbs" type="text" value="/{{.Username}}/Documents"/>
<button></button>
<button>🔎</button>
<button style="margin-left: 16px;">_</button>
<button></button>
<button class="button_red"></button>
</div>
<div class="directory_area">
{{$files := .PixelAPI.UserFiles 0 20}}
{{range $files.Files}}
<a class="file_button" href="/u/{{.ID}}" target="_blank">
<img src="{{$.APIEndpoint}}/file/{{.ID}}/thumbnail" alt="{{.FileName}}" />
{{.FileName}}
</a>
{{end}}
</div>
<div class="status_bar highlight_light border_top border_bottom">
13 items (5 directories, 7 files). Total size: 1.23 GB
</div>
</div>
{{template "analytics"}}
</body>

View File

@@ -13,13 +13,13 @@
<link rel="shortcut icon" href="/res/img/tray32.png"/>
<link rel="icon" sizes="180x180" href="/res/img/pixeldrain.png"/>
<link rel="icon" sizes="256x256" href="/res/img/pixeldrain_big.png"/>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css"/>
<!-- <link rel="alternate" type="application/json+oembed" th:href="*{oEmbedHref}" th:title="*{ogTitle}" /> OEmbed will return soon -->
{{template "bgpattern"}}
<meta name="theme-color" content="#202020"/>
<meta name="twitter:image" content="{{.OGData.Image}}" />
<meta property="og:title" content="{{.OGData.Title}}" />
@@ -49,12 +49,10 @@
<!--Views: <span id="views" th:text="${data.views}">0</span>--><br/>
<form action="/" target="_self">
<button id="btnHome" class="toolbar_button button_full_width">
<img src="/res/img/pixeldrain_small.png" alt="Back to the Home page"/>
<span>Home</span>
</button>
</form>
<a href="/" id="btnHome" class="button toolbar_button button_full_width">
<img src="/res/img/pixeldrain_small.png" alt="Back to the Home page"/>
<span>Home</span>
</a>
<button id="btnDownload" class="toolbar_button button_full_width" onClick="Toolbar.download();">
<img src="/res/img/floppy_small.png" alt="Download this file"/>
@@ -77,8 +75,8 @@
</button>
<iframe id='sponsors' data-aa='73974'
src='//ad.a-ads.com/73974?size=120x600&amp;background_color=000000&amp;text_color=eeeeee&amp;title_color=eeeeee&amp;link_color=9fcf6c&amp;link_hover_color=d2ffa1&amp;title_hover_color=d2ffa1'
scrolling='no' allowtransparency='true' seamless="seamless">
src='//ad.a-ads.com/73974?size=120x600&amp;background_color=000000&amp;text_color=eeeeee&amp;title_color=eeeeee&amp;link_color=9fcf6c&amp;link_hover_color=d2ffa1&amp;title_hover_color=d2ffa1'
scrolling='no' allowtransparency='true' seamless="seamless">
</iframe>
<iframe id="frmDownload">
@@ -87,7 +85,7 @@
</div>
</div>
</div>
<div id="sharebar" class="sidebar">
Share on:<br/>
<button class="sharebar-button button_full_width" onclick="window.open('https://www.reddit.com/submit?url=' + window.location.href);">
@@ -125,20 +123,20 @@
</div>
<div id="info-popup" class="full-popup">
<img alt="Close" src="/res/img/cross.png"
<img alt="Close" src="/res/img/cross.png"
style="position: absolute; top: 5px; right: 5px; width: 40px; height: 40px; cursor: pointer;"
onclick="DetailsWindow.toggle();"/>
Click the help button again to close this overlay.<br/>
<h3>File Info</h3>
<span id="info-fileDetails"></span>
<span id="info-about">{{template "file_info_popup"}}</span>
</div>
<div id="filepreview">
Loading...
</div>
<script src="/res/script/jquery.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script src="/res/script/Keyboard.js"></script>
@@ -147,7 +145,7 @@
<script src="/res/script/DetailsWindow.js"></script>
<script src="/res/script/Viewer.js"></script>
<script src="/res/script/ListNavigator.js"></script>
<script>
// This info gets filled in on the server side to prevent having to make an API call right after the page loads.
// Just to slice another few milliseconds from the load time :)
@@ -157,4 +155,4 @@
{{template "analytics"}}
</body>
</html>
{{end}}
{{end}}

View File

@@ -36,7 +36,7 @@
The Sia integration is still very experimental and could
fail, resulting in data loss. Do not upload files to this server
that you cannot afford to lose. Use the stable main server instead:
<a href="https://pixeldrain.com">https://pixeldrain.com</a>.
<a class="button" href="https://pixeldrain.com">https://pixeldrain.com</a>.
</p>
<p>
But don't let all that stop you from trying the new Pixeldrain!

View File

@@ -30,11 +30,10 @@
<img src="/res/img/upload_small.png" alt="Start Upload"/>
<span>Upload</span>
</button>
<form action="/">
<button class="toolbar_button button_full_width">
<a href="/" class="button toolbar_button button_full_width">
<img src="/res/img/pixeldrain_small.png" alt="Visit the home page" style="width:22px; height: 22px;"/>
<span>Home</span>
</button>
</a>
</form>
<iframe id='sponsors' data-aa='73974'
src='//ad.a-ads.com/73974?size=120x600&amp;background_color=000000&amp;text_color=eeeeee&amp;title_color=eeeeee&amp;link_color=9fcf6c&amp;link_hover_color=d2ffa1&amp;title_hover_color=d2ffa1'

View File

@@ -23,21 +23,21 @@ func (wc *WebController) serveFilePreview(w http.ResponseWriter, r *http.Request
serveFilePreviewDemo(w) // Required for a-ads.com quality check
return
}
inf, err := wc.api.GetFileInfo(p.ByName("id")) // TODO: Error handling
var api = pixelapi.New(wc.conf.APIURLInternal, "")
inf, err := api.GetFileInfo(p.ByName("id")) // TODO: Error handling
if err != nil {
wc.serveNotFound(w, r)
return
}
var fp = FilePreview{
var fp = filePreview{
APIURL: wc.conf.APIURLExternal,
PixelAPI: wc.api,
PixelAPI: api,
}
io.WriteString(w, fp.Run(inf))
io.WriteString(w, fp.run(inf))
}
type FilePreview struct {
type filePreview struct {
FileInfo *pixelapi.FileInfo
FileURL string
DownloadURL string
@@ -46,7 +46,7 @@ type FilePreview struct {
PixelAPI *pixelapi.PixelAPI
}
func (f FilePreview) Run(inf *pixelapi.FileInfo) string {
func (f filePreview) run(inf *pixelapi.FileInfo) string {
f.FileInfo = inf
f.FileURL = f.APIURL + "/file/" + f.FileInfo.ID
f.DownloadURL = f.APIURL + "/file/" + f.FileInfo.ID + "/download"
@@ -92,7 +92,7 @@ func (f FilePreview) Run(inf *pixelapi.FileInfo) string {
return f.def()
}
func (f FilePreview) image() string {
func (f filePreview) image() string {
return fmt.Sprintf(`<div class="image-container">
<img id="displayImg" src="%s" class="pannable drop-shadow"/>
</div>
@@ -100,7 +100,7 @@ func (f FilePreview) image() string {
f.FileURL)
}
func (f FilePreview) audio() string {
func (f filePreview) audio() string {
return fmt.Sprintf(`<div class="image-container">
<br/><br/>
<img src="/res/img/mime/audio.png" alt="Audio"/>
@@ -115,7 +115,7 @@ func (f FilePreview) audio() string {
)
}
func (f FilePreview) video() string {
func (f filePreview) video() string {
return fmt.Sprintf(`<div class="image-container">
<video id="videoPlayer" autoplay="autoplay" controls="controls" class="center drop-shadow">
<source src="%s"/>
@@ -128,12 +128,12 @@ Your web browser does not support the HTML video tag.
}
func (f FilePreview) pdf() string {
func (f filePreview) pdf() string {
u, _ := url.Parse(f.FileURL)
return f.frame("/res/misc/pdf-viewer/web/viewer.html?file=" + u.String())
}
func (f FilePreview) text() string {
func (f filePreview) text() string {
htmlOut := `<div class="text-container">
<pre class="pre-container %s" style="width: 100%%;">%s</pre>
</div>`
@@ -180,7 +180,7 @@ func (f FilePreview) text() string {
return fmt.Sprintf(htmlOut, prettyPrint, result)
}
func (f FilePreview) frame(url string) string {
func (f filePreview) frame(url string) string {
return fmt.Sprintf(`<iframe src="%s" class="image-container"
seamless="seamless" frameborder="0" allowtransparency="true"
</iframe>`,
@@ -188,7 +188,7 @@ seamless="seamless" frameborder="0" allowtransparency="true"
)
}
func (f FilePreview) def() string {
func (f filePreview) def() string {
return fmt.Sprintf(
`%s<br/>%s<br/><a href="%s"><img src="%s" class="image"></a>`,
f.FileInfo.FileName,

View File

@@ -26,9 +26,10 @@ func (wc *WebController) serveFileViewer(w http.ResponseWriter, r *http.Request,
ids = append(ids, p.ByName("id"))
}
var api = pixelapi.New(wc.conf.APIURLInternal, "")
var finfo []*pixelapi.FileInfo
for _, id := range ids {
inf, err := wc.api.GetFileInfo(id)
inf, err := api.GetFileInfo(id)
if err != nil {
continue
}

View File

@@ -12,7 +12,8 @@ import (
// ServeListViewer controller for GET /l/:id
func (wc *WebController) serveListViewer(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
var list, err = wc.api.GetList(p.ByName("id"))
var api = pixelapi.New(wc.conf.APIURLInternal, "")
var list, err = api.GetList(p.ByName("id"))
if err != nil {
if (err.(pixelapi.Error)).ReqError {
log.Error("API request error occurred: %s", (err.(pixelapi.Error)).Value)

View File

@@ -7,25 +7,26 @@ import (
"github.com/google/uuid"
"fornaxian.com/pixeldrain-web/init/conf"
"fornaxian.com/pixeldrain-web/pixelapi"
"fornaxian.com/pixeldrain-web/webcontroller/templates"
"github.com/Fornaxian/log"
"github.com/julienschmidt/httprouter"
)
// WebController controls how requests are handled and makes sure they have
// proper context when running
type WebController struct {
conf *conf.PixelWebConfig
api *pixelapi.PixelAPI // Shared instance, only used for unauthenticated requests
templates *templates.TemplateManager
staticResourceDir string
}
// New initializes a new WebController by registering all the request handlers
// and parsing all templates in the resource directory
func New(r *httprouter.Router, prefix string, conf *conf.PixelWebConfig) *WebController {
var wc = &WebController{
conf: conf,
staticResourceDir: conf.StaticResourceDir,
}
wc.api = pixelapi.New(conf.APIURLInternal, "")
wc.templates = templates.New(
conf.TemplateDir,
conf.APIURLExternal,
@@ -36,22 +37,25 @@ func New(r *httprouter.Router, prefix string, conf *conf.PixelWebConfig) *WebCon
// Serve static files
r.ServeFiles(prefix+"/res/*filepath", http.Dir(wc.staticResourceDir+"/res"))
r.GET(prefix+"/" /* */, wc.serveTemplate("home", false))
r.GET(prefix+"/favicon.ico" /* */, wc.serveFile("/favicon.ico"))
r.GET(prefix+"/global.css" /* */, wc.globalCSSHandler)
r.GET(prefix+"/api" /* */, wc.serveTemplate("apidoc", false))
r.GET(prefix+"/history" /* */, wc.serveTemplate("history_cookies", false))
r.GET(prefix+"/u/:id" /* */, wc.serveFileViewer)
r.GET(prefix+"/u/:id/preview" /**/, wc.serveFilePreview)
r.GET(prefix+"/l/:id" /* */, wc.serveListViewer)
r.GET(prefix+"/t" /* */, wc.serveTemplate("paste", false))
// General navigation
r.GET(prefix+"/" /* */, wc.serveTemplate("home", false))
r.GET(prefix+"/favicon.ico" /* */, wc.serveFile("/favicon.ico"))
r.GET(prefix+"/global.css" /* */, wc.globalCSSHandler)
r.GET(prefix+"/api" /* */, wc.serveTemplate("apidoc", false))
r.GET(prefix+"/history" /* */, wc.serveTemplate("history_cookies", false))
r.GET(prefix+"/u/:id" /* */, wc.serveFileViewer)
r.GET(prefix+"/u/:id/preview" /* */, wc.serveFilePreview)
r.GET(prefix+"/l/:id" /* */, wc.serveListViewer)
r.GET(prefix+"/t" /* */, wc.serveTemplate("paste", false))
r.GET(prefix+"/register" /* */, wc.serveTemplate("register", false))
r.GET(prefix+"/login" /* */, wc.serveTemplate("login", false))
r.GET(prefix+"/logout" /* */, wc.serveTemplate("logout", true))
r.POST(prefix+"/logout" /* */, wc.serveLogout)
r.GET(prefix+"/user" /* */, wc.serveTemplate("user_home", true))
r.GET(prefix+"/user/files" /* */, wc.serveTemplate("user_files", true))
// User account pages
r.GET(prefix+"/register" /* */, wc.serveTemplate("register", false))
r.GET(prefix+"/login" /* */, wc.serveTemplate("login", false))
r.GET(prefix+"/logout" /* */, wc.serveTemplate("logout", true))
r.POST(prefix+"/logout" /* */, wc.serveLogout)
r.GET(prefix+"/user" /* */, wc.serveTemplate("user_home", true))
r.GET(prefix+"/user/files" /* */, wc.serveTemplate("user_files", true))
r.GET(prefix+"/user/filemanager" /**/, wc.serveTemplate("file_manager", true))
r.NotFound = http.HandlerFunc(wc.serveNotFound)