albums: basic support (json array using contented/album mime-type)
This commit is contained in:
parent
156e2ab540
commit
4294738337
@ -22,6 +22,8 @@ var SERVER_HEADER string = `contented/0.0.0-dev`
|
|||||||
|
|
||||||
const DEFAULT_MAX_CONCURRENT_THUMBS = 16
|
const DEFAULT_MAX_CONCURRENT_THUMBS = 16
|
||||||
|
|
||||||
|
const ALBUM_MIMETYPE = `contented/album`
|
||||||
|
|
||||||
type ServerPublicProperties struct {
|
type ServerPublicProperties struct {
|
||||||
AppTitle string
|
AppTitle string
|
||||||
MaxUploadBytes int64
|
MaxUploadBytes int64
|
||||||
|
58
preview.go
58
preview.go
@ -1,11 +1,13 @@
|
|||||||
package contented
|
package contented
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html"
|
"html"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -56,6 +58,19 @@ html, body {
|
|||||||
line-height: 0;
|
line-height: 0;
|
||||||
width: 340px;
|
width: 340px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.thumbnail-overlay {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 4px;
|
||||||
|
right: 4px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
line-height: 1.5em;
|
||||||
|
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
background: red;
|
||||||
|
color: white;
|
||||||
}
|
}
|
||||||
.properties {
|
.properties {
|
||||||
background: #000;
|
background: #000;
|
||||||
@ -82,6 +97,48 @@ html, body {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if m.MimeType == ALBUM_MIMETYPE {
|
||||||
|
// Special handling for albums
|
||||||
|
f, err := os.Open(filepath.Join(this.opts.DataDirectory, m.FileHash))
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Opening file '%s' for preview of album '%s': %s", m.FileHash, fileID, err.Error())
|
||||||
|
http.Error(w, "Internal error", 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var childIDs []string
|
||||||
|
err = json.NewDecoder(f).Decode(&childIDs)
|
||||||
|
f.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed to parse album '%s': %s", fileID, err)
|
||||||
|
http.Error(w, "Internal error", 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(childIDs) == 0 {
|
||||||
|
log.Printf("Failed to parse album '%s': no entries in album", fileID)
|
||||||
|
http.Error(w, "Internal error", 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpl += `
|
||||||
|
<div class="entry">
|
||||||
|
<div class="thumbnail">
|
||||||
|
<a href="` + html.EscapeString(`/p/`+strings.Join(childIDs, `-`)) + `"><img src="` + html.EscapeString(`/thumb/m/`+childIDs[0]) + `"></a>
|
||||||
|
<div class="thumbnail-overlay">` + fmt.Sprintf("%d", len(childIDs)) + ` image(s)</div>
|
||||||
|
</div>
|
||||||
|
<div class="properties">
|
||||||
|
<b>Name:</b> ` + html.EscapeString(m.Filename) + `<br>
|
||||||
|
<b>Hash:</b> <span title="` + html.EscapeString(m.FileHash) + `">hover</span><br>
|
||||||
|
<b>File type:</b> Album<br>
|
||||||
|
<b>Size:</b> ` + fmt.Sprintf("%d", len(childIDs)) + ` image(s)<br>
|
||||||
|
<b>Uploader:</b> ` + html.EscapeString(m.UploadIP) + `<br>
|
||||||
|
<b>Uploaded at:</b> ` + html.EscapeString(m.UploadTime.Format(time.RFC3339)) + `<br>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
|
||||||
|
} else {
|
||||||
tmpl += `
|
tmpl += `
|
||||||
<div class="entry">
|
<div class="entry">
|
||||||
<div class="thumbnail">
|
<div class="thumbnail">
|
||||||
@ -98,6 +155,7 @@ html, body {
|
|||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if this.opts.EnableHomepage {
|
if this.opts.EnableHomepage {
|
||||||
tmpl += `
|
tmpl += `
|
||||||
|
@ -178,6 +178,12 @@
|
|||||||
<path fill="#000000" d="M16.84,2.73C16.45,2.73 16.07,2.88 15.77,3.17L13.65,5.29L18.95,10.6L21.07,8.5C21.67,7.89 21.67,6.94 21.07,6.36L17.9,3.17C17.6,2.88 17.22,2.73 16.84,2.73M12.94,6L4.84,14.11L7.4,14.39L7.58,16.68L9.86,16.85L10.15,19.41L18.25,11.3M4.25,15.04L2.5,21.73L9.2,19.94L8.96,17.78L6.65,17.61L6.47,15.29" />
|
<path fill="#000000" d="M16.84,2.73C16.45,2.73 16.07,2.88 15.77,3.17L13.65,5.29L18.95,10.6L21.07,8.5C21.67,7.89 21.67,6.94 21.07,6.36L17.9,3.17C17.6,2.88 17.22,2.73 16.84,2.73M12.94,6L4.84,14.11L7.4,14.39L7.58,16.68L9.86,16.85L10.15,19.41L18.25,11.3M4.25,15.04L2.5,21.73L9.2,19.94L8.96,17.78L6.65,17.61L6.47,15.29" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="contented-upload-type" data-upload-type="album" title="Album">
|
||||||
|
<svg viewBox="0 0 24 24">
|
||||||
|
<path fill="#000000" d="M3,3H21V7H3V3M4,8H20V21H4V8M9.5,11A0.5,0.5 0 0,0 9,11.5V13H15V11.5A0.5,0.5 0 0,0 14.5,11H9.5Z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="contented-content-area">
|
<div class="contented-content-area">
|
||||||
@ -204,6 +210,15 @@
|
|||||||
<label>...</label>
|
<label>...</label>
|
||||||
<div class="contented-progress-bar"><div class="contented-progress-element"></div></div>
|
<div class="contented-progress-bar"><div class="contented-progress-element"></div></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="contented-upload-if contented-if-album">
|
||||||
|
<label>
|
||||||
|
Type a list of short IDs, separated with commas:<br>
|
||||||
|
<input class="contented-album-input" type="text">
|
||||||
|
</label>
|
||||||
|
<br><br>
|
||||||
|
<button class="contented-album-upload">Make album »</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
@ -307,6 +322,32 @@
|
|||||||
handleUploadFrom([blob]);
|
handleUploadFrom([blob]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Album
|
||||||
|
|
||||||
|
$f.find(".contented-album-upload").on("click", function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
var childIDs = $(".contented-album-input").val().split(",");
|
||||||
|
|
||||||
|
for (var i = 0; i < childIDs.length; ++i) {
|
||||||
|
childIDs[i] = childIDs[i].trim(); // Basic validation - can't really perform full validation here
|
||||||
|
|
||||||
|
if (childIDs[i].length == 0) {
|
||||||
|
alert("Entry " + (i+1) + " is too short, expected non-zero length");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! childIDs[i].match(/^[a-zA-Z0-9]+$/)) {
|
||||||
|
alert("Entry " + (i+1) + " contains unexpected character");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var blob = new Blob([JSON.stringify(childIDs)], {type : 'contented/album'});
|
||||||
|
handleUploadFrom([blob]);
|
||||||
|
});
|
||||||
|
|
||||||
// Ctrl+V uploads
|
// Ctrl+V uploads
|
||||||
|
|
||||||
var pasteHandler = function(e) {
|
var pasteHandler = function(e) {
|
||||||
|
Loading…
Reference in New Issue
Block a user