Skip to content

Commit

Permalink
fix(ui): improve dropdown box UX
Browse files Browse the repository at this point in the history
  • Loading branch information
leg100 committed Jul 24, 2023
1 parent 75a9eef commit d67de76
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 24 deletions.
8 changes: 4 additions & 4 deletions internal/auth/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,10 @@ func (u *User) IsSiteAdmin() bool {

func (u *User) CanAccessSite(action rbac.Action) bool {
switch action {
case rbac.CreateUserAction:
// A user can create a user account only if they are an owner of at least
// one organization. This permits an owner to create a user before adding
// them to a team.
case rbac.CreateUserAction, rbac.ListUsersAction:
// A user can perform these actions only if they are an owner of at
// least one organization. This permits an owner to search users or create
// a user before adding them to a team.
for _, team := range u.Teams {
if team.IsOwners() {
return true
Expand Down
8 changes: 8 additions & 0 deletions internal/http/html/static/css/output.css
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,10 @@ select {
padding-left: 2.5rem;
}

.pb-4 {
padding-bottom: 1rem;
}

.text-left {
text-align: left;
}
Expand Down Expand Up @@ -1171,6 +1175,10 @@ select {
font-weight: 600;
}

.italic {
font-style: italic;
}

.leading-snug {
line-height: 1.375;
}
Expand Down
21 changes: 11 additions & 10 deletions internal/http/html/static/templates/partials/search_dropdown.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,22 @@
>
<div
x-ref="panel"
x-show="open"
x-show="open && (existing?.includes(search) || isNew || filterAvailable?.length > 0)"
x-transition.origin.top.left
:id="$id('dropdown-button')"
x-cloak
class="absolute {{ get $width .Width }} mt-1 bg-white border border-black overflow-x-auto"
class="absolute flex flex-col {{ get $width .Width }} mt-1 bg-white overflow-x-auto border border-black"
>
<div class="sticky bottom-0 flex flex-col">
<button form="search-dropdown" class="text-left focus:bg-gray-200 hover:bg-gray-200 py-1 px-2" x-show="isNew">
Create:<span class="" x-text="search"></span>
</button>
<span class="text-left py-1 px-2 text-gray-600 italic" x-show="existing?.includes(search)">
<span x-text="search"></span> already added
</span>
<button form="search-dropdown" class="text-left focus:bg-gray-200 hover:bg-gray-200 py-1 px-2" x-show="isNew">
Create:<span x-text="search"></span>
</button>

<template x-for="item in filterAvailable" :key="item">
<button @click="search = item" form="search-dropdown" class="text-left focus:bg-gray-200 hover:bg-gray-200 py-1 px-2" x-text="item"></button>
</template>
</div>
<template x-for="item in filterAvailable" :key="item">
<button @click="search = item" form="search-dropdown" class="text-left focus:bg-gray-200 hover:bg-gray-200 py-1 px-2" x-text="item"></button>
</template>
</div>
</div>
{{ end }}
39 changes: 29 additions & 10 deletions internal/integration/team_ui_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package integration

import (
"fmt"
"testing"

"github.com/chromedp/cdproto/input"
"github.com/chromedp/chromedp"
"github.com/stretchr/testify/require"
)

// TestIntegration_TeamUI demonstrates managing teams and team members via the
Expand All @@ -14,7 +14,10 @@ func TestIntegration_TeamUI(t *testing.T) {
integrationTest(t)

daemon, org, ctx := setup(t, nil)
newbie := daemon.createUser(t)
_, err := daemon.CreateUser(ctx, "bob")
require.NoError(t, err)
_, err = daemon.CreateUser(ctx, "alice")
require.NoError(t, err)

browser.Run(t, ctx, chromedp.Tasks{
chromedp.Tasks{
Expand All @@ -27,20 +30,36 @@ func TestIntegration_TeamUI(t *testing.T) {
// go to owners team page
chromedp.Click(`//div[@class='content-list']//a[text()='owners']`),
screenshot(t, "owners_team_page"),
// select newbie as new team member
// set focus to search box
chromedp.Focus(`//input[@x-ref='input-search']`),
input.InsertText(newbie.Username),
input.InsertText(""),
// should trigger dropdown box showing both alice and bob
chromedp.WaitVisible(`//div[@x-ref='searchdrop']//button[text()='bob']`),
chromedp.WaitVisible(`//div[@x-ref='searchdrop']//button[text()='alice']`),
// select bob as new team member
input.InsertText("bob"),
screenshot(t),
// submit
chromedp.Submit(`//input[@x-ref='input-search']`),
screenshot(t),
// confirm newbie added
matchText(t, "//div[@role='alert']", "added team member: "+newbie.Username),
// remove newbie from team
chromedp.Click(fmt.Sprintf(`//div[@id='item-user-%s']//button[@id='remove-member-button']`, newbie.Username)),
// confirm bob added
matchText(t, "//div[@role='alert']", "added team member: bob"),
// remove bob from team
chromedp.Click(`//div[@id='item-user-bob']//button[@id='remove-member-button']`),
screenshot(t),
// confirm newbie removed
matchText(t, "//div[@role='alert']", "removed team member: "+newbie.Username),
// confirm bob removed
matchText(t, "//div[@role='alert']", "removed team member: bob"),
// now demonstrate specifying a username that doesn't belong to an
// existing user. The dropdown box should prompt to create the user
// and add them to the team.
chromedp.Focus(`//input[@x-ref='input-search']`),
input.InsertText("sarah"),
matchRegex(t, `//div[@x-ref='searchdrop']//button`, `Create:.*sarah`),
// submit
chromedp.Submit(`//input[@x-ref='input-search']`),
screenshot(t),
// confirm sarah added
matchText(t, "//div[@role='alert']", "added team member: sarah"),
},
})
}

0 comments on commit d67de76

Please sign in to comment.