mirror of
https://github.com/Theodor-Springmann-Stiftung/musenalm.git
synced 2025-10-29 09:15:33 +00:00
Allerhand Kleinigkeiten; Einzelansichten Reihen u Personen; Bandansicht
This commit is contained in:
@@ -23,6 +23,37 @@ func AgentForId(app core.App, id string) (*Agent, error) {
|
||||
return agent, nil
|
||||
}
|
||||
|
||||
func FTS5SearchAgents(app core.App, query string) ([]*Agent, error) {
|
||||
a := []*Agent{}
|
||||
q := NormalizeQuery(query)
|
||||
if len(q) == 0 {
|
||||
return a, nil
|
||||
}
|
||||
|
||||
ids, err := FTS5Search(app, AGENTS_TABLE, FTS5QueryRequest{
|
||||
Fields: []string{AGENTS_NAME_FIELD, AGENTS_PSEUDONYMS_FIELD, REFERENCES_FIELD, AGENTS_BIOGRAPHICAL_DATA_FIELD, ANNOTATION_FIELD},
|
||||
Query: q,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
idany := []any{}
|
||||
for _, id := range ids {
|
||||
idany = append(idany, id.ID)
|
||||
}
|
||||
|
||||
err = app.RecordQuery(AGENTS_TABLE).
|
||||
Where(dbx.HashExp{ID_FIELD: idany}).
|
||||
All(&a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func AgentsForEntries(app core.App, entries []*Entry) (map[string]*Agent, AgentsEntries, error) {
|
||||
eids := []any{}
|
||||
for _, e := range entries {
|
||||
|
||||
@@ -103,6 +103,17 @@ func EntryForId(app core.App, id string) (*Entry, error) {
|
||||
return entry, nil
|
||||
}
|
||||
|
||||
func EntriesForIds(app core.App, ids []any) ([]*Entry, error) {
|
||||
entries := []*Entry{}
|
||||
err := app.RecordQuery(ENTRIES_TABLE).
|
||||
Where(dbx.HashExp{ID_FIELD: ids}).
|
||||
All(&entries)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return entries, nil
|
||||
}
|
||||
|
||||
func EntryForMusenalmID(app core.App, id string) (*Entry, error) {
|
||||
entry := &Entry{}
|
||||
err := app.RecordQuery(ENTRIES_TABLE).
|
||||
|
||||
@@ -31,6 +31,7 @@ var AGENTS_FTS5_FIELDS = []string{
|
||||
AGENTS_PSEUDONYMS_FIELD,
|
||||
ANNOTATION_FIELD,
|
||||
COMMENT_FIELD,
|
||||
REFERENCES_FIELD,
|
||||
}
|
||||
|
||||
var PLACES_FTS5_FIELDS = []string{
|
||||
@@ -384,6 +385,7 @@ func FTS5ValuesAgent(agent *Agent) []string {
|
||||
agent.Pseudonyms(),
|
||||
datatypes.DeleteTags(agent.Annotation()),
|
||||
datatypes.DeleteTags(agent.Comment()),
|
||||
agent.References(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
57
dbmodels/queries.go
Normal file
57
dbmodels/queries.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package dbmodels
|
||||
|
||||
import (
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
)
|
||||
|
||||
// INFO: Queries to be reused
|
||||
// Rules
|
||||
// 1. Only one return type + error for every function
|
||||
// 2. Parameters can only be two
|
||||
// - core.App
|
||||
// - any id or multiple IDs (of an indexed field)
|
||||
// 3. Naming convention: <TableName>_<FilteredField>[s]
|
||||
// For scanning, with an Iter_ prefix, yields single row results
|
||||
|
||||
func REntriesAgents_Agent(app core.App, id string) ([]*REntriesAgents, error) {
|
||||
return TableByField[[]*REntriesAgents](
|
||||
app,
|
||||
RelationTableName(ENTRIES_TABLE, AGENTS_TABLE),
|
||||
AGENTS_TABLE,
|
||||
id,
|
||||
)
|
||||
}
|
||||
|
||||
func RContentsAgents_Agent(app core.App, id string) ([]*RContentsAgents, error) {
|
||||
return TableByField[[]*RContentsAgents](
|
||||
app,
|
||||
RelationTableName(CONTENTS_TABLE, AGENTS_TABLE),
|
||||
AGENTS_TABLE,
|
||||
id,
|
||||
)
|
||||
}
|
||||
|
||||
func REntriesSeries_Entries(app core.App, ids any) ([]*REntriesSeries, error) {
|
||||
return TableByField[[]*REntriesSeries](
|
||||
app,
|
||||
RelationTableName(ENTRIES_TABLE, SERIES_TABLE),
|
||||
ENTRIES_TABLE,
|
||||
ids,
|
||||
)
|
||||
}
|
||||
|
||||
func Agents_ID(app core.App, id string) (*Agent, error) {
|
||||
return TableByID[*Agent](app, AGENTS_TABLE, id)
|
||||
}
|
||||
|
||||
func Entries_IDs(app core.App, ids []any) ([]*Entry, error) {
|
||||
return TableByID[[]*Entry](app, ENTRIES_TABLE, ids)
|
||||
}
|
||||
|
||||
func Series_IDs(app core.App, ids []any) ([]*Series, error) {
|
||||
return TableByID[[]*Series](app, SERIES_TABLE, ids)
|
||||
}
|
||||
|
||||
func Contents_IDs(app core.App, ids []any) ([]*Content, error) {
|
||||
return TableByID[[]*Content](app, CONTENTS_TABLE, ids)
|
||||
}
|
||||
37
dbmodels/queries_iter.go
Normal file
37
dbmodels/queries_iter.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package dbmodels
|
||||
|
||||
import (
|
||||
"iter"
|
||||
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
)
|
||||
|
||||
// INFO: Iterator queries to be reused
|
||||
// Rules
|
||||
// 1. Only iterator return type + error for every function
|
||||
// 2. Parameters can only be two
|
||||
// - core.App
|
||||
// - any id or multiple IDs (of an indexed field)
|
||||
// 3. Naming convention: Iter_<TableName>_<FilteredField>[s]
|
||||
|
||||
// BUG: this is not working as expected, see Iter_TableByField in queryhelpers.go
|
||||
func Iter_REntriesAgents_Agent(app core.App, id string) (iter.Seq2[*REntriesAgents, error], error) {
|
||||
innerIterator, err := Iter_TableByField[REntriesAgents](
|
||||
app,
|
||||
RelationTableName(ENTRIES_TABLE, AGENTS_TABLE),
|
||||
AGENTS_TABLE,
|
||||
id,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return func(yield func(*REntriesAgents, error) bool) {
|
||||
for item, err := range innerIterator {
|
||||
if !yield(item, err) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
99
dbmodels/queryhelpers.go
Normal file
99
dbmodels/queryhelpers.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package dbmodels
|
||||
|
||||
import (
|
||||
"iter"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
)
|
||||
|
||||
// INFO: These functions are very abstract interfaces to the DB that help w querying
|
||||
|
||||
// BUG: this is not working:
|
||||
// github.com/pocketbase/pocketbase/apis.NewRouter.panicRecover.func3.1()
|
||||
// /home/simon/go/pkg/mod/github.com/pocketbase/pocketbase@v0.25.5/apis/middlewares.go:269 +0x13c
|
||||
// panic({0x15b34c0?, 0x2831680?})
|
||||
// /usr/local/go/src/runtime/panic.go:787 +0x132
|
||||
// github.com/pocketbase/pocketbase/core.(*Record).FieldsData(0xc000632820)
|
||||
// /home/simon/go/pkg/mod/github.com/pocketbase/pocketbase@v0.25.5/core/record_model.go:774 +0x1a
|
||||
// github.com/pocketbase/pocketbase/core.(*Record).PostScan(0xc000632820)
|
||||
// /home/simon/go/pkg/mod/github.com/pocketbase/pocketbase@v0.25.5/core/record_model.go:591 +0x4e
|
||||
// github.com/pocketbase/dbx.(*Rows).ScanStruct(0xc00052e6d0, {0x175f840?, 0xc000586060?})
|
||||
// /home/simon/go/pkg/mod/github.com/pocketbase/dbx@v1.11.0/rows.go:97 +0x32e
|
||||
// github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels.Iter_TableByField[...].func1()
|
||||
// /home/simon/source/musenalm/dbmodels/queryhelpers.go:23 +0x65
|
||||
// github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels.Iter_REntriesAgents_Agent.func1(0xc000624840)
|
||||
// /home/simon/source/musenalm/dbmodels/queries_iter.go:30 +0xae
|
||||
// github.com/Theodor-Springmann-Stiftung/musenalm/pages.(*PersonResult).FilterEntriesByPerson(0x1762c40?, {0x1dfba88, 0xc000438870}, {0xc00004627c, 0xf}, 0xc000064720)
|
||||
// /home/simon/source/musenalm/pages/person.go:111 +0x248
|
||||
// github.com/Theodor-Springmann-Stiftung/musenalm/pages.NewPersonResult({0x1dfba88, 0xc000438870}, {0xc00004627c, 0xf})
|
||||
// /home/simon/source/musenalm/pages/person.go:92 +0x4f
|
||||
// github.com/Theodor-Springmann-Stiftung/musenalm/pages.(*PersonPage).Setup.func1(0xc0002da000)
|
||||
// /home/simon/source/musenalm/pages/person.go:46 +0x1ee
|
||||
// github.com/pocketbase/pocketbase/tools/hook.(*Hook[...]).Trigger.func1()
|
||||
// /home/simon/go/pkg/mod/github.com/pocketbase/pocketbase@v0.25.5/tools/hook/hook.go:169 +0x5d
|
||||
// github.com/pocketbase/pocketbase/tools/hook.(*Event).Next(0xc0002da000?)
|
||||
// /home/simon/go/pkg/mod/github.com/pocketbase/pocketbase@v0.25.5/tools/hook/event.go:32 +0x17
|
||||
// github.com/pocketbase/pocketbase/apis.NewRouter.BodyLimit.func7(0xc0002da000)
|
||||
// /home
|
||||
func Iter_TableByField[T interface{}](app core.App, table, field string, value interface{}) (iter.Seq2[*T, error], error) {
|
||||
rows, err := app.RecordQuery(table).
|
||||
Where(dbx.HashExp{field: value}).
|
||||
Rows()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return func(yield func(*T, error) bool) {
|
||||
for rows.Next() {
|
||||
var item T
|
||||
err := rows.ScanStruct(&item)
|
||||
if !yield(&item, err) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
func Iter_TableByID[T interface{}](app core.App, table, id interface{}) (iter.Seq2[*T, error], error) {
|
||||
rows, err := app.RecordQuery(table).
|
||||
Where(dbx.HashExp{ID_FIELD: id}).
|
||||
Rows()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return func(yield func(*T, error) bool) {
|
||||
for rows.Next() {
|
||||
var item T
|
||||
rows.Scan(&item)
|
||||
if !yield(&item, nil) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
func TableByField[T interface{}](app core.App, table, field string, value interface{}) (T, error) {
|
||||
var ret T
|
||||
err := app.RecordQuery(table).
|
||||
Where(dbx.HashExp{field: value}).
|
||||
All(&ret)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func TableByID[T interface{}](app core.App, table, id interface{}) (T, error) {
|
||||
var ret T
|
||||
err := app.RecordQuery(table).
|
||||
Where(dbx.HashExp{ID_FIELD: id}).
|
||||
All(&ret)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
@@ -8,19 +8,11 @@ import (
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/collate"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
type SeriesEntries map[string][]*REntriesSeries
|
||||
|
||||
func SortSeriessesByTitle(series []*Series) {
|
||||
collator := collate.New(language.German)
|
||||
slices.SortFunc(series, func(i, j *Series) int {
|
||||
return collator.CompareString(i.Title(), j.Title())
|
||||
})
|
||||
}
|
||||
|
||||
func MusenalmIDSearchSeries(app core.App, query string) ([]*Series, error) {
|
||||
series := []*Series{}
|
||||
err := app.RecordQuery(SERIES_TABLE).
|
||||
|
||||
43
dbmodels/sorting.go
Normal file
43
dbmodels/sorting.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package dbmodels
|
||||
|
||||
import (
|
||||
"slices"
|
||||
|
||||
"golang.org/x/text/collate"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
func Sort_Series_Title(series []*Series) {
|
||||
collator := collate.New(language.German)
|
||||
slices.SortFunc(series, func(i, j *Series) int {
|
||||
return collator.CompareString(i.Title(), j.Title())
|
||||
})
|
||||
}
|
||||
|
||||
func Sort_Entries_Title_Year(entries []*Entry) {
|
||||
collator := collate.New(language.German)
|
||||
slices.SortFunc(entries, func(i, j *Entry) int {
|
||||
if i.PreferredTitle() == j.PreferredTitle() {
|
||||
return i.Year() - j.Year()
|
||||
}
|
||||
return collator.CompareString(i.PreferredTitle(), j.PreferredTitle())
|
||||
})
|
||||
}
|
||||
|
||||
func Sort_Entries_Year_Title(entries []*Entry) {
|
||||
collator := collate.New(language.German)
|
||||
slices.SortFunc(entries, func(i, j *Entry) int {
|
||||
if i.Year() == j.Year() {
|
||||
return collator.CompareString(i.PreferredTitle(), j.PreferredTitle())
|
||||
}
|
||||
return i.Year() - j.Year()
|
||||
})
|
||||
}
|
||||
|
||||
func Sort_REntriesSeries_Year(entries []*REntriesSeries, entriesMap map[string]*Entry) {
|
||||
slices.SortFunc(entries, func(i, j *REntriesSeries) int {
|
||||
ientry := entriesMap[i.Entry()]
|
||||
jentry := entriesMap[j.Entry()]
|
||||
return ientry.Year() - jentry.Year()
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user