Added status messages

This commit is contained in:
Eduard Urbach 2017-07-12 20:37:34 +02:00
parent ab938e804c
commit 9d309b2e8c
9 changed files with 124 additions and 48 deletions

View File

@ -90,6 +90,10 @@ func InstallGoogleAuth(app *aero.Application) {
return ctx.Error(http.StatusBadRequest, "Failed parsing user data (JSON)", err) return ctx.Error(http.StatusBadRequest, "Failed parsing user data (JSON)", err)
} }
if googleUser.Sub == "" {
return ctx.Error(http.StatusBadRequest, "Failed retrieving Google data", errors.New("Empty ID"))
}
// Change googlemail.com to gmail.com // Change googlemail.com to gmail.com
googleUser.Email = strings.Replace(googleUser.Email, "googlemail.com", "gmail.com", 1) googleUser.Email = strings.Replace(googleUser.Email, "googlemail.com", "gmail.com", 1)

View File

@ -25,10 +25,17 @@ component Layout(app *aero.Application, ctx *aero.Context, user *arn.User, openG
#content-container #content-container
main#content.fade!= content main#content.fade!= content
LoadingAnimation LoadingAnimation
StatusMessage
if user != nil if user != nil
#user(data-id=user.ID) #user(data-id=user.ID)
script(src="/scripts") script(src="/scripts")
component StatusMessage
#status-message.fade.fade-out
#status-message-text
a.status-message-action.action(href="#", data-trigger="click", data-action="closeStatusMessage")
RawIcon("close")
component LoadingAnimation component LoadingAnimation
#loading.sk-cube-grid.fade #loading.sk-cube-grid.fade
.sk-cube.hide .sk-cube.hide

View File

@ -33,18 +33,18 @@ component Postable(post arn.Postable, user *arn.User, highlightAuthorID string)
if user.ID != post.Author().ID if user.ID != post.Author().ID
if post.LikedBy(user.ID) if post.LikedBy(user.ID)
a.post-tool.post-unlike.action(id="unlike-" + post.ID(), title="Unlike", data-action="unlike", data-trigger="click") a.post-tool.post-unlike.action(id="unlike-" + post.ID(), title="Unlike", data-action="unlike", data-trigger="click")
RawIcon("thumbs-down") Icon("thumbs-down")
else else
a.post-tool.post-like.action(id="like-" + post.ID(), title="Like", data-action="like", data-trigger="click") a.post-tool.post-like.action(id="like-" + post.ID(), title="Like", data-action="like", data-trigger="click")
RawIcon("thumbs-up") Icon("thumbs-up")
if user.ID == post.Author().ID if user.ID == post.Author().ID
a.post-tool.post-edit.action(data-action="editPost", data-trigger="click", data-id=post.ID(), title="Edit") a.post-tool.post-edit.action(data-action="editPost", data-trigger="click", data-id=post.ID(), title="Edit")
RawIcon("pencil") Icon("pencil")
if post.Type() != "Thread" if post.Type() != "Thread"
a.post-tool.post-permalink.ajax(href=post.Link(), title="Permalink") a.post-tool.post-permalink.ajax(href=post.Link(), title="Permalink")
RawIcon("link") Icon("link")
//- if type === "Messages" && user && (user.ID === post.authorId || user.ID === post.recipientId) //- if type === "Messages" && user && (user.ID === post.authorId || user.ID === post.recipientId)
//- a.post-tool.post-delete(onclick=`if(confirm("Do you really want to delete this ${typeSingular.toLowerCase()} from ${post.author.nick}?")) $.delete${typeSingular}("${post.ID}")`, title="Delete") //- a.post-tool.post-delete(onclick=`if(confirm("Do you really want to delete this ${typeSingular.toLowerCase()} from ${post.author.nick}?")) $.delete${typeSingular}("${post.ID}")`, title="Delete")

View File

@ -1,40 +1,43 @@
package main package main
// This patch is disabled because it would be dangerous to run it accidentally. import (
"github.com/animenotifier/arn"
"github.com/fatih/color"
)
func main() { func main() {
// color.Yellow("Deleting private user data") color.Yellow("Deleting private user data")
// // Get a stream of all users // Get a stream of all users
// allUsers, err := arn.StreamUsers() allUsers, err := arn.StreamUsers()
// if err != nil { if err != nil {
// panic(err) panic(err)
// } }
// arn.DB.DeleteTable("EmailToUser") arn.DB.DeleteTable("EmailToUser")
// arn.DB.DeleteTable("GoogleToUser") arn.DB.DeleteTable("GoogleToUser")
// // Iterate over the stream // Iterate over the stream
// count := 0 count := 0
// for user := range allUsers { for user := range allUsers {
// count++ count++
// println(count, user.Nick) println(count, user.Nick)
// // Delete private data // Delete private data
// user.Email = "" user.Email = ""
// user.Gender = "" user.Gender = ""
// user.FirstName = "" user.FirstName = ""
// user.LastName = "" user.LastName = ""
// user.IP = "" user.IP = ""
// user.Accounts.Facebook.ID = "" user.Accounts.Facebook.ID = ""
// user.Accounts.Google.ID = "" user.Accounts.Google.ID = ""
// user.AgeRange = arn.UserAgeRange{} user.AgeRange = arn.UserAgeRange{}
// user.Location = arn.UserLocation{} user.Location = arn.UserLocation{}
// // Save in DB // Save in DB
// user.Save() user.Save()
// } }
// color.Green("Finished.") color.Green("Finished.")
} }

