diff --git a/dbmodels/fts5.go b/dbmodels/fts5.go index e9bc560..14df672 100644 --- a/dbmodels/fts5.go +++ b/dbmodels/fts5.go @@ -94,6 +94,7 @@ var CONTENTS_FTS5_FIELDS = []string{ ENTRIES_TABLE, AGENTS_TABLE, MUSENALMID_FIELD, + MUSENALM_INHALTE_TYPE_FIELD, ANNOTATION_FIELD, COMMENT_FIELD, } @@ -375,6 +376,11 @@ func FTS5ValuesContent(content *Content, entry *Entry, agents []*Agent) []string entrystring += "; [o.J.]" } + typestring := "" + for _, typ := range content.MusenalmType() { + typestring += typ + " " + } + return []string{ content.PreferredTitle(), content.VariantTitle(), @@ -392,6 +398,7 @@ func FTS5ValuesContent(content *Content, entry *Entry, agents []*Agent) []string entrystring, agentstring, strconv.Itoa(content.MusenalmID()), + typestring, datatypes.DeleteTags(content.Annotation()), datatypes.DeleteTags(content.Comment()), } diff --git a/dbmodels/sorting.go b/dbmodels/sorting.go index ec19712..738f2ee 100644 --- a/dbmodels/sorting.go +++ b/dbmodels/sorting.go @@ -15,6 +15,13 @@ func Sort_Series_Title(series []*Series) { }) } +func Sort_Agents_Name(agents []*Agent) { + collator := collate.New(language.German) + slices.SortFunc(agents, func(i, j *Agent) int { + return collator.CompareString(i.Name(), j.Name()) + }) +} + func Sort_Entries_Title_Year(entries []*Entry) { collator := collate.New(language.German) slices.SortFunc(entries, func(i, j *Entry) int { diff --git a/pages/suche.go b/pages/suche.go index 4c28387..5355c0f 100644 --- a/pages/suche.go +++ b/pages/suche.go @@ -76,12 +76,13 @@ func (p *SuchePage) SimpleSearchReihenRequest(app core.App, engine *templating.E func (p *SuchePage) SearchBeitraegeRequest(app core.App, engine *templating.Engine, e *core.RequestEvent, params SearchParameters) error { data := make(map[string]interface{}) - - result, err := NewSearchBeitraege(app, params) + filterparams := NewBeitraegeFilterParameters(e) + result, err := NewSearchBeitraege(app, params, filterparams) if err != nil { return engine.Response404(e, err, nil) } + data["filters"] = filterparams data["parameters"] = params data["result"] = result return engine.Response200(e, p.Template+params.Collection+"/", data, p.Layout) diff --git a/pages/suche_beitraege.go b/pages/suche_beitraege.go index 0538c84..bc31ae9 100644 --- a/pages/suche_beitraege.go +++ b/pages/suche_beitraege.go @@ -2,6 +2,9 @@ package pages import ( "database/sql" + "maps" + "slices" + "sort" "github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels" "github.com/Theodor-Springmann-Stiftung/musenalm/helpers/datatypes" @@ -10,8 +13,60 @@ import ( const ( DEFAULT_PAGESIZE = 80 + + FILTER_PARAM_BEIAEGE_AGENT = "agentfilter" + FILTER_PARAM_BEIAEGE_TYPE = "typefilter" + FILTER_PARAM_BEIAEGE_ONLYSCANS = "onlyscans" + FILTER_PARAM_BEIAEGE_YEAR = "yearfilter" ) +type BeitraegeFilterParameters struct { + Agent string + Type string + Year string + OnlyScans bool +} + +func NewBeitraegeFilterParameters(ev *core.RequestEvent) BeitraegeFilterParameters { + agent := ev.Request.URL.Query().Get(FILTER_PARAM_BEIAEGE_AGENT) + typ := ev.Request.URL.Query().Get(FILTER_PARAM_BEIAEGE_TYPE) + year := ev.Request.URL.Query().Get(FILTER_PARAM_BEIAEGE_YEAR) + onlyscans := ev.Request.URL.Query().Get(FILTER_PARAM_BEIAEGE_ONLYSCANS) == "on" + return BeitraegeFilterParameters{ + Agent: agent, + Type: typ, + Year: year, + OnlyScans: onlyscans, + } +} + +func (p *BeitraegeFilterParameters) FieldSetBeitraege() []dbmodels.FTS5QueryRequest { + ret := []dbmodels.FTS5QueryRequest{} + + if p.Agent != "" { + q := "\"" + p.Agent + "\"" + que := dbmodels.NormalizeQuery(q) + req := dbmodels.IntoQueryRequests([]string{dbmodels.AGENTS_TABLE}, que) + ret = append(ret, req...) + } + + if p.Type != "" { + q := "\"" + p.Type + "\"" + que := dbmodels.NormalizeQuery(q) + req := dbmodels.IntoQueryRequests([]string{dbmodels.MUSENALM_INHALTE_TYPE_FIELD}, que) + ret = append(ret, req...) + } + + if p.Year != "" { + q := "\"" + p.Year + "\"" + que := dbmodels.NormalizeQuery(q) + req := dbmodels.IntoQueryRequests([]string{dbmodels.ENTRIES_TABLE}, que) + ret = append(ret, req...) + } + + return ret +} + type SearchResultBeitraege struct { Queries []dbmodels.FTS5QueryRequest @@ -23,6 +78,10 @@ type SearchResultBeitraege struct { ContentsAgents map[string][]*dbmodels.RContentsAgents // <- Key: Content ID Pages []int + + AgentsList []*dbmodels.Agent + TypesList []string + YearList []int } func EmptyResultBeitraege() *SearchResultBeitraege { @@ -35,9 +94,11 @@ func EmptyResultBeitraege() *SearchResultBeitraege { } } -func NewSearchBeitraege(app core.App, params SearchParameters) (*SearchResultBeitraege, error) { +func NewSearchBeitraege(app core.App, params SearchParameters, filters BeitraegeFilterParameters) (*SearchResultBeitraege, error) { contents := []*dbmodels.Content{} queries := params.FieldSetBeitraege() + fqueries := filters.FieldSetBeitraege() + queries = append(queries, fqueries...) if params.AlmString != "" { e, err := dbmodels.Contents_MusenalmID(app, params.AlmString) @@ -70,14 +131,33 @@ func NewSearchBeitraege(app core.App, params SearchParameters) (*SearchResultBei return nil, err } + if filters.OnlyScans { + scans := []*dbmodels.Content{} + for _, c := range cs { + if len(c.Scans()) > 0 { + scans = append(scans, c) + } + } + cs = scans + } + contents = append(contents, cs...) } resultids := []any{} - resultentryids := []string{} + uniqueresultentryids := map[string]bool{} + types := make(map[string]bool) for _, content := range contents { resultids = append(resultids, content.Id) - resultentryids = append(resultentryids, content.Entry()) + uniqueresultentryids[content.Entry()] = true + for _, typ := range content.MusenalmType() { + types[typ] = true + } + } + + resultentryids := []any{} + for entryid, _ := range uniqueresultentryids { + resultentryids = append(resultentryids, entryid) } entries, err := dbmodels.Entries_IDs(app, datatypes.ToAny(resultentryids)) @@ -96,9 +176,14 @@ func NewSearchBeitraege(app core.App, params SearchParameters) (*SearchResultBei return nil, err } - aids := []any{} + uniqueaids := map[string]bool{} for _, a := range arels { - aids = append(aids, a.Agent()) + uniqueaids[a.Agent()] = true + } + + aids := []any{} + for aid, _ := range uniqueaids { + aids = append(aids, aid) } agents, err := dbmodels.Agents_IDs(app, aids) @@ -111,6 +196,10 @@ func NewSearchBeitraege(app core.App, params SearchParameters) (*SearchResultBei contentsmap[c.Entry()] = append(contentsmap[c.Entry()], c) } + for _, c := range contentsmap { + dbmodels.Sort_Contents_Numbering(c) + } + contentsagents := make(map[string][]*dbmodels.RContentsAgents) for _, a := range arels { contentsagents[a.Content()] = append(contentsagents[a.Content()], a) @@ -122,8 +211,10 @@ func NewSearchBeitraege(app core.App, params SearchParameters) (*SearchResultBei } entriesmap := make(map[string]*dbmodels.Entry) + years := make(map[int]bool) for _, e := range entries { entriesmap[e.Id] = e + years[e.Year()] = true } hits := []string{} @@ -142,6 +233,14 @@ func NewSearchBeitraege(app core.App, params SearchParameters) (*SearchResultBei hits = hits[pages[params.Page-1]:pages[params.Page]] } + tL := slices.Collect(maps.Keys(types)) + sort.Strings(tL) + + yL := slices.Collect(maps.Keys(years)) + sort.Ints(yL) + + dbmodels.Sort_Agents_Name(agents) + return &SearchResultBeitraege{ Queries: queries, Hits: hits, @@ -150,6 +249,9 @@ func NewSearchBeitraege(app core.App, params SearchParameters) (*SearchResultBei Contents: contentsmap, ContentsAgents: contentsagents, Pages: pages, + AgentsList: agents, + TypesList: tL, + YearList: yL, }, nil } diff --git a/pages/suche_parameters.go b/pages/suche_parameters.go index 8e99ee8..0d8fbe3 100644 --- a/pages/suche_parameters.go +++ b/pages/suche_parameters.go @@ -22,6 +22,7 @@ const ( BAENDE_PARAM_REFS = "references" BEITRAEGE_PARAM_ENTRY = "entry" BEITRAEGE_PARAM_INCIPT = "incipit" + BEITRAEGE_PARAM_TYPE = "type" ) type SearchParameters struct { @@ -48,6 +49,7 @@ type SearchParameters struct { YearString string EntryString string IncipitString string + TypeString string Page int } @@ -61,7 +63,9 @@ func NewSearchParameters(e *core.RequestEvent, p Parameters) (*SearchParameters, 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") + typestring := e.Request.URL.Query().Get(BEITRAEGE_PARAM_TYPE) series := e.Request.URL.Query().Get(BAENDE_PARAM_SERIES) == "on" seriesstring := e.Request.URL.Query().Get(BAENDE_PARAM_SERIES + "string") @@ -125,6 +129,7 @@ func NewSearchParameters(e *core.RequestEvent, p Parameters) (*SearchParameters, YearString: yearstring, EntryString: entrystring, IncipitString: incipitstring, + TypeString: typestring, }, nil } @@ -151,6 +156,7 @@ func (p SearchParameters) AllSearchTermsBeitraege() string { res = append(res, p.includedParams(p.YearString)...) res = append(res, p.includedParams(p.EntryString)...) res = append(res, p.includedParams(p.IncipitString)...) + res = append(res, p.includedParams(p.TypeString)...) return strings.Join(res, " ") } @@ -199,6 +205,7 @@ func (p SearchParameters) ToQueryParamsBeitraege() string { if p.Incipit { q += "&incipit=on" } + } if p.YearString != "" { @@ -225,6 +232,10 @@ func (p SearchParameters) ToQueryParamsBeitraege() string { q += fmt.Sprintf("&incipitstring=%s", p.IncipitString) } + if p.TypeString != "" { + q += fmt.Sprintf("&typestring=%s", p.TypeString) + } + return q } @@ -359,6 +370,12 @@ func (p SearchParameters) FieldSetBeitraege() []dbmodels.FTS5QueryRequest { ret = append(ret, req...) } + if p.TypeString != "" { + que := dbmodels.NormalizeQuery(p.TypeString) + req := dbmodels.IntoQueryRequests([]string{dbmodels.MUSENALM_INHALTE_TYPE_FIELD}, que) + ret = append(ret, req...) + } + return ret } diff --git a/scratchpad.md b/scratchpad.md index d340084..dcf1714 100644 --- a/scratchpad.md +++ b/scratchpad.md @@ -61,11 +61,8 @@ TODO danach: - Cache? -- HTMX + Smooth scroll - Personen: related - Inhaltsliste: Personen sehen komisch aus -- V\Boosted links gen by webcomponents -- Sammlungen u. Querverweise müssen die URL als Parameter bekommen - Sammlungen neuer versuch - Inhaltsliste Personen - Sortierung nach Band A-Z? diff --git a/views/routes/suche/beitraege/body.gohtml b/views/routes/suche/beitraege/body.gohtml index 12104fb..ebc4e80 100644 --- a/views/routes/suche/beitraege/body.gohtml +++ b/views/routes/suche/beitraege/body.gohtml @@ -37,6 +37,14 @@ EntryString string IncipitString string } + +.filters +type BeitraegeFilterParameters struct { + Agent string + Type string + Year string + OnlyScans bool +} */}} {{ $isAlm := false }} @@ -76,33 +84,51 @@ {{ template "_searchboxsimple" Arr $model.parameters true $q }}
@@ -116,114 +142,37 @@ {{- if $model.parameters.IsBeitraegeSearch -}}