mirror of
https://github.com/Theodor-Springmann-Stiftung/musenalm.git
synced 2025-10-29 17:25:32 +00:00
Basis Suche Inhalte
This commit is contained in:
@@ -417,6 +417,8 @@ var PUBLIC_VIEW_RULE = types.Pointer("")
|
|||||||
var PUBLIC_LIST_RULE = types.Pointer("")
|
var PUBLIC_LIST_RULE = types.Pointer("")
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
FTS_LIMIT = 100000
|
||||||
|
|
||||||
PLACES_TABLE = "places"
|
PLACES_TABLE = "places"
|
||||||
AGENTS_TABLE = "agents"
|
AGENTS_TABLE = "agents"
|
||||||
SERIES_TABLE = "series"
|
SERIES_TABLE = "series"
|
||||||
|
|||||||
@@ -204,6 +204,10 @@ func (e *Entry) MusenalmID() int {
|
|||||||
return e.GetInt(MUSENALMID_FIELD)
|
return e.GetInt(MUSENALMID_FIELD)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Entry) MusenalmIDString() string {
|
||||||
|
return e.GetString(MUSENALMID_FIELD)
|
||||||
|
}
|
||||||
|
|
||||||
func (e *Entry) SetMusenalmID(musenalmID int) {
|
func (e *Entry) SetMusenalmID(musenalmID int) {
|
||||||
e.Set(MUSENALMID_FIELD, musenalmID)
|
e.Set(MUSENALMID_FIELD, musenalmID)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package dbmodels
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
@@ -162,7 +161,6 @@ func NormalizeQuery(query string) Query {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, r := range query {
|
for _, r := range query {
|
||||||
fmt.Printf("Rune: %v\n", r)
|
|
||||||
if r == '"' {
|
if r == '"' {
|
||||||
if isInQuotes {
|
if isInQuotes {
|
||||||
addToken()
|
addToken()
|
||||||
@@ -185,12 +183,6 @@ func NormalizeQuery(query string) Query {
|
|||||||
at()
|
at()
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Query: %v\n", query)
|
|
||||||
fmt.Printf("Include: %v\n", include)
|
|
||||||
fmt.Printf("Exclude: %v\n", exclude)
|
|
||||||
fmt.Printf("UnsafeI: %v\n", unsafeI)
|
|
||||||
fmt.Printf("UnsafeE: %v\n", unsafeE)
|
|
||||||
|
|
||||||
return Query{
|
return Query{
|
||||||
Include: include,
|
Include: include,
|
||||||
Exclude: exclude,
|
Exclude: exclude,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package dbmodels
|
package dbmodels
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/Theodor-Springmann-Stiftung/musenalm/helpers/datatypes"
|
"github.com/Theodor-Springmann-Stiftung/musenalm/helpers/datatypes"
|
||||||
@@ -146,7 +147,7 @@ func (q *FTS5Query) Query() string {
|
|||||||
query += " { " + strings.Join(m.Fields, " ") + " } : \"" + q.Escape(m.Value) + "\""
|
query += " { " + strings.Join(m.Fields, " ") + " } : \"" + q.Escape(m.Value) + "\""
|
||||||
}
|
}
|
||||||
|
|
||||||
query += "'"
|
query += "' LIMIT " + strconv.Itoa(FTS_LIMIT)
|
||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
// For scanning, with an Iter_ prefix, yields single row results
|
// For scanning, with an Iter_ prefix, yields single row results
|
||||||
|
|
||||||
func REntriesAgents_Agent(app core.App, id string) ([]*REntriesAgents, error) {
|
func REntriesAgents_Agent(app core.App, id string) ([]*REntriesAgents, error) {
|
||||||
return TableByFields[[]*REntriesAgents](
|
return TableByFields[*REntriesAgents](
|
||||||
app,
|
app,
|
||||||
RelationTableName(ENTRIES_TABLE, AGENTS_TABLE),
|
RelationTableName(ENTRIES_TABLE, AGENTS_TABLE),
|
||||||
AGENTS_TABLE,
|
AGENTS_TABLE,
|
||||||
@@ -23,7 +23,7 @@ func REntriesAgents_Agent(app core.App, id string) ([]*REntriesAgents, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func REntriesAgents_Entry(app core.App, id string) ([]*REntriesAgents, error) {
|
func REntriesAgents_Entry(app core.App, id string) ([]*REntriesAgents, error) {
|
||||||
return TableByFields[[]*REntriesAgents](
|
return TableByFields[*REntriesAgents](
|
||||||
app,
|
app,
|
||||||
RelationTableName(ENTRIES_TABLE, AGENTS_TABLE),
|
RelationTableName(ENTRIES_TABLE, AGENTS_TABLE),
|
||||||
ENTRIES_TABLE,
|
ENTRIES_TABLE,
|
||||||
@@ -32,7 +32,7 @@ func REntriesAgents_Entry(app core.App, id string) ([]*REntriesAgents, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func REntriesAgents_Entries(app core.App, ids []any) ([]*REntriesAgents, error) {
|
func REntriesAgents_Entries(app core.App, ids []any) ([]*REntriesAgents, error) {
|
||||||
return TableByFields[[]*REntriesAgents](
|
return TableByFields[*REntriesAgents](
|
||||||
app,
|
app,
|
||||||
RelationTableName(ENTRIES_TABLE, AGENTS_TABLE),
|
RelationTableName(ENTRIES_TABLE, AGENTS_TABLE),
|
||||||
ENTRIES_TABLE,
|
ENTRIES_TABLE,
|
||||||
@@ -41,7 +41,7 @@ func REntriesAgents_Entries(app core.App, ids []any) ([]*REntriesAgents, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RContentsAgents_Agent(app core.App, id string) ([]*RContentsAgents, error) {
|
func RContentsAgents_Agent(app core.App, id string) ([]*RContentsAgents, error) {
|
||||||
return TableByFields[[]*RContentsAgents](
|
return TableByFields[*RContentsAgents](
|
||||||
app,
|
app,
|
||||||
RelationTableName(CONTENTS_TABLE, AGENTS_TABLE),
|
RelationTableName(CONTENTS_TABLE, AGENTS_TABLE),
|
||||||
AGENTS_TABLE,
|
AGENTS_TABLE,
|
||||||
@@ -50,7 +50,7 @@ func RContentsAgents_Agent(app core.App, id string) ([]*RContentsAgents, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RContentsAgents_Contents(app core.App, id []any) ([]*RContentsAgents, error) {
|
func RContentsAgents_Contents(app core.App, id []any) ([]*RContentsAgents, error) {
|
||||||
return TableByFields[[]*RContentsAgents](
|
return TableByFields[*RContentsAgents](
|
||||||
app,
|
app,
|
||||||
RelationTableName(CONTENTS_TABLE, AGENTS_TABLE),
|
RelationTableName(CONTENTS_TABLE, AGENTS_TABLE),
|
||||||
CONTENTS_TABLE,
|
CONTENTS_TABLE,
|
||||||
@@ -59,7 +59,7 @@ func RContentsAgents_Contents(app core.App, id []any) ([]*RContentsAgents, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RContentsAgents_Content(app core.App, id string) ([]*RContentsAgents, error) {
|
func RContentsAgents_Content(app core.App, id string) ([]*RContentsAgents, error) {
|
||||||
return TableByFields[[]*RContentsAgents](
|
return TableByFields[*RContentsAgents](
|
||||||
app,
|
app,
|
||||||
RelationTableName(CONTENTS_TABLE, AGENTS_TABLE),
|
RelationTableName(CONTENTS_TABLE, AGENTS_TABLE),
|
||||||
CONTENTS_TABLE,
|
CONTENTS_TABLE,
|
||||||
@@ -68,7 +68,7 @@ func RContentsAgents_Content(app core.App, id string) ([]*RContentsAgents, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func REntriesSeries_Entries(app core.App, ids []any) ([]*REntriesSeries, error) {
|
func REntriesSeries_Entries(app core.App, ids []any) ([]*REntriesSeries, error) {
|
||||||
return TableByFields[[]*REntriesSeries](
|
return TableByFields[*REntriesSeries](
|
||||||
app,
|
app,
|
||||||
RelationTableName(ENTRIES_TABLE, SERIES_TABLE),
|
RelationTableName(ENTRIES_TABLE, SERIES_TABLE),
|
||||||
ENTRIES_TABLE,
|
ENTRIES_TABLE,
|
||||||
@@ -77,7 +77,7 @@ func REntriesSeries_Entries(app core.App, ids []any) ([]*REntriesSeries, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func REntriesSeries_Entry(app core.App, id string) ([]*REntriesSeries, error) {
|
func REntriesSeries_Entry(app core.App, id string) ([]*REntriesSeries, error) {
|
||||||
return TableByFields[[]*REntriesSeries](
|
return TableByFields[*REntriesSeries](
|
||||||
app,
|
app,
|
||||||
RelationTableName(ENTRIES_TABLE, SERIES_TABLE),
|
RelationTableName(ENTRIES_TABLE, SERIES_TABLE),
|
||||||
ENTRIES_TABLE,
|
ENTRIES_TABLE,
|
||||||
@@ -86,7 +86,7 @@ func REntriesSeries_Entry(app core.App, id string) ([]*REntriesSeries, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func REntriesSeries_Seriess(app core.App, ids []any) ([]*REntriesSeries, error) {
|
func REntriesSeries_Seriess(app core.App, ids []any) ([]*REntriesSeries, error) {
|
||||||
return TableByFields[[]*REntriesSeries](
|
return TableByFields[*REntriesSeries](
|
||||||
app,
|
app,
|
||||||
RelationTableName(ENTRIES_TABLE, SERIES_TABLE),
|
RelationTableName(ENTRIES_TABLE, SERIES_TABLE),
|
||||||
SERIES_TABLE,
|
SERIES_TABLE,
|
||||||
@@ -100,7 +100,7 @@ func Agents_ID(app core.App, id string) (*Agent, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Agents_IDs(app core.App, ids []any) ([]*Agent, error) {
|
func Agents_IDs(app core.App, ids []any) ([]*Agent, error) {
|
||||||
return TableByIDs[[]*Agent](app, AGENTS_TABLE, ids)
|
return TableByIDs[*Agent](app, AGENTS_TABLE, ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Entries_ID(app core.App, id string) (*Entry, error) {
|
func Entries_ID(app core.App, id string) (*Entry, error) {
|
||||||
@@ -114,11 +114,11 @@ func Entries_MusenalmID(app core.App, id string) (*Entry, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Entries_IDs(app core.App, ids []any) ([]*Entry, error) {
|
func Entries_IDs(app core.App, ids []any) ([]*Entry, error) {
|
||||||
return TableByIDs[[]*Entry](app, ENTRIES_TABLE, ids)
|
return TableByIDs[*Entry](app, ENTRIES_TABLE, ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Series_IDs(app core.App, ids []any) ([]*Series, error) {
|
func Series_IDs(app core.App, ids []any) ([]*Series, error) {
|
||||||
return TableByIDs[[]*Series](app, SERIES_TABLE, ids)
|
return TableByIDs[*Series](app, SERIES_TABLE, ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Series_MusenalmID(app core.App, id string) (*Series, error) {
|
func Series_MusenalmID(app core.App, id string) (*Series, error) {
|
||||||
@@ -132,15 +132,15 @@ func Series_ID(app core.App, id string) (*Series, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Places_IDs(app core.App, ids []any) ([]*Place, error) {
|
func Places_IDs(app core.App, ids []any) ([]*Place, error) {
|
||||||
return TableByIDs[[]*Place](app, PLACES_TABLE, ids)
|
return TableByIDs[*Place](app, PLACES_TABLE, ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Contents_IDs(app core.App, ids []any) ([]*Content, error) {
|
func Contents_IDs(app core.App, ids []any) ([]*Content, error) {
|
||||||
return TableByIDs[[]*Content](app, CONTENTS_TABLE, ids)
|
return TableByIDs[*Content](app, CONTENTS_TABLE, ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Contents_Entry(app core.App, id string) ([]*Content, error) {
|
func Contents_Entry(app core.App, id string) ([]*Content, error) {
|
||||||
return TableByFields[[]*Content](
|
return TableByFields[*Content](
|
||||||
app,
|
app,
|
||||||
CONTENTS_TABLE,
|
CONTENTS_TABLE,
|
||||||
ENTRIES_TABLE,
|
ENTRIES_TABLE,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package dbmodels
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"iter"
|
"iter"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
"github.com/pocketbase/dbx"
|
"github.com/pocketbase/dbx"
|
||||||
"github.com/pocketbase/pocketbase/core"
|
"github.com/pocketbase/pocketbase/core"
|
||||||
@@ -61,6 +62,11 @@ import (
|
|||||||
// github.com/pocketbase/pocketbase/apis.NewRouter.BodyLimit.func7(0xc0002da000)
|
// github.com/pocketbase/pocketbase/apis.NewRouter.BodyLimit.func7(0xc0002da000)
|
||||||
//
|
//
|
||||||
// /home
|
// /home
|
||||||
|
|
||||||
|
const (
|
||||||
|
QUERY_PARTITION_SIZE = 1200
|
||||||
|
)
|
||||||
|
|
||||||
func Iter_TableByField[T interface{}](app core.App, table, field string, value interface{}) (iter.Seq2[*T, error], error) {
|
func Iter_TableByField[T interface{}](app core.App, table, field string, value interface{}) (iter.Seq2[*T, error], error) {
|
||||||
rows, err := app.RecordQuery(table).
|
rows, err := app.RecordQuery(table).
|
||||||
Where(dbx.HashExp{field: value}).
|
Where(dbx.HashExp{field: value}).
|
||||||
@@ -111,13 +117,42 @@ func TableByField[T interface{}](app core.App, table, field string, value string
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TableByFields[T interface{}](app core.App, table, field string, values any) (T, error) {
|
func TableByFields[T interface{}](app core.App, table, field string, values any) ([]T, error) {
|
||||||
var ret T
|
var ret []T
|
||||||
err := app.RecordQuery(table).
|
if reflect.TypeOf(values).Kind() == reflect.Slice {
|
||||||
Where(dbx.HashExp{field: values}).
|
v := values.([]any)
|
||||||
All(&ret)
|
if len(v) > QUERY_PARTITION_SIZE {
|
||||||
if err != nil {
|
for i := 0; i < len(v); i += QUERY_PARTITION_SIZE {
|
||||||
return ret, err
|
part := v[i:]
|
||||||
|
if len(part) > QUERY_PARTITION_SIZE {
|
||||||
|
part = part[:QUERY_PARTITION_SIZE]
|
||||||
|
}
|
||||||
|
|
||||||
|
var partret []T
|
||||||
|
err := app.RecordQuery(table).
|
||||||
|
Where(dbx.HashExp{field: part}).
|
||||||
|
All(&partret)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = append(ret, partret...)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err := app.RecordQuery(table).
|
||||||
|
Where(dbx.HashExp{field: values}).
|
||||||
|
All(&ret)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err := app.RecordQuery(table).
|
||||||
|
Where(dbx.HashExp{field: values}).
|
||||||
|
All(&ret)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret, nil
|
return ret, nil
|
||||||
@@ -135,13 +170,32 @@ func TableByID[T interface{}](app core.App, table, id string) (T, error) {
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TableByIDs[T interface{}](app core.App, table string, ids []any) (T, error) {
|
func TableByIDs[T interface{}](app core.App, table string, ids []any) ([]T, error) {
|
||||||
var ret T
|
var ret []T
|
||||||
err := app.RecordQuery(table).
|
if len(ids) > QUERY_PARTITION_SIZE {
|
||||||
Where(dbx.HashExp{ID_FIELD: ids}).
|
for i := 0; i < len(ids); i += QUERY_PARTITION_SIZE {
|
||||||
All(&ret)
|
part := ids[i:]
|
||||||
if err != nil {
|
if len(part) > QUERY_PARTITION_SIZE {
|
||||||
return ret, err
|
part = part[:QUERY_PARTITION_SIZE]
|
||||||
|
}
|
||||||
|
|
||||||
|
var partret []T
|
||||||
|
err := app.RecordQuery(table).
|
||||||
|
Where(dbx.HashExp{ID_FIELD: part}).
|
||||||
|
All(&partret)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = append(ret, partret...)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err := app.RecordQuery(table).
|
||||||
|
Where(dbx.HashExp{ID_FIELD: ids}).
|
||||||
|
All(&ret)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret, nil
|
return ret, nil
|
||||||
|
|||||||
@@ -44,11 +44,11 @@ func First(s string) string {
|
|||||||
return string(r[0])
|
return string(r[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func LinksAnnotation(s string) string {
|
func LinksAnnotation(s, link string) string {
|
||||||
annotation := linksexp.ReplaceAllStringFunc(s, func(match string) string {
|
annotation := linksexp.ReplaceAllStringFunc(s, func(match string) string {
|
||||||
submatches := linksexp.FindStringSubmatch(match)
|
submatches := linksexp.FindStringSubmatch(match)
|
||||||
if len(submatches) > 1 {
|
if len(submatches) > 1 {
|
||||||
return fmt.Sprintf(`<a href="#%s" class="link-default oldstyle-nums">%s</a>`, submatches[1], match)
|
return fmt.Sprintf(`<a href="`+link+`#%s" class="link-default oldstyle-nums">%s</a>`, submatches[1], match)
|
||||||
}
|
}
|
||||||
return match
|
return match
|
||||||
})
|
})
|
||||||
|
|||||||
484
pages/suche.go
484
pages/suche.go
@@ -1,11 +1,9 @@
|
|||||||
package pages
|
package pages
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/Theodor-Springmann-Stiftung/musenalm/app"
|
"github.com/Theodor-Springmann-Stiftung/musenalm/app"
|
||||||
"github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels"
|
"github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels"
|
||||||
@@ -23,9 +21,9 @@ const (
|
|||||||
URL_SUCHE = "/suche/{type}"
|
URL_SUCHE = "/suche/{type}"
|
||||||
URL_SUCHE_ALT = "/suche/{$}"
|
URL_SUCHE_ALT = "/suche/{$}"
|
||||||
DEFAULT_SUCHE = "/suche/baende"
|
DEFAULT_SUCHE = "/suche/baende"
|
||||||
PARAM_QUERY = "q"
|
|
||||||
PARAM_EXTENDED = "extended"
|
PARAM_EXTENDED = "extended"
|
||||||
TEMPLATE_SUCHE = "/suche/"
|
TEMPLATE_SUCHE = "/suche/"
|
||||||
|
PARAM_QUERY = "q"
|
||||||
)
|
)
|
||||||
|
|
||||||
var availableTypes = []string{"baende", "beitraege"}
|
var availableTypes = []string{"baende", "beitraege"}
|
||||||
@@ -60,6 +58,10 @@ func (p *SuchePage) Setup(router *router.Router[*core.RequestEvent], app core.Ap
|
|||||||
return p.SearchBaendeRequest(app, engine, e, *allparas)
|
return p.SearchBaendeRequest(app, engine, e, *allparas)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if allparas.IsBeitraegeSearch() {
|
||||||
|
return p.SearchBeitraegeRequest(app, engine, e, *allparas)
|
||||||
|
}
|
||||||
|
|
||||||
data := make(map[string]interface{})
|
data := make(map[string]interface{})
|
||||||
data["parameters"] = allparas
|
data["parameters"] = allparas
|
||||||
return engine.Response200(e, p.Template+paras.Collection+"/", data, p.Layout)
|
return engine.Response200(e, p.Template+paras.Collection+"/", data, p.Layout)
|
||||||
@@ -72,10 +74,10 @@ func (p *SuchePage) SimpleSearchReihenRequest(app core.App, engine *templating.E
|
|||||||
return engine.Response404(e, nil, nil)
|
return engine.Response404(e, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SuchePage) SearchBaendeRequest(app core.App, engine *templating.Engine, e *core.RequestEvent, params SearchParameters) error {
|
func (p *SuchePage) SearchBeitraegeRequest(app core.App, engine *templating.Engine, e *core.RequestEvent, params SearchParameters) error {
|
||||||
data := make(map[string]interface{})
|
data := make(map[string]interface{})
|
||||||
|
|
||||||
result, err := SimpleSearchBaende(app, params)
|
result, err := NewSearchBeitraege(app, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return engine.Response404(e, err, nil)
|
return engine.Response404(e, err, nil)
|
||||||
}
|
}
|
||||||
@@ -85,38 +87,20 @@ func (p *SuchePage) SearchBaendeRequest(app core.App, engine *templating.Engine,
|
|||||||
return engine.Response200(e, p.Template+params.Collection+"/", data, p.Layout)
|
return engine.Response200(e, p.Template+params.Collection+"/", data, p.Layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
func (p *SuchePage) SearchBaendeRequest(app core.App, engine *templating.Engine, e *core.RequestEvent, params SearchParameters) error {
|
||||||
BEITRAEGE_PARAM_ALM_NR = "nr"
|
data := make(map[string]interface{})
|
||||||
BEITRAEGE_PARAM_TITLE = "title"
|
|
||||||
BEITRAEGE_PARAM_INCIPT = "incipit"
|
|
||||||
BEITRAEGE_PARAM_PERSONS = "persons"
|
|
||||||
BEITRAEGE_PARAM_ANNOTATIONS = "annotations"
|
|
||||||
// INFO: this is expanded search only:
|
|
||||||
BEITRAEGE_PARAM_PSEUDONYMS = "pseudonyms"
|
|
||||||
// INFO: these are filter types & expanded search:
|
|
||||||
BEITRAEGE_PARAM_TYPE = "type"
|
|
||||||
BEITRAEGE_PARAM_SCANS = "scans"
|
|
||||||
|
|
||||||
REIHEN_PARAM_TITLE = "title"
|
result, err := NewSearchBaende(app, params)
|
||||||
REIHEN_PARAM_ANNOTATIONS = "annotations"
|
if err != nil {
|
||||||
REIHEN_PARAM_REFERENCES = "references"
|
return engine.Response404(e, err, nil)
|
||||||
|
}
|
||||||
|
|
||||||
BAENDE_PARAM_ALM_NR = "alm"
|
data["parameters"] = params
|
||||||
BAENDE_PARAM_TITLE = "title"
|
data["result"] = result
|
||||||
BAENDE_PARAM_SERIES = "series"
|
return engine.Response200(e, p.Template+params.Collection+"/", data, p.Layout)
|
||||||
BAENDE_PARAM_PERSONS = "persons"
|
}
|
||||||
BAENDE_PARAM_PLACES = "places"
|
|
||||||
BAENDE_PARAM_REFS = "references"
|
|
||||||
BAENDE_PARAM_ANNOTATIONS = "annotations"
|
|
||||||
BAENDE_PARAM_YEAR = "year"
|
|
||||||
// INFO: this is expanded search only:
|
|
||||||
BAENDE_PARAM_PSEUDONYMS = "pseudonyms"
|
|
||||||
// INFO: this is a filter type & expanded search:
|
|
||||||
BAENDE_PARAM_STATE = "state" // STATE: "full" "partial" "none"
|
|
||||||
)
|
|
||||||
|
|
||||||
var ErrInvalidCollectionType = fmt.Errorf("Invalid collection type")
|
var ErrInvalidCollectionType = fmt.Errorf("Invalid collection type")
|
||||||
var ErrNoQuery = fmt.Errorf("No query")
|
|
||||||
|
|
||||||
type Parameters struct {
|
type Parameters struct {
|
||||||
Extended bool
|
Extended bool
|
||||||
@@ -145,437 +129,3 @@ func NewParameters(e *core.RequestEvent) (*Parameters, error) {
|
|||||||
func (p *Parameters) NormalizeQuery() dbmodels.Query {
|
func (p *Parameters) NormalizeQuery() dbmodels.Query {
|
||||||
return dbmodels.NormalizeQuery(p.Query)
|
return dbmodels.NormalizeQuery(p.Query)
|
||||||
}
|
}
|
||||||
|
|
||||||
type SearchParameters struct {
|
|
||||||
Parameters
|
|
||||||
Sort string
|
|
||||||
|
|
||||||
Annotations bool
|
|
||||||
Persons bool
|
|
||||||
Title bool
|
|
||||||
Series bool
|
|
||||||
Places bool
|
|
||||||
Refs bool
|
|
||||||
Year bool
|
|
||||||
|
|
||||||
AnnotationsString string
|
|
||||||
PersonsString string
|
|
||||||
TitleString string
|
|
||||||
AlmString string
|
|
||||||
SeriesString string
|
|
||||||
PlacesString string
|
|
||||||
RefsString string
|
|
||||||
YearString string
|
|
||||||
|
|
||||||
TypeFilter string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewSearchParameters(e *core.RequestEvent, p Parameters) (*SearchParameters, error) {
|
|
||||||
title := e.Request.URL.Query().Get(BAENDE_PARAM_TITLE) == "on"
|
|
||||||
series := e.Request.URL.Query().Get(BAENDE_PARAM_SERIES) == "on"
|
|
||||||
persons := e.Request.URL.Query().Get(BAENDE_PARAM_PERSONS) == "on"
|
|
||||||
places := e.Request.URL.Query().Get(BAENDE_PARAM_PLACES) == "on"
|
|
||||||
refs := e.Request.URL.Query().Get(BAENDE_PARAM_REFS) == "on"
|
|
||||||
annotations := e.Request.URL.Query().Get(BAENDE_PARAM_ANNOTATIONS) == "on"
|
|
||||||
year := e.Request.URL.Query().Get(BAENDE_PARAM_YEAR) == "on"
|
|
||||||
|
|
||||||
almstring := e.Request.URL.Query().Get(BAENDE_PARAM_ALM_NR + "string")
|
|
||||||
|
|
||||||
titlestring := e.Request.URL.Query().Get(BAENDE_PARAM_TITLE + "string")
|
|
||||||
seriesstring := e.Request.URL.Query().Get(BAENDE_PARAM_SERIES + "string")
|
|
||||||
personsstring := e.Request.URL.Query().Get(BAENDE_PARAM_PERSONS + "string")
|
|
||||||
placesstring := e.Request.URL.Query().Get(BAENDE_PARAM_PLACES + "string")
|
|
||||||
annotationsstring := e.Request.URL.Query().Get(BAENDE_PARAM_ANNOTATIONS + "string")
|
|
||||||
yearstring := e.Request.URL.Query().Get(BAENDE_PARAM_YEAR + "string")
|
|
||||||
|
|
||||||
refss := e.Request.URL.Query().Get(BAENDE_PARAM_REFS + "string")
|
|
||||||
if refss != "" {
|
|
||||||
refss = "\"" + refss + "\""
|
|
||||||
}
|
|
||||||
|
|
||||||
sort := e.Request.URL.Query().Get("sort")
|
|
||||||
if sort == "" {
|
|
||||||
sort = "year"
|
|
||||||
}
|
|
||||||
|
|
||||||
return &SearchParameters{
|
|
||||||
Parameters: p,
|
|
||||||
Sort: sort,
|
|
||||||
// INFO: Common parameters
|
|
||||||
Title: title,
|
|
||||||
Persons: persons,
|
|
||||||
Annotations: annotations,
|
|
||||||
|
|
||||||
// INFO: Baende parameters
|
|
||||||
Places: places,
|
|
||||||
Refs: refs,
|
|
||||||
Year: year,
|
|
||||||
Series: series,
|
|
||||||
|
|
||||||
// INFO: Expanded search
|
|
||||||
AlmString: almstring,
|
|
||||||
TitleString: titlestring,
|
|
||||||
SeriesString: seriesstring,
|
|
||||||
PersonsString: personsstring,
|
|
||||||
PlacesString: placesstring,
|
|
||||||
RefsString: refss,
|
|
||||||
AnnotationsString: annotationsstring,
|
|
||||||
YearString: yearstring,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p SearchParameters) AllSearchTerms() string {
|
|
||||||
res := []string{}
|
|
||||||
res = append(res, p.includedParams(p.Query)...)
|
|
||||||
res = append(res, p.includedParams(p.AnnotationsString)...)
|
|
||||||
res = append(res, p.includedParams(p.PersonsString)...)
|
|
||||||
res = append(res, p.includedParams(p.TitleString)...)
|
|
||||||
res = append(res, p.includedParams(p.SeriesString)...)
|
|
||||||
res = append(res, p.includedParams(p.PlacesString)...)
|
|
||||||
res = append(res, p.includedParams(p.RefsString)...)
|
|
||||||
res = append(res, p.includedParams(p.YearString)...)
|
|
||||||
res = append(res, p.AlmString)
|
|
||||||
return strings.Join(res, " ")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p SearchParameters) includedParams(q string) []string {
|
|
||||||
res := []string{}
|
|
||||||
que := dbmodels.NormalizeQuery(q)
|
|
||||||
for _, qq := range que.Include {
|
|
||||||
res = append(res, qq)
|
|
||||||
}
|
|
||||||
for _, qq := range que.UnsafeI {
|
|
||||||
res = append(res, qq)
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p SearchParameters) ToQueryParams() string {
|
|
||||||
q := "?"
|
|
||||||
|
|
||||||
// TODO: use variables, url escape
|
|
||||||
if p.Extended {
|
|
||||||
q += "extended=true"
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Query != "" {
|
|
||||||
q += fmt.Sprintf("q=%s", p.Query)
|
|
||||||
|
|
||||||
if p.Title {
|
|
||||||
q += "&title=on"
|
|
||||||
}
|
|
||||||
if p.Persons {
|
|
||||||
q += "&persons=on"
|
|
||||||
}
|
|
||||||
if p.Annotations {
|
|
||||||
q += "&annotations=on"
|
|
||||||
}
|
|
||||||
if p.Series {
|
|
||||||
q += "&series=on"
|
|
||||||
}
|
|
||||||
if p.Places {
|
|
||||||
q += "&places=on"
|
|
||||||
}
|
|
||||||
if p.Refs {
|
|
||||||
q += "&references=on"
|
|
||||||
}
|
|
||||||
if p.Year {
|
|
||||||
q += "&year=on"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.YearString != "" {
|
|
||||||
q += fmt.Sprintf("&yearstring=%s", p.YearString)
|
|
||||||
}
|
|
||||||
if p.AnnotationsString != "" {
|
|
||||||
q += fmt.Sprintf("&annotationsstring=%s", p.AnnotationsString)
|
|
||||||
}
|
|
||||||
if p.PersonsString != "" {
|
|
||||||
q += fmt.Sprintf("&personsstring=%s", p.PersonsString)
|
|
||||||
}
|
|
||||||
if p.TitleString != "" {
|
|
||||||
q += fmt.Sprintf("&titlestring=%s", p.TitleString)
|
|
||||||
}
|
|
||||||
if p.SeriesString != "" {
|
|
||||||
q += fmt.Sprintf("&seriesstring=%s", p.SeriesString)
|
|
||||||
}
|
|
||||||
if p.PlacesString != "" {
|
|
||||||
q += fmt.Sprintf("&placesstring=%s", p.PlacesString)
|
|
||||||
}
|
|
||||||
if p.RefsString != "" {
|
|
||||||
q += fmt.Sprintf("&refsstring=%s", p.RefsString)
|
|
||||||
}
|
|
||||||
|
|
||||||
return q
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p SearchParameters) IsBaendeSearch() bool {
|
|
||||||
return p.Collection == "baende" && (p.Query != "" || p.AlmString != "" || p.AnnotationsString != "" || p.PersonsString != "" || p.TitleString != "" || p.SeriesString != "" || p.PlacesString != "" || p.RefsString != "" || p.YearString != "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p SearchParameters) FieldSetBaende() []dbmodels.FTS5QueryRequest {
|
|
||||||
ret := []dbmodels.FTS5QueryRequest{}
|
|
||||||
if p.Query != "" {
|
|
||||||
fields := []string{dbmodels.ID_FIELD}
|
|
||||||
if p.Title {
|
|
||||||
// INFO: Preferred Title is not here to avoid hitting the Reihentitel
|
|
||||||
fields = append(fields,
|
|
||||||
dbmodels.TITLE_STMT_FIELD,
|
|
||||||
dbmodels.SUBTITLE_STMT_FIELD,
|
|
||||||
dbmodels.INCIPIT_STMT_FIELD,
|
|
||||||
dbmodels.VARIANT_TITLE_FIELD,
|
|
||||||
dbmodels.PARALLEL_TITLE_FIELD,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if p.Series {
|
|
||||||
fields = append(fields, dbmodels.SERIES_TABLE)
|
|
||||||
}
|
|
||||||
if p.Persons {
|
|
||||||
fields = append(fields, dbmodels.RESPONSIBILITY_STMT_FIELD, dbmodels.AGENTS_TABLE)
|
|
||||||
}
|
|
||||||
if p.Places {
|
|
||||||
fields = append(fields, dbmodels.PLACES_TABLE, dbmodels.PLACE_STMT_FIELD)
|
|
||||||
}
|
|
||||||
if p.Refs {
|
|
||||||
fields = append(fields, dbmodels.REFERENCES_FIELD)
|
|
||||||
}
|
|
||||||
if p.Annotations {
|
|
||||||
fields = append(fields, dbmodels.ANNOTATION_FIELD)
|
|
||||||
}
|
|
||||||
if p.Year {
|
|
||||||
fields = append(fields, dbmodels.YEAR_FIELD)
|
|
||||||
}
|
|
||||||
|
|
||||||
que := p.NormalizeQuery()
|
|
||||||
req := dbmodels.IntoQueryRequests(fields, que)
|
|
||||||
ret = append(ret, req...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.AnnotationsString != "" {
|
|
||||||
que := dbmodels.NormalizeQuery(p.AnnotationsString)
|
|
||||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.ANNOTATION_FIELD}, que)
|
|
||||||
ret = append(ret, req...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.PersonsString != "" {
|
|
||||||
que := dbmodels.NormalizeQuery(p.PersonsString)
|
|
||||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.AGENTS_TABLE, dbmodels.RESPONSIBILITY_STMT_FIELD}, que)
|
|
||||||
ret = append(ret, req...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.TitleString != "" {
|
|
||||||
que := dbmodels.NormalizeQuery(p.TitleString)
|
|
||||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.TITLE_STMT_FIELD, dbmodels.SUBTITLE_STMT_FIELD, dbmodels.INCIPIT_STMT_FIELD, dbmodels.VARIANT_TITLE_FIELD, dbmodels.PARALLEL_TITLE_FIELD}, que)
|
|
||||||
ret = append(ret, req...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.SeriesString != "" {
|
|
||||||
que := dbmodels.NormalizeQuery(p.SeriesString)
|
|
||||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.SERIES_TABLE}, que)
|
|
||||||
ret = append(ret, req...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.PlacesString != "" {
|
|
||||||
que := dbmodels.NormalizeQuery(p.PlacesString)
|
|
||||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.PLACES_TABLE, dbmodels.PLACE_STMT_FIELD}, que)
|
|
||||||
ret = append(ret, req...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.RefsString != "" {
|
|
||||||
que := dbmodels.NormalizeQuery(p.RefsString)
|
|
||||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.REFERENCES_FIELD}, que)
|
|
||||||
ret = append(ret, req...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.YearString != "" {
|
|
||||||
que := dbmodels.NormalizeQuery(p.YearString)
|
|
||||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.YEAR_FIELD}, que)
|
|
||||||
ret = append(ret, req...)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p SearchParameters) IsExtendedSearch() bool {
|
|
||||||
return p.AnnotationsString != "" || p.PersonsString != "" || p.TitleString != "" || p.AlmString != "" || p.SeriesString != "" || p.PlacesString != "" || p.RefsString != "" || p.YearString != ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p SearchParameters) NormalizeQuery() dbmodels.Query {
|
|
||||||
return dbmodels.NormalizeQuery(p.Query)
|
|
||||||
}
|
|
||||||
|
|
||||||
type SearchResultBaende struct {
|
|
||||||
Queries []dbmodels.FTS5QueryRequest
|
|
||||||
|
|
||||||
// these are the sorted IDs for hits
|
|
||||||
Hits []string
|
|
||||||
Series map[string]*dbmodels.Series // <- Key: Series ID
|
|
||||||
Entries map[string]*dbmodels.Entry // <- Key: Entry ID
|
|
||||||
Places map[string]*dbmodels.Place // <- All places, Key: Place IDs
|
|
||||||
Agents map[string]*dbmodels.Agent // <- Key: Agent IDs
|
|
||||||
|
|
||||||
// INFO: this is as they say doppelt gemoppelt bc of a logic error i made while tired
|
|
||||||
EntriesSeries map[string][]*dbmodels.REntriesSeries // <- Key: Entry ID
|
|
||||||
SeriesEntries map[string][]*dbmodels.REntriesSeries // <- Key: Series ID
|
|
||||||
EntriesAgents map[string][]*dbmodels.REntriesAgents // <- Key: Entry ID
|
|
||||||
}
|
|
||||||
|
|
||||||
func EmptyResultBaende() *SearchResultBaende {
|
|
||||||
return &SearchResultBaende{
|
|
||||||
Hits: []string{},
|
|
||||||
Series: make(map[string]*dbmodels.Series),
|
|
||||||
Entries: make(map[string]*dbmodels.Entry),
|
|
||||||
Places: make(map[string]*dbmodels.Place),
|
|
||||||
Agents: make(map[string]*dbmodels.Agent),
|
|
||||||
EntriesSeries: make(map[string][]*dbmodels.REntriesSeries),
|
|
||||||
SeriesEntries: make(map[string][]*dbmodels.REntriesSeries),
|
|
||||||
EntriesAgents: make(map[string][]*dbmodels.REntriesAgents),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func SimpleSearchBaende(app core.App, params SearchParameters) (*SearchResultBaende, error) {
|
|
||||||
entries := []*dbmodels.Entry{}
|
|
||||||
queries := params.FieldSetBaende()
|
|
||||||
|
|
||||||
if params.AlmString != "" {
|
|
||||||
e, err := dbmodels.Entries_MusenalmID(app, params.AlmString)
|
|
||||||
if err != nil && err == sql.ErrNoRows {
|
|
||||||
return EmptyResultBaende(), nil
|
|
||||||
} else if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
entries = append(entries, e)
|
|
||||||
} else {
|
|
||||||
if len(queries) == 0 {
|
|
||||||
return nil, ErrNoQuery
|
|
||||||
}
|
|
||||||
|
|
||||||
ids, err := dbmodels.FTS5Search(app, dbmodels.ENTRIES_TABLE, queries...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resultids := []any{}
|
|
||||||
for _, id := range ids {
|
|
||||||
resultids = append(resultids, id.ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
e, err := dbmodels.Entries_IDs(app, resultids)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
entries = e
|
|
||||||
}
|
|
||||||
|
|
||||||
resultids := []any{}
|
|
||||||
for _, entry := range entries {
|
|
||||||
resultids = append(resultids, entry.Id)
|
|
||||||
}
|
|
||||||
|
|
||||||
entriesmap := make(map[string]*dbmodels.Entry)
|
|
||||||
for _, entry := range entries {
|
|
||||||
entriesmap[entry.Id] = entry
|
|
||||||
}
|
|
||||||
|
|
||||||
series, relations, err := Series_Entries(app, entries)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
seriesmap := make(map[string]*dbmodels.Series)
|
|
||||||
for _, s := range series {
|
|
||||||
seriesmap[s.Id] = s
|
|
||||||
}
|
|
||||||
|
|
||||||
relationsmap := make(map[string][]*dbmodels.REntriesSeries)
|
|
||||||
invrelationsmap := make(map[string][]*dbmodels.REntriesSeries)
|
|
||||||
for _, r := range relations {
|
|
||||||
invrelationsmap[r.Series()] = append(invrelationsmap[r.Series()], r)
|
|
||||||
relationsmap[r.Entry()] = append(relationsmap[r.Entry()], r)
|
|
||||||
}
|
|
||||||
|
|
||||||
agents, arelations, err := Agents_Entries_IDs(app, resultids)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
agentsmap := make(map[string]*dbmodels.Agent)
|
|
||||||
for _, a := range agents {
|
|
||||||
agentsmap[a.Id] = a
|
|
||||||
}
|
|
||||||
|
|
||||||
relationsagentsmap := make(map[string][]*dbmodels.REntriesAgents)
|
|
||||||
for _, r := range arelations {
|
|
||||||
relationsagentsmap[r.Entry()] = append(relationsagentsmap[r.Entry()], r)
|
|
||||||
}
|
|
||||||
|
|
||||||
placesids := []any{}
|
|
||||||
for _, entry := range entries {
|
|
||||||
for _, place := range entry.Places() {
|
|
||||||
placesids = append(placesids, place)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
places, err := dbmodels.Places_IDs(app, placesids)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
placesmap := make(map[string]*dbmodels.Place)
|
|
||||||
for _, place := range places {
|
|
||||||
placesmap[place.Id] = place
|
|
||||||
}
|
|
||||||
|
|
||||||
hits := []string{}
|
|
||||||
if params.Sort == "series" {
|
|
||||||
dbmodels.Sort_Series_Title(series)
|
|
||||||
for _, s := range series {
|
|
||||||
hits = append(hits, s.Id)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
dbmodels.Sort_Entries_Year_Title(entries)
|
|
||||||
for _, e := range entries {
|
|
||||||
hits = append(hits, e.Id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &SearchResultBaende{
|
|
||||||
Hits: hits,
|
|
||||||
Series: seriesmap,
|
|
||||||
Entries: entriesmap,
|
|
||||||
Places: placesmap,
|
|
||||||
Agents: agentsmap,
|
|
||||||
EntriesSeries: relationsmap,
|
|
||||||
SeriesEntries: invrelationsmap,
|
|
||||||
EntriesAgents: relationsagentsmap,
|
|
||||||
}, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r SearchResultBaende) Count() int {
|
|
||||||
return len(r.Entries)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r SearchResultBaende) SeriesCount() int {
|
|
||||||
return len(r.Series)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Agents_Entries_IDs(app core.App, ids []any) ([]*dbmodels.Agent, []*dbmodels.REntriesAgents, error) {
|
|
||||||
relations, err := dbmodels.REntriesAgents_Entries(app, ids)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
agentids := []any{}
|
|
||||||
for _, r := range relations {
|
|
||||||
agentids = append(agentids, r.Agent())
|
|
||||||
}
|
|
||||||
|
|
||||||
agents, err := dbmodels.Agents_IDs(app, agentids)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return agents, relations, nil
|
|
||||||
}
|
|
||||||
|
|||||||
186
pages/suche_baende.go
Normal file
186
pages/suche_baende.go
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
package pages
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
|
||||||
|
"github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels"
|
||||||
|
"github.com/pocketbase/pocketbase/core"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SearchResultBaende struct {
|
||||||
|
Queries []dbmodels.FTS5QueryRequest
|
||||||
|
|
||||||
|
// these are the sorted IDs for hits
|
||||||
|
Hits []string
|
||||||
|
Series map[string]*dbmodels.Series // <- Key: Series ID
|
||||||
|
Entries map[string]*dbmodels.Entry // <- Key: Entry ID
|
||||||
|
Places map[string]*dbmodels.Place // <- All places, Key: Place IDs
|
||||||
|
Agents map[string]*dbmodels.Agent // <- Key: Agent IDs
|
||||||
|
|
||||||
|
// INFO: this is as they say doppelt gemoppelt bc of a logic error i made while tired
|
||||||
|
EntriesSeries map[string][]*dbmodels.REntriesSeries // <- Key: Entry ID
|
||||||
|
SeriesEntries map[string][]*dbmodels.REntriesSeries // <- Key: Series ID
|
||||||
|
EntriesAgents map[string][]*dbmodels.REntriesAgents // <- Key: Entry ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func EmptyResultBaende() *SearchResultBaende {
|
||||||
|
return &SearchResultBaende{
|
||||||
|
Hits: []string{},
|
||||||
|
Series: make(map[string]*dbmodels.Series),
|
||||||
|
Entries: make(map[string]*dbmodels.Entry),
|
||||||
|
Places: make(map[string]*dbmodels.Place),
|
||||||
|
Agents: make(map[string]*dbmodels.Agent),
|
||||||
|
EntriesSeries: make(map[string][]*dbmodels.REntriesSeries),
|
||||||
|
SeriesEntries: make(map[string][]*dbmodels.REntriesSeries),
|
||||||
|
EntriesAgents: make(map[string][]*dbmodels.REntriesAgents),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSearchBaende(app core.App, params SearchParameters) (*SearchResultBaende, error) {
|
||||||
|
entries := []*dbmodels.Entry{}
|
||||||
|
queries := params.FieldSetBaende()
|
||||||
|
|
||||||
|
if params.AlmString != "" {
|
||||||
|
e, err := dbmodels.Entries_MusenalmID(app, params.AlmString)
|
||||||
|
if err != nil && err == sql.ErrNoRows {
|
||||||
|
return EmptyResultBaende(), nil
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
entries = append(entries, e)
|
||||||
|
} else {
|
||||||
|
if len(queries) == 0 {
|
||||||
|
return nil, ErrNoQuery
|
||||||
|
}
|
||||||
|
|
||||||
|
ids, err := dbmodels.FTS5Search(app, dbmodels.ENTRIES_TABLE, queries...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if len(ids) == 0 {
|
||||||
|
return EmptyResultBaende(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
resultids := []any{}
|
||||||
|
for _, id := range ids {
|
||||||
|
resultids = append(resultids, id.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
e, err := dbmodels.Entries_IDs(app, resultids)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
entries = e
|
||||||
|
}
|
||||||
|
|
||||||
|
resultids := []any{}
|
||||||
|
for _, entry := range entries {
|
||||||
|
resultids = append(resultids, entry.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
entriesmap := make(map[string]*dbmodels.Entry)
|
||||||
|
for _, entry := range entries {
|
||||||
|
entriesmap[entry.Id] = entry
|
||||||
|
}
|
||||||
|
|
||||||
|
series, relations, err := Series_Entries(app, entries)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
seriesmap := make(map[string]*dbmodels.Series)
|
||||||
|
for _, s := range series {
|
||||||
|
seriesmap[s.Id] = s
|
||||||
|
}
|
||||||
|
|
||||||
|
relationsmap := make(map[string][]*dbmodels.REntriesSeries)
|
||||||
|
invrelationsmap := make(map[string][]*dbmodels.REntriesSeries)
|
||||||
|
for _, r := range relations {
|
||||||
|
invrelationsmap[r.Series()] = append(invrelationsmap[r.Series()], r)
|
||||||
|
relationsmap[r.Entry()] = append(relationsmap[r.Entry()], r)
|
||||||
|
}
|
||||||
|
|
||||||
|
agents, arelations, err := Agents_Entries_IDs(app, resultids)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
agentsmap := make(map[string]*dbmodels.Agent)
|
||||||
|
for _, a := range agents {
|
||||||
|
agentsmap[a.Id] = a
|
||||||
|
}
|
||||||
|
|
||||||
|
relationsagentsmap := make(map[string][]*dbmodels.REntriesAgents)
|
||||||
|
for _, r := range arelations {
|
||||||
|
relationsagentsmap[r.Entry()] = append(relationsagentsmap[r.Entry()], r)
|
||||||
|
}
|
||||||
|
|
||||||
|
placesids := []any{}
|
||||||
|
for _, entry := range entries {
|
||||||
|
for _, place := range entry.Places() {
|
||||||
|
placesids = append(placesids, place)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
places, err := dbmodels.Places_IDs(app, placesids)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
placesmap := make(map[string]*dbmodels.Place)
|
||||||
|
for _, place := range places {
|
||||||
|
placesmap[place.Id] = place
|
||||||
|
}
|
||||||
|
|
||||||
|
hits := []string{}
|
||||||
|
if params.Sort == "series" {
|
||||||
|
dbmodels.Sort_Series_Title(series)
|
||||||
|
for _, s := range series {
|
||||||
|
hits = append(hits, s.Id)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dbmodels.Sort_Entries_Year_Title(entries)
|
||||||
|
for _, e := range entries {
|
||||||
|
hits = append(hits, e.Id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &SearchResultBaende{
|
||||||
|
Hits: hits,
|
||||||
|
Series: seriesmap,
|
||||||
|
Entries: entriesmap,
|
||||||
|
Places: placesmap,
|
||||||
|
Agents: agentsmap,
|
||||||
|
EntriesSeries: relationsmap,
|
||||||
|
SeriesEntries: invrelationsmap,
|
||||||
|
EntriesAgents: relationsagentsmap,
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r SearchResultBaende) Count() int {
|
||||||
|
return len(r.Entries)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r SearchResultBaende) SeriesCount() int {
|
||||||
|
return len(r.Series)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Agents_Entries_IDs(app core.App, ids []any) ([]*dbmodels.Agent, []*dbmodels.REntriesAgents, error) {
|
||||||
|
relations, err := dbmodels.REntriesAgents_Entries(app, ids)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
agentids := []any{}
|
||||||
|
for _, r := range relations {
|
||||||
|
agentids = append(agentids, r.Agent())
|
||||||
|
}
|
||||||
|
|
||||||
|
agents, err := dbmodels.Agents_IDs(app, agentids)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return agents, relations, nil
|
||||||
|
}
|
||||||
188
pages/suche_beitraege.go
Normal file
188
pages/suche_beitraege.go
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
package pages
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
|
||||||
|
"github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels"
|
||||||
|
"github.com/Theodor-Springmann-Stiftung/musenalm/helpers/datatypes"
|
||||||
|
"github.com/pocketbase/pocketbase/core"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DEFAULT_PAGESIZE = 80
|
||||||
|
)
|
||||||
|
|
||||||
|
type SearchResultBeitraege struct {
|
||||||
|
Queries []dbmodels.FTS5QueryRequest
|
||||||
|
|
||||||
|
// these are the sorted IDs for hits
|
||||||
|
Hits []string
|
||||||
|
Entries map[string]*dbmodels.Entry // <- Key: Entry ID
|
||||||
|
Agents map[string]*dbmodels.Agent // <- Key: Agent IDs
|
||||||
|
Contents map[string][]*dbmodels.Content // <- Key: Entry ID, or year
|
||||||
|
|
||||||
|
ContentsAgents map[string][]*dbmodels.RContentsAgents // <- Key: Content ID
|
||||||
|
Pages []int
|
||||||
|
}
|
||||||
|
|
||||||
|
func EmptyResultBeitraege() *SearchResultBeitraege {
|
||||||
|
return &SearchResultBeitraege{
|
||||||
|
Hits: []string{},
|
||||||
|
Entries: make(map[string]*dbmodels.Entry),
|
||||||
|
Agents: make(map[string]*dbmodels.Agent),
|
||||||
|
Contents: make(map[string][]*dbmodels.Content),
|
||||||
|
ContentsAgents: make(map[string][]*dbmodels.RContentsAgents),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSearchBeitraege(app core.App, params SearchParameters) (*SearchResultBeitraege, error) {
|
||||||
|
contents := []*dbmodels.Content{}
|
||||||
|
queries := params.FieldSetBeitraege()
|
||||||
|
|
||||||
|
if params.AlmString != "" {
|
||||||
|
e, err := dbmodels.Contents_MusenalmID(app, params.AlmString)
|
||||||
|
if err != nil && err == sql.ErrNoRows {
|
||||||
|
return EmptyResultBeitraege(), nil
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
contents = append(contents, e)
|
||||||
|
} else {
|
||||||
|
if len(queries) == 0 {
|
||||||
|
return nil, ErrNoQuery
|
||||||
|
}
|
||||||
|
|
||||||
|
hits, err := dbmodels.FTS5Search(app, dbmodels.CONTENTS_TABLE, queries...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if len(hits) == 0 {
|
||||||
|
return EmptyResultBeitraege(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ids := []any{}
|
||||||
|
for _, hit := range hits {
|
||||||
|
ids = append(ids, hit.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
cs, err := dbmodels.Contents_IDs(app, ids)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
contents = append(contents, cs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
resultids := []any{}
|
||||||
|
resultentryids := []string{}
|
||||||
|
for _, content := range contents {
|
||||||
|
resultids = append(resultids, content.Id)
|
||||||
|
resultentryids = append(resultentryids, content.Entry())
|
||||||
|
}
|
||||||
|
|
||||||
|
entries, err := dbmodels.Entries_IDs(app, datatypes.ToAny(resultentryids))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if params.Sort == "year" {
|
||||||
|
dbmodels.Sort_Entries_Year_Title(entries)
|
||||||
|
} else {
|
||||||
|
dbmodels.Sort_Entries_Title_Year(entries)
|
||||||
|
}
|
||||||
|
|
||||||
|
arels, err := dbmodels.RContentsAgents_Contents(app, resultids)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
aids := []any{}
|
||||||
|
for _, a := range arels {
|
||||||
|
aids = append(aids, a.Agent())
|
||||||
|
}
|
||||||
|
|
||||||
|
agents, err := dbmodels.Agents_IDs(app, aids)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
contentsmap := make(map[string][]*dbmodels.Content)
|
||||||
|
for _, c := range contents {
|
||||||
|
contentsmap[c.Entry()] = append(contentsmap[c.Entry()], c)
|
||||||
|
}
|
||||||
|
|
||||||
|
contentsagents := make(map[string][]*dbmodels.RContentsAgents)
|
||||||
|
for _, a := range arels {
|
||||||
|
contentsagents[a.Content()] = append(contentsagents[a.Content()], a)
|
||||||
|
}
|
||||||
|
|
||||||
|
agentsmap := make(map[string]*dbmodels.Agent)
|
||||||
|
for _, a := range agents {
|
||||||
|
agentsmap[a.Id] = a
|
||||||
|
}
|
||||||
|
|
||||||
|
entriesmap := make(map[string]*dbmodels.Entry)
|
||||||
|
for _, e := range entries {
|
||||||
|
entriesmap[e.Id] = e
|
||||||
|
}
|
||||||
|
|
||||||
|
hits := []string{}
|
||||||
|
for _, e := range entries {
|
||||||
|
hits = append(hits, e.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pages := PagesEntries(hits, contentsmap, DEFAULT_PAGESIZE)
|
||||||
|
if params.Page < 1 || params.Page > len(pages) {
|
||||||
|
params.Page = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if params.Page == len(pages) {
|
||||||
|
hits = hits[pages[params.Page-1]:]
|
||||||
|
} else {
|
||||||
|
hits = hits[pages[params.Page-1]:pages[params.Page]]
|
||||||
|
}
|
||||||
|
|
||||||
|
return &SearchResultBeitraege{
|
||||||
|
Queries: queries,
|
||||||
|
Hits: hits,
|
||||||
|
Entries: entriesmap,
|
||||||
|
Agents: agentsmap,
|
||||||
|
Contents: contentsmap,
|
||||||
|
ContentsAgents: contentsagents,
|
||||||
|
Pages: pages,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *SearchResultBeitraege) CountEntries() int {
|
||||||
|
return len(p.Entries)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *SearchResultBeitraege) Count() int {
|
||||||
|
cnt := 0
|
||||||
|
for _, c := range p.Contents {
|
||||||
|
cnt += len(c)
|
||||||
|
}
|
||||||
|
return cnt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *SearchResultBeitraege) PagesCount() int {
|
||||||
|
return len(p.Pages) - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func PagesEntries[T any](hits []string, hitmap map[string][]*T, pagesize int) []int {
|
||||||
|
ret := []int{0}
|
||||||
|
m := 0
|
||||||
|
for i, hit := range hits {
|
||||||
|
m += len(hitmap[hit])
|
||||||
|
if m >= pagesize {
|
||||||
|
ret = append(ret, i)
|
||||||
|
m = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if m > 0 {
|
||||||
|
ret = append(ret, len(hits))
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
465
pages/suche_parameters.go
Normal file
465
pages/suche_parameters.go
Normal file
@@ -0,0 +1,465 @@
|
|||||||
|
package pages
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels"
|
||||||
|
"github.com/pocketbase/pocketbase/core"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ErrNoQuery = fmt.Errorf("No query")
|
||||||
|
|
||||||
|
const (
|
||||||
|
SEARCH_PARAM_ALM_NR = "alm"
|
||||||
|
SEARCH_PARAM_TITLE = "title"
|
||||||
|
SEARCH_PARAM_PERSONS = "persons"
|
||||||
|
SEARCH_PARAM_ANNOTATIONS = "annotations"
|
||||||
|
SEARCH_PARAM_YEAR = "year"
|
||||||
|
BAENDE_PARAM_PLACES = "places"
|
||||||
|
BAENDE_PARAM_SERIES = "series"
|
||||||
|
BAENDE_PARAM_REFS = "references"
|
||||||
|
BEITRAEGE_PARAM_ENTRY = "entry"
|
||||||
|
BEITRAEGE_PARAM_INCIPT = "incipit"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SearchParameters struct {
|
||||||
|
Parameters
|
||||||
|
Sort string // year, entry,
|
||||||
|
|
||||||
|
Annotations bool
|
||||||
|
Persons bool
|
||||||
|
Title bool
|
||||||
|
Series bool
|
||||||
|
Places bool
|
||||||
|
Refs bool
|
||||||
|
Year bool
|
||||||
|
Entry bool
|
||||||
|
Incipit bool
|
||||||
|
|
||||||
|
AnnotationsString string
|
||||||
|
PersonsString string
|
||||||
|
TitleString string
|
||||||
|
AlmString string
|
||||||
|
SeriesString string
|
||||||
|
PlacesString string
|
||||||
|
RefsString string
|
||||||
|
YearString string
|
||||||
|
EntryString string
|
||||||
|
IncipitString string
|
||||||
|
|
||||||
|
Page int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSearchParameters(e *core.RequestEvent, p Parameters) (*SearchParameters, error) {
|
||||||
|
almstring := e.Request.URL.Query().Get(SEARCH_PARAM_ALM_NR + "string")
|
||||||
|
title := e.Request.URL.Query().Get(SEARCH_PARAM_TITLE) == "on"
|
||||||
|
titlestring := e.Request.URL.Query().Get(SEARCH_PARAM_TITLE + "string")
|
||||||
|
persons := e.Request.URL.Query().Get(SEARCH_PARAM_PERSONS) == "on"
|
||||||
|
personsstring := e.Request.URL.Query().Get(SEARCH_PARAM_PERSONS + "string")
|
||||||
|
annotations := e.Request.URL.Query().Get(SEARCH_PARAM_ANNOTATIONS) == "on"
|
||||||
|
annotationsstring := e.Request.URL.Query().Get(SEARCH_PARAM_ANNOTATIONS + "string")
|
||||||
|
year := e.Request.URL.Query().Get(SEARCH_PARAM_YEAR) == "on"
|
||||||
|
yearstring := e.Request.URL.Query().Get(SEARCH_PARAM_YEAR + "string")
|
||||||
|
|
||||||
|
series := e.Request.URL.Query().Get(BAENDE_PARAM_SERIES) == "on"
|
||||||
|
seriesstring := e.Request.URL.Query().Get(BAENDE_PARAM_SERIES + "string")
|
||||||
|
places := e.Request.URL.Query().Get(BAENDE_PARAM_PLACES) == "on"
|
||||||
|
placesstring := e.Request.URL.Query().Get(BAENDE_PARAM_PLACES + "string")
|
||||||
|
refs := e.Request.URL.Query().Get(BAENDE_PARAM_REFS) == "on"
|
||||||
|
|
||||||
|
refss := e.Request.URL.Query().Get(BAENDE_PARAM_REFS + "string")
|
||||||
|
if refss != "" {
|
||||||
|
refss = "\"" + refss + "\""
|
||||||
|
}
|
||||||
|
|
||||||
|
incipit := e.Request.URL.Query().Get(BEITRAEGE_PARAM_INCIPT) == "on"
|
||||||
|
incipitstring := e.Request.URL.Query().Get(BEITRAEGE_PARAM_INCIPT + "string")
|
||||||
|
entry := e.Request.URL.Query().Get(BEITRAEGE_PARAM_ENTRY) == "on"
|
||||||
|
entrystring := e.Request.URL.Query().Get(BEITRAEGE_PARAM_ENTRY + "string")
|
||||||
|
|
||||||
|
sort := e.Request.URL.Query().Get("sort")
|
||||||
|
if sort == "" {
|
||||||
|
sort = "year"
|
||||||
|
}
|
||||||
|
|
||||||
|
page := e.Request.URL.Query().Get("page")
|
||||||
|
if page == "" {
|
||||||
|
page = "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
pageint, err := strconv.Atoi(page)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &SearchParameters{
|
||||||
|
Parameters: p,
|
||||||
|
Sort: sort,
|
||||||
|
Page: pageint,
|
||||||
|
|
||||||
|
// INFO: Common parameters
|
||||||
|
Title: title,
|
||||||
|
Persons: persons,
|
||||||
|
Annotations: annotations,
|
||||||
|
Year: year,
|
||||||
|
|
||||||
|
// INFO: Baende parameters
|
||||||
|
Places: places,
|
||||||
|
Refs: refs,
|
||||||
|
Series: series,
|
||||||
|
|
||||||
|
// INFO: Beitraege parameters
|
||||||
|
Entry: entry,
|
||||||
|
Incipit: incipit,
|
||||||
|
|
||||||
|
// INFO: Expanded search
|
||||||
|
AlmString: almstring,
|
||||||
|
TitleString: titlestring,
|
||||||
|
SeriesString: seriesstring,
|
||||||
|
PersonsString: personsstring,
|
||||||
|
PlacesString: placesstring,
|
||||||
|
RefsString: refss,
|
||||||
|
AnnotationsString: annotationsstring,
|
||||||
|
YearString: yearstring,
|
||||||
|
EntryString: entrystring,
|
||||||
|
IncipitString: incipitstring,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p SearchParameters) AllSearchTermsBaende() string {
|
||||||
|
res := []string{}
|
||||||
|
res = append(res, p.includedParams(p.Query)...)
|
||||||
|
res = append(res, p.includedParams(p.AnnotationsString)...)
|
||||||
|
res = append(res, p.includedParams(p.PersonsString)...)
|
||||||
|
res = append(res, p.includedParams(p.TitleString)...)
|
||||||
|
res = append(res, p.includedParams(p.SeriesString)...)
|
||||||
|
res = append(res, p.includedParams(p.PlacesString)...)
|
||||||
|
res = append(res, p.includedParams(p.RefsString)...)
|
||||||
|
res = append(res, p.includedParams(p.YearString)...)
|
||||||
|
res = append(res, p.AlmString)
|
||||||
|
return strings.Join(res, " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p SearchParameters) AllSearchTermsBeitraege() string {
|
||||||
|
res := []string{}
|
||||||
|
res = append(res, p.includedParams(p.Query)...)
|
||||||
|
res = append(res, p.includedParams(p.AnnotationsString)...)
|
||||||
|
res = append(res, p.includedParams(p.PersonsString)...)
|
||||||
|
res = append(res, p.includedParams(p.TitleString)...)
|
||||||
|
res = append(res, p.includedParams(p.YearString)...)
|
||||||
|
res = append(res, p.includedParams(p.EntryString)...)
|
||||||
|
res = append(res, p.includedParams(p.IncipitString)...)
|
||||||
|
return strings.Join(res, " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p SearchParameters) includedParams(q string) []string {
|
||||||
|
res := []string{}
|
||||||
|
que := dbmodels.NormalizeQuery(q)
|
||||||
|
for _, qq := range que.Include {
|
||||||
|
res = append(res, qq)
|
||||||
|
}
|
||||||
|
for _, qq := range que.UnsafeI {
|
||||||
|
res = append(res, qq)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p SearchParameters) ToQueryParamsBeitraege() string {
|
||||||
|
q := "?"
|
||||||
|
|
||||||
|
if p.Extended {
|
||||||
|
q += "extended=true"
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.Query != "" {
|
||||||
|
q += fmt.Sprintf("q=%s", p.Query)
|
||||||
|
|
||||||
|
if p.Title {
|
||||||
|
q += "&title=on"
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.Persons {
|
||||||
|
q += "&persons=on"
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.Annotations {
|
||||||
|
q += "&annotations=on"
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.Year {
|
||||||
|
q += "&year=on"
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.Entry {
|
||||||
|
q += "&entry=on"
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.Incipit {
|
||||||
|
q += "&incipit=on"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.YearString != "" {
|
||||||
|
q += fmt.Sprintf("&yearstring=%s", p.YearString)
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.AnnotationsString != "" {
|
||||||
|
q += fmt.Sprintf("&annotationsstring=%s", p.AnnotationsString)
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.PersonsString != "" {
|
||||||
|
q += fmt.Sprintf("&personsstring=%s", p.PersonsString)
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.TitleString != "" {
|
||||||
|
q += fmt.Sprintf("&titlestring=%s", p.TitleString)
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.EntryString != "" {
|
||||||
|
q += fmt.Sprintf("&entrystring=%s", p.EntryString)
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.IncipitString != "" {
|
||||||
|
q += fmt.Sprintf("&incipitstring=%s", p.IncipitString)
|
||||||
|
}
|
||||||
|
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p SearchParameters) ToQueryParamsBaende() string {
|
||||||
|
q := "?"
|
||||||
|
|
||||||
|
// TODO: use variables, url escape
|
||||||
|
if p.Extended {
|
||||||
|
q += "extended=true"
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.Query != "" {
|
||||||
|
q += fmt.Sprintf("q=%s", p.Query)
|
||||||
|
|
||||||
|
if p.Title {
|
||||||
|
q += "&title=on"
|
||||||
|
}
|
||||||
|
if p.Persons {
|
||||||
|
q += "&persons=on"
|
||||||
|
}
|
||||||
|
if p.Annotations {
|
||||||
|
q += "&annotations=on"
|
||||||
|
}
|
||||||
|
if p.Series {
|
||||||
|
q += "&series=on"
|
||||||
|
}
|
||||||
|
if p.Places {
|
||||||
|
q += "&places=on"
|
||||||
|
}
|
||||||
|
if p.Refs {
|
||||||
|
q += "&references=on"
|
||||||
|
}
|
||||||
|
if p.Year {
|
||||||
|
q += "&year=on"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.YearString != "" {
|
||||||
|
q += fmt.Sprintf("&yearstring=%s", p.YearString)
|
||||||
|
}
|
||||||
|
if p.AnnotationsString != "" {
|
||||||
|
q += fmt.Sprintf("&annotationsstring=%s", p.AnnotationsString)
|
||||||
|
}
|
||||||
|
if p.PersonsString != "" {
|
||||||
|
q += fmt.Sprintf("&personsstring=%s", p.PersonsString)
|
||||||
|
}
|
||||||
|
if p.TitleString != "" {
|
||||||
|
q += fmt.Sprintf("&titlestring=%s", p.TitleString)
|
||||||
|
}
|
||||||
|
if p.SeriesString != "" {
|
||||||
|
q += fmt.Sprintf("&seriesstring=%s", p.SeriesString)
|
||||||
|
}
|
||||||
|
if p.PlacesString != "" {
|
||||||
|
q += fmt.Sprintf("&placesstring=%s", p.PlacesString)
|
||||||
|
}
|
||||||
|
if p.RefsString != "" {
|
||||||
|
q += fmt.Sprintf("&refsstring=%s", p.RefsString)
|
||||||
|
}
|
||||||
|
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p SearchParameters) IsBeitraegeSearch() bool {
|
||||||
|
return p.Collection == "beitraege" && (p.Query != "" || p.AlmString != "" || p.AnnotationsString != "" || p.PersonsString != "" || p.TitleString != "" || p.YearString != "" || p.EntryString != "" || p.IncipitString != "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p SearchParameters) IsBaendeSearch() bool {
|
||||||
|
return p.Collection == "baende" && (p.Query != "" || p.AlmString != "" || p.AnnotationsString != "" || p.PersonsString != "" || p.TitleString != "" || p.SeriesString != "" || p.PlacesString != "" || p.RefsString != "" || p.YearString != "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p SearchParameters) FieldSetBeitraege() []dbmodels.FTS5QueryRequest {
|
||||||
|
ret := []dbmodels.FTS5QueryRequest{}
|
||||||
|
if p.Query != "" {
|
||||||
|
fields := []string{dbmodels.ID_FIELD}
|
||||||
|
if p.Title {
|
||||||
|
fields = append(fields, dbmodels.TITLE_STMT_FIELD, dbmodels.SUBTITLE_STMT_FIELD, dbmodels.VARIANT_TITLE_FIELD, dbmodels.PARALLEL_TITLE_FIELD)
|
||||||
|
}
|
||||||
|
if p.Persons {
|
||||||
|
fields = append(fields, dbmodels.RESPONSIBILITY_STMT_FIELD, dbmodels.AGENTS_TABLE)
|
||||||
|
}
|
||||||
|
if p.Annotations {
|
||||||
|
fields = append(fields, dbmodels.ANNOTATION_FIELD)
|
||||||
|
}
|
||||||
|
if p.Year {
|
||||||
|
fields = append(fields, dbmodels.YEAR_FIELD)
|
||||||
|
}
|
||||||
|
if p.Entry {
|
||||||
|
fields = append(fields, dbmodels.ENTRIES_TABLE)
|
||||||
|
}
|
||||||
|
if p.Incipit {
|
||||||
|
fields = append(fields, dbmodels.INCIPIT_STMT_FIELD)
|
||||||
|
}
|
||||||
|
|
||||||
|
que := p.NormalizeQuery()
|
||||||
|
req := dbmodels.IntoQueryRequests(fields, que)
|
||||||
|
ret = append(ret, req...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.AnnotationsString != "" {
|
||||||
|
que := dbmodels.NormalizeQuery(p.AnnotationsString)
|
||||||
|
req := dbmodels.IntoQueryRequests([]string{dbmodels.ANNOTATION_FIELD}, que)
|
||||||
|
ret = append(ret, req...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.PersonsString != "" {
|
||||||
|
que := dbmodels.NormalizeQuery(p.PersonsString)
|
||||||
|
req := dbmodels.IntoQueryRequests([]string{dbmodels.AGENTS_TABLE, dbmodels.RESPONSIBILITY_STMT_FIELD}, que)
|
||||||
|
ret = append(ret, req...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.TitleString != "" {
|
||||||
|
que := dbmodels.NormalizeQuery(p.TitleString)
|
||||||
|
req := dbmodels.IntoQueryRequests([]string{dbmodels.TITLE_STMT_FIELD, dbmodels.SUBTITLE_STMT_FIELD, dbmodels.VARIANT_TITLE_FIELD, dbmodels.PARALLEL_TITLE_FIELD}, que)
|
||||||
|
ret = append(ret, req...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.YearString != "" {
|
||||||
|
que := dbmodels.NormalizeQuery(p.YearString)
|
||||||
|
req := dbmodels.IntoQueryRequests([]string{dbmodels.YEAR_FIELD}, que)
|
||||||
|
ret = append(ret, req...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.EntryString != "" {
|
||||||
|
que := dbmodels.NormalizeQuery(p.EntryString)
|
||||||
|
req := dbmodels.IntoQueryRequests([]string{dbmodels.ENTRIES_TABLE}, que)
|
||||||
|
ret = append(ret, req...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.IncipitString != "" {
|
||||||
|
que := dbmodels.NormalizeQuery(p.IncipitString)
|
||||||
|
req := dbmodels.IntoQueryRequests([]string{dbmodels.INCIPIT_STMT_FIELD}, que)
|
||||||
|
ret = append(ret, req...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p SearchParameters) FieldSetBaende() []dbmodels.FTS5QueryRequest {
|
||||||
|
ret := []dbmodels.FTS5QueryRequest{}
|
||||||
|
if p.Query != "" {
|
||||||
|
fields := []string{dbmodels.ID_FIELD}
|
||||||
|
if p.Title {
|
||||||
|
// INFO: Preferred Title is not here to avoid hitting the Reihentitel
|
||||||
|
fields = append(fields,
|
||||||
|
dbmodels.TITLE_STMT_FIELD,
|
||||||
|
dbmodels.SUBTITLE_STMT_FIELD,
|
||||||
|
dbmodels.INCIPIT_STMT_FIELD,
|
||||||
|
dbmodels.VARIANT_TITLE_FIELD,
|
||||||
|
dbmodels.PARALLEL_TITLE_FIELD,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if p.Series {
|
||||||
|
fields = append(fields, dbmodels.SERIES_TABLE)
|
||||||
|
}
|
||||||
|
if p.Persons {
|
||||||
|
fields = append(fields, dbmodels.RESPONSIBILITY_STMT_FIELD, dbmodels.AGENTS_TABLE)
|
||||||
|
}
|
||||||
|
if p.Places {
|
||||||
|
fields = append(fields, dbmodels.PLACES_TABLE, dbmodels.PLACE_STMT_FIELD)
|
||||||
|
}
|
||||||
|
if p.Refs {
|
||||||
|
fields = append(fields, dbmodels.REFERENCES_FIELD)
|
||||||
|
}
|
||||||
|
if p.Annotations {
|
||||||
|
fields = append(fields, dbmodels.ANNOTATION_FIELD)
|
||||||
|
}
|
||||||
|
if p.Year {
|
||||||
|
fields = append(fields, dbmodels.YEAR_FIELD)
|
||||||
|
}
|
||||||
|
|
||||||
|
que := p.NormalizeQuery()
|
||||||
|
req := dbmodels.IntoQueryRequests(fields, que)
|
||||||
|
ret = append(ret, req...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.AnnotationsString != "" {
|
||||||
|
que := dbmodels.NormalizeQuery(p.AnnotationsString)
|
||||||
|
req := dbmodels.IntoQueryRequests([]string{dbmodels.ANNOTATION_FIELD}, que)
|
||||||
|
ret = append(ret, req...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.PersonsString != "" {
|
||||||
|
que := dbmodels.NormalizeQuery(p.PersonsString)
|
||||||
|
req := dbmodels.IntoQueryRequests([]string{dbmodels.AGENTS_TABLE, dbmodels.RESPONSIBILITY_STMT_FIELD}, que)
|
||||||
|
ret = append(ret, req...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.TitleString != "" {
|
||||||
|
que := dbmodels.NormalizeQuery(p.TitleString)
|
||||||
|
req := dbmodels.IntoQueryRequests([]string{dbmodels.TITLE_STMT_FIELD, dbmodels.SUBTITLE_STMT_FIELD, dbmodels.INCIPIT_STMT_FIELD, dbmodels.VARIANT_TITLE_FIELD, dbmodels.PARALLEL_TITLE_FIELD}, que)
|
||||||
|
ret = append(ret, req...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.SeriesString != "" {
|
||||||
|
que := dbmodels.NormalizeQuery(p.SeriesString)
|
||||||
|
req := dbmodels.IntoQueryRequests([]string{dbmodels.SERIES_TABLE}, que)
|
||||||
|
ret = append(ret, req...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.PlacesString != "" {
|
||||||
|
que := dbmodels.NormalizeQuery(p.PlacesString)
|
||||||
|
req := dbmodels.IntoQueryRequests([]string{dbmodels.PLACES_TABLE, dbmodels.PLACE_STMT_FIELD}, que)
|
||||||
|
ret = append(ret, req...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.RefsString != "" {
|
||||||
|
que := dbmodels.NormalizeQuery(p.RefsString)
|
||||||
|
req := dbmodels.IntoQueryRequests([]string{dbmodels.REFERENCES_FIELD}, que)
|
||||||
|
ret = append(ret, req...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.YearString != "" {
|
||||||
|
que := dbmodels.NormalizeQuery(p.YearString)
|
||||||
|
req := dbmodels.IntoQueryRequests([]string{dbmodels.YEAR_FIELD}, que)
|
||||||
|
ret = append(ret, req...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p SearchParameters) IsExtendedSearch() bool {
|
||||||
|
return p.AnnotationsString != "" || p.PersonsString != "" || p.TitleString != "" || p.AlmString != "" || p.SeriesString != "" || p.PlacesString != "" || p.RefsString != "" || p.YearString != "" || p.EntryString != "" || p.IncipitString != ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p SearchParameters) NormalizeQuery() dbmodels.Query {
|
||||||
|
return dbmodels.NormalizeQuery(p.Query)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p SearchParameters) Prev() int {
|
||||||
|
if p.Page > 1 {
|
||||||
|
return p.Page - 1
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p SearchParameters) Next() int {
|
||||||
|
return p.Page + 1
|
||||||
|
}
|
||||||
@@ -64,6 +64,8 @@ TODO danach:
|
|||||||
- HTMX + Smooth scroll
|
- HTMX + Smooth scroll
|
||||||
- Personen: related
|
- Personen: related
|
||||||
- Inhaltsliste: Personen sehen komisch aus
|
- Inhaltsliste: Personen sehen komisch aus
|
||||||
|
- V\Boosted links gen by webcomponents
|
||||||
|
- Sammlungen u. Querverweise müssen die URL als Parameter bekommen
|
||||||
- Sammlungen neuer versuch
|
- Sammlungen neuer versuch
|
||||||
- Inhaltsliste Personen
|
- Inhaltsliste Personen
|
||||||
- Sortierung nach Band A-Z?
|
- Sortierung nach Band A-Z?
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
<html class="w-full h-full" {{ if .lang }}lang="{{ .lang }}"{{ end }}>
|
<html class="w-full h-full" {{ if .lang }}lang="{{ .lang }}"{{ end }}>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
|
<meta
|
||||||
|
name="htmx-config"
|
||||||
|
content='{"defaultSwapStyle":"outerHTML", "scrollBehavior": "instant"}' />
|
||||||
|
|
||||||
{{ block "head" . }}
|
{{ block "head" . }}
|
||||||
<!-- Default Head elements -->
|
<!-- Default Head elements -->
|
||||||
|
|||||||
@@ -4,6 +4,32 @@
|
|||||||
.3 - []*RContentsAgents
|
.3 - []*RContentsAgents
|
||||||
.4 - map[string]*Agent
|
.4 - map[string]*Agent
|
||||||
.5 bool SingleView
|
.5 bool SingleView
|
||||||
|
.6 .parameters:
|
||||||
|
type SearchParameters struct {
|
||||||
|
Parameters
|
||||||
|
Sort string
|
||||||
|
|
||||||
|
Annotations bool
|
||||||
|
Persons bool
|
||||||
|
Title bool
|
||||||
|
Series bool
|
||||||
|
Places bool
|
||||||
|
Refs bool
|
||||||
|
Year bool
|
||||||
|
Entry bool
|
||||||
|
Incipit bool
|
||||||
|
|
||||||
|
AnnotationsString string
|
||||||
|
PersonsString string
|
||||||
|
TitleString string
|
||||||
|
AlmString string
|
||||||
|
SeriesString string
|
||||||
|
PlacesString string
|
||||||
|
RefsString string
|
||||||
|
YearString string
|
||||||
|
EntryString string
|
||||||
|
IncipitString string
|
||||||
|
}
|
||||||
*/}}
|
*/}}
|
||||||
|
|
||||||
{{- $content := index . 0 -}}
|
{{- $content := index . 0 -}}
|
||||||
@@ -21,6 +47,27 @@
|
|||||||
{{- $entrySubView = index . 5 -}}
|
{{- $entrySubView = index . 5 -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
|
{{ $isAlm := false }}
|
||||||
|
{{ $isTitle := false }}
|
||||||
|
{{ $isYear := false }}
|
||||||
|
{{ $isPerson := false }}
|
||||||
|
{{ $isAnnotation := false }}
|
||||||
|
{{ $isIncipit := false }}
|
||||||
|
{{ $isEntry := false }}
|
||||||
|
|
||||||
|
{{- $searchparameters := false -}}
|
||||||
|
{{- if gt (len .) 6 -}}
|
||||||
|
{{- $searchparameters = index . 6 -}}
|
||||||
|
|
||||||
|
{{- $isAlm = $searchparameters.AlmString -}}
|
||||||
|
{{- $isTitle = or $searchparameters.Title $searchparameters.TitleString -}}
|
||||||
|
{{- $isYear = or $searchparameters.Year $searchparameters.YearString -}}
|
||||||
|
{{- $isPerson = or $searchparameters.Persons $searchparameters.PersonsString -}}
|
||||||
|
{{- $isAnnotation = or $searchparameters.Annotations $searchparameters.AnnotationsString -}}
|
||||||
|
{{- $isIncipit = or $searchparameters.Incipit $searchparameters.IncipitString -}}
|
||||||
|
{{- $isEntry = or $searchparameters.Entry $searchparameters.EntryString -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="content flex flex-row font-serif {{ if or $entrySubView $singleView -}}text-lg{{- end -}}"
|
class="content flex flex-row font-serif {{ if or $entrySubView $singleView -}}text-lg{{- end -}}"
|
||||||
@@ -50,8 +97,8 @@
|
|||||||
<div class="fields">
|
<div class="fields">
|
||||||
{{- if or $singleView $entrySubView -}}
|
{{- if or $singleView $entrySubView -}}
|
||||||
<div class="fieldlabel">Almanach</div>
|
<div class="fieldlabel">Almanach</div>
|
||||||
<div class="fieldvalue">
|
<div class="fieldvalue {{ if $isEntry }}search-text{{ end }}">
|
||||||
<a href="/almanach/{{- $entry.MusenalmID -}}">
|
<a href="/almanach/{{- $entry.MusenalmID -}}#{{- $content.MusenalmID -}}">
|
||||||
{{- $entry.PreferredTitle -}}
|
{{- $entry.PreferredTitle -}}
|
||||||
</a>
|
</a>
|
||||||
{{- if $content.Extent -}}
|
{{- if $content.Extent -}}
|
||||||
@@ -62,15 +109,21 @@
|
|||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- if $content.TitleStmt -}}
|
{{- if $content.TitleStmt -}}
|
||||||
<div class="fieldlabel">Titel</div>
|
<div class="fieldlabel">Titel</div>
|
||||||
<div class="italic fieldvalue">{{- $content.TitleStmt -}}</div>
|
<div class="italic fieldvalue {{ if $isTitle }}search-text{{ end }}">
|
||||||
|
{{- $content.TitleStmt -}}
|
||||||
|
</div>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- if $content.IncipitStmt -}}
|
{{- if $content.IncipitStmt -}}
|
||||||
<div class="fieldlabel">Incipit</div>
|
<div class="fieldlabel">Incipit</div>
|
||||||
<div class="italic fieldvalue">{{ $content.IncipitStmt }}…</div>
|
<div class="italic fieldvalue {{ if $isIncipit }}search-text{{ end }}">
|
||||||
|
{{ $content.IncipitStmt }}…
|
||||||
|
</div>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- if $content.ResponsibilityStmt -}}
|
{{- if $content.ResponsibilityStmt -}}
|
||||||
<div class="fieldlabel">Autorangabe</div>
|
<div class="fieldlabel">Autorangabe</div>
|
||||||
<div class="fieldvalue italic">{{- $content.ResponsibilityStmt -}}</div>
|
<div class="fieldvalue italic {{ if $isPerson }}search-text{{ end }}">
|
||||||
|
{{- $content.ResponsibilityStmt -}}
|
||||||
|
</div>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- if $rcas -}}
|
{{- if $rcas -}}
|
||||||
<div class="fieldlabel">Personen</div>
|
<div class="fieldlabel">Personen</div>
|
||||||
@@ -79,7 +132,11 @@
|
|||||||
{{- range $_, $rca := $rcas -}}
|
{{- range $_, $rca := $rcas -}}
|
||||||
{{- $agent := index $agents $rca.Agent -}}
|
{{- $agent := index $agents $rca.Agent -}}
|
||||||
<div class="font-sans text-base bg-stone-100 px-1 py-0.5 rounded w-max">
|
<div class="font-sans text-base bg-stone-100 px-1 py-0.5 rounded w-max">
|
||||||
<a href="/person/{{- $agent.Id -}}">{{- $agent.Name -}}</a>
|
<a
|
||||||
|
href="/person/{{- $agent.Id -}}"
|
||||||
|
class="inline-block {{ if $isPerson }}search-text{{ end }}">
|
||||||
|
{{- $agent.Name -}}
|
||||||
|
</a>
|
||||||
({{ $agent.BiographicalData -}})
|
({{ $agent.BiographicalData -}})
|
||||||
</div>
|
</div>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
@@ -87,10 +144,11 @@
|
|||||||
</div>
|
</div>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- if $content.Annotation -}}
|
{{- if $content.Annotation -}}
|
||||||
|
{{- $link := printf "%s%s" "/almanach/" $entry.MusenalmIDString -}}
|
||||||
<div class="fieldlabel">Anmerkung</div>
|
<div class="fieldlabel">Anmerkung</div>
|
||||||
<div class="fieldvalue">
|
<div class="fieldvalue {{ if $isAnnotation }}search-text{{ end }}">
|
||||||
{{- Safe (LinksAnnotation (ReplaceSlashParen
|
{{- Safe (LinksAnnotation (ReplaceSlashParen
|
||||||
$content.Annotation))
|
$content.Annotation) $link)
|
||||||
-}}
|
-}}
|
||||||
</div>
|
</div>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
@@ -131,7 +189,9 @@
|
|||||||
<div class="w-24 shrink-0 grow-0 items-end flex flex-col gap-y-1 columnfour">
|
<div class="w-24 shrink-0 grow-0 items-end flex flex-col gap-y-1 columnfour">
|
||||||
<div class="font-sans text-sm bg-stone-100 px-2 font-bold py-0.5 rounded w-max">
|
<div class="font-sans text-sm bg-stone-100 px-2 font-bold py-0.5 rounded w-max">
|
||||||
<span class="text-xs font-normal pr-1">NR</span>
|
<span class="text-xs font-normal pr-1">NR</span>
|
||||||
{{ $content.MusenalmID -}}
|
<span class="{{ if $isAlm }}search-text{{ end }}">
|
||||||
|
{{- $content.MusenalmID -}}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{{- if $entrySubView -}}
|
{{- if $entrySubView -}}
|
||||||
{{- if $content.MusenalmType -}}
|
{{- if $content.MusenalmType -}}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<div class="container-normal">
|
<div class="container-normal">
|
||||||
<div class="text">
|
<div class="text mt-6">
|
||||||
{{ Safe .record.Text }}
|
{{ Safe .record.Text }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -68,25 +68,7 @@
|
|||||||
<div id="searchcontrol" class="container-normal">
|
<div id="searchcontrol" class="container-normal">
|
||||||
{{- template "_heading" $model.parameters -}}
|
{{- template "_heading" $model.parameters -}}
|
||||||
<div id="searchform" class="border-l border-zinc-300 px-8 py-10 relative">
|
<div id="searchform" class="border-l border-zinc-300 px-8 py-10 relative">
|
||||||
<form
|
{{- template "_musenalmidbox" Arr $model.parameters.AlmString "baende" -}}
|
||||||
id="lookupform"
|
|
||||||
class="w-full font-serif grid grid-cols-12 gap-x-4 mb-4"
|
|
||||||
method="get"
|
|
||||||
action="/suche/baende"
|
|
||||||
autocomplete="off">
|
|
||||||
<label for="almstring" class="col-span-3 align-middle hidden">Almanach-Nummer:</label>
|
|
||||||
<input
|
|
||||||
autocomplete="off"
|
|
||||||
minlength="1"
|
|
||||||
required="true"
|
|
||||||
type="search"
|
|
||||||
name="almstring"
|
|
||||||
id="almstring"
|
|
||||||
value="{{ $model.parameters.AlmString }}"
|
|
||||||
placeholder="Alm-Nummer"
|
|
||||||
class="w-full col-span-3 placeholder:italic" />
|
|
||||||
<button id="submitbutton" type="submit" class="col-span-2">Nachschlagen</button>
|
|
||||||
</form>
|
|
||||||
<form
|
<form
|
||||||
id="simplesearchform"
|
id="simplesearchform"
|
||||||
class="w-full font-serif"
|
class="w-full font-serif"
|
||||||
@@ -122,11 +104,7 @@
|
|||||||
type="checkbox"
|
type="checkbox"
|
||||||
name="persons"
|
name="persons"
|
||||||
id="persons"
|
id="persons"
|
||||||
{{ if or $isBase
|
{{ if or $isBase $isPersons -}}checked{{- end -}} />
|
||||||
$isPersons
|
|
||||||
-}}
|
|
||||||
checked
|
|
||||||
{{- end -}} />
|
|
||||||
<label for="persons">Personen & Verlage</label>
|
<label for="persons">Personen & Verlage</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="selectgroup-option">
|
<div class="selectgroup-option">
|
||||||
@@ -266,7 +244,7 @@
|
|||||||
class="h-min pb-1 border-b-4 border-zinc-300 px-1.5"
|
class="h-min pb-1 border-b-4 border-zinc-300 px-1.5"
|
||||||
name="sort"
|
name="sort"
|
||||||
id="sort"
|
id="sort"
|
||||||
hx-get="{{- $model.parameters.ToQueryParams -}}"
|
hx-get="{{- $model.parameters.ToQueryParamsBaende -}}"
|
||||||
trigger="change"
|
trigger="change"
|
||||||
hx-push-url="true"
|
hx-push-url="true"
|
||||||
hx-select="main"
|
hx-select="main"
|
||||||
@@ -315,7 +293,7 @@
|
|||||||
let mark_instance = new Mark(elements);
|
let mark_instance = new Mark(elements);
|
||||||
// INFO: we wait a little bit before marking, to settle everything
|
// INFO: we wait a little bit before marking, to settle everything
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
mark_instance.mark('{{ $model.parameters.AllSearchTerms }}', {
|
mark_instance.mark('{{ $model.parameters.AllSearchTermsBaende }}', {
|
||||||
"seperateWordSearch": true,
|
"seperateWordSearch": true,
|
||||||
});
|
});
|
||||||
}, 200);
|
}, 200);
|
||||||
@@ -326,40 +304,3 @@
|
|||||||
<div class="container-normal">Keine Bände gefunden.</div>
|
<div class="container-normal">Keine Bände gefunden.</div>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
|
|
||||||
<script type="module">
|
|
||||||
const form = document.getElementById("simplesearchform");
|
|
||||||
let submitBtn = null;
|
|
||||||
if (form) {
|
|
||||||
submitBtn = form.querySelector("#submitbutton");
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkValidity(f, btn) {
|
|
||||||
if (f.checkValidity()) {
|
|
||||||
btn.disabled = false;
|
|
||||||
} else {
|
|
||||||
btn.disabled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (form && submitBtn) {
|
|
||||||
checkValidity(form, submitBtn);
|
|
||||||
form.addEventListener("input", (event) => {
|
|
||||||
checkValidity(form, submitBtn);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const lookupform = document.getElementById("lookupform");
|
|
||||||
let lookupsubmitBtn = null;
|
|
||||||
if (lookupform) {
|
|
||||||
lookupsubmitBtn = lookupform.querySelector("#submitbutton");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lookupform && lookupsubmitBtn) {
|
|
||||||
checkValidity(lookupform, lookupsubmitBtn);
|
|
||||||
lookupform.addEventListener("input", (event) => {
|
|
||||||
checkValidity(lookupform, lookupsubmitBtn);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|||||||
@@ -1,11 +1,69 @@
|
|||||||
{{ $model := . }}
|
{{ $model := . }}
|
||||||
|
{{/* .result:
|
||||||
|
type SearchResultBeitraege struct {
|
||||||
|
Queries []dbmodels.FTS5QueryRequest
|
||||||
|
|
||||||
|
// these are the sorted IDs for hits
|
||||||
|
Hits []string
|
||||||
|
Entries map[string]*dbmodels.Entry // <- Key: Entry ID
|
||||||
|
Agents map[string]*dbmodels.Agent // <- Key: Agent IDs
|
||||||
|
Contents map[string][]*dbmodels.Content // <- Key: Entry ID, or year
|
||||||
|
|
||||||
|
ContentsAgents map[string][]*dbmodels.RContentsAgents // <- Key: Content ID
|
||||||
|
}
|
||||||
|
.parameters:
|
||||||
|
type SearchParameters struct {
|
||||||
|
Parameters
|
||||||
|
Sort string
|
||||||
|
|
||||||
|
Annotations bool
|
||||||
|
Persons bool
|
||||||
|
Title bool
|
||||||
|
Series bool
|
||||||
|
Places bool
|
||||||
|
Refs bool
|
||||||
|
Year bool
|
||||||
|
Entry bool
|
||||||
|
Incipit bool
|
||||||
|
|
||||||
|
AnnotationsString string
|
||||||
|
PersonsString string
|
||||||
|
TitleString string
|
||||||
|
AlmString string
|
||||||
|
SeriesString string
|
||||||
|
PlacesString string
|
||||||
|
RefsString string
|
||||||
|
YearString string
|
||||||
|
EntryString string
|
||||||
|
IncipitString string
|
||||||
|
}
|
||||||
|
*/}}
|
||||||
|
|
||||||
|
{{ $isAlm := false }}
|
||||||
|
{{ $isTitle := false }}
|
||||||
|
{{ $isYear := false }}
|
||||||
|
{{ $isPerson := false }}
|
||||||
|
{{ $isAnnotation := false }}
|
||||||
|
{{ $isIncipit := false }}
|
||||||
|
{{ $isEntry := false }}
|
||||||
|
|
||||||
|
{{- $isAlm = $model.parameters.AlmString -}}
|
||||||
|
{{- $isTitle = or $model.parameters.Title $model.parameters.TitleString -}}
|
||||||
|
{{- $isYear = or $model.parameters.Year $model.parameters.YearString -}}
|
||||||
|
{{- $isPerson = or $model.parameters.Persons $model.parameters.PersonsString -}}
|
||||||
|
{{- $isAnnotation = or $model.parameters.Annotations $model.parameters.AnnotationsString -}}
|
||||||
|
{{- $isIncipit = or $model.parameters.Incipit $model.parameters.IncipitString -}}
|
||||||
|
{{- $isEntry = or $model.parameters.Entry $model.parameters.EntryString -}}
|
||||||
|
|
||||||
|
{{- $isBase := not (or $isTitle $isYear $isPerson $isAnnotation $isIncipit $isEntry) -}}
|
||||||
|
|
||||||
|
|
||||||
<div id="searchcontrol" class="container-normal">
|
<div id="searchcontrol" class="container-normal">
|
||||||
{{- template "_heading" $model.parameters -}}
|
{{- template "_heading" $model.parameters -}}
|
||||||
<div id="" class="border-l border-zinc-300 px-8 py-10 relative">
|
<div id="searchform" class="border-l border-zinc-300 px-8 py-10 relative">
|
||||||
|
{{- template "_musenalmidbox" Arr $model.parameters.AlmString "beitraege" -}}
|
||||||
<form
|
<form
|
||||||
id="searchform"
|
id="simplesearchform"
|
||||||
class="w-full font-serif"
|
class="w-full font-serif"
|
||||||
method="get"
|
method="get"
|
||||||
action="/suche/beitraege"
|
action="/suche/beitraege"
|
||||||
@@ -18,29 +76,35 @@
|
|||||||
{{ template "_searchboxsimple" Arr $model.parameters true $q }}
|
{{ template "_searchboxsimple" Arr $model.parameters true $q }}
|
||||||
<fieldset class="selectgroup">
|
<fieldset class="selectgroup">
|
||||||
<div class="selectgroup-option">
|
<div class="selectgroup-option">
|
||||||
<input type="checkbox" name="number" id="number" checked />
|
<input type="checkbox" name="title" id="title"
|
||||||
<label for="number">Almanach-Nr.</label>
|
{{ if or $isBase $isTitle -}}checked{{- end -}} />
|
||||||
|
<label for="title">Titel</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="selectgroup-option">
|
<div class="selectgroup-option">
|
||||||
<input type="checkbox" name="title" id="title" checked />
|
<input type="checkbox" name="incipit" id="incipit"
|
||||||
<label for="title">Titelinformationen</label>
|
{{ if or $isBase $isIncipit -}}checked{{- end -}} />
|
||||||
|
<label for="incipit">Incipit</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="selectgroup-option">
|
<div class="selectgroup-option">
|
||||||
<input type="checkbox" name="entry" id="entry" checked />
|
<input type="checkbox" name="persons" id="persons"
|
||||||
<label for="entry">Bandtitel</label>
|
{{ if or $isBase $isPerson -}}checked{{- end -}} />
|
||||||
</div>
|
|
||||||
<div class="selectgroup-option">
|
|
||||||
<input type="checkbox" name="person" id="person" checked />
|
|
||||||
<label for="person">Personen & Pseudonyme</label>
|
<label for="person">Personen & Pseudonyme</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="selectgroup-option">
|
<div class="selectgroup-option">
|
||||||
<input type="checkbox" name="annotations" id="annotations" checked />
|
<input type="checkbox" name="entry" id="entry"
|
||||||
<label for="annotations">Anmerkungen</label>
|
{{ if or $isBase $isEntry -}}checked{{- end -}} />
|
||||||
|
<label for="entry">Bandtitel</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="selectgroup-option">
|
<div class="selectgroup-option">
|
||||||
<input type="checkbox" name="year" id="year" checked />
|
<input type="checkbox" name="year" id="year"
|
||||||
|
{{ if or $isBase $isYear -}}checked{{- end -}} />
|
||||||
<label for="year">Jahr</label>
|
<label for="year">Jahr</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="selectgroup-option">
|
||||||
|
<input type="checkbox" name="annotations" id="annotations"
|
||||||
|
{{ if or $isBase $isAnnotation -}}checked{{- end -}} />
|
||||||
|
<label for="annotations">Anmerkungen</label>
|
||||||
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
{{ template "_infotextsimple" true }}
|
{{ template "_infotextsimple" true }}
|
||||||
</div>
|
</div>
|
||||||
@@ -49,3 +113,127 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{- template "_fieldscript" -}}
|
{{- template "_fieldscript" -}}
|
||||||
|
|
||||||
|
{{- if $model.parameters.IsBeitraegeSearch -}}
|
||||||
|
<div class="container-normal" id="searchresults">
|
||||||
|
<div class="border-b border-zinc-300 flex flex-row justify-between">
|
||||||
|
<div>
|
||||||
|
{{ if $model.parameters.Query -}}
|
||||||
|
Suche nach <b>»{{ $model.parameters.Query }}«</b> ·
|
||||||
|
{{- end -}}
|
||||||
|
{{- if $isAlm -}}
|
||||||
|
Inhaltsnummer <b>»{{ $model.parameters.AlmString }}«</b> ·
|
||||||
|
{{- end -}}
|
||||||
|
<i class="ri-book-line"></i>
|
||||||
|
{{ if eq $model.result.Count 1 -}}
|
||||||
|
Ein Beitrag
|
||||||
|
{{ else -}}
|
||||||
|
{{ $model.result.Count }} Beiträge
|
||||||
|
{{- end }}
|
||||||
|
in
|
||||||
|
{{ if eq ($model.result.Entries | len) 1 -}}
|
||||||
|
einem Band
|
||||||
|
{{ else -}}
|
||||||
|
{{ $model.result.Entries | len }} Bänden
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
|
{{- if gt (len $model.result.Pages) 1 }}
|
||||||
|
<div>
|
||||||
|
{{ if gt $model.parameters.Page 1 -}}
|
||||||
|
<a
|
||||||
|
href="{{- $model.parameters.ToQueryParamsBeitraege -}}&page={{ $model.parameters.Prev
|
||||||
|
}}" class="mr-1.5">
|
||||||
|
<i class="ri-arrow-left-long-line"></i>
|
||||||
|
</a>
|
||||||
|
{{- end -}}
|
||||||
|
S. {{ $model.parameters.Page }} /
|
||||||
|
{{ $model.result.PagesCount }}
|
||||||
|
{{ if lt $model.parameters.Page ($model.result.PagesCount) -}}
|
||||||
|
<a
|
||||||
|
href="{{- $model.parameters.ToQueryParamsBeitraege -}}&page={{ $model.parameters.Next
|
||||||
|
}}" class="ml-1.5">
|
||||||
|
<i class="ri-arrow-right-long-line"></i>
|
||||||
|
</a>
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
{{- if not $isAlm -}}
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
for="sort"
|
||||||
|
class="align-baseline h-min self-end pb-1 mr-2 text-sm font-sans
|
||||||
|
text-stone-700"
|
||||||
|
>Sortierung</label
|
||||||
|
>
|
||||||
|
|
||||||
|
{{/* INFO: We always redrect to letter = A bc some letters dont exist for other professions */}}
|
||||||
|
<select
|
||||||
|
class="h-min pb-1 border-b-4 border-zinc-300 px-1.5"
|
||||||
|
name="sort"
|
||||||
|
id="sort"
|
||||||
|
autocomplete="off"
|
||||||
|
hx-get="{{- $model.parameters.ToQueryParamsBeitraege -}}"
|
||||||
|
trigger="change"
|
||||||
|
hx-push-url="true"
|
||||||
|
hx-select="main"
|
||||||
|
hx-target="main">
|
||||||
|
<option
|
||||||
|
value="year"
|
||||||
|
{{ if eq $model.parameters.Sort "year" -}}
|
||||||
|
selected
|
||||||
|
{{- end -}}>
|
||||||
|
Jahr
|
||||||
|
</option>
|
||||||
|
<option value="entry" {{ if eq $model.parameters.Sort "entry" -}}selected{{- end -}}>
|
||||||
|
Bände A-Z
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{- if $model.result.Hits -}}
|
||||||
|
|
||||||
|
<div class="mt-8" id="almanachcontents">
|
||||||
|
{{- range $_, $hit := $model.result.Hits -}}
|
||||||
|
{{- $e := index $model.result.Entries $hit -}}
|
||||||
|
{{- $contents := index $model.result.Contents $e.Id -}}
|
||||||
|
<div
|
||||||
|
class="font-serif flex flex-row justify-between text-stone-800
|
||||||
|
font-bold border-b pb-0.5 mb-2 tab-list-head items-end">
|
||||||
|
<div>
|
||||||
|
{{ $e.PreferredTitle }}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="inline-block font-sans bg-slate-800 text-white h-max text-sm px-1.5 rounded">
|
||||||
|
{{- len $contents -}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-7 tab-list-panel">
|
||||||
|
{{- range $i, $c := $contents -}}
|
||||||
|
{{- $rels := index $model.result.ContentsAgents $c.Id -}}
|
||||||
|
{{- template "_content" Arr $c $e $rels $model.result.Agents false true
|
||||||
|
$model.parameters
|
||||||
|
-}}
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<script type="module">
|
||||||
|
let elements = document.querySelectorAll('.search-text');
|
||||||
|
let mark_instance = new Mark(elements);
|
||||||
|
// INFO: we wait a little bit before marking, to settle everything
|
||||||
|
setTimeout(() => {
|
||||||
|
mark_instance.mark('{{ $model.parameters.AllSearchTermsBaende }}', {
|
||||||
|
"seperateWordSearch": true,
|
||||||
|
});
|
||||||
|
}, 200);
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{- end -}}
|
||||||
|
|||||||
@@ -14,4 +14,38 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const form = document.getElementById("simplesearchform");
|
||||||
|
let submitBtn = null;
|
||||||
|
if (form) {
|
||||||
|
submitBtn = form.querySelector("#submitbutton");
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkValidity(f, btn) {
|
||||||
|
if (f.checkValidity()) {
|
||||||
|
btn.disabled = false;
|
||||||
|
} else {
|
||||||
|
btn.disabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (form && submitBtn) {
|
||||||
|
checkValidity(form, submitBtn);
|
||||||
|
form.addEventListener("input", (event) => {
|
||||||
|
checkValidity(form, submitBtn);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const lookupform = document.getElementById("lookupform");
|
||||||
|
let lookupsubmitBtn = null;
|
||||||
|
if (lookupform) {
|
||||||
|
lookupsubmitBtn = lookupform.querySelector("#submitbutton");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lookupform && lookupsubmitBtn) {
|
||||||
|
checkValidity(lookupform, lookupsubmitBtn);
|
||||||
|
lookupform.addEventListener("input", (event) => {
|
||||||
|
checkValidity(lookupform, lookupsubmitBtn);
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
21
views/routes/suche/components/_musenalmidbox.gohtml
Normal file
21
views/routes/suche/components/_musenalmidbox.gohtml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{{ $p := index . 0 }}
|
||||||
|
{{ $t := index . 1 }}
|
||||||
|
<form
|
||||||
|
id="lookupform"
|
||||||
|
class="w-full font-serif grid grid-cols-12 gap-x-4 mb-4"
|
||||||
|
method="get"
|
||||||
|
action="/suche/{{- $t -}}"
|
||||||
|
autocomplete="off">
|
||||||
|
<label for="almstring" class="col-span-3 align-middle hidden">Almanach-Nummer:</label>
|
||||||
|
<input
|
||||||
|
autocomplete="off"
|
||||||
|
minlength="1"
|
||||||
|
required="true"
|
||||||
|
type="search"
|
||||||
|
name="almstring"
|
||||||
|
id="almstring"
|
||||||
|
value="{{ $p }}"
|
||||||
|
placeholder="Alm-Nummer"
|
||||||
|
class="w-full col-span-3 placeholder:italic" />
|
||||||
|
<button id="submitbutton" type="submit" class="col-span-2">Nachschlagen</button>
|
||||||
|
</form>
|
||||||
@@ -46,6 +46,7 @@
|
|||||||
@layer components {
|
@layer components {
|
||||||
html {
|
html {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
scroll-behavior: auto !important;
|
||||||
}
|
}
|
||||||
@media (max-width: 1280px) {
|
@media (max-width: 1280px) {
|
||||||
html {
|
html {
|
||||||
@@ -458,4 +459,8 @@
|
|||||||
@apply bg-stone-100 pr-6 py-4;
|
@apply bg-stone-100 pr-6 py-4;
|
||||||
/*direction: rtl;*/
|
/*direction: rtl;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tab-list-head[aria-pressed="true"] {
|
||||||
|
@apply !text-slate-800 bg-stone-50;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user