Skip to content
This repository was archived by the owner on Jul 12, 2023. It is now read-only.

Commit 35cff81

Browse files
authored
Search mobile apps (#1043)
1 parent 25680fe commit 35cff81

File tree

4 files changed

+46
-6
lines changed

4 files changed

+46
-6
lines changed

cmd/server/assets/mobileapps/index.html

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,23 @@
2323
</a>
2424
</div>
2525

26+
<div class="card-body">
27+
<form method="GET" action="/mobile-apps" id="search-form">
28+
<div class="input-group">
29+
<input type="search" name="q" id="search" value="{{.query}}" placeholder="Search..."
30+
autocomplete="off" class="form-control" />
31+
<div class="input-group-append">
32+
<button type="submit" class="btn btn-primary">
33+
<span class="oi oi-magnifying-glass" aria-hidden="true"></span>
34+
<span class="sr-only">Search</span>
35+
</button>
36+
</div>
37+
</div>
38+
</form>
39+
</div>
40+
2641
{{if $apps}}
27-
<table class="table table-bordered table-striped table-fixed table-inner-border-only mb-0">
42+
<table class="table table-bordered table-striped table-fixed table-inner-border-only border-top mb-0">
2843
<thead>
2944
<tr>
3045
<th scope="col" width="40"></th>
@@ -72,7 +87,7 @@
7287
</table>
7388
{{else}}
7489
<p class="card-body text-center mb-0">
75-
<em>There are no mobile apps.</em>
90+
<em>There are no mobile apps{{if .query}} that match the query{{end}}.</em>
7691
</p>
7792
{{end}}
7893
</div>

pkg/controller/mobileapps/index.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ import (
2323
"github.com/google/exposure-notifications-verification-server/pkg/pagination"
2424
)
2525

26+
const (
27+
// QueryKeySearch is the query key where the search query exists.
28+
QueryKeySearch = "q"
29+
)
30+
2631
func (c *Controller) HandleIndex() http.Handler {
2732
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2833
ctx := r.Context()
@@ -39,22 +44,27 @@ func (c *Controller) HandleIndex() http.Handler {
3944
return
4045
}
4146

47+
var scopes []database.Scope
48+
q := r.FormValue(QueryKeySearch)
49+
scopes = append(scopes, database.WithMobileAppSearch(q))
50+
4251
// Perform the lazy load on authorized apps for the realm.
43-
apps, paginator, err := realm.ListMobileApps(c.db, pageParams)
52+
apps, paginator, err := realm.ListMobileApps(c.db, pageParams, scopes...)
4453
if err != nil {
4554
controller.InternalError(w, r, c.h, err)
4655
return
4756
}
4857

49-
c.renderIndex(ctx, w, apps, paginator)
58+
c.renderIndex(ctx, w, apps, paginator, q)
5059
})
5160
}
5261

5362
// renderIndex renders the index page.
54-
func (c *Controller) renderIndex(ctx context.Context, w http.ResponseWriter, apps []*database.MobileApp, paginator *pagination.Paginator) {
63+
func (c *Controller) renderIndex(ctx context.Context, w http.ResponseWriter, apps []*database.MobileApp, paginator *pagination.Paginator, query string) {
5564
m := templateMap(ctx)
5665
m.Title("Mobile apps")
5766
m["apps"] = apps
67+
m["query"] = query
5868
m["paginator"] = paginator
5969
c.h.RenderHTML(w, "mobileapps/index", m)
6070
}

pkg/database/realm.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -735,11 +735,12 @@ func (r *Realm) FindAuthorizedApp(db *Database, id interface{}) (*AuthorizedApp,
735735
}
736736

737737
// ListMobileApps gets all the mobile apps for the realm.
738-
func (r *Realm) ListMobileApps(db *Database, p *pagination.PageParams) ([]*MobileApp, *pagination.Paginator, error) {
738+
func (r *Realm) ListMobileApps(db *Database, p *pagination.PageParams, scopes ...Scope) ([]*MobileApp, *pagination.Paginator, error) {
739739
var mobileApps []*MobileApp
740740
query := db.db.
741741
Unscoped().
742742
Model(&MobileApp{}).
743+
Scopes(scopes...).
743744
Where("realm_id = ?", r.ID).
744745
Order("mobile_apps.deleted_at DESC, LOWER(mobile_apps.name)")
745746

pkg/database/scopes.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,20 @@ func WithAuthorizedAppSearch(q string) Scope {
8383
}
8484
}
8585

86+
// WithMobileAppSearch returns a scope that adds querying for mobile apps by
87+
// name, case-insensitive. It's only applicable to functions that query
88+
// MobileApp.
89+
func WithMobileAppSearch(q string) Scope {
90+
return func(db *gorm.DB) *gorm.DB {
91+
q = project.TrimSpace(q)
92+
if q != "" {
93+
q = `%` + q + `%`
94+
return db.Where("mobile_apps.name ILIKE ?", q)
95+
}
96+
return db
97+
}
98+
}
99+
86100
// WithRealmSearch returns a scope that adds querying for realms by name. It's
87101
// only applicable to functions that query Realm.
88102
func WithRealmSearch(q string) Scope {

0 commit comments

Comments
 (0)