✨ Added the list of quotes sorted by last and best with a correct design.
The design has been verified to be responsive and compatible with the dark theme
This commit is contained in:
parent
9eb4d1a234
commit
c51cb4743b
23
mixins/Quote.pixy
Normal file
23
mixins/Quote.pixy
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
component Quote(quote *arn.Quote)
|
||||||
|
.quote.mountable(id=quote.ID)
|
||||||
|
QuoteContent(quote)
|
||||||
|
QuoteFooter(quote)
|
||||||
|
|
||||||
|
component QuoteContent(quote *arn.Quote)
|
||||||
|
.quote-content
|
||||||
|
a.quotation.ajax(href="/quote/" + quote.ID)
|
||||||
|
blockquote
|
||||||
|
p
|
||||||
|
q= quote.Description
|
||||||
|
if quote.Character() != nil
|
||||||
|
footer.quote-character
|
||||||
|
span= "by"
|
||||||
|
a.ajax(href="/character/" + quote.Character().ID)= quote.Character().Name
|
||||||
|
CharacterSmall(quote.Character())
|
||||||
|
|
||||||
|
component QuoteFooter(quote *arn.Quote)
|
||||||
|
.quote-footer
|
||||||
|
span posted
|
||||||
|
span.utc-date(data-date=quote.Created)
|
||||||
|
span by
|
||||||
|
a.ajax(href=quote.Creator().Link())= quote.Creator().Nick + " "
|
@ -107,7 +107,10 @@ func Configure(app *aero.Application) {
|
|||||||
// Quotes
|
// Quotes
|
||||||
l.Page("/quote/:id", quote.Get)
|
l.Page("/quote/:id", quote.Get)
|
||||||
l.Page("/quote/:id/edit", quote.Edit)
|
l.Page("/quote/:id/edit", quote.Edit)
|
||||||
l.Page("/quotes", quotes.Get)
|
l.Page("/quotes", quotes.Latest)
|
||||||
|
l.Page("/quotes/from/:index", quotes.LatestFrom)
|
||||||
|
l.Page("/quotes/best", quotes.Best)
|
||||||
|
l.Page("/quotes/best/from/:index", quotes.BestFrom)
|
||||||
|
|
||||||
// Calendar
|
// Calendar
|
||||||
l.Page("/calendar", calendar.Get)
|
l.Page("/calendar", calendar.Get)
|
||||||
|
@ -28,5 +28,9 @@ func Edit(ctx *aero.Context) string {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if quote.Character() != nil {
|
||||||
|
ctx.Data.(*arn.OpenGraph).Tags["og:image"] = quote.Character().Image
|
||||||
|
}
|
||||||
|
|
||||||
return ctx.HTML(components.QuoteTabs(quote, user) + editform.Render(quote, "Edit quote", user))
|
return ctx.HTML(components.QuoteTabs(quote, user) + editform.Render(quote, "Edit quote", user))
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ func Get(ctx *aero.Context) string {
|
|||||||
return ctx.Error(http.StatusNotFound, "Quote not found", err)
|
return ctx.Error(http.StatusNotFound, "Quote not found", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
character, err := arn.GetCharacter(quote.Character)
|
character, err := arn.GetCharacter(quote.CharacterId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ctx.Error(http.StatusNotFound, "Quote not found", err)
|
return ctx.Error(http.StatusNotFound, "Quote not found", err)
|
||||||
}
|
}
|
||||||
|
66
pages/quotes/best.go
Normal file
66
pages/quotes/best.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package quotes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/aerogo/aero"
|
||||||
|
"github.com/animenotifier/arn"
|
||||||
|
"github.com/animenotifier/notify.moe/components"
|
||||||
|
"github.com/animenotifier/notify.moe/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Best renders the quotes page ordered by the most favorites first.
|
||||||
|
func Best(ctx *aero.Context) string {
|
||||||
|
user := utils.GetUser(ctx)
|
||||||
|
|
||||||
|
quotes := arn.FilterQuotes(func(track *arn.Quote) bool {
|
||||||
|
return !track.IsDraft && len(track.Description) > 0
|
||||||
|
})
|
||||||
|
|
||||||
|
arn.SortQuotesPopularFirst(quotes)
|
||||||
|
|
||||||
|
if len(quotes) > maxQuotes {
|
||||||
|
quotes = quotes[:maxQuotes]
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.HTML(components.Quotes(quotes, maxQuotes, user))
|
||||||
|
}
|
||||||
|
|
||||||
|
// BestFrom renders the quotes from the given index.
|
||||||
|
func BestFrom(ctx *aero.Context) string {
|
||||||
|
user := utils.GetUser(ctx)
|
||||||
|
index, err := ctx.GetInt("index")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return ctx.Error(http.StatusBadRequest, "Invalid start index", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
allQuotes := arn.FilterQuotes(func(track *arn.Quote) bool {
|
||||||
|
return !track.IsDraft && len(track.Description) > 0
|
||||||
|
})
|
||||||
|
|
||||||
|
if index < 0 || index >= len(allQuotes) {
|
||||||
|
return ctx.Error(http.StatusBadRequest, "Invalid start index (maximum is "+strconv.Itoa(len(allQuotes))+")", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
arn.SortQuotesPopularFirst(allQuotes)
|
||||||
|
|
||||||
|
quotes := allQuotes[index:]
|
||||||
|
|
||||||
|
if len(quotes) > maxQuotes {
|
||||||
|
quotes = quotes[:maxQuotes]
|
||||||
|
}
|
||||||
|
|
||||||
|
nextIndex := index + maxQuotes
|
||||||
|
|
||||||
|
if nextIndex >= len(allQuotes) {
|
||||||
|
// End of data - no more scrolling
|
||||||
|
ctx.Response().Header().Set("X-LoadMore-Index", "-1")
|
||||||
|
} else {
|
||||||
|
// Send the index for the next request
|
||||||
|
ctx.Response().Header().Set("X-LoadMore-Index", strconv.Itoa(nextIndex))
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.HTML(components.QuotesScrollable(quotes, user))
|
||||||
|
}
|
@ -5,12 +5,62 @@ import (
|
|||||||
"github.com/animenotifier/arn"
|
"github.com/animenotifier/arn"
|
||||||
"github.com/animenotifier/notify.moe/components"
|
"github.com/animenotifier/notify.moe/components"
|
||||||
"github.com/animenotifier/notify.moe/utils"
|
"github.com/animenotifier/notify.moe/utils"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Get renders the quotes page.
|
const maxQuotes = 12
|
||||||
func Get(ctx *aero.Context) string {
|
|
||||||
|
// Latest renders the quotes page.
|
||||||
|
func Latest(ctx *aero.Context) string {
|
||||||
user := utils.GetUser(ctx)
|
user := utils.GetUser(ctx)
|
||||||
|
|
||||||
quotes := arn.AllQuotes()
|
quotes := arn.FilterQuotes(func(track *arn.Quote) bool {
|
||||||
return ctx.HTML(components.Quotes(quotes, user))
|
return !track.IsDraft && len(track.Description) > 0
|
||||||
|
})
|
||||||
|
|
||||||
|
arn.SortQuotesLatestFirst(quotes)
|
||||||
|
|
||||||
|
if len(quotes) > maxQuotes {
|
||||||
|
quotes = quotes[:maxQuotes]
|
||||||
|
}
|
||||||
|
return ctx.HTML(components.Quotes(quotes, maxQuotes, user))
|
||||||
|
}
|
||||||
|
|
||||||
|
// LatestFrom renders the quotes from the given index.
|
||||||
|
func LatestFrom(ctx *aero.Context) string {
|
||||||
|
user := utils.GetUser(ctx)
|
||||||
|
index, err := ctx.GetInt("index")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return ctx.Error(http.StatusBadRequest, "Invalid start index", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
allQuotes := arn.FilterQuotes(func(track *arn.Quote) bool {
|
||||||
|
return !track.IsDraft && len(track.Description) > 0
|
||||||
|
})
|
||||||
|
|
||||||
|
if index < 0 || index >= len(allQuotes) {
|
||||||
|
return ctx.Error(http.StatusBadRequest, "Invalid start index (maximum is "+strconv.Itoa(len(allQuotes))+")", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
arn.SortQuotesLatestFirst(allQuotes)
|
||||||
|
|
||||||
|
quotes := allQuotes[index:]
|
||||||
|
|
||||||
|
if len(quotes) > maxQuotes {
|
||||||
|
quotes = quotes[:maxQuotes]
|
||||||
|
}
|
||||||
|
|
||||||
|
nextIndex := index + maxQuotes
|
||||||
|
|
||||||
|
if nextIndex >= len(allQuotes) {
|
||||||
|
// End of data - no more scrolling
|
||||||
|
ctx.Response().Header().Set("X-LoadMore-Index", "-1")
|
||||||
|
} else {
|
||||||
|
// Send the index for the next request
|
||||||
|
ctx.Response().Header().Set("X-LoadMore-Index", strconv.Itoa(nextIndex))
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.HTML(components.QuotesScrollable(quotes, user))
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
component Quotes(quotes []*arn.Quote, user *arn.User)
|
component Quotes(quotes []*arn.Quote, quotesPerPage int, user *arn.User)
|
||||||
h1.page-title Quotes
|
h1.page-title Quotes
|
||||||
|
|
||||||
|
QuotesTabs
|
||||||
|
|
||||||
.corner-buttons
|
.corner-buttons
|
||||||
if user != nil
|
if user != nil
|
||||||
if user.DraftIndex().QuoteID == ""
|
if user.DraftIndex().QuoteID == ""
|
||||||
@ -12,6 +14,18 @@ component Quotes(quotes []*arn.Quote, user *arn.User)
|
|||||||
Icon("pencil")
|
Icon("pencil")
|
||||||
span Edit draft
|
span Edit draft
|
||||||
|
|
||||||
ul
|
#load-more-target.quotes
|
||||||
each quote in quotes
|
QuotesScrollable(quotes, user)
|
||||||
li= quote.Description
|
|
||||||
|
if len(quotes) == quotesPerPage
|
||||||
|
.buttons
|
||||||
|
LoadMore(quotesPerPage)
|
||||||
|
|
||||||
|
component QuotesScrollable(quotes []*arn.Quote, user *arn.User)
|
||||||
|
each quote in quotes
|
||||||
|
Quote(quote)
|
||||||
|
|
||||||
|
component QuotesTabs
|
||||||
|
.tabs
|
||||||
|
Tab("Latest", "quote-left", "/quotes")
|
||||||
|
Tab("Best", "heart", "/quotes/best")
|
87
pages/quotes/quotes.scarlet
Normal file
87
pages/quotes/quotes.scarlet
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
.quotes
|
||||||
|
horizontal-wrap
|
||||||
|
justify-content space-around
|
||||||
|
|
||||||
|
.quote
|
||||||
|
vertical
|
||||||
|
flex 1
|
||||||
|
flex-basis 500px
|
||||||
|
padding 1rem
|
||||||
|
|
||||||
|
.quote-content
|
||||||
|
vertical
|
||||||
|
border-radius 3px
|
||||||
|
border-left 5px solid quote-side-border-color
|
||||||
|
overflow hidden
|
||||||
|
box-shadow shadow-light
|
||||||
|
align-items stretch
|
||||||
|
align-content stretch
|
||||||
|
|
||||||
|
.quote-character
|
||||||
|
horizontal
|
||||||
|
align-self flex-end
|
||||||
|
align-items baseline
|
||||||
|
justify-content space-around
|
||||||
|
padding 0 1em 1em 0
|
||||||
|
|
||||||
|
span
|
||||||
|
opacity 0.65
|
||||||
|
|
||||||
|
a
|
||||||
|
display inline
|
||||||
|
margin-left 0.5em
|
||||||
|
|
||||||
|
|
||||||
|
.quote-footer
|
||||||
|
text-align center
|
||||||
|
margin-bottom 1rem
|
||||||
|
margin-top 0.4rem
|
||||||
|
font-size 0.9em
|
||||||
|
|
||||||
|
span
|
||||||
|
opacity 0.65
|
||||||
|
|
||||||
|
.quotation
|
||||||
|
height 100%
|
||||||
|
display flex
|
||||||
|
flex-grow 1
|
||||||
|
align-items stretch
|
||||||
|
align-content stretch
|
||||||
|
|
||||||
|
blockquote
|
||||||
|
flex-grow 1
|
||||||
|
padding 1em
|
||||||
|
|
||||||
|
p
|
||||||
|
line-height 2em
|
||||||
|
|
||||||
|
q
|
||||||
|
quotes "\201C""\201D"
|
||||||
|
|
||||||
|
:before
|
||||||
|
color quote-color
|
||||||
|
content open-quote
|
||||||
|
font-size 4em
|
||||||
|
line-height 0.1em
|
||||||
|
margin-right 0.25em
|
||||||
|
vertical-align -0.4em
|
||||||
|
|
||||||
|
:after
|
||||||
|
color quote-color
|
||||||
|
content close-quote
|
||||||
|
font-size 4em
|
||||||
|
line-height 0.1em
|
||||||
|
margin-left 0.25em
|
||||||
|
vertical-align -0.4em
|
||||||
|
|
||||||
|
|
||||||
|
.character
|
||||||
|
display none !important
|
||||||
|
|
||||||
|
> 800px
|
||||||
|
.character
|
||||||
|
margin 0.5em 0 0 0.5em !important
|
||||||
|
display block !important
|
||||||
|
|
||||||
|
.quote-character a
|
||||||
|
display none
|
@ -35,7 +35,9 @@ let dark = {
|
|||||||
|
|
||||||
"post-like-color": "var(--link-color)",
|
"post-like-color": "var(--link-color)",
|
||||||
"post-unlike-color": "var(--link-color)",
|
"post-unlike-color": "var(--link-color)",
|
||||||
"post-permalink-color": "var(--link-color)"
|
"post-permalink-color": "var(--link-color)",
|
||||||
|
|
||||||
|
"quote-color" : "var(--text-color)"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle theme
|
// Toggle theme
|
||||||
|
@ -59,6 +59,10 @@ nav-link-hover-slide-color = main-color
|
|||||||
// nav-link-color = rgb(160, 160, 160)
|
// nav-link-color = rgb(160, 160, 160)
|
||||||
// nav-link-hover-color = rgb(80, 80, 80)
|
// nav-link-hover-color = rgb(80, 80, 80)
|
||||||
|
|
||||||
|
// Quote
|
||||||
|
quote-color = hsl(0, 0%, 45%)
|
||||||
|
quote-side-border-color = quote-color
|
||||||
|
|
||||||
// Forum
|
// Forum
|
||||||
post-like-color = green !important
|
post-like-color = green !important
|
||||||
post-unlike-color = rgb(255, 32, 12) !important
|
post-unlike-color = rgb(255, 32, 12) !important
|
||||||
|
@ -34,4 +34,7 @@
|
|||||||
// // Forum
|
// // Forum
|
||||||
// post-like-color = link-color
|
// post-like-color = link-color
|
||||||
// post-unlike-color = link-color
|
// post-unlike-color = link-color
|
||||||
// post-permalink-color = link-color
|
// post-permalink-color = link-color
|
||||||
|
|
||||||
|
// // Quote
|
||||||
|
// quote-color = text-color
|
Loading…
Reference in New Issue
Block a user