From a7b616e63aff646b7e0fb5fac178480585bd9d2a Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Fri, 11 May 2018 17:33:10 +0100 Subject: [PATCH] Implements user dropdown and the ability to log out. --- forum.nim | 5 ++++- redesign/header.nim | 16 ++++++++------ redesign/nimforum.scss | 7 ++++++ redesign/threadlist.nim | 2 +- redesign/usermenu.nim | 48 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 redesign/usermenu.nim diff --git a/forum.nim b/forum.nim index 03b9390..ce1bc6f 100644 --- a/forum.nim +++ b/forum.nim @@ -1170,8 +1170,11 @@ routes: get "/karax/status.json": createTFD() + let user = - if c.loggedIn(): + if @"logout" == "true": + logout(c); none[threadlist.User]() + elif c.loggedIn(): some(threadlist.User( name: c.username, avatarUrl: c.email.getGravatarUrl(), diff --git a/redesign/header.nim b/redesign/header.nim index cf07135..9c08d16 100644 --- a/redesign/header.nim +++ b/redesign/header.nim @@ -9,7 +9,7 @@ when defined(js): include karax/prelude import karax / [kajax] - import login, signup + import login, signup, usermenu import karaxutils from dom import setTimeout, window, document, getElementById, focus @@ -22,12 +22,13 @@ when defined(js): lastUpdate: Time loginModal: LoginModal signupModal: SignupModal + userMenu: UserMenu proc newState(): State var state = newState() - proc getStatus + proc getStatus(logout: bool=false) proc newState(): State = State( data: none[UserStatus](), @@ -40,6 +41,9 @@ when defined(js): signupModal: newSignupModal( () => (state.lastUpdate = fromUnix(0); getStatus()), () => state.loginModal.show() + ), + userMenu: newUserMenu( + () => (state.lastUpdate = fromUnix(0); getStatus(logout=true)) ) ) @@ -53,19 +57,19 @@ when defined(js): state.lastUpdate = getTime() - proc getStatus = + proc getStatus(logout: bool=false) = if state.loading: return let diff = getTime() - state.lastUpdate if diff.minutes < 5: return state.loading = true - let uri = makeUri("status.json") + let uri = makeUri("status.json", [("logout", $logout)]) ajaxGet(uri, @[], onStatus) proc renderHeader*(): VNode = if state.data.isNone: - getStatus() + getStatus() # TODO: Call this every render? let user = state.data.map(x => x.user).flatten result = buildHtml(tdiv()): # TODO: Why do some buildHtml's need this? @@ -91,7 +95,7 @@ when defined(js): italic(class="fas fa-sign-in-alt") text " Log in" else: - render(user.get(), "avatar") + render(state.userMenu, user.get()) # Modals render(state.loginModal) diff --git a/redesign/nimforum.scss b/redesign/nimforum.scss index a819796..99cf68b 100644 --- a/redesign/nimforum.scss +++ b/redesign/nimforum.scss @@ -81,6 +81,13 @@ $logo-height: $navbar-height - 20px; height: $logo-height; } +.menu-right { + // To make sure the user menu doesn't move off the screen. + left: auto; + right: 0; + position: absolute; +} + // - Main buttons #main-buttons { margin-top: $control-padding-y*2; diff --git a/redesign/threadlist.nim b/redesign/threadlist.nim index 58094be..7ab611f 100644 --- a/redesign/threadlist.nim +++ b/redesign/threadlist.nim @@ -1,4 +1,4 @@ -import strformat, times, options, json, httpcore +import strformat, times, options, json, httpcore, sugar import category diff --git a/redesign/usermenu.nim b/redesign/usermenu.nim new file mode 100644 index 0000000..2bb35a1 --- /dev/null +++ b/redesign/usermenu.nim @@ -0,0 +1,48 @@ + +when defined(js): + import sugar + + include karax/prelude + import karax/[vstyles] + import karaxutils + + import threadlist + type + UserMenu* = ref object + shown: bool + user: User + onLogout: proc () + + proc newUserMenu*(onLogout: proc ()): UserMenu = + UserMenu( + shown: false, + onLogout: onLogout + ) + + proc render*(state: UserMenu, user: User): VNode = + result = buildHtml(): + tdiv(): + figure(class="avatar c-hand", + onClick=(e: Event, n: VNode) => (state.shown = true)): + img(src=user.avatarUrl, title=user.name) + if user.isOnline: + italic(class="avatar-presense online") + + ul(class="menu menu-right", style=style( + StyleAttr.display, if state.shown: "inherit" else: "none" + )): + li(class="menu-item"): + tdiv(class="tile tile-centered"): + tdiv(class="tile-icon"): + img(class="avatar", src=user.avatarUrl, + title=user.name) + tdiv(class="tile-content"): + text user.name + li(class="divider") + li(class="menu-item"): + a(href=makeUri("/profile/" & user.name)): + text "My profile" + li(class="menu-item c-hand"): + a(onClick = (e: Event, n: VNode) => + (state.shown=false; state.onLogout())): + text "Logout" \ No newline at end of file