View File

@ -40,7 +40,7 @@ export function save(arn: AnimeNotifier, input: HTMLInputElement | HTMLTextAreaE
throw body throw body
} }
}) })
.catch(console.error) .catch(err => arn.statusMessage.showError(err))
.then(() => { .then(() => {
arn.loading(false) arn.loading(false)
@ -54,6 +54,11 @@ export function save(arn: AnimeNotifier, input: HTMLInputElement | HTMLTextAreaE
}) })
} }
// Close status message
export function closeStatusMessage(arn: AnimeNotifier) {
arn.statusMessage.close()
}
// Load // Load
export function load(arn: AnimeNotifier, element: HTMLElement) { export function load(arn: AnimeNotifier, element: HTMLElement) {
let url = element.dataset.url || (element as HTMLAnchorElement).getAttribute("href") let url = element.dataset.url || (element as HTMLAnchorElement).getAttribute("href")
@ -112,7 +117,7 @@ export function savePost(arn: AnimeNotifier, element: HTMLElement) {
arn.post(apiEndpoint, updates) arn.post(apiEndpoint, updates)
.then(() => arn.reloadContent()) .then(() => arn.reloadContent())
.catch(console.error) .catch(err => arn.statusMessage.showError(err))
} }
// like // like
@ -121,7 +126,7 @@ export function like(arn: AnimeNotifier, element: HTMLElement) {
arn.post(apiEndpoint + "/like", null) arn.post(apiEndpoint + "/like", null)
.then(() => arn.reloadContent()) .then(() => arn.reloadContent())
.catch(console.error) .catch(err => arn.statusMessage.showError(err))
} }
// unlike // unlike
@ -130,7 +135,7 @@ export function unlike(arn: AnimeNotifier, element: HTMLElement) {
arn.post(apiEndpoint + "/unlike", null) arn.post(apiEndpoint + "/unlike", null)
.then(() => arn.reloadContent()) .then(() => arn.reloadContent())
.catch(console.error) .catch(err => arn.statusMessage.showError(err))
} }
// Forum reply // Forum reply
@ -147,7 +152,7 @@ export function forumReply(arn: AnimeNotifier) {
arn.post("/api/new/post", post) arn.post("/api/new/post", post)
.then(() => arn.reloadContent()) .then(() => arn.reloadContent())
.then(() => textarea.value = "") .then(() => textarea.value = "")
.catch(console.error) .catch(err => arn.statusMessage.showError(err))
} }
// Create thread // Create thread
@ -164,7 +169,7 @@ export function createThread(arn: AnimeNotifier) {
arn.post("/api/new/thread", thread) arn.post("/api/new/thread", thread)
.then(() => arn.app.load("/forum/" + thread.tags[0])) .then(() => arn.app.load("/forum/" + thread.tags[0]))
.catch(console.error) .catch(err => arn.statusMessage.showError(err))
} }
// Create soundtrack // Create soundtrack
@ -180,15 +185,9 @@ export function createSoundTrack(arn: AnimeNotifier, button: HTMLButtonElement)
tags: [anime.value, osu.value], tags: [anime.value, osu.value],
} }
button.innerText = "Adding..."
button.disabled = true
arn.post("/api/new/soundtrack", soundtrack) arn.post("/api/new/soundtrack", soundtrack)
.then(() => arn.app.load("/music")) .then(() => arn.app.load("/music"))
.catch(err => { .catch(err => arn.statusMessage.showError(err))
console.error(err)
arn.reloadContent()
})
} }
// Search // Search
@ -250,7 +249,7 @@ export function addAnimeToCollection(arn: AnimeNotifier, button: HTMLElement) {
return arn.reloadContent() return arn.reloadContent()
}) })
.catch(console.error) .catch(err => arn.statusMessage.showError(err))
.then(() => arn.loading(false)) .then(() => arn.loading(false))
} }
@ -274,7 +273,7 @@ export function removeAnimeFromCollection(arn: AnimeNotifier, button: HTMLElemen
return arn.app.load("/+" + userNick + "/animelist") return arn.app.load("/+" + userNick + "/animelist")
}) })
.catch(console.error) .catch(err => arn.statusMessage.showError(err))
.then(() => arn.loading(false)) .then(() => arn.loading(false))
} }

