Mutation to get all tags (#76)

Reviewed-on: #76
Co-authored-by: Daniel Ponte <amigan@gmail.com>
Co-committed-by: Daniel Ponte <amigan@gmail.com>
This commit is contained in:
Daniel Ponte 2024-12-18 10:51:26 -05:00 committed by amigan
parent a63ebb470d
commit d95cda6b44
6 changed files with 108 additions and 0 deletions

View file

@ -936,6 +936,64 @@ func (_c *Store_GetAPIKey_Call) RunAndReturn(run func(context.Context, string) (
return _c
}
// GetAllTalkgroupTags provides a mock function with given fields: ctx
func (_m *Store) GetAllTalkgroupTags(ctx context.Context) ([]string, error) {
ret := _m.Called(ctx)
if len(ret) == 0 {
panic("no return value specified for GetAllTalkgroupTags")
}
var r0 []string
var r1 error
if rf, ok := ret.Get(0).(func(context.Context) ([]string, error)); ok {
return rf(ctx)
}
if rf, ok := ret.Get(0).(func(context.Context) []string); ok {
r0 = rf(ctx)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]string)
}
}
if rf, ok := ret.Get(1).(func(context.Context) error); ok {
r1 = rf(ctx)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Store_GetAllTalkgroupTags_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAllTalkgroupTags'
type Store_GetAllTalkgroupTags_Call struct {
*mock.Call
}
// GetAllTalkgroupTags is a helper method to define mock.On call
// - ctx context.Context
func (_e *Store_Expecter) GetAllTalkgroupTags(ctx interface{}) *Store_GetAllTalkgroupTags_Call {
return &Store_GetAllTalkgroupTags_Call{Call: _e.mock.On("GetAllTalkgroupTags", ctx)}
}
func (_c *Store_GetAllTalkgroupTags_Call) Run(run func(ctx context.Context)) *Store_GetAllTalkgroupTags_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context))
})
return _c
}
func (_c *Store_GetAllTalkgroupTags_Call) Return(_a0 []string, _a1 error) *Store_GetAllTalkgroupTags_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *Store_GetAllTalkgroupTags_Call) RunAndReturn(run func(context.Context) ([]string, error)) *Store_GetAllTalkgroupTags_Call {
_c.Call.Return(run)
return _c
}
// GetAppPrefs provides a mock function with given fields: ctx, appName, uid
func (_m *Store) GetAppPrefs(ctx context.Context, appName string, uid int) ([]byte, error) {
ret := _m.Called(ctx, appName, uid)

View file

@ -24,6 +24,7 @@ type Querier interface {
DeleteTalkgroup(ctx context.Context, systemID int32, tGID int32) error
DeleteUser(ctx context.Context, username string) error
GetAPIKey(ctx context.Context, apiKey string) (ApiKey, error)
GetAllTalkgroupTags(ctx context.Context) ([]string, error)
GetAppPrefs(ctx context.Context, appName string, uid int) ([]byte, error)
GetCallAudioByID(ctx context.Context, id uuid.UUID) (GetCallAudioByIDRow, error)
GetDatabaseSize(ctx context.Context) (string, error)

View file

@ -93,6 +93,30 @@ func (q *Queries) DeleteTalkgroup(ctx context.Context, systemID int32, tGID int3
return err
}
const getAllTalkgroupTags = `-- name: GetAllTalkgroupTags :many
SELECT UNNEST(tgs.tags)::TEXT tag FROM talkgroups tgs GROUP BY tag ORDER BY COUNT(*) DESC
`
func (q *Queries) GetAllTalkgroupTags(ctx context.Context) ([]string, error) {
rows, err := q.db.Query(ctx, getAllTalkgroupTags)
if err != nil {
return nil, err
}
defer rows.Close()
var items []string
for rows.Next() {
var tag string
if err := rows.Scan(&tag); err != nil {
return nil, err
}
items = append(items, tag)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getSystemName = `-- name: GetSystemName :one
SELECT name FROM systems WHERE id = $1
`

View file

@ -44,6 +44,8 @@ func (tga *talkgroupAPI) Subrouter() http.Handler {
r.Delete(`/{system:\d+}`, tga.deleteSystem)
r.Delete(`/{system:\d+}/{id:\d+}`, tga.deleteTalkgroup)
r.Get(`/tags`, tga.tags)
r.Post("/import", tga.tgImport)
r.Post("/export", tga.tgExport)
@ -356,3 +358,16 @@ func (tga *talkgroupAPI) putSystem(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNoContent)
}
func (tga *talkgroupAPI) tags(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
tgs := tgstore.FromCtx(ctx)
tags, err := tgs.Tags(ctx)
if err != nil {
wErr(w, r, autoError(err))
return
}
respond(w, r, tags)
}

View file

@ -60,6 +60,9 @@ type Store interface {
// SystemName retrieves a system name from the store. It returns the record and whether one was found.
SystemName(ctx context.Context, id int) (string, bool)
// Tags returns all distinct tags.
Tags(ctx context.Context) ([]string, error)
// Hint hints the Store that the provided talkgroups will be asked for.
Hint(ctx context.Context, tgs []tgsp.ID) error
@ -731,3 +734,7 @@ func (t *cache) CreateSystem(ctx context.Context, id int, name string) error {
return database.FromCtx(ctx).CreateSystem(ctx, id, name)
}
func (t *cache) Tags(ctx context.Context) ([]string, error) {
return database.FromCtx(ctx).GetAllTalkgroupTags(ctx)
}

View file

@ -24,6 +24,9 @@ WHERE system_id = @system_id AND tgid = @tg_id;
SELECT sqlc.embed(talkgroups) FROM talkgroups
WHERE (system_id, tgid) = (@system_id, @tg_id);
-- name: GetAllTalkgroupTags :many
SELECT UNNEST(tgs.tags)::TEXT tag FROM talkgroups tgs GROUP BY tag ORDER BY COUNT(*) DESC;
-- name: GetTalkgroupWithLearned :one
SELECT
sqlc.embed(tg), sqlc.embed(sys)