From 524ab3fff9b3853771232bec3579126faf6be093 Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Fri, 21 Jul 2017 10:10:48 +0200 Subject: [PATCH] Added user follows --- mixins/Navigation.pixy | 8 +++--- pages/animelist/animelist.scarlet | 9 ++++--- pages/profile/profile.pixy | 20 +++++++++++--- pages/profile/profile.scarlet | 12 +++++++-- patches/add-follows/add-follows.go | 42 ++++++++++++++++++++++++++++++ scripts/Actions.ts | 16 ++++++++++++ scripts/AnimeNotifier.ts | 16 ++++++++++-- scripts/StatusMessage.ts | 9 +++++-- styles/status-message.scarlet | 6 ++++- tests.go | 6 +++++ 10 files changed, 126 insertions(+), 18 deletions(-) create mode 100644 patches/add-follows/add-follows.go diff --git a/mixins/Navigation.pixy b/mixins/Navigation.pixy index 5d8608cd..e612aae7 100644 --- a/mixins/Navigation.pixy +++ b/mixins/Navigation.pixy @@ -39,8 +39,8 @@ component LoggedInMenu(user *arn.User) .extra-navigation NavigationButton("Forum", "/forum", "comment") - .extra-navigation - NavigationButton("Soundtracks", "/soundtracks", "headphones") + //- .extra-navigation + //- NavigationButton("Soundtracks", "/soundtracks", "headphones") FuzzySearch @@ -56,8 +56,8 @@ component LoggedInMenu(user *arn.User) .hide-landscape NavigationButton("Settings", "/settings", "cog") - .extra-navigation.hide-landscape - NavigationButtonNoAJAX("Logout", "/logout", "sign-out") + //- .extra-navigation.hide-landscape + //- NavigationButtonNoAJAX("Logout", "/logout", "sign-out") component FuzzySearch input#search.action(data-action="search", data-trigger="input", type="text", placeholder="Search...", title="Shortcut: F") diff --git a/pages/animelist/animelist.scarlet b/pages/animelist/animelist.scarlet index f71df96d..475afdc5 100644 --- a/pages/animelist/animelist.scarlet +++ b/pages/animelist/animelist.scarlet @@ -65,8 +65,7 @@ width 65px .anime-list-item-actions - display none - width 30px + display none !important // // Beautify icon alignment // .raw-icon @@ -74,7 +73,11 @@ > 740px .anime-list-item-actions - display block + display flex !important + width 30px + + :empty + display none !important .anime-list-item-airing-date display none !important diff --git a/pages/profile/profile.pixy b/pages/profile/profile.pixy index 733bf09d..06e529c5 100644 --- a/pages/profile/profile.pixy +++ b/pages/profile/profile.pixy @@ -44,10 +44,22 @@ component ProfileHeader(viewUser *arn.User, user *arn.User, uri string) Icon("rocket") span= arn.Capitalize(viewUser.Role) - //- .profile-actions - //- button.action(data-action="followUser", data-trigger="click") - //- Icon("user-plus") - //- span Follow + if user != nil + .profile-actions + if user.ID != viewUser.ID + if !user.Follows().Contains(viewUser.ID) + button.profile-action.action(data-action="followUser", data-trigger="click", data-api="/api/userfollows/" + user.ID + "/add", data-view-user-id=viewUser.ID) + Icon("user-plus") + span Follow + else + button.profile-action.action(data-action="unfollowUser", data-trigger="click", data-api="/api/userfollows/" + user.ID + "/remove", data-view-user-id=viewUser.ID) + Icon("user-times") + span Unfollow + + if user.Role == "admin" || user.Role == "editor" + a.button.profile-action(href="/api/user/" + viewUser.ID) + Icon("search-plus") + span API ProfileNavigation(viewUser, uri) diff --git a/pages/profile/profile.scarlet b/pages/profile/profile.scarlet index 3f34e932..1d377010 100644 --- a/pages/profile/profile.scarlet +++ b/pages/profile/profile.scarlet @@ -31,7 +31,15 @@ profile-boot-duration = 2s margin-top calc(content-padding * 1.5) .profile-actions - horizontal + vertical + margin-top content-padding + + :empty + display none + +.profile-action + margin-bottom 0.5rem + text-shadow none !important > 740px .profile @@ -50,11 +58,11 @@ profile-boot-duration = 2s max-width 900px .profile-actions - vertical position absolute top 0 right 0 padding content-padding + margin-top 0 // animation appear // 0% diff --git a/patches/add-follows/add-follows.go b/patches/add-follows/add-follows.go new file mode 100644 index 00000000..5b0923c2 --- /dev/null +++ b/patches/add-follows/add-follows.go @@ -0,0 +1,42 @@ +package main + +import ( + "fmt" + + "github.com/animenotifier/arn" + "github.com/fatih/color" +) + +func main() { + color.Yellow("Adding user follows to users who don't have one") + + // Get a stream of all users + allUsers, err := arn.StreamUsers() + + if err != nil { + panic(err) + } + + // Iterate over the stream + for user := range allUsers { + // exists, err := arn.DB.Exists("UserFollows", user.ID) + + // if err != nil || exists { + // continue + // } + + fmt.Println(user.Nick) + + follows := &arn.UserFollows{} + follows.UserID = user.ID + follows.Items = user.Following + + err = arn.DB.Set("UserFollows", follows.UserID, follows) + + if err != nil { + color.Red(err.Error()) + } + } + + color.Green("Finished.") +} diff --git a/scripts/Actions.ts b/scripts/Actions.ts index 5c77caf0..901d7871 100644 --- a/scripts/Actions.ts +++ b/scripts/Actions.ts @@ -3,6 +3,22 @@ import { AnimeNotifier } from "./AnimeNotifier" import { Diff } from "./Diff" import { findAll } from "./Utils" +// Follow user +export function followUser(arn: AnimeNotifier, elem: HTMLElement) { + return arn.post(elem.dataset.api, elem.dataset.viewUserId) + .then(() => arn.reloadContent()) + .then(() => arn.statusMessage.showInfo("You are now following " + arn.app.find("nick").innerText + ".")) + .catch(err => arn.statusMessage.showError(err)) +} + +// Unfollow user +export function unfollowUser(arn: AnimeNotifier, elem: HTMLElement) { + return arn.post(elem.dataset.api, elem.dataset.viewUserId) + .then(() => arn.reloadContent()) + .then(() => arn.statusMessage.showInfo("You stopped following " + arn.app.find("nick").innerText + ".")) + .catch(err => arn.statusMessage.showError(err)) +} + // Toggle sidebar export function toggleSidebar(arn: AnimeNotifier) { arn.app.find("sidebar").classList.toggle("sidebar-visible") diff --git a/scripts/AnimeNotifier.ts b/scripts/AnimeNotifier.ts index 316e6638..22563390 100644 --- a/scripts/AnimeNotifier.ts +++ b/scripts/AnimeNotifier.ts @@ -580,18 +580,30 @@ export class AnimeNotifier { }) } - post(url, obj) { + post(url, body) { + if(typeof body !== "string") { + body = JSON.stringify(body) + } + + this.loading(true) + return fetch(url, { method: "POST", - body: JSON.stringify(obj), + body, credentials: "same-origin" }) .then(response => response.text()) .then(body => { + this.loading(false) + if(body !== "ok") { throw body } }) + .catch(err => { + this.loading(false) + throw err + }) } scrollTo(target: HTMLElement) { diff --git a/scripts/StatusMessage.ts b/scripts/StatusMessage.ts index 0820b90e..126e30c1 100644 --- a/scripts/StatusMessage.ts +++ b/scripts/StatusMessage.ts @@ -9,7 +9,7 @@ export class StatusMessage { this.text = text } - show(message: string, duration?: number) { + show(message: string, duration: number) { let messageId = String(Date.now()) this.text.innerText = message @@ -27,10 +27,15 @@ export class StatusMessage { } showError(message: string, duration?: number) { - this.show(message, duration) + this.show(message, duration || 4000) this.container.classList.add("error-message") } + showInfo(message: string, duration?: number) { + this.show(message, duration || 2000) + this.container.classList.add("info-message") + } + close() { this.container.classList.add("fade-out") } diff --git a/styles/status-message.scarlet b/styles/status-message.scarlet index e08f83f5..7b0aaf62 100644 --- a/styles/status-message.scarlet +++ b/styles/status-message.scarlet @@ -17,4 +17,8 @@ .error-message color white - background-color hsl(0, 75%, 50%) \ No newline at end of file + background-color hsl(0, 75%, 50%) + +.info-message + color white + background-color forum-tag-hover-color \ No newline at end of file diff --git a/tests.go b/tests.go index e6176bb8..fd13ff74 100644 --- a/tests.go +++ b/tests.go @@ -228,6 +228,12 @@ var interfaceImplementations = map[string][]reflect.Type{ "AnimeList": []reflect.Type{ collection, }, + "PushSubscriptions": []reflect.Type{ + collection, + }, + "UserFollows": []reflect.Type{ + collection, + }, } func init() {