View File

@ -3,6 +3,7 @@ import { Diff } from "./Diff"
import { displayAiringDate, displayDate } from "./DateView" import { displayAiringDate, displayDate } from "./DateView"
import { findAll, delay, canUseWebP } from "./Utils" import { findAll, delay, canUseWebP } from "./Utils"
import { MutationQueue } from "./MutationQueue" import { MutationQueue } from "./MutationQueue"
import { StatusMessage } from "./StatusMessage"
import * as actions from "./Actions" import * as actions from "./Actions"
export class AnimeNotifier { export class AnimeNotifier {
@ -10,6 +11,7 @@ export class AnimeNotifier {
user: HTMLElement user: HTMLElement
title: string title: string
webpEnabled: boolean webpEnabled: boolean
statusMessage: StatusMessage
visibilityObserver: IntersectionObserver visibilityObserver: IntersectionObserver
imageFound: MutationQueue imageFound: MutationQueue
@ -89,6 +91,12 @@ export class AnimeNotifier {
this.app.content = this.app.find("content") this.app.content = this.app.find("content")
this.app.loading = this.app.find("loading") this.app.loading = this.app.find("loading")
// Status message
this.statusMessage = new StatusMessage(
this.app.find("status-message"),
this.app.find("status-message-text")
)
// Let's start // Let's start
this.app.run() this.app.run()
} }

37
scripts/StatusMessage.ts Normal file
View File

@ -0,0 +1,37 @@
import { delay } from "./Utils"
export class StatusMessage {
container: HTMLElement
text: HTMLElement
constructor(container: HTMLElement, text: HTMLElement) {
this.container = container
this.text = text
}
show(message: string, duration?: number) {
let messageId = String(Date.now())
this.text.innerText = message
this.container.classList.remove("fade-out")
this.container.dataset.messageId = messageId
delay(duration || 4000).then(() => {
if(this.container.dataset.messageId !== messageId) {
return
}
this.close()
})
}
showError(message: string, duration?: number) {
this.show(message, duration)
this.container.classList.add("error-message")
}
close() {
this.container.classList.add("fade-out")
}
}

View File

@ -0,0 +1,18 @@
#status-message
horizontal
position fixed
bottom 0
left 0
width 100%
padding calc(content-padding / 2) content-padding
#status-message-text
flex 1
text-align center
.status-message-action
color white !important
.error-message
color white
background-color hsl(0, 75%, 50%)

View File

@ -24,5 +24,5 @@ func Icon(name string) string {
// RawIcon ... // RawIcon ...
func RawIcon(name string) string { func RawIcon(name string) string {
return strings.Replace(svgIcons[name], "class='icon'", "class='raw-icon'", 1) return strings.Replace(svgIcons[name], "class='icon", "class='raw-icon", 1)
} }