New settings page
This commit is contained in:
parent
b0b819306b
commit
7cf3c2564b
11
main.go
11
main.go
@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/aerogo/session-store-nano"
|
"github.com/aerogo/session-store-nano"
|
||||||
"github.com/animenotifier/arn"
|
"github.com/animenotifier/arn"
|
||||||
"github.com/animenotifier/notify.moe/auth"
|
"github.com/animenotifier/notify.moe/auth"
|
||||||
|
"github.com/animenotifier/notify.moe/components"
|
||||||
"github.com/animenotifier/notify.moe/components/css"
|
"github.com/animenotifier/notify.moe/components/css"
|
||||||
"github.com/animenotifier/notify.moe/layout"
|
"github.com/animenotifier/notify.moe/layout"
|
||||||
"github.com/animenotifier/notify.moe/middleware"
|
"github.com/animenotifier/notify.moe/middleware"
|
||||||
@ -94,7 +95,6 @@ func configure(app *aero.Application) *aero.Application {
|
|||||||
app.Ajax("/post/:id", posts.Get)
|
app.Ajax("/post/:id", posts.Get)
|
||||||
app.Ajax("/character/:id", character.Get)
|
app.Ajax("/character/:id", character.Get)
|
||||||
app.Ajax("/new/thread", newthread.Get)
|
app.Ajax("/new/thread", newthread.Get)
|
||||||
app.Ajax("/settings", settings.Get)
|
|
||||||
app.Ajax("/artworks", artworks.Get)
|
app.Ajax("/artworks", artworks.Get)
|
||||||
app.Ajax("/amvs", amvs.Get)
|
app.Ajax("/amvs", amvs.Get)
|
||||||
app.Ajax("/users", users.Active)
|
app.Ajax("/users", users.Active)
|
||||||
@ -104,6 +104,15 @@ func configure(app *aero.Application) *aero.Application {
|
|||||||
app.Ajax("/statistics/anime", statistics.Anime)
|
app.Ajax("/statistics/anime", statistics.Anime)
|
||||||
app.Ajax("/login", login.Get)
|
app.Ajax("/login", login.Get)
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
app.Ajax("/settings", settings.Get(components.SettingsPersonal))
|
||||||
|
app.Ajax("/settings/accounts", settings.Get(components.SettingsAccounts))
|
||||||
|
app.Ajax("/settings/notifications", settings.Get(components.SettingsNotifications))
|
||||||
|
app.Ajax("/settings/apps", settings.Get(components.SettingsApps))
|
||||||
|
app.Ajax("/settings/avatar", settings.Get(components.SettingsAvatar))
|
||||||
|
app.Ajax("/settings/formatting", settings.Get(components.SettingsFormatting))
|
||||||
|
app.Ajax("/settings/pro", settings.Get(components.SettingsPro))
|
||||||
|
|
||||||
// Soundtracks
|
// Soundtracks
|
||||||
app.Ajax("/soundtracks", soundtracks.Get)
|
app.Ajax("/soundtracks", soundtracks.Get)
|
||||||
app.Ajax("/soundtracks/from/:index", soundtracks.From)
|
app.Ajax("/soundtracks/from/:index", soundtracks.From)
|
||||||
|
@ -4,17 +4,19 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/aerogo/aero"
|
"github.com/aerogo/aero"
|
||||||
"github.com/animenotifier/notify.moe/components"
|
"github.com/animenotifier/arn"
|
||||||
"github.com/animenotifier/notify.moe/utils"
|
"github.com/animenotifier/notify.moe/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Get user settings page.
|
// Get settings.
|
||||||
func Get(ctx *aero.Context) string {
|
func Get(component func(*arn.User) string) func(*aero.Context) string {
|
||||||
|
return func(ctx *aero.Context) string {
|
||||||
user := utils.GetUser(ctx)
|
user := utils.GetUser(ctx)
|
||||||
|
|
||||||
if user == nil {
|
if user == nil {
|
||||||
return ctx.Error(http.StatusUnauthorized, "Not logged in", nil)
|
return ctx.Error(http.StatusUnauthorized, "Not logged in", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils.AllowEmbed(ctx, ctx.HTML(components.Settings(user)))
|
return ctx.HTML(component(user))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,17 @@
|
|||||||
component SettingsTabs
|
component SettingsTabs
|
||||||
.tabs
|
.tabs
|
||||||
Tab("Personal", "user", "/settings/personal")
|
Tab("Personal", "user", "/settings")
|
||||||
|
Tab("Accounts", "cubes", "/settings/accounts")
|
||||||
|
Tab("Notifications", "bell", "/settings/notifications")
|
||||||
|
Tab("Apps", "puzzle-piece", "/settings/apps")
|
||||||
|
Tab("Avatar", "picture-o", "/settings/avatar")
|
||||||
|
Tab("Formatting", "font", "/settings/formatting")
|
||||||
|
Tab("PRO", "star", "/settings/pro")
|
||||||
|
|
||||||
component Settings(user *arn.User)
|
component SettingsPersonal(user *arn.User)
|
||||||
h1.page-title Settings
|
SettingsTabs
|
||||||
|
|
||||||
|
h1.page-title Personal settings
|
||||||
|
|
||||||
.settings
|
.settings
|
||||||
.widget.mountable(data-api="/api/user/" + user.ID)
|
.widget.mountable(data-api="/api/user/" + user.ID)
|
||||||
@ -15,17 +23,12 @@ component Settings(user *arn.User)
|
|||||||
InputText("Tagline", user.Tagline, "Tagline", "Text that appears below your username")
|
InputText("Tagline", user.Tagline, "Tagline", "Text that appears below your username")
|
||||||
InputText("Website", user.Website, "Website", "Your homepage")
|
InputText("Website", user.Website, "Website", "Your homepage")
|
||||||
|
|
||||||
.widget.mountable(data-api="/api/user/" + user.ID)
|
component SettingsNotifications(user *arn.User)
|
||||||
h3.widget-title
|
SettingsTabs
|
||||||
Icon("cubes")
|
|
||||||
span Accounts
|
|
||||||
|
|
||||||
InputText("Accounts.AniList.Nick", user.Accounts.AniList.Nick, "AniList", "Your username on anilist.co")
|
h1.page-title Notification settings
|
||||||
InputText("Accounts.MyAnimeList.Nick", user.Accounts.MyAnimeList.Nick, "MyAnimeList", "Your username on myanimelist.net")
|
|
||||||
InputText("Accounts.Kitsu.Nick", user.Accounts.Kitsu.Nick, "Kitsu", "Your username on kitsu.io")
|
|
||||||
InputText("Accounts.Osu.Nick", user.Accounts.Osu.Nick, "Osu", "Your username on osu.ppy.sh")
|
|
||||||
//- InputText("Accounts.AnimePlanet.Nick", user.Accounts.AnimePlanet.Nick, "AnimePlanet", "Your username on anime-planet.com")
|
|
||||||
|
|
||||||
|
.settings
|
||||||
.widget.mountable
|
.widget.mountable
|
||||||
h3.widget-title
|
h3.widget-title
|
||||||
Icon("bell")
|
Icon("bell")
|
||||||
@ -49,6 +52,130 @@ component Settings(user *arn.User)
|
|||||||
Icon("paper-plane")
|
Icon("paper-plane")
|
||||||
span Send test notification
|
span Send test notification
|
||||||
|
|
||||||
|
component SettingsApps(user *arn.User)
|
||||||
|
SettingsTabs
|
||||||
|
|
||||||
|
h1.page-title App settings
|
||||||
|
|
||||||
|
.settings
|
||||||
|
.widget.mountable
|
||||||
|
h3.widget-title
|
||||||
|
Icon("puzzle-piece")
|
||||||
|
span Apps
|
||||||
|
|
||||||
|
.widget-section
|
||||||
|
label Chrome Extension:
|
||||||
|
button.action(data-action="installExtension", data-trigger="click")
|
||||||
|
Icon("chrome")
|
||||||
|
span Get the Chrome Extension
|
||||||
|
|
||||||
|
.widget-section
|
||||||
|
label Desktop App:
|
||||||
|
button.action(data-action="installApp", data-trigger="click")
|
||||||
|
Icon("desktop")
|
||||||
|
span Get the Desktop App
|
||||||
|
|
||||||
|
.widget-section
|
||||||
|
label Android App:
|
||||||
|
a.button(href="https://www.youtube.com/watch?v=opyt4cw0ep8", target="_blank", rel="noopener")
|
||||||
|
Icon("android")
|
||||||
|
span Get the Android App
|
||||||
|
|
||||||
|
component SettingsAvatar(user *arn.User)
|
||||||
|
SettingsTabs
|
||||||
|
|
||||||
|
h1.page-title Avatar settings
|
||||||
|
|
||||||
|
.settings
|
||||||
|
.widget.mountable(data-api="/api/settings/" + user.ID)
|
||||||
|
h3.widget-title
|
||||||
|
Icon("picture-o")
|
||||||
|
span Avatar
|
||||||
|
|
||||||
|
.widget-section
|
||||||
|
label(for="Avatar.Source") Source:
|
||||||
|
select.widget-ui-element.action(id="Avatar.Source", data-field="Avatar.Source", value=user.Settings().Avatar.Source, data-action="save", data-trigger="change")
|
||||||
|
option(value="") Automatic
|
||||||
|
option(value="Gravatar") Gravatar
|
||||||
|
option(value="URL") Link
|
||||||
|
//- option(value="FileSystem") Upload
|
||||||
|
|
||||||
|
if user.Settings().Avatar.Source == "URL"
|
||||||
|
InputText("Avatar.SourceURL", user.Settings().Avatar.SourceURL, "Link", "Post the link to the image here")
|
||||||
|
|
||||||
|
if user.Settings().Avatar.Source == "Gravatar" || (user.Settings().Avatar.Source == "" && user.Avatar.Source == "Gravatar")
|
||||||
|
.profile-image-container.avatar-preview
|
||||||
|
img.profile-image.mountable(src=user.Gravatar(), alt="Gravatar")
|
||||||
|
|
||||||
|
if user.Settings().Avatar.Source == "URL" && user.Settings().Avatar.SourceURL != ""
|
||||||
|
.profile-image-container.avatar-preview
|
||||||
|
img.profile-image.mountable(src=strings.Replace(user.Settings().Avatar.SourceURL, "http://", "https://", 1), alt="Avatar preview")
|
||||||
|
|
||||||
|
component SettingsFormatting(user *arn.User)
|
||||||
|
SettingsTabs
|
||||||
|
|
||||||
|
h1.page-title Formatting settings
|
||||||
|
|
||||||
|
.settings
|
||||||
|
.widget.mountable(data-api="/api/settings/" + user.ID)
|
||||||
|
h3.widget-title
|
||||||
|
Icon("font")
|
||||||
|
span Formatting
|
||||||
|
|
||||||
|
.widget-section
|
||||||
|
label(for="TitleLanguage")= "Title language:"
|
||||||
|
select.widget-ui-element.action(id="TitleLanguage", data-field="TitleLanguage", value=user.Settings().TitleLanguage, title="Language of anime titles", data-action="save", data-trigger="change")
|
||||||
|
option(value="canonical") Canonical
|
||||||
|
option(value="english") English
|
||||||
|
option(value="romaji") Romaji
|
||||||
|
option(value="japanese") 日本語
|
||||||
|
|
||||||
|
InputNumber("Format.RatingsPrecision", float64(user.Settings().Format.RatingsPrecision), "Ratings precision", "How many decimals after the comma would you like to display in ratings on anime pages?", "0", "2", "1")
|
||||||
|
|
||||||
|
component SettingsPro(user *arn.User)
|
||||||
|
SettingsTabs
|
||||||
|
|
||||||
|
h1.page-title PRO settings
|
||||||
|
|
||||||
|
.settings
|
||||||
|
.widget.mountable(data-api="/api/settings/" + user.ID)
|
||||||
|
h3.widget-title
|
||||||
|
Icon("star")
|
||||||
|
span PRO
|
||||||
|
|
||||||
|
if user.IsPro()
|
||||||
|
.widget-section
|
||||||
|
label
|
||||||
|
span Your PRO account expires in
|
||||||
|
span.utc-date(data-date=user.ProExpires)
|
||||||
|
span .
|
||||||
|
a.button.ajax(href="/shop")
|
||||||
|
Icon("star")
|
||||||
|
span Extend PRO account duration
|
||||||
|
else
|
||||||
|
.widget-section
|
||||||
|
label Would you like to support the site development?
|
||||||
|
a.button.ajax(href="/shop")
|
||||||
|
Icon("star")
|
||||||
|
span Go PRO
|
||||||
|
|
||||||
|
component SettingsAccounts(user *arn.User)
|
||||||
|
SettingsTabs
|
||||||
|
|
||||||
|
h1.page-title Accounts settings
|
||||||
|
|
||||||
|
.settings
|
||||||
|
.widget.mountable(data-api="/api/user/" + user.ID)
|
||||||
|
h3.widget-title
|
||||||
|
Icon("cubes")
|
||||||
|
span Accounts
|
||||||
|
|
||||||
|
InputText("Accounts.AniList.Nick", user.Accounts.AniList.Nick, "AniList", "Your username on anilist.co")
|
||||||
|
InputText("Accounts.MyAnimeList.Nick", user.Accounts.MyAnimeList.Nick, "MyAnimeList", "Your username on myanimelist.net")
|
||||||
|
InputText("Accounts.Kitsu.Nick", user.Accounts.Kitsu.Nick, "Kitsu", "Your username on kitsu.io")
|
||||||
|
InputText("Accounts.Osu.Nick", user.Accounts.Osu.Nick, "Osu", "Your username on osu.ppy.sh")
|
||||||
|
//- InputText("Accounts.AnimePlanet.Nick", user.Accounts.AnimePlanet.Nick, "AnimePlanet", "Your username on anime-planet.com")
|
||||||
|
|
||||||
.widget.mountable
|
.widget.mountable
|
||||||
h3.widget-title
|
h3.widget-title
|
||||||
Icon("user-plus")
|
Icon("user-plus")
|
||||||
@ -77,29 +204,6 @@ component Settings(user *arn.User)
|
|||||||
Icon("circle-o")
|
Icon("circle-o")
|
||||||
span Not connected
|
span Not connected
|
||||||
|
|
||||||
.widget.mountable
|
|
||||||
h3.widget-title
|
|
||||||
Icon("puzzle-piece")
|
|
||||||
span Apps
|
|
||||||
|
|
||||||
.widget-section
|
|
||||||
label Chrome Extension:
|
|
||||||
button.action(data-action="installExtension", data-trigger="click")
|
|
||||||
Icon("chrome")
|
|
||||||
span Get the Chrome Extension
|
|
||||||
|
|
||||||
.widget-section
|
|
||||||
label Desktop App:
|
|
||||||
button.action(data-action="installApp", data-trigger="click")
|
|
||||||
Icon("desktop")
|
|
||||||
span Get the Desktop App
|
|
||||||
|
|
||||||
.widget-section
|
|
||||||
label Android App:
|
|
||||||
a.button(href="https://www.youtube.com/watch?v=opyt4cw0ep8", target="_blank", rel="noopener")
|
|
||||||
Icon("android")
|
|
||||||
span Get the Android App
|
|
||||||
|
|
||||||
.widget.mountable
|
.widget.mountable
|
||||||
h3.widget-title
|
h3.widget-title
|
||||||
Icon("download")
|
Icon("download")
|
||||||
@ -117,70 +221,3 @@ component Settings(user *arn.User)
|
|||||||
a.button(href="/api/animelist/" + user.ID)
|
a.button(href="/api/animelist/" + user.ID)
|
||||||
Icon("upload")
|
Icon("upload")
|
||||||
span Export anime list as JSON
|
span Export anime list as JSON
|
||||||
|
|
||||||
.widget.mountable(data-api="/api/settings/" + user.ID)
|
|
||||||
h3.widget-title
|
|
||||||
Icon("picture-o")
|
|
||||||
span Avatar
|
|
||||||
|
|
||||||
.widget-section
|
|
||||||
label(for="Avatar.Source") Source:
|
|
||||||
select.widget-ui-element.action(id="Avatar.Source", data-field="Avatar.Source", value=user.Settings().Avatar.Source, data-action="save", data-trigger="change")
|
|
||||||
option(value="") Automatic
|
|
||||||
option(value="Gravatar") Gravatar
|
|
||||||
option(value="URL") Link
|
|
||||||
//- option(value="FileSystem") Upload
|
|
||||||
|
|
||||||
if user.Settings().Avatar.Source == "URL"
|
|
||||||
InputText("Avatar.SourceURL", user.Settings().Avatar.SourceURL, "Link", "Post the link to the image here")
|
|
||||||
|
|
||||||
if user.Settings().Avatar.Source == "Gravatar" || (user.Settings().Avatar.Source == "" && user.Avatar.Source == "Gravatar")
|
|
||||||
.profile-image-container.avatar-preview
|
|
||||||
img.profile-image.mountable(src=user.Gravatar(), alt="Gravatar")
|
|
||||||
|
|
||||||
if user.Settings().Avatar.Source == "URL" && user.Settings().Avatar.SourceURL != ""
|
|
||||||
.profile-image-container.avatar-preview
|
|
||||||
img.profile-image.mountable(src=strings.Replace(user.Settings().Avatar.SourceURL, "http://", "https://", 1), alt="Avatar preview")
|
|
||||||
|
|
||||||
.widget.mountable(data-api="/api/settings/" + user.ID)
|
|
||||||
h3.widget-title
|
|
||||||
Icon("font")
|
|
||||||
span Formatting
|
|
||||||
|
|
||||||
.widget-section
|
|
||||||
label(for="TitleLanguage")= "Title language:"
|
|
||||||
select.widget-ui-element.action(id="TitleLanguage", data-field="TitleLanguage", value=user.Settings().TitleLanguage, title="Language of anime titles", data-action="save", data-trigger="change")
|
|
||||||
option(value="canonical") Canonical
|
|
||||||
option(value="english") English
|
|
||||||
option(value="romaji") Romaji
|
|
||||||
option(value="japanese") 日本語
|
|
||||||
|
|
||||||
InputNumber("Format.RatingsPrecision", float64(user.Settings().Format.RatingsPrecision), "Ratings precision", "How many decimals after the comma would you like to display in ratings on anime pages?", "0", "2", "1")
|
|
||||||
|
|
||||||
.widget.mountable(data-api="/api/settings/" + user.ID)
|
|
||||||
h3.widget-title
|
|
||||||
Icon("star")
|
|
||||||
span PRO
|
|
||||||
|
|
||||||
if user.IsPro()
|
|
||||||
.widget-section
|
|
||||||
label
|
|
||||||
span Your PRO account expires in
|
|
||||||
span.utc-date(data-date=user.ProExpires)
|
|
||||||
span .
|
|
||||||
a.button.ajax(href="/shop")
|
|
||||||
Icon("star")
|
|
||||||
span Extend PRO account duration
|
|
||||||
else
|
|
||||||
.widget-section
|
|
||||||
label Would you like to support the site development?
|
|
||||||
a.button.ajax(href="/shop")
|
|
||||||
Icon("star")
|
|
||||||
span Go PRO
|
|
||||||
|
|
||||||
//- .widget.mountable(data-api="/api/settings/" + user.ID)
|
|
||||||
//- h3.widget-title
|
|
||||||
//- Icon("cogs")
|
|
||||||
//- span Settings
|
|
||||||
|
|
||||||
//- InputText("TitleLanguage", user.Settings().TitleLanguage, "Title language", "Language of anime titles")
|
|
@ -1,7 +1,11 @@
|
|||||||
.settings
|
.settings
|
||||||
vertical
|
horizontal-wrap-center
|
||||||
margin 0 auto
|
// vertical
|
||||||
width 100%
|
// margin 0 auto
|
||||||
|
// width 100%
|
||||||
|
// max-width 400px
|
||||||
|
|
||||||
|
.widget
|
||||||
max-width 400px
|
max-width 400px
|
||||||
|
|
||||||
.widget-section > button,
|
.widget-section > button,
|
||||||
|
@ -13,7 +13,7 @@ item-color-anime-support-ticket = hsl(217, 64%, 50%)
|
|||||||
padding 0.5rem 1rem
|
padding 0.5rem 1rem
|
||||||
|
|
||||||
.shop-item-name
|
.shop-item-name
|
||||||
font-size 1.7rem
|
font-size 1.6rem
|
||||||
text-align center
|
text-align center
|
||||||
padding 0.75rem 0
|
padding 0.75rem 0
|
||||||
// border-bottom 1px solid rgba(0, 0, 0, 0.1)
|
// border-bottom 1px solid rgba(0, 0, 0, 0.1)
|
||||||
|
@ -13,8 +13,8 @@ var items = []*arn.Item{
|
|||||||
|
|
||||||
Includes:
|
Includes:
|
||||||
|
|
||||||
* Special highlight on the forums
|
|
||||||
* Chrome extension for quick list access
|
* Chrome extension for quick list access
|
||||||
|
* Special highlight on the forums
|
||||||
* Access to the VIP channel on Discord
|
* Access to the VIP channel on Discord
|
||||||
* PRO star on your profile
|
* PRO star on your profile
|
||||||
* High priority for your personal suggestions
|
* High priority for your personal suggestions
|
||||||
@ -34,8 +34,8 @@ Includes:
|
|||||||
|
|
||||||
Includes:
|
Includes:
|
||||||
|
|
||||||
* Special highlight on the forums
|
|
||||||
* Chrome extension for quick list access
|
* Chrome extension for quick list access
|
||||||
|
* Special highlight on the forums
|
||||||
* Access to the VIP channel on Discord
|
* Access to the VIP channel on Discord
|
||||||
* PRO star on your profile
|
* PRO star on your profile
|
||||||
* High priority for your personal suggestions
|
* High priority for your personal suggestions
|
||||||
@ -55,8 +55,8 @@ Includes:
|
|||||||
|
|
||||||
Includes:
|
Includes:
|
||||||
|
|
||||||
* Special highlight on the forums
|
|
||||||
* Chrome extension for quick list access
|
* Chrome extension for quick list access
|
||||||
|
* Special highlight on the forums
|
||||||
* Access to the VIP channel on Discord
|
* Access to the VIP channel on Discord
|
||||||
* PRO star on your profile
|
* PRO star on your profile
|
||||||
* High priority for your personal suggestions
|
* High priority for your personal suggestions
|
||||||
@ -76,8 +76,8 @@ Includes:
|
|||||||
|
|
||||||
Includes:
|
Includes:
|
||||||
|
|
||||||
* Special highlight on the forums
|
|
||||||
* Chrome extension for quick list access
|
* Chrome extension for quick list access
|
||||||
|
* Special highlight on the forums
|
||||||
* Access to the VIP channel on Discord
|
* Access to the VIP channel on Discord
|
||||||
* PRO star on your profile
|
* PRO star on your profile
|
||||||
* High priority for your personal suggestions
|
* High priority for your personal suggestions
|
||||||
|
6
tests.go
6
tests.go
@ -251,6 +251,12 @@ var routeTests = map[string][]string{
|
|||||||
"/dark-flame-master": nil,
|
"/dark-flame-master": nil,
|
||||||
"/user": nil,
|
"/user": nil,
|
||||||
"/settings": nil,
|
"/settings": nil,
|
||||||
|
"/settings/accounts": nil,
|
||||||
|
"/settings/notifications": nil,
|
||||||
|
"/settings/apps": nil,
|
||||||
|
"/settings/avatar": nil,
|
||||||
|
"/settings/formatting": nil,
|
||||||
|
"/settings/pro": nil,
|
||||||
"/shop": nil,
|
"/shop": nil,
|
||||||
"/shop/history": nil,
|
"/shop/history": nil,
|
||||||
"/charge": nil,
|
"/charge": nil,
|
||||||
|
Loading…
Reference in New Issue
Block a user