Add a profile dropdown menu
This commit is contained in:
parent
a646dddec0
commit
dffd1c94b5
|
@ -8298,7 +8298,7 @@ header .header-nav > .root-item > a {
|
|||
display: block;
|
||||
padding: var(--spacing-3);
|
||||
}
|
||||
header .header-nav .submenu {
|
||||
header .submenu {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
|
@ -8309,16 +8309,16 @@ header .header-nav .submenu {
|
|||
border-width: 1px;
|
||||
border-top-width: 0;
|
||||
}
|
||||
header .header-nav .submenu > a {
|
||||
header .submenu > a {
|
||||
padding: var(--spacing-2) var(--spacing-3);
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
z-index: 1;
|
||||
}
|
||||
header .header-nav .root-item:not(:hover):not(.clicked) > .submenu {
|
||||
header .root-item:not(:hover):not(.clicked) > .submenu {
|
||||
display: none;
|
||||
}
|
||||
header .header-nav .root-item.clicked .svgicon {
|
||||
header .root-item.clicked .svgicon {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
header:not(.clicked) .root-item:not(:hover) > .submenu,
|
||||
|
|
|
@ -67,7 +67,7 @@ func TestLoginWithDiscord(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestLogoutAction(t *testing.T) {
|
||||
AssertRegexMatch(t, BuildLogoutAction(""), RegexLogoutAction, nil)
|
||||
AssertRegexMatch(t, BuildLogoutAction(""), RegexLogout, nil)
|
||||
}
|
||||
|
||||
func TestRegister(t *testing.T) {
|
||||
|
|
|
@ -219,7 +219,7 @@ func BuildLoginWithDiscord(redirectTo string) string {
|
|||
return Url("/login-with-discord", []Q{{Name: "redirect", Value: redirectTo}})
|
||||
}
|
||||
|
||||
var RegexLogoutAction = regexp.MustCompile("^/logout$")
|
||||
var RegexLogout = regexp.MustCompile("^/logout$")
|
||||
|
||||
func BuildLogoutAction(redir string) string {
|
||||
defer CatchPanic()
|
||||
|
|
|
@ -144,34 +144,34 @@ header {
|
|||
display: block;
|
||||
padding: var(--spacing-3);
|
||||
}
|
||||
}
|
||||
|
||||
.submenu {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
min-width: 8rem;
|
||||
background-color: var(--c3);
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-top-width: 0;
|
||||
.submenu {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
min-width: 8rem;
|
||||
background-color: var(--c3);
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-top-width: 0;
|
||||
|
||||
>a {
|
||||
padding: var(--spacing-2) var(--spacing-3);
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
z-index: 1;
|
||||
}
|
||||
>a {
|
||||
padding: var(--spacing-2) var(--spacing-3);
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.root-item {
|
||||
&:not(:hover):not(.clicked)>.submenu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.root-item {
|
||||
&:not(:hover):not(.clicked)>.submenu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.clicked .svgicon {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
&.clicked .svgicon {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,13 +39,22 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a class="db {{ if .User }}pv2 ph3{{ else }}pa3{{ end }} lh-solid flex f6 {{ if not .User }}bl{{ end }}" href="{{ or .Header.UserProfileUrl .LoginPageUrl }}">
|
||||
{{ with .User }}
|
||||
<img class="avatar avatar-user" src="{{ .AvatarUrl }}">
|
||||
{{ else }}
|
||||
Log In
|
||||
<div class="root-item f6">
|
||||
<a class="db {{ if .User }}pv2 ph3{{ else }}pa3{{ end }} lh-solid flex f6 {{ if not .User }}bl{{ end }}" href="{{ or .Header.UserProfileUrl .LoginPageUrl }}">
|
||||
{{ with .User }}
|
||||
<img class="avatar avatar-user" src="{{ .AvatarUrl }}">
|
||||
{{ else }}
|
||||
Log In
|
||||
{{ end }}
|
||||
</a>
|
||||
{{ if .User }}
|
||||
<div class="submenu right-0" id="profile-submenu">
|
||||
<a href="{{ .Header.UserProfileUrl }}">Profile</a>
|
||||
<a href="{{ .Header.UserSettingsUrl }}">Settings</a>
|
||||
<a href="{{ .Header.LogoutUrl }}">Log Out</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
<script type="text/javascript">
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<a class="dib pv2 pl2" href="{{ .Header.UserProfileUrl }}">{{ .User.Username }}</a>
|
||||
<a class="dib pv2 pr2" href="{{ .Header.UserSettingsUrl }}">(settings)</a>
|
||||
</div>
|
||||
<a class="pa2" href="{{ .Header.LogoutActionUrl }}"><span class="icon-logout"></span> Log Out</a>
|
||||
<a class="pa2" href="{{ .Header.LogoutUrl }}"><span class="icon-logout"></span> Log Out</a>
|
||||
{{ else }}
|
||||
<a class="pa2" id="register-link" href="{{ .Header.RegisterUrl }}">Register</a>
|
||||
<a class="pa2" id="login-link" href="{{ .LoginPageUrl }}">Log in</a>
|
||||
|
|
|
@ -40,14 +40,12 @@ func (bd *BaseData) AddImmediateNotice(class, content string) {
|
|||
}
|
||||
|
||||
type Header struct {
|
||||
AdminUrl string
|
||||
UserProfileUrl string
|
||||
UserSettingsUrl string
|
||||
LoginActionUrl string
|
||||
LogoutActionUrl string
|
||||
ForgotPasswordUrl string
|
||||
RegisterUrl string
|
||||
LoginWithDiscordUrl string
|
||||
AdminUrl string
|
||||
UserProfileUrl string
|
||||
UserSettingsUrl string
|
||||
LogoutUrl string
|
||||
ForgotPasswordUrl string
|
||||
RegisterUrl string
|
||||
|
||||
HMNHomepageUrl string
|
||||
ProjectIndexUrl string
|
||||
|
|
|
@ -64,13 +64,11 @@ func getBaseData(c *RequestContext, title string, breadcrumbs []templates.Breadc
|
|||
|
||||
IsProjectPage: !project.IsHMN(),
|
||||
Header: templates.Header{
|
||||
AdminUrl: hmnurl.BuildAdminApprovalQueue(), // TODO(asaf): Replace with general-purpose admin page
|
||||
UserSettingsUrl: hmnurl.BuildUserSettings(""),
|
||||
LoginActionUrl: hmnurl.BuildLoginAction(c.FullUrl()),
|
||||
LogoutActionUrl: hmnurl.BuildLogoutAction(c.FullUrl()),
|
||||
ForgotPasswordUrl: hmnurl.BuildRequestPasswordReset(),
|
||||
RegisterUrl: hmnurl.BuildRegister(""),
|
||||
LoginWithDiscordUrl: hmnurl.BuildLoginWithDiscord(c.FullUrl()),
|
||||
AdminUrl: hmnurl.BuildAdminApprovalQueue(), // TODO(asaf): Replace with general-purpose admin page
|
||||
UserSettingsUrl: hmnurl.BuildUserSettings(""),
|
||||
LogoutUrl: hmnurl.BuildLogoutAction(c.FullUrl()),
|
||||
ForgotPasswordUrl: hmnurl.BuildRequestPasswordReset(),
|
||||
RegisterUrl: hmnurl.BuildRegister(""),
|
||||
|
||||
HMNHomepageUrl: hmnurl.BuildHomepage(),
|
||||
ProjectIndexUrl: hmnurl.BuildProjectIndex(),
|
||||
|
|
|
@ -137,7 +137,7 @@ func NewWebsiteRoutes(conn *pgxpool.Pool) http.Handler {
|
|||
hmnOnly.GET(hmnurl.RegexOldHome, Index)
|
||||
|
||||
hmnOnly.POST(hmnurl.RegexLoginAction, securityTimerMiddleware(time.Millisecond*100, Login))
|
||||
hmnOnly.GET(hmnurl.RegexLogoutAction, Logout)
|
||||
hmnOnly.GET(hmnurl.RegexLogout, Logout)
|
||||
hmnOnly.GET(hmnurl.RegexLoginPage, LoginPage)
|
||||
hmnOnly.GET(hmnurl.RegexLoginWithDiscord, LoginWithDiscord)
|
||||
|
||||
|
|
Loading…
Reference in New Issue