mirror of
https://github.com/Theodor-Springmann-Stiftung/musenalm.git
synced 2025-10-29 09:15:33 +00:00
Abschluss Bandsuche
This commit is contained in:
@@ -26,14 +26,13 @@ func AgentForId(app core.App, id string) (*Agent, error) {
|
|||||||
func FTS5SearchAgents(app core.App, query string) ([]*Agent, error) {
|
func FTS5SearchAgents(app core.App, query string) ([]*Agent, error) {
|
||||||
a := []*Agent{}
|
a := []*Agent{}
|
||||||
q := NormalizeQuery(query)
|
q := NormalizeQuery(query)
|
||||||
if len(q) == 0 {
|
req := IntoQueryRequests([]string{AGENTS_NAME_FIELD, AGENTS_PSEUDONYMS_FIELD, REFERENCES_FIELD, AGENTS_BIOGRAPHICAL_DATA_FIELD, ANNOTATION_FIELD}, q)
|
||||||
|
|
||||||
|
if len(req) == 0 {
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ids, err := FTS5Search(app, AGENTS_TABLE, FTS5QueryRequest{
|
ids, err := FTS5Search(app, AGENTS_TABLE, req...)
|
||||||
Fields: []string{AGENTS_NAME_FIELD, AGENTS_PSEUDONYMS_FIELD, REFERENCES_FIELD, AGENTS_BIOGRAPHICAL_DATA_FIELD, ANNOTATION_FIELD},
|
|
||||||
Query: q,
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
140
dbmodels/fts5.go
140
dbmodels/fts5.go
@@ -2,8 +2,10 @@ package dbmodels
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
"github.com/Theodor-Springmann-Stiftung/musenalm/helpers/datatypes"
|
"github.com/Theodor-Springmann-Stiftung/musenalm/helpers/datatypes"
|
||||||
"github.com/pocketbase/dbx"
|
"github.com/pocketbase/dbx"
|
||||||
@@ -99,22 +101,125 @@ var CONTENTS_FTS5_FIELDS = []string{
|
|||||||
|
|
||||||
var ErrInvalidQuery = errors.New("invalid input into the search function")
|
var ErrInvalidQuery = errors.New("invalid input into the search function")
|
||||||
|
|
||||||
func NormalizeQuery(query string) []string {
|
type Query struct {
|
||||||
query = datatypes.NormalizeString(query)
|
Include []string // Phrases that should be matched
|
||||||
query = datatypes.DeleteTags(query)
|
Exclude []string // Phrases that should not be matched
|
||||||
query = datatypes.RemovePunctuation(query)
|
UnsafeI []string // Phrases < 3 characters
|
||||||
query = cases.Lower(language.German).String(query)
|
UnsafeE []string // Phrases < 3 characters excluded
|
||||||
// TODO: how to normalize, which unicode normalization to use?
|
}
|
||||||
|
|
||||||
split := strings.Split(query, " ")
|
// Parses query strings like
|
||||||
res := []string{}
|
// word another "this is a phrase" -notthis aword -alsonotthis -"also not this"
|
||||||
for _, s := range split {
|
// into seperate phrases
|
||||||
if len(s) > 2 {
|
func NormalizeQuery(query string) Query {
|
||||||
res = append(res, s)
|
query = datatypes.NormalizeString(query)
|
||||||
|
// TODO: how to normalize, which unicode normalization to use?
|
||||||
|
// query = datatypes.RemovePunctuation(query)
|
||||||
|
query = cases.Lower(language.German).String(query)
|
||||||
|
|
||||||
|
var include []string
|
||||||
|
var exclude []string
|
||||||
|
var unsafeI []string
|
||||||
|
var unsafeE []string
|
||||||
|
|
||||||
|
isInQuotes := false
|
||||||
|
isExcluded := false
|
||||||
|
|
||||||
|
var cToken strings.Builder
|
||||||
|
|
||||||
|
at := func() {
|
||||||
|
if cToken.Len() == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t := cToken.String()
|
||||||
|
if len(t) < 3 && isExcluded {
|
||||||
|
unsafeE = append(unsafeE, t)
|
||||||
|
return
|
||||||
|
} else if len(t) < 3 {
|
||||||
|
unsafeI = append(unsafeI, t)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(t) >= 3 && isExcluded {
|
||||||
|
exclude = append(exclude, t)
|
||||||
|
return
|
||||||
|
} else if len(t) >= 3 {
|
||||||
|
include = append(include, t)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res
|
reset := func() {
|
||||||
|
isInQuotes = false
|
||||||
|
isExcluded = false
|
||||||
|
cToken.Reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
addToken := func() {
|
||||||
|
at()
|
||||||
|
reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, r := range query {
|
||||||
|
fmt.Printf("Rune: %v\n", r)
|
||||||
|
if r == '"' {
|
||||||
|
if isInQuotes {
|
||||||
|
addToken()
|
||||||
|
} else if cToken.Len() == 0 {
|
||||||
|
isInQuotes = true
|
||||||
|
}
|
||||||
|
// INFO: - is punctuation, so the order of cases is important
|
||||||
|
} else if r == 45 && cToken.Len() == 0 {
|
||||||
|
isExcluded = true
|
||||||
|
} else if unicode.IsSpace(r) && !isInQuotes {
|
||||||
|
addToken()
|
||||||
|
} else if unicode.IsPunct(r) && !isInQuotes {
|
||||||
|
addToken()
|
||||||
|
} else {
|
||||||
|
cToken.WriteRune(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cToken.Len() > 0 {
|
||||||
|
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{
|
||||||
|
Include: include,
|
||||||
|
Exclude: exclude,
|
||||||
|
UnsafeI: unsafeI,
|
||||||
|
UnsafeE: unsafeE,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// INFO: Takes in fields and a Query object
|
||||||
|
func IntoQueryRequests(f []string, q Query) []FTS5QueryRequest {
|
||||||
|
ret := []FTS5QueryRequest{}
|
||||||
|
|
||||||
|
if len(q.Include) > 0 {
|
||||||
|
ret = append(ret, FTS5QueryRequest{
|
||||||
|
Fields: f,
|
||||||
|
Query: q.Include,
|
||||||
|
OP: OP_AND,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(q.Exclude) > 0 {
|
||||||
|
ret = append(ret, FTS5QueryRequest{
|
||||||
|
Fields: f,
|
||||||
|
Query: q.Exclude,
|
||||||
|
OP: OP_NOT,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func FTS5Search(app core.App, table string, mapfq ...FTS5QueryRequest) ([]*FTS5IDQueryResult, error) {
|
func FTS5Search(app core.App, table string, mapfq ...FTS5QueryRequest) ([]*FTS5IDQueryResult, error) {
|
||||||
@@ -125,7 +230,16 @@ func FTS5Search(app core.App, table string, mapfq ...FTS5QueryRequest) ([]*FTS5I
|
|||||||
q := NewFTS5Query().From(table).SelectID()
|
q := NewFTS5Query().From(table).SelectID()
|
||||||
for _, v := range mapfq {
|
for _, v := range mapfq {
|
||||||
for _, que := range v.Query {
|
for _, que := range v.Query {
|
||||||
q.AndMatch(v.Fields, que)
|
switch v.OP {
|
||||||
|
case OP_AND:
|
||||||
|
q.AndMatch(v.Fields, que)
|
||||||
|
case OP_OR:
|
||||||
|
q.OrMatch(v.Fields, que)
|
||||||
|
case OP_NOT:
|
||||||
|
q.NotMatch(v.Fields, que)
|
||||||
|
case NONE:
|
||||||
|
q.AndMatch(v.Fields, que)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
type FTS5QueryRequest struct {
|
type FTS5QueryRequest struct {
|
||||||
Fields []string
|
Fields []string
|
||||||
Query []string
|
Query []string
|
||||||
|
OP Operator
|
||||||
}
|
}
|
||||||
|
|
||||||
type FTS5IDQueryResult struct {
|
type FTS5IDQueryResult struct {
|
||||||
|
|||||||
@@ -112,6 +112,11 @@ 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) {
|
||||||
|
ret, err := TableByField[Series](app, SERIES_TABLE, MUSENALMID_FIELD, id)
|
||||||
|
return &ret, err
|
||||||
|
}
|
||||||
|
|
||||||
func Series_ID(app core.App, id string) (*Series, error) {
|
func Series_ID(app core.App, id string) (*Series, error) {
|
||||||
ret, err := TableByID[Series](app, SERIES_TABLE, id)
|
ret, err := TableByID[Series](app, SERIES_TABLE, id)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
|
|||||||
@@ -43,14 +43,13 @@ func BasicSearchSeries(app core.App, query string) ([]*Series, []*Series, error)
|
|||||||
|
|
||||||
// INFO: Needing to differentiate matches
|
// INFO: Needing to differentiate matches
|
||||||
querysplit := NormalizeQuery(query)
|
querysplit := NormalizeQuery(query)
|
||||||
if len(querysplit) == 0 {
|
req := IntoQueryRequests([]string{SERIES_TITLE_FIELD, ANNOTATION_FIELD, REFERENCES_FIELD}, querysplit)
|
||||||
|
|
||||||
|
if len(req) == 0 {
|
||||||
return series, []*Series{}, nil
|
return series, []*Series{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
altids, err := FTS5Search(app, SERIES_TABLE, FTS5QueryRequest{
|
altids, err := FTS5Search(app, SERIES_TABLE, req...)
|
||||||
Fields: []string{SERIES_TITLE_FIELD, ANNOTATION_FIELD, REFERENCES_FIELD},
|
|
||||||
Query: querysplit,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,13 +35,13 @@ func (p *ReihePage) Setup(router *router.Router[*core.RequestEvent], app core.Ap
|
|||||||
router.GET(URL_REIHE, func(e *core.RequestEvent) error {
|
router.GET(URL_REIHE, func(e *core.RequestEvent) error {
|
||||||
id := e.Request.PathValue("id")
|
id := e.Request.PathValue("id")
|
||||||
data := make(map[string]interface{})
|
data := make(map[string]interface{})
|
||||||
reihe, err := dbmodels.Series_ID(app, id)
|
reihe, err := dbmodels.Series_MusenalmID(app, id)
|
||||||
if err != nil {
|
if err != nil || reihe == nil || reihe.Id == "" {
|
||||||
return engine.Response404(e, err, data)
|
return engine.Response404(e, err, data)
|
||||||
}
|
}
|
||||||
data["series"] = reihe
|
data["series"] = reihe
|
||||||
|
|
||||||
entries, relations, err := Entries_Series_IDs(app, []any{id})
|
entries, relations, err := Entries_Series_IDs(app, []any{reihe.Id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return engine.Response404(e, err, data)
|
return engine.Response404(e, err, data)
|
||||||
}
|
}
|
||||||
|
|||||||
235
pages/suche.go
235
pages/suche.go
@@ -1,9 +1,11 @@
|
|||||||
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"
|
||||||
@@ -54,7 +56,7 @@ func (p *SuchePage) Setup(router *router.Router[*core.RequestEvent], app core.Ap
|
|||||||
|
|
||||||
allparas, _ := NewSearchParameters(e, *paras)
|
allparas, _ := NewSearchParameters(e, *paras)
|
||||||
|
|
||||||
if paras.Query != "" || allparas.IsBaendeSearch() {
|
if allparas.IsBaendeSearch() {
|
||||||
return p.SearchBaendeRequest(app, engine, e, *allparas)
|
return p.SearchBaendeRequest(app, engine, e, *allparas)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +142,7 @@ func NewParameters(e *core.RequestEvent) (*Parameters, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parameters) NormalizeQuery() []string {
|
func (p *Parameters) NormalizeQuery() dbmodels.Query {
|
||||||
return dbmodels.NormalizeQuery(p.Query)
|
return dbmodels.NormalizeQuery(p.Query)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,7 +153,6 @@ type SearchParameters struct {
|
|||||||
Annotations bool
|
Annotations bool
|
||||||
Persons bool
|
Persons bool
|
||||||
Title bool
|
Title bool
|
||||||
Alm bool
|
|
||||||
Series bool
|
Series bool
|
||||||
Places bool
|
Places bool
|
||||||
Refs bool
|
Refs bool
|
||||||
@@ -170,7 +171,6 @@ type SearchParameters struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewSearchParameters(e *core.RequestEvent, p Parameters) (*SearchParameters, error) {
|
func NewSearchParameters(e *core.RequestEvent, p Parameters) (*SearchParameters, error) {
|
||||||
alm := e.Request.URL.Query().Get(BAENDE_PARAM_ALM_NR) == "on"
|
|
||||||
title := e.Request.URL.Query().Get(BAENDE_PARAM_TITLE) == "on"
|
title := e.Request.URL.Query().Get(BAENDE_PARAM_TITLE) == "on"
|
||||||
series := e.Request.URL.Query().Get(BAENDE_PARAM_SERIES) == "on"
|
series := e.Request.URL.Query().Get(BAENDE_PARAM_SERIES) == "on"
|
||||||
persons := e.Request.URL.Query().Get(BAENDE_PARAM_PERSONS) == "on"
|
persons := e.Request.URL.Query().Get(BAENDE_PARAM_PERSONS) == "on"
|
||||||
@@ -180,14 +180,19 @@ func NewSearchParameters(e *core.RequestEvent, p Parameters) (*SearchParameters,
|
|||||||
year := e.Request.URL.Query().Get(BAENDE_PARAM_YEAR) == "on"
|
year := e.Request.URL.Query().Get(BAENDE_PARAM_YEAR) == "on"
|
||||||
|
|
||||||
almstring := e.Request.URL.Query().Get(BAENDE_PARAM_ALM_NR + "string")
|
almstring := e.Request.URL.Query().Get(BAENDE_PARAM_ALM_NR + "string")
|
||||||
|
|
||||||
titlestring := e.Request.URL.Query().Get(BAENDE_PARAM_TITLE + "string")
|
titlestring := e.Request.URL.Query().Get(BAENDE_PARAM_TITLE + "string")
|
||||||
seriesstring := e.Request.URL.Query().Get(BAENDE_PARAM_SERIES + "string")
|
seriesstring := e.Request.URL.Query().Get(BAENDE_PARAM_SERIES + "string")
|
||||||
personsstring := e.Request.URL.Query().Get(BAENDE_PARAM_PERSONS + "string")
|
personsstring := e.Request.URL.Query().Get(BAENDE_PARAM_PERSONS + "string")
|
||||||
placesstring := e.Request.URL.Query().Get(BAENDE_PARAM_PLACES + "string")
|
placesstring := e.Request.URL.Query().Get(BAENDE_PARAM_PLACES + "string")
|
||||||
refsstring := e.Request.URL.Query().Get(BAENDE_PARAM_REFS + "string")
|
|
||||||
annotationsstring := e.Request.URL.Query().Get(BAENDE_PARAM_ANNOTATIONS + "string")
|
annotationsstring := e.Request.URL.Query().Get(BAENDE_PARAM_ANNOTATIONS + "string")
|
||||||
yearstring := e.Request.URL.Query().Get(BAENDE_PARAM_YEAR + "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")
|
sort := e.Request.URL.Query().Get("sort")
|
||||||
if sort == "" {
|
if sort == "" {
|
||||||
sort = "year"
|
sort = "year"
|
||||||
@@ -197,7 +202,6 @@ func NewSearchParameters(e *core.RequestEvent, p Parameters) (*SearchParameters,
|
|||||||
Parameters: p,
|
Parameters: p,
|
||||||
Sort: sort,
|
Sort: sort,
|
||||||
// INFO: Common parameters
|
// INFO: Common parameters
|
||||||
Alm: alm,
|
|
||||||
Title: title,
|
Title: title,
|
||||||
Persons: persons,
|
Persons: persons,
|
||||||
Annotations: annotations,
|
Annotations: annotations,
|
||||||
@@ -214,15 +218,36 @@ func NewSearchParameters(e *core.RequestEvent, p Parameters) (*SearchParameters,
|
|||||||
SeriesString: seriesstring,
|
SeriesString: seriesstring,
|
||||||
PersonsString: personsstring,
|
PersonsString: personsstring,
|
||||||
PlacesString: placesstring,
|
PlacesString: placesstring,
|
||||||
RefsString: refsstring,
|
RefsString: refss,
|
||||||
AnnotationsString: annotationsstring,
|
AnnotationsString: annotationsstring,
|
||||||
YearString: yearstring,
|
YearString: yearstring,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p SearchParameters) AllSearchTerms() string {
|
func (p SearchParameters) AllSearchTerms() string {
|
||||||
q := p.Query + " " + p.AnnotationsString + " " + p.PersonsString + " " + p.TitleString + " " + p.AlmString + " " + p.SeriesString + " " + p.PlacesString + " " + p.RefsString + " " + p.YearString
|
res := []string{}
|
||||||
return q
|
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 {
|
func (p SearchParameters) ToQueryParams() string {
|
||||||
@@ -235,31 +260,28 @@ func (p SearchParameters) ToQueryParams() string {
|
|||||||
|
|
||||||
if p.Query != "" {
|
if p.Query != "" {
|
||||||
q += fmt.Sprintf("q=%s", p.Query)
|
q += fmt.Sprintf("q=%s", p.Query)
|
||||||
}
|
|
||||||
|
|
||||||
if p.Alm {
|
if p.Title {
|
||||||
q += "&alm=on"
|
q += "&title=on"
|
||||||
}
|
}
|
||||||
if p.Title {
|
if p.Persons {
|
||||||
q += "&title=on"
|
q += "&persons=on"
|
||||||
}
|
}
|
||||||
if p.Persons {
|
if p.Annotations {
|
||||||
q += "&persons=on"
|
q += "&annotations=on"
|
||||||
}
|
}
|
||||||
if p.Annotations {
|
if p.Series {
|
||||||
q += "&annotations=on"
|
q += "&series=on"
|
||||||
}
|
}
|
||||||
if p.Series {
|
if p.Places {
|
||||||
q += "&series=on"
|
q += "&places=on"
|
||||||
}
|
}
|
||||||
if p.Places {
|
if p.Refs {
|
||||||
q += "&places=on"
|
q += "&references=on"
|
||||||
}
|
}
|
||||||
if p.Refs {
|
if p.Year {
|
||||||
q += "&references=on"
|
q += "&year=on"
|
||||||
}
|
}
|
||||||
if p.Year {
|
|
||||||
q += "&year=on"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.YearString != "" {
|
if p.YearString != "" {
|
||||||
@@ -274,9 +296,6 @@ func (p SearchParameters) ToQueryParams() string {
|
|||||||
if p.TitleString != "" {
|
if p.TitleString != "" {
|
||||||
q += fmt.Sprintf("&titlestring=%s", p.TitleString)
|
q += fmt.Sprintf("&titlestring=%s", p.TitleString)
|
||||||
}
|
}
|
||||||
if p.AlmString != "" {
|
|
||||||
q += fmt.Sprintf("&almstring=%s", p.AlmString)
|
|
||||||
}
|
|
||||||
if p.SeriesString != "" {
|
if p.SeriesString != "" {
|
||||||
q += fmt.Sprintf("&seriesstring=%s", p.SeriesString)
|
q += fmt.Sprintf("&seriesstring=%s", p.SeriesString)
|
||||||
}
|
}
|
||||||
@@ -291,16 +310,13 @@ func (p SearchParameters) ToQueryParams() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p SearchParameters) IsBaendeSearch() bool {
|
func (p SearchParameters) IsBaendeSearch() bool {
|
||||||
return p.Collection == "baende" && (p.Query != "" || (p.AnnotationsString != "" || p.PersonsString != "" || p.TitleString != "" || p.AlmString != "" || p.SeriesString != "" || p.PlacesString != "" || p.RefsString != "" || p.YearString != ""))
|
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 {
|
func (p SearchParameters) FieldSetBaende() []dbmodels.FTS5QueryRequest {
|
||||||
ret := []dbmodels.FTS5QueryRequest{}
|
ret := []dbmodels.FTS5QueryRequest{}
|
||||||
if p.Query != "" {
|
if p.Query != "" {
|
||||||
fields := []string{dbmodels.ID_FIELD}
|
fields := []string{dbmodels.ID_FIELD}
|
||||||
if p.Alm {
|
|
||||||
fields = append(fields, dbmodels.MUSENALMID_FIELD)
|
|
||||||
}
|
|
||||||
if p.Title {
|
if p.Title {
|
||||||
// INFO: Preferred Title is not here to avoid hitting the Reihentitel
|
// INFO: Preferred Title is not here to avoid hitting the Reihentitel
|
||||||
fields = append(fields,
|
fields = append(fields,
|
||||||
@@ -331,93 +347,50 @@ func (p SearchParameters) FieldSetBaende() []dbmodels.FTS5QueryRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
que := p.NormalizeQuery()
|
que := p.NormalizeQuery()
|
||||||
|
req := dbmodels.IntoQueryRequests(fields, que)
|
||||||
if len(que) > 0 {
|
ret = append(ret, req...)
|
||||||
ret = append(ret, dbmodels.FTS5QueryRequest{
|
|
||||||
Fields: fields,
|
|
||||||
Query: p.NormalizeQuery(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.AnnotationsString != "" {
|
if p.AnnotationsString != "" {
|
||||||
que := dbmodels.NormalizeQuery(p.AnnotationsString)
|
que := dbmodels.NormalizeQuery(p.AnnotationsString)
|
||||||
if len(que) > 0 {
|
req := dbmodels.IntoQueryRequests([]string{dbmodels.ANNOTATION_FIELD}, que)
|
||||||
ret = append(ret, dbmodels.FTS5QueryRequest{
|
ret = append(ret, req...)
|
||||||
Fields: []string{dbmodels.ANNOTATION_FIELD},
|
|
||||||
Query: que,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.PersonsString != "" {
|
if p.PersonsString != "" {
|
||||||
que := dbmodels.NormalizeQuery(p.PersonsString)
|
que := dbmodels.NormalizeQuery(p.PersonsString)
|
||||||
if len(que) > 0 {
|
req := dbmodels.IntoQueryRequests([]string{dbmodels.AGENTS_TABLE, dbmodels.RESPONSIBILITY_STMT_FIELD}, que)
|
||||||
ret = append(ret, dbmodels.FTS5QueryRequest{
|
ret = append(ret, req...)
|
||||||
Fields: []string{dbmodels.AGENTS_TABLE, dbmodels.RESPONSIBILITY_STMT_FIELD},
|
|
||||||
Query: que,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.TitleString != "" {
|
if p.TitleString != "" {
|
||||||
que := dbmodels.NormalizeQuery(p.TitleString)
|
que := dbmodels.NormalizeQuery(p.TitleString)
|
||||||
if len(que) > 0 {
|
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, dbmodels.FTS5QueryRequest{
|
ret = append(ret, req...)
|
||||||
Fields: []string{dbmodels.TITLE_STMT_FIELD, dbmodels.SUBTITLE_STMT_FIELD, dbmodels.INCIPIT_STMT_FIELD, dbmodels.VARIANT_TITLE_FIELD, dbmodels.PARALLEL_TITLE_FIELD},
|
|
||||||
Query: que,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.AlmString != "" {
|
|
||||||
que := dbmodels.NormalizeQuery(p.AlmString)
|
|
||||||
if len(que) > 0 {
|
|
||||||
ret = append(ret, dbmodels.FTS5QueryRequest{
|
|
||||||
Fields: []string{dbmodels.MUSENALMID_FIELD},
|
|
||||||
Query: que,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.SeriesString != "" {
|
if p.SeriesString != "" {
|
||||||
que := dbmodels.NormalizeQuery(p.SeriesString)
|
que := dbmodels.NormalizeQuery(p.SeriesString)
|
||||||
if len(que) > 0 {
|
req := dbmodels.IntoQueryRequests([]string{dbmodels.SERIES_TABLE}, que)
|
||||||
ret = append(ret, dbmodels.FTS5QueryRequest{
|
ret = append(ret, req...)
|
||||||
Fields: []string{dbmodels.SERIES_TABLE},
|
|
||||||
Query: que,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.PlacesString != "" {
|
if p.PlacesString != "" {
|
||||||
que := dbmodels.NormalizeQuery(p.PlacesString)
|
que := dbmodels.NormalizeQuery(p.PlacesString)
|
||||||
if len(que) > 0 {
|
req := dbmodels.IntoQueryRequests([]string{dbmodels.PLACES_TABLE, dbmodels.PLACE_STMT_FIELD}, que)
|
||||||
ret = append(ret, dbmodels.FTS5QueryRequest{
|
ret = append(ret, req...)
|
||||||
Fields: []string{dbmodels.PLACES_TABLE, dbmodels.PLACE_STMT_FIELD},
|
|
||||||
Query: que,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.RefsString != "" {
|
if p.RefsString != "" {
|
||||||
que := dbmodels.NormalizeQuery(p.RefsString)
|
que := dbmodels.NormalizeQuery(p.RefsString)
|
||||||
if len(que) > 0 {
|
req := dbmodels.IntoQueryRequests([]string{dbmodels.REFERENCES_FIELD}, que)
|
||||||
ret = append(ret, dbmodels.FTS5QueryRequest{
|
ret = append(ret, req...)
|
||||||
Fields: []string{dbmodels.REFERENCES_FIELD},
|
|
||||||
Query: que,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.YearString != "" {
|
if p.YearString != "" {
|
||||||
que := dbmodels.NormalizeQuery(p.YearString)
|
que := dbmodels.NormalizeQuery(p.YearString)
|
||||||
if len(que) > 0 {
|
req := dbmodels.IntoQueryRequests([]string{dbmodels.YEAR_FIELD}, que)
|
||||||
ret = append(ret, dbmodels.FTS5QueryRequest{
|
ret = append(ret, req...)
|
||||||
Fields: []string{dbmodels.YEAR_FIELD},
|
|
||||||
Query: dbmodels.NormalizeQuery(p.YearString),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
@@ -427,11 +400,13 @@ func (p SearchParameters) IsExtendedSearch() bool {
|
|||||||
return p.AnnotationsString != "" || p.PersonsString != "" || p.TitleString != "" || p.AlmString != "" || p.SeriesString != "" || p.PlacesString != "" || p.RefsString != "" || p.YearString != ""
|
return p.AnnotationsString != "" || p.PersonsString != "" || p.TitleString != "" || p.AlmString != "" || p.SeriesString != "" || p.PlacesString != "" || p.RefsString != "" || p.YearString != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p SearchParameters) NormalizeQuery() []string {
|
func (p SearchParameters) NormalizeQuery() dbmodels.Query {
|
||||||
return dbmodels.NormalizeQuery(p.Query)
|
return dbmodels.NormalizeQuery(p.Query)
|
||||||
}
|
}
|
||||||
|
|
||||||
type SearchResultBaende struct {
|
type SearchResultBaende struct {
|
||||||
|
Queries []dbmodels.FTS5QueryRequest
|
||||||
|
|
||||||
// these are the sorted IDs for hits
|
// these are the sorted IDs for hits
|
||||||
Hits []string
|
Hits []string
|
||||||
Series map[string]*dbmodels.Series // <- Key: Series ID
|
Series map[string]*dbmodels.Series // <- Key: Series ID
|
||||||
@@ -445,25 +420,57 @@ type SearchResultBaende struct {
|
|||||||
EntriesAgents map[string][]*dbmodels.REntriesAgents // <- Key: Entry ID
|
EntriesAgents map[string][]*dbmodels.REntriesAgents // <- Key: Entry ID
|
||||||
}
|
}
|
||||||
|
|
||||||
func SimpleSearchBaende(app core.App, params SearchParameters) (*SearchResultBaende, error) {
|
func EmptyResultBaende() *SearchResultBaende {
|
||||||
fields := params.FieldSetBaende()
|
return &SearchResultBaende{
|
||||||
if len(fields) == 0 {
|
Hits: []string{},
|
||||||
return nil, ErrNoQuery
|
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),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ids, err := dbmodels.FTS5Search(app, dbmodels.ENTRIES_TABLE, fields...)
|
func SimpleSearchBaende(app core.App, params SearchParameters) (*SearchResultBaende, error) {
|
||||||
if err != nil {
|
entries := []*dbmodels.Entry{}
|
||||||
return nil, err
|
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{}
|
resultids := []any{}
|
||||||
for _, id := range ids {
|
for _, entry := range entries {
|
||||||
resultids = append(resultids, id.ID)
|
resultids = append(resultids, entry.Id)
|
||||||
}
|
|
||||||
|
|
||||||
entries, err := dbmodels.Entries_IDs(app, resultids)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
entriesmap := make(map[string]*dbmodels.Entry)
|
entriesmap := make(map[string]*dbmodels.Entry)
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
Annotations bool
|
Annotations bool
|
||||||
Persons bool
|
Persons bool
|
||||||
Title bool
|
Title bool
|
||||||
Alm bool
|
|
||||||
Series bool
|
Series bool
|
||||||
Places bool
|
Places bool
|
||||||
Refs bool
|
Refs bool
|
||||||
@@ -52,7 +51,7 @@
|
|||||||
{{ $isPersons := false }}
|
{{ $isPersons := false }}
|
||||||
{{ $isAnnotations := false }}
|
{{ $isAnnotations := false }}
|
||||||
|
|
||||||
{{- $isAlm = or $model.parameters.Alm $model.parameters.AlmString -}}
|
{{- $isAlm = $model.parameters.AlmString -}}
|
||||||
{{- $isTitle = or $model.parameters.Title $model.parameters.TitleString -}}
|
{{- $isTitle = or $model.parameters.Title $model.parameters.TitleString -}}
|
||||||
{{- $isRefs = or $model.parameters.Refs $model.parameters.RefsString -}}
|
{{- $isRefs = or $model.parameters.Refs $model.parameters.RefsString -}}
|
||||||
{{- $isPlaces = or $model.parameters.Places $model.parameters.PlacesString -}}
|
{{- $isPlaces = or $model.parameters.Places $model.parameters.PlacesString -}}
|
||||||
@@ -61,16 +60,33 @@
|
|||||||
{{- $isPersons = or $model.parameters.Persons $model.parameters.PersonsString -}}
|
{{- $isPersons = or $model.parameters.Persons $model.parameters.PersonsString -}}
|
||||||
{{- $isAnnotations = or $model.parameters.Annotations $model.parameters.AnnotationsString -}}
|
{{- $isAnnotations = or $model.parameters.Annotations $model.parameters.AnnotationsString -}}
|
||||||
|
|
||||||
{{- $isBase := not (or $isAlm $isTitle $isRefs $isPlaces $isYear $isSeries $isPersons
|
{{- $isBase := not (or $isTitle $isRefs $isPlaces $isYear $isSeries $isPersons
|
||||||
$isAnnotations)
|
$isAnnotations)
|
||||||
-}}
|
-}}
|
||||||
|
|
||||||
|
|
||||||
<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">
|
||||||
<form
|
<form
|
||||||
id="searchform"
|
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"
|
||||||
|
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
|
||||||
|
id="simplesearchform"
|
||||||
class="w-full font-serif"
|
class="w-full font-serif"
|
||||||
method="get"
|
method="get"
|
||||||
action="/suche/baende"
|
action="/suche/baende"
|
||||||
@@ -83,14 +99,6 @@
|
|||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{ template "_searchboxsimple" Arr $model.parameters true $q }}
|
{{ template "_searchboxsimple" Arr $model.parameters true $q }}
|
||||||
<fieldset class="selectgroup">
|
<fieldset class="selectgroup">
|
||||||
<div class="selectgroup-option">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
name="alm"
|
|
||||||
id="alm"
|
|
||||||
{{ if or $isBase $isAlm -}}checked{{- end -}} />
|
|
||||||
<label for="alm">Almanach-Nr.</label>
|
|
||||||
</div>
|
|
||||||
<div class="selectgroup-option">
|
<div class="selectgroup-option">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@@ -172,12 +180,6 @@
|
|||||||
name="titlestring"
|
name="titlestring"
|
||||||
id="titlestring"
|
id="titlestring"
|
||||||
value="{{ $model.parameters.TitleString }}" />
|
value="{{ $model.parameters.TitleString }}" />
|
||||||
<label for="almstring">Almanach-Nr.</label>
|
|
||||||
<input
|
|
||||||
type="search"
|
|
||||||
name="almstring"
|
|
||||||
id="almstring"
|
|
||||||
value="{{ $model.parameters.AlmString }}" />
|
|
||||||
<label for="seriesstring">Reihentitel</label>
|
<label for="seriesstring">Reihentitel</label>
|
||||||
<input
|
<input
|
||||||
type="search"
|
type="search"
|
||||||
@@ -231,6 +233,9 @@
|
|||||||
{{ if $model.parameters.Query -}}
|
{{ if $model.parameters.Query -}}
|
||||||
Suche nach <b>»{{ $model.parameters.Query }}«</b> ·
|
Suche nach <b>»{{ $model.parameters.Query }}«</b> ·
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
{{- if $isAlm -}}
|
||||||
|
Almanach-Nummer <b>»{{ $model.parameters.AlmString }}«</b> ·
|
||||||
|
{{- end -}}
|
||||||
<i class="ri-book-line"></i>
|
<i class="ri-book-line"></i>
|
||||||
{{ if eq $model.result.Count 1 -}}
|
{{ if eq $model.result.Count 1 -}}
|
||||||
Ein Band
|
Ein Band
|
||||||
@@ -245,37 +250,39 @@
|
|||||||
{{- end -}}
|
{{- end -}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
{{- if not $isAlm -}}
|
||||||
<label
|
<div>
|
||||||
for="sort"
|
<label
|
||||||
class="align-baseline h-min self-end pb-1 mr-2 text-sm font-sans
|
for="sort"
|
||||||
|
class="align-baseline h-min self-end pb-1 mr-2 text-sm font-sans
|
||||||
text-stone-700"
|
text-stone-700"
|
||||||
>Sortierung</label
|
>Sortierung</label
|
||||||
>
|
>
|
||||||
|
|
||||||
{{/* INFO: We always redrect to letter = A bc some letters dont exist for other professions */}}
|
{{/* INFO: We always redrect to letter = A bc some letters dont exist for other professions */}}
|
||||||
<select
|
<select
|
||||||
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.ToQueryParams -}}"
|
||||||
trigger="change"
|
trigger="change"
|
||||||
hx-push-url="true"
|
hx-push-url="true"
|
||||||
hx-select="main"
|
hx-select="main"
|
||||||
auto-complete="off"
|
auto-complete="off"
|
||||||
hx-target="main">
|
hx-target="main">
|
||||||
<option
|
<option
|
||||||
value="year"
|
value="year"
|
||||||
{{ if eq $model.parameters.Sort "year" -}}
|
{{ if eq $model.parameters.Sort "year" -}}
|
||||||
selected
|
selected
|
||||||
{{- end -}}>
|
{{- end -}}>
|
||||||
Erscheinungsjahr
|
Erscheinungsjahr
|
||||||
</option>
|
</option>
|
||||||
<option value="series" {{ if eq $model.parameters.Sort "series" -}}selected{{- end -}}>
|
<option value="series" {{ if eq $model.parameters.Sort "series" -}}selected{{- end -}}>
|
||||||
Reihentitel A-Z
|
Reihentitel A-Z
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
{{- end -}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{- if $model.result.Hits -}}
|
{{- if $model.result.Hits -}}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
Annotations bool
|
Annotations bool
|
||||||
Persons bool
|
Persons bool
|
||||||
Title bool
|
Title bool
|
||||||
Alm bool
|
|
||||||
Series bool
|
Series bool
|
||||||
Places bool
|
Places bool
|
||||||
Refs bool
|
Refs bool
|
||||||
@@ -44,7 +43,7 @@
|
|||||||
}
|
}
|
||||||
*/}}
|
*/}}
|
||||||
|
|
||||||
{{- $isAlm := or $model.parameters.Alm $model.parameters.AlmString -}}
|
{{- $isAlm := $model.parameters.AlmString -}}
|
||||||
{{- $isTitle := or $model.parameters.Title $model.parameters.TitleString -}}
|
{{- $isTitle := or $model.parameters.Title $model.parameters.TitleString -}}
|
||||||
{{- $isRefs := or $model.parameters.Refs $model.parameters.RefsString -}}
|
{{- $isRefs := or $model.parameters.Refs $model.parameters.RefsString -}}
|
||||||
{{- $isPlaces := or $model.parameters.Places $model.parameters.PlacesString -}}
|
{{- $isPlaces := or $model.parameters.Places $model.parameters.PlacesString -}}
|
||||||
@@ -61,7 +60,7 @@
|
|||||||
<div class="inline-block ml-1 whitespace-nowrap">
|
<div class="inline-block ml-1 whitespace-nowrap">
|
||||||
{{- if not $entry.TitleStmt -}}
|
{{- if not $entry.TitleStmt -}}
|
||||||
<tool-tip position="right">
|
<tool-tip position="right">
|
||||||
<i class="ri-forbid-line"></i>
|
<i class="ri-forbid-2-line"></i>
|
||||||
<div class="data-tip">Keine nähere Erfassung</div>
|
<div class="data-tip">Keine nähere Erfassung</div>
|
||||||
</tool-tip>
|
</tool-tip>
|
||||||
{{- else if eq $entry.EditState "Edited" -}}
|
{{- else if eq $entry.EditState "Edited" -}}
|
||||||
|
|||||||
@@ -9,9 +9,11 @@
|
|||||||
Die Suche durchsucht ganze Datensätze nach dem Vorkommen aller eingegebenen Suchbegriffe. Felder
|
Die Suche durchsucht ganze Datensätze nach dem Vorkommen aller eingegebenen Suchbegriffe. Felder
|
||||||
können oben einzeln aus der Suche ausgeschlossen werden. Auch partielle Treffer in Worten werden
|
können oben einzeln aus der Suche ausgeschlossen werden. Auch partielle Treffer in Worten werden
|
||||||
angezeigt. Wörter mit weniger als drei Zeichen, Sonderzeichen – auch Satzzeichen –
|
angezeigt. Wörter mit weniger als drei Zeichen, Sonderzeichen – auch Satzzeichen –
|
||||||
sowie die Groß- und Kleinschreibung werden dabei ignoriert
|
sowie Groß- und Kleinschreibung werden dabei ignoriert. Mit einem Minus [-] können Begiffe
|
||||||
|
ausgeschlossen, mit Anfühungsstrichen [""] zusammenhängende Phrasen gesucht werden
|
||||||
{{- if $extendable }}
|
{{- if $extendable }}
|
||||||
(für mehr Optionen s. die → <a href="?extended=true">erweiterte Suche</a>)
|
(für eine genaue Eingenzung von Feldern s. die →
|
||||||
|
<a href="?extended=true">erweiterte Suche</a>)
|
||||||
{{- end -}}.
|
{{- end -}}.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -25,8 +25,10 @@
|
|||||||
|
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
const form = document.getElementById("searchform");
|
const form = document.getElementById("simplesearchform");
|
||||||
const submitBtn = document.getElementById("submitbutton");
|
if (form) {
|
||||||
|
const submitBtn = form.getElementById("submitbutton");
|
||||||
|
}
|
||||||
|
|
||||||
function checkValidity() {
|
function checkValidity() {
|
||||||
if (form.checkValidity()) {
|
if (form.checkValidity()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user