Improved file upload
This commit is contained in:
parent
42c72b6174
commit
1ecc3e3fa4
@ -43,10 +43,10 @@ component InputSelection(id string, value string, label string, placeholder stri
|
|||||||
each option in options
|
each option in options
|
||||||
option(value=option.Value)= option.Label
|
option(value=option.Value)= option.Label
|
||||||
|
|
||||||
component InputImage(id string, label string, endpoint string)
|
component InputFileUpload(id string, label string, uploadType string, endpoint string)
|
||||||
.widget-section
|
.widget-section
|
||||||
label(for=id)= label + ":"
|
label(for=id)= label + ":"
|
||||||
button.action(data-action="selectFile", data-trigger="click", data-preview-image-id=id + "-preview", data-endpoint=endpoint)
|
button.action(id=id, data-action="selectFile", data-trigger="click", data-endpoint=endpoint, data-type=uploadType)
|
||||||
Icon("upload")
|
Icon("upload")
|
||||||
span Select file
|
span Select file
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ component EditAnimeImages(anime *arn.Anime)
|
|||||||
Icon("picture-o")
|
Icon("picture-o")
|
||||||
span Image
|
span Image
|
||||||
|
|
||||||
InputImage("anime-image-input", "File", "/api/upload/anime/" + anime.ID + "/image")
|
InputFileUpload("anime-image-input", "File", "image", "/api/upload/anime/" + anime.ID + "/image")
|
||||||
|
|
||||||
.anime-image-container
|
.anime-image-container
|
||||||
img#anime-image-input-preview.anime-cover-image.lazy(data-src=anime.ImageLink("large"), data-webp="true", data-color=anime.AverageColor(), alt="Anime image")
|
img#anime-image-input-preview.anime-cover-image.lazy(data-src=anime.ImageLink("large"), data-webp="true", data-color=anime.AverageColor(), alt="Anime image")
|
@ -55,7 +55,7 @@ component SettingsPersonal(user *arn.User)
|
|||||||
//- //- File upload
|
//- //- File upload
|
||||||
//- if user.Settings().Avatar.Source == "FileSystem"
|
//- if user.Settings().Avatar.Source == "FileSystem"
|
||||||
|
|
||||||
InputImage("avatar-input", "File", "/api/upload/avatar")
|
InputFileUpload("avatar-input", "File", "image", "/api/upload/avatar")
|
||||||
|
|
||||||
.profile-image-container.avatar-preview
|
.profile-image-container.avatar-preview
|
||||||
if user.HasAvatar()
|
if user.HasAvatar()
|
||||||
@ -71,7 +71,7 @@ component SettingsPersonal(user *arn.User)
|
|||||||
Icon("picture-o")
|
Icon("picture-o")
|
||||||
span Cover
|
span Cover
|
||||||
|
|
||||||
InputImage("cover-input", "File", "/api/upload/cover")
|
InputFileUpload("cover-input", "File", "image", "/api/upload/cover")
|
||||||
|
|
||||||
.cover-preview(title="Recommended: 1920 x 450 | PNG or JPG")
|
.cover-preview(title="Recommended: 1920 x 450 | PNG or JPG")
|
||||||
img#cover-input-preview.profile-cover.lazy(data-src=user.CoverLink("small"), data-webp="true", alt="Cover image")
|
img#cover-input-preview.profile-cover.lazy(data-src=user.CoverLink("small"), data-webp="true", alt="Cover image")
|
||||||
|
@ -8,7 +8,7 @@ export function selectFile(arn: AnimeNotifier, button: HTMLButtonElement) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let preview = document.getElementById(button.dataset.previewImageId) as HTMLImageElement
|
let fileType = button.dataset.type
|
||||||
let endpoint = button.dataset.endpoint
|
let endpoint = button.dataset.endpoint
|
||||||
|
|
||||||
// Click on virtual file input element
|
// Click on virtual file input element
|
||||||
@ -22,18 +22,64 @@ export function selectFile(arn: AnimeNotifier, button: HTMLButtonElement) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!file.type.startsWith("image/")) {
|
// Check mime type for images
|
||||||
|
if(fileType === "image" && !file.type.startsWith("image/")) {
|
||||||
arn.statusMessage.showError(file.name + " is not an image file!")
|
arn.statusMessage.showError(file.name + " is not an image file!")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check mime type for videos
|
||||||
|
if(fileType === "video" && !file.type.startsWith("video/webm")) {
|
||||||
|
arn.statusMessage.showError(file.name + " is not a WebM video file!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preview image
|
||||||
|
if(fileType === "image") {
|
||||||
|
let preview = document.getElementById(button.id + "-preview") as HTMLImageElement
|
||||||
|
|
||||||
|
if(preview) {
|
||||||
previewImage(file, endpoint, preview)
|
previewImage(file, endpoint, preview)
|
||||||
uploadFile(file, endpoint, arn)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadFile(file, fileType, endpoint, arn)
|
||||||
}
|
}
|
||||||
|
|
||||||
input.click()
|
input.click()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Upload file
|
||||||
|
function uploadFile(file: File, fileType: string, endpoint: string, arn: AnimeNotifier) {
|
||||||
|
let reader = new FileReader()
|
||||||
|
|
||||||
|
reader.onloadend = async () => {
|
||||||
|
arn.statusMessage.showInfo(`Uploading ${fileType}...`, 60000)
|
||||||
|
|
||||||
|
let response = await fetch(endpoint, {
|
||||||
|
method: "POST",
|
||||||
|
credentials: "include",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/octet-stream"
|
||||||
|
},
|
||||||
|
body: reader.result
|
||||||
|
})
|
||||||
|
|
||||||
|
if(endpoint === "/api/upload/avatar") {
|
||||||
|
let newURL = await response.text()
|
||||||
|
updateSideBarAvatar(newURL)
|
||||||
|
}
|
||||||
|
|
||||||
|
if(response.ok) {
|
||||||
|
arn.statusMessage.showInfo(`Successfully uploaded your new ${fileType}.`)
|
||||||
|
} else {
|
||||||
|
arn.statusMessage.showError(`Failed uploading your new ${fileType}.`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.readAsArrayBuffer(file)
|
||||||
|
}
|
||||||
|
|
||||||
// Preview image
|
// Preview image
|
||||||
function previewImage(file: File, endpoint: string, preview: HTMLImageElement) {
|
function previewImage(file: File, endpoint: string, preview: HTMLImageElement) {
|
||||||
let reader = new FileReader()
|
let reader = new FileReader()
|
||||||
@ -54,37 +100,6 @@ function previewImage(file: File, endpoint: string, preview: HTMLImageElement) {
|
|||||||
reader.readAsDataURL(file)
|
reader.readAsDataURL(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upload file
|
|
||||||
function uploadFile(file: File, endpoint: string, arn: AnimeNotifier) {
|
|
||||||
let reader = new FileReader()
|
|
||||||
|
|
||||||
reader.onloadend = async () => {
|
|
||||||
arn.statusMessage.showInfo("Uploading image...", 60000)
|
|
||||||
|
|
||||||
let response = await fetch(endpoint, {
|
|
||||||
method: "POST",
|
|
||||||
credentials: "include",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/octet-stream"
|
|
||||||
},
|
|
||||||
body: reader.result
|
|
||||||
})
|
|
||||||
|
|
||||||
if(endpoint === "/api/upload/avatar") {
|
|
||||||
let newURL = await response.text()
|
|
||||||
updateSideBarAvatar(newURL)
|
|
||||||
}
|
|
||||||
|
|
||||||
if(response.ok) {
|
|
||||||
arn.statusMessage.showInfo("Successfully uploaded your new image.")
|
|
||||||
} else {
|
|
||||||
arn.statusMessage.showError("Failed uploading your new image.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.readAsArrayBuffer(file)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update sidebar avatar
|
// Update sidebar avatar
|
||||||
function updateSideBarAvatar(url: string) {
|
function updateSideBarAvatar(url: string) {
|
||||||
let sidebar = document.getElementById("sidebar")
|
let sidebar = document.getElementById("sidebar")
|
||||||
|
@ -120,7 +120,7 @@ func RenderField(b *bytes.Buffer, v *reflect.Value, field reflect.StructField, i
|
|||||||
// Try to infer the ID type by the field name
|
// Try to infer the ID type by the field name
|
||||||
if idType == "" {
|
if idType == "" {
|
||||||
switch field.Name {
|
switch field.Name {
|
||||||
case "AnimeID", "MainAnimeID":
|
case "AnimeID":
|
||||||
idType = "Anime"
|
idType = "Anime"
|
||||||
|
|
||||||
case "CharacterID":
|
case "CharacterID":
|
||||||
@ -141,6 +141,8 @@ func RenderField(b *bytes.Buffer, v *reflect.Value, field reflect.StructField, i
|
|||||||
b.WriteString(components.InputSelection(idPrefix+field.Name, fieldValue.String(), field.Name, field.Tag.Get("tooltip"), values))
|
b.WriteString(components.InputSelection(idPrefix+field.Name, fieldValue.String(), field.Name, field.Tag.Get("tooltip"), values))
|
||||||
} else if field.Tag.Get("type") == "textarea" {
|
} else if field.Tag.Get("type") == "textarea" {
|
||||||
b.WriteString(components.InputTextArea(idPrefix+field.Name, fieldValue.String(), field.Name, field.Tag.Get("tooltip")))
|
b.WriteString(components.InputTextArea(idPrefix+field.Name, fieldValue.String(), field.Name, field.Tag.Get("tooltip")))
|
||||||
|
} else if field.Tag.Get("type") == "upload" {
|
||||||
|
b.WriteString(components.InputFileUpload(idPrefix+field.Name, field.Name, field.Tag.Get("filetype"), field.Tag.Get("endpoint")))
|
||||||
} else {
|
} else {
|
||||||
b.WriteString(components.InputText(idPrefix+field.Name, fieldValue.String(), field.Name, field.Tag.Get("tooltip")))
|
b.WriteString(components.InputText(idPrefix+field.Name, fieldValue.String(), field.Name, field.Tag.Get("tooltip")))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user