mirror of
https://github.com/Theodor-Springmann-Stiftung/musenalm.git
synced 2025-10-29 01:05:32 +00:00
Allerhand Kleinigkeiten; Einzelansichten Reihen u Personen; Bandansicht
This commit is contained in:
@@ -23,6 +23,37 @@ func AgentForId(app core.App, id string) (*Agent, error) {
|
||||
return agent, nil
|
||||
}
|
||||
|
||||
func FTS5SearchAgents(app core.App, query string) ([]*Agent, error) {
|
||||
a := []*Agent{}
|
||||
q := NormalizeQuery(query)
|
||||
if len(q) == 0 {
|
||||
return a, nil
|
||||
}
|
||||
|
||||
ids, err := FTS5Search(app, AGENTS_TABLE, FTS5QueryRequest{
|
||||
Fields: []string{AGENTS_NAME_FIELD, AGENTS_PSEUDONYMS_FIELD, REFERENCES_FIELD, AGENTS_BIOGRAPHICAL_DATA_FIELD, ANNOTATION_FIELD},
|
||||
Query: q,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
idany := []any{}
|
||||
for _, id := range ids {
|
||||
idany = append(idany, id.ID)
|
||||
}
|
||||
|
||||
err = app.RecordQuery(AGENTS_TABLE).
|
||||
Where(dbx.HashExp{ID_FIELD: idany}).
|
||||
All(&a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func AgentsForEntries(app core.App, entries []*Entry) (map[string]*Agent, AgentsEntries, error) {
|
||||
eids := []any{}
|
||||
for _, e := range entries {
|
||||
|
||||
@@ -103,6 +103,17 @@ func EntryForId(app core.App, id string) (*Entry, error) {
|
||||
return entry, nil
|
||||
}
|
||||
|
||||
func EntriesForIds(app core.App, ids []any) ([]*Entry, error) {
|
||||
entries := []*Entry{}
|
||||
err := app.RecordQuery(ENTRIES_TABLE).
|
||||
Where(dbx.HashExp{ID_FIELD: ids}).
|
||||
All(&entries)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return entries, nil
|
||||
}
|
||||
|
||||
func EntryForMusenalmID(app core.App, id string) (*Entry, error) {
|
||||
entry := &Entry{}
|
||||
err := app.RecordQuery(ENTRIES_TABLE).
|
||||
|
||||
@@ -31,6 +31,7 @@ var AGENTS_FTS5_FIELDS = []string{
|
||||
AGENTS_PSEUDONYMS_FIELD,
|
||||
ANNOTATION_FIELD,
|
||||
COMMENT_FIELD,
|
||||
REFERENCES_FIELD,
|
||||
}
|
||||
|
||||
var PLACES_FTS5_FIELDS = []string{
|
||||
@@ -384,6 +385,7 @@ func FTS5ValuesAgent(agent *Agent) []string {
|
||||
agent.Pseudonyms(),
|
||||
datatypes.DeleteTags(agent.Annotation()),
|
||||
datatypes.DeleteTags(agent.Comment()),
|
||||
agent.References(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
57
dbmodels/queries.go
Normal file
57
dbmodels/queries.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package dbmodels
|
||||
|
||||
import (
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
)
|
||||
|
||||
// INFO: Queries to be reused
|
||||
// Rules
|
||||
// 1. Only one return type + error for every function
|
||||
// 2. Parameters can only be two
|
||||
// - core.App
|
||||
// - any id or multiple IDs (of an indexed field)
|
||||
// 3. Naming convention: <TableName>_<FilteredField>[s]
|
||||
// For scanning, with an Iter_ prefix, yields single row results
|
||||
|
||||
func REntriesAgents_Agent(app core.App, id string) ([]*REntriesAgents, error) {
|
||||
return TableByField[[]*REntriesAgents](
|
||||
app,
|
||||
RelationTableName(ENTRIES_TABLE, AGENTS_TABLE),
|
||||
AGENTS_TABLE,
|
||||
id,
|
||||
)
|
||||
}
|
||||
|
||||
func RContentsAgents_Agent(app core.App, id string) ([]*RContentsAgents, error) {
|
||||
return TableByField[[]*RContentsAgents](
|
||||
app,
|
||||
RelationTableName(CONTENTS_TABLE, AGENTS_TABLE),
|
||||
AGENTS_TABLE,
|
||||
id,
|
||||
)
|
||||
}
|
||||
|
||||
func REntriesSeries_Entries(app core.App, ids any) ([]*REntriesSeries, error) {
|
||||
return TableByField[[]*REntriesSeries](
|
||||
app,
|
||||
RelationTableName(ENTRIES_TABLE, SERIES_TABLE),
|
||||
ENTRIES_TABLE,
|
||||
ids,
|
||||
)
|
||||
}
|
||||
|
||||
func Agents_ID(app core.App, id string) (*Agent, error) {
|
||||
return TableByID[*Agent](app, AGENTS_TABLE, id)
|
||||
}
|
||||
|
||||
func Entries_IDs(app core.App, ids []any) ([]*Entry, error) {
|
||||
return TableByID[[]*Entry](app, ENTRIES_TABLE, ids)
|
||||
}
|
||||
|
||||
func Series_IDs(app core.App, ids []any) ([]*Series, error) {
|
||||
return TableByID[[]*Series](app, SERIES_TABLE, ids)
|
||||
}
|
||||
|
||||
func Contents_IDs(app core.App, ids []any) ([]*Content, error) {
|
||||
return TableByID[[]*Content](app, CONTENTS_TABLE, ids)
|
||||
}
|
||||
37
dbmodels/queries_iter.go
Normal file
37
dbmodels/queries_iter.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package dbmodels
|
||||
|
||||
import (
|
||||
"iter"
|
||||
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
)
|
||||
|
||||
// INFO: Iterator queries to be reused
|
||||
// Rules
|
||||
// 1. Only iterator return type + error for every function
|
||||
// 2. Parameters can only be two
|
||||
// - core.App
|
||||
// - any id or multiple IDs (of an indexed field)
|
||||
// 3. Naming convention: Iter_<TableName>_<FilteredField>[s]
|
||||
|
||||
// BUG: this is not working as expected, see Iter_TableByField in queryhelpers.go
|
||||
func Iter_REntriesAgents_Agent(app core.App, id string) (iter.Seq2[*REntriesAgents, error], error) {
|
||||
innerIterator, err := Iter_TableByField[REntriesAgents](
|
||||
app,
|
||||
RelationTableName(ENTRIES_TABLE, AGENTS_TABLE),
|
||||
AGENTS_TABLE,
|
||||
id,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return func(yield func(*REntriesAgents, error) bool) {
|
||||
for item, err := range innerIterator {
|
||||
if !yield(item, err) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
99
dbmodels/queryhelpers.go
Normal file
99
dbmodels/queryhelpers.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package dbmodels
|
||||
|
||||
import (
|
||||
"iter"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
)
|
||||
|
||||
// INFO: These functions are very abstract interfaces to the DB that help w querying
|
||||
|
||||
// BUG: this is not working:
|
||||
// github.com/pocketbase/pocketbase/apis.NewRouter.panicRecover.func3.1()
|
||||
// /home/simon/go/pkg/mod/github.com/pocketbase/pocketbase@v0.25.5/apis/middlewares.go:269 +0x13c
|
||||
// panic({0x15b34c0?, 0x2831680?})
|
||||
// /usr/local/go/src/runtime/panic.go:787 +0x132
|
||||
// github.com/pocketbase/pocketbase/core.(*Record).FieldsData(0xc000632820)
|
||||
// /home/simon/go/pkg/mod/github.com/pocketbase/pocketbase@v0.25.5/core/record_model.go:774 +0x1a
|
||||
// github.com/pocketbase/pocketbase/core.(*Record).PostScan(0xc000632820)
|
||||
// /home/simon/go/pkg/mod/github.com/pocketbase/pocketbase@v0.25.5/core/record_model.go:591 +0x4e
|
||||
// github.com/pocketbase/dbx.(*Rows).ScanStruct(0xc00052e6d0, {0x175f840?, 0xc000586060?})
|
||||
// /home/simon/go/pkg/mod/github.com/pocketbase/dbx@v1.11.0/rows.go:97 +0x32e
|
||||
// github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels.Iter_TableByField[...].func1()
|
||||
// /home/simon/source/musenalm/dbmodels/queryhelpers.go:23 +0x65
|
||||
// github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels.Iter_REntriesAgents_Agent.func1(0xc000624840)
|
||||
// /home/simon/source/musenalm/dbmodels/queries_iter.go:30 +0xae
|
||||
// github.com/Theodor-Springmann-Stiftung/musenalm/pages.(*PersonResult).FilterEntriesByPerson(0x1762c40?, {0x1dfba88, 0xc000438870}, {0xc00004627c, 0xf}, 0xc000064720)
|
||||
// /home/simon/source/musenalm/pages/person.go:111 +0x248
|
||||
// github.com/Theodor-Springmann-Stiftung/musenalm/pages.NewPersonResult({0x1dfba88, 0xc000438870}, {0xc00004627c, 0xf})
|
||||
// /home/simon/source/musenalm/pages/person.go:92 +0x4f
|
||||
// github.com/Theodor-Springmann-Stiftung/musenalm/pages.(*PersonPage).Setup.func1(0xc0002da000)
|
||||
// /home/simon/source/musenalm/pages/person.go:46 +0x1ee
|
||||
// github.com/pocketbase/pocketbase/tools/hook.(*Hook[...]).Trigger.func1()
|
||||
// /home/simon/go/pkg/mod/github.com/pocketbase/pocketbase@v0.25.5/tools/hook/hook.go:169 +0x5d
|
||||
// github.com/pocketbase/pocketbase/tools/hook.(*Event).Next(0xc0002da000?)
|
||||
// /home/simon/go/pkg/mod/github.com/pocketbase/pocketbase@v0.25.5/tools/hook/event.go:32 +0x17
|
||||
// github.com/pocketbase/pocketbase/apis.NewRouter.BodyLimit.func7(0xc0002da000)
|
||||
// /home
|
||||
func Iter_TableByField[T interface{}](app core.App, table, field string, value interface{}) (iter.Seq2[*T, error], error) {
|
||||
rows, err := app.RecordQuery(table).
|
||||
Where(dbx.HashExp{field: value}).
|
||||
Rows()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return func(yield func(*T, error) bool) {
|
||||
for rows.Next() {
|
||||
var item T
|
||||
err := rows.ScanStruct(&item)
|
||||
if !yield(&item, err) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
func Iter_TableByID[T interface{}](app core.App, table, id interface{}) (iter.Seq2[*T, error], error) {
|
||||
rows, err := app.RecordQuery(table).
|
||||
Where(dbx.HashExp{ID_FIELD: id}).
|
||||
Rows()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return func(yield func(*T, error) bool) {
|
||||
for rows.Next() {
|
||||
var item T
|
||||
rows.Scan(&item)
|
||||
if !yield(&item, nil) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
func TableByField[T interface{}](app core.App, table, field string, value interface{}) (T, error) {
|
||||
var ret T
|
||||
err := app.RecordQuery(table).
|
||||
Where(dbx.HashExp{field: value}).
|
||||
All(&ret)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func TableByID[T interface{}](app core.App, table, id interface{}) (T, error) {
|
||||
var ret T
|
||||
err := app.RecordQuery(table).
|
||||
Where(dbx.HashExp{ID_FIELD: id}).
|
||||
All(&ret)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
@@ -8,19 +8,11 @@ import (
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/collate"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
type SeriesEntries map[string][]*REntriesSeries
|
||||
|
||||
func SortSeriessesByTitle(series []*Series) {
|
||||
collator := collate.New(language.German)
|
||||
slices.SortFunc(series, func(i, j *Series) int {
|
||||
return collator.CompareString(i.Title(), j.Title())
|
||||
})
|
||||
}
|
||||
|
||||
func MusenalmIDSearchSeries(app core.App, query string) ([]*Series, error) {
|
||||
series := []*Series{}
|
||||
err := app.RecordQuery(SERIES_TABLE).
|
||||
|
||||
43
dbmodels/sorting.go
Normal file
43
dbmodels/sorting.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package dbmodels
|
||||
|
||||
import (
|
||||
"slices"
|
||||
|
||||
"golang.org/x/text/collate"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
func Sort_Series_Title(series []*Series) {
|
||||
collator := collate.New(language.German)
|
||||
slices.SortFunc(series, func(i, j *Series) int {
|
||||
return collator.CompareString(i.Title(), j.Title())
|
||||
})
|
||||
}
|
||||
|
||||
func Sort_Entries_Title_Year(entries []*Entry) {
|
||||
collator := collate.New(language.German)
|
||||
slices.SortFunc(entries, func(i, j *Entry) int {
|
||||
if i.PreferredTitle() == j.PreferredTitle() {
|
||||
return i.Year() - j.Year()
|
||||
}
|
||||
return collator.CompareString(i.PreferredTitle(), j.PreferredTitle())
|
||||
})
|
||||
}
|
||||
|
||||
func Sort_Entries_Year_Title(entries []*Entry) {
|
||||
collator := collate.New(language.German)
|
||||
slices.SortFunc(entries, func(i, j *Entry) int {
|
||||
if i.Year() == j.Year() {
|
||||
return collator.CompareString(i.PreferredTitle(), j.PreferredTitle())
|
||||
}
|
||||
return i.Year() - j.Year()
|
||||
})
|
||||
}
|
||||
|
||||
func Sort_REntriesSeries_Year(entries []*REntriesSeries, entriesMap map[string]*Entry) {
|
||||
slices.SortFunc(entries, func(i, j *REntriesSeries) int {
|
||||
ientry := entriesMap[i.Entry()]
|
||||
jentry := entriesMap[j.Entry()]
|
||||
return ientry.Year() - jentry.Year()
|
||||
})
|
||||
}
|
||||
@@ -1 +1,9 @@
|
||||
package datatypes
|
||||
|
||||
func ToAny[T any](s []T) []any {
|
||||
result := make([]any, len(s))
|
||||
for i, v := range s {
|
||||
result[i] = v
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -4,6 +4,10 @@ func Length(arr []any) int {
|
||||
return len(arr)
|
||||
}
|
||||
|
||||
func MapLen[T comparable, U any](m map[T]U) int {
|
||||
return len(m)
|
||||
}
|
||||
|
||||
func Contains(arr []string, val string) bool {
|
||||
for _, v := range arr {
|
||||
if v == val {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package functions
|
||||
|
||||
import "html/template"
|
||||
import (
|
||||
"html/template"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Safe(s string) template.HTML {
|
||||
if len(s) == 0 {
|
||||
@@ -8,3 +11,7 @@ func Safe(s string) template.HTML {
|
||||
}
|
||||
return template.HTML(s)
|
||||
}
|
||||
|
||||
func ReplaceSlashParen(s string) string {
|
||||
return strings.ReplaceAll(s, "/)", "<p>")
|
||||
}
|
||||
|
||||
187
pages/person.go
187
pages/person.go
@@ -1,6 +1,8 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/Theodor-Springmann-Stiftung/musenalm/app"
|
||||
"github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels"
|
||||
"github.com/Theodor-Springmann-Stiftung/musenalm/pagemodels"
|
||||
@@ -36,45 +38,164 @@ func (p *PersonPage) Setup(router *router.Router[*core.RequestEvent], app core.A
|
||||
data := make(map[string]interface{})
|
||||
data[PARAM_PERSON] = person
|
||||
|
||||
agent, err := dbmodels.AgentForId(app, person)
|
||||
result, err := NewAgentResult(app, person)
|
||||
if err != nil {
|
||||
return engine.Response404(e, err, data)
|
||||
}
|
||||
data["a"] = agent
|
||||
|
||||
series, relations, entries, err := dbmodels.SeriesForAgent(app, person)
|
||||
if err != nil {
|
||||
return engine.Response404(e, err, data)
|
||||
}
|
||||
|
||||
dbmodels.SortSeriessesByTitle(series)
|
||||
data["series"] = series
|
||||
data["relations"] = relations
|
||||
data["entries"] = entries
|
||||
|
||||
contents, err := dbmodels.ContentsForAgent(app, person)
|
||||
if err != nil {
|
||||
return engine.Response404(e, err, data)
|
||||
}
|
||||
|
||||
agents, crelations, err := dbmodels.AgentsForContents(app, contents)
|
||||
if err != nil {
|
||||
return engine.Response404(e, err, data)
|
||||
}
|
||||
data["agents"] = agents
|
||||
data["crelations"] = crelations
|
||||
|
||||
centries, err := dbmodels.EntriesForContents(app, contents)
|
||||
if err != nil {
|
||||
return engine.Response404(e, err, data)
|
||||
}
|
||||
data["centries"] = centries
|
||||
|
||||
dbmodels.SortContentsByEntryNumbering(contents, centries)
|
||||
data["contents"] = contents
|
||||
data["result"] = result
|
||||
|
||||
return engine.Response200(e, p.Template, data, p.Layout)
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type AgentResult struct {
|
||||
Agent *dbmodels.Agent
|
||||
|
||||
BResult []*dbmodels.Series // Sorted
|
||||
Entries map[string]*dbmodels.Entry // KEY: Entry ID
|
||||
EntriesSeries map[string][]*dbmodels.REntriesSeries // KEY: Series ID
|
||||
EntriesAgents map[string][]*dbmodels.REntriesAgents // KEY: Entry ID
|
||||
|
||||
// INFO: we could save a DB query by quering the entries table only once
|
||||
CResult []*dbmodels.Entry /// Sorted
|
||||
Contents map[string][]*dbmodels.Content // KEY: entry ID
|
||||
ContentsAgents map[string][]*dbmodels.RContentsAgents // KEY: Content ID
|
||||
}
|
||||
|
||||
func NewAgentResult(app core.App, id string) (*AgentResult, error) {
|
||||
agent, err := dbmodels.AgentForId(app, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := &AgentResult{
|
||||
Agent: agent,
|
||||
}
|
||||
|
||||
err = res.FilterEntriesByPerson(app, id, res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (p *AgentResult) FilterEntriesByPerson(app core.App, id string, res *AgentResult) error {
|
||||
// 1. DB Hit
|
||||
relations, err := dbmodels.REntriesAgents_Agent(app, id)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(relations) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
entriesagents := make(map[string][]*dbmodels.REntriesAgents)
|
||||
entryIds := []any{}
|
||||
for _, r := range relations {
|
||||
entryIds = append(entryIds, r.Entry())
|
||||
entriesagents[r.Entry()] = append(entriesagents[r.Entry()], r)
|
||||
}
|
||||
res.EntriesAgents = entriesagents
|
||||
|
||||
// 2. DB Hit
|
||||
entries, err := dbmodels.Entries_IDs(app, entryIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
entryMap := make(map[string]*dbmodels.Entry, len(entries))
|
||||
for _, e := range entries {
|
||||
entryMap[e.Id] = e
|
||||
}
|
||||
res.Entries = entryMap
|
||||
|
||||
// 3. DB Hit
|
||||
entriesseries, err := dbmodels.REntriesSeries_Entries(app, entryIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
entriesseriesmap := make(map[string][]*dbmodels.REntriesSeries, len(entriesseries))
|
||||
for _, r := range entriesseries {
|
||||
entriesseriesmap[r.Series()] = append(entriesseriesmap[r.Series()], r)
|
||||
}
|
||||
|
||||
for _, r := range entriesseriesmap {
|
||||
dbmodels.Sort_REntriesSeries_Year(r, entryMap)
|
||||
}
|
||||
|
||||
res.EntriesSeries = entriesseriesmap
|
||||
|
||||
seriesIds := []any{}
|
||||
for _, s := range entriesseries {
|
||||
seriesIds = append(seriesIds, s.Series())
|
||||
}
|
||||
|
||||
// 4. DB Hit
|
||||
series, err := dbmodels.Series_IDs(app, seriesIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res.BResult = series
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *AgentResult) FilterContentsByEntry(app core.App, id string, res *AgentResult) error {
|
||||
// 1. DB Hit
|
||||
relations, err := dbmodels.RContentsAgents_Agent(app, id)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(relations) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
contentsagents := make(map[string][]*dbmodels.RContentsAgents)
|
||||
contentIds := []any{}
|
||||
for _, r := range relations {
|
||||
contentIds = append(contentIds, r.Content())
|
||||
contentsagents[r.Content()] = append(contentsagents[r.Content()], r)
|
||||
}
|
||||
res.ContentsAgents = contentsagents
|
||||
|
||||
// 2. DB Hit
|
||||
contents, err := dbmodels.Contents_IDs(app, contentIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
contentMap := make(map[string][]*dbmodels.Content, len(contents))
|
||||
entrykeys := []any{}
|
||||
for _, c := range contents {
|
||||
contentMap[c.Entry()] = append(contentMap[c.Entry()], c)
|
||||
entrykeys = append(entrykeys, c.Entry())
|
||||
}
|
||||
res.Contents = contentMap
|
||||
|
||||
// 3. DB Hit
|
||||
entries, err := dbmodels.Entries_IDs(app, entrykeys)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
res.CResult = entries
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *AgentResult) LenEntries() int {
|
||||
return len(p.Entries)
|
||||
}
|
||||
|
||||
func (p *AgentResult) LenSeries() int {
|
||||
return len(p.BResult)
|
||||
}
|
||||
|
||||
func (p *AgentResult) LenContents() int {
|
||||
return len(p.Contents)
|
||||
}
|
||||
|
||||
@@ -104,11 +104,26 @@ func (p *PersonenPage) FilterRequest(app core.App, engine *templating.Engine, e
|
||||
func (p *PersonenPage) SearchRequest(app core.App, engine *templating.Engine, e *core.RequestEvent) error {
|
||||
search := e.Request.URL.Query().Get(PARAM_SEARCH)
|
||||
data := map[string]interface{}{}
|
||||
agents := []*dbmodels.Agent{}
|
||||
altagents := []*dbmodels.Agent{}
|
||||
|
||||
agents, altagents, err := dbmodels.BasicSearchAgents(app, search)
|
||||
a, err := dbmodels.FTS5SearchAgents(app, search)
|
||||
if err != nil {
|
||||
return engine.Response404(e, err, data)
|
||||
}
|
||||
agents = a
|
||||
|
||||
if len(agents) == 0 {
|
||||
// INFO: Fallback to regular search, if FTS5 fails
|
||||
a, aa, err := dbmodels.BasicSearchAgents(app, search)
|
||||
if err != nil {
|
||||
return engine.Response404(e, err, data)
|
||||
}
|
||||
agents = a
|
||||
altagents = aa
|
||||
} else {
|
||||
data["FTS"] = true
|
||||
}
|
||||
|
||||
dbmodels.SortAgentsByName(agents)
|
||||
dbmodels.SortAgentsByName(altagents)
|
||||
|
||||
@@ -100,7 +100,7 @@ func (p *ReihenPage) LetterRequest(app core.App, engine *templating.Engine, e *c
|
||||
return engine.Response404(e, err, data)
|
||||
}
|
||||
// INFO: We sort again since the query can't sort german umlauts correctly
|
||||
dbmodels.SortSeriessesByTitle(series)
|
||||
dbmodels.Sort_Series_Title(series)
|
||||
data["series"] = series
|
||||
|
||||
rmap, bmap, err := dbmodels.EntriesForSeriesses(app, series)
|
||||
@@ -129,7 +129,7 @@ func (p *ReihenPage) PersonRequest(app core.App, engine *templating.Engine, e *c
|
||||
if err != nil {
|
||||
return engine.Response404(e, err, data)
|
||||
}
|
||||
dbmodels.SortSeriessesByTitle(series)
|
||||
dbmodels.Sort_Series_Title(series)
|
||||
data["series"] = series
|
||||
data["relations"] = relations
|
||||
data["entries"] = entries
|
||||
@@ -172,8 +172,8 @@ func (p *ReihenPage) SearchRequest(app core.App, engine *templating.Engine, e *c
|
||||
if err != nil {
|
||||
return engine.Response404(e, err, data)
|
||||
}
|
||||
dbmodels.SortSeriessesByTitle(series)
|
||||
dbmodels.SortSeriessesByTitle(altseries)
|
||||
dbmodels.Sort_Series_Title(series)
|
||||
dbmodels.Sort_Series_Title(altseries)
|
||||
data["series"] = series
|
||||
data["altseries"] = altseries
|
||||
|
||||
@@ -208,7 +208,7 @@ func (p *ReihenPage) SearchRequest(app core.App, engine *templating.Engine, e *c
|
||||
return engine.Response404(e, err, data)
|
||||
}
|
||||
|
||||
dbmodels.SortSeriessesByTitle(idseries)
|
||||
dbmodels.Sort_Series_Title(idseries)
|
||||
data["idseries"] = idseries
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -141,7 +141,7 @@ func (p *SuchePage) SimpleSearchReihenRequest(app core.App, engine *templating.E
|
||||
return engine.Response500(e, err, nil)
|
||||
}
|
||||
|
||||
dbmodels.SortSeriessesByTitle(series)
|
||||
dbmodels.Sort_Series_Title(series)
|
||||
data["series"] = series
|
||||
data["relations"] = rmap
|
||||
data["entries"] = bmap
|
||||
|
||||
@@ -58,6 +58,10 @@ func (e *Engine) funcs() error {
|
||||
e.AddFunc("HasPrefix", strings.HasPrefix)
|
||||
e.AddFunc("Contains", functions.Contains)
|
||||
e.AddFunc("Add", functions.Add)
|
||||
e.AddFunc("Len", functions.Length)
|
||||
|
||||
// String Functions
|
||||
e.AddFunc("ReplaceSlashParen", functions.ReplaceSlashParen)
|
||||
|
||||
// Time & Date Functions
|
||||
e.AddFunc("Today", functions.Today)
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -33,7 +33,7 @@
|
||||
|
||||
<body class="w-full text-lg" hx-ext="response-targets" hx-boost="true">
|
||||
<div class="flex flex-col min-h-screen w-full">
|
||||
<header class="container-normal" id="header">
|
||||
<header class="container-normal pb-0" id="header">
|
||||
{{ block "_menu" . }}
|
||||
<!-- Default app menu... -->
|
||||
{{ end }}
|
||||
|
||||
@@ -4,7 +4,35 @@
|
||||
{{ $isEng := false }}
|
||||
|
||||
|
||||
<div class="container-normal" id="">
|
||||
<div id="breadcrumbs">
|
||||
{{- range $i, $s := $model.series -}}
|
||||
<div>
|
||||
<div class="{{ if $i -}}opacity-0 pointer-events-none select-none{{- end -}}">
|
||||
Reihentitel <i class="ri-arrow-right-wide-line"></i>
|
||||
</div>
|
||||
<div>
|
||||
<a href="/reihe/{{- $s.MusenalmID -}}">{{ $s.Title }}</a>
|
||||
</div>
|
||||
<div>
|
||||
{{- if $model.entry.Year -}}
|
||||
<i class="ri-arrow-right-wide-line"></i> <b>{{ $model.entry.Year }}</b>
|
||||
{{- else -}}
|
||||
<i class="ri-arrow-right-wide-line"></i> <b>{{ $model.entry.PreferredTitle }}</b>
|
||||
{{- end -}}
|
||||
</div>
|
||||
<div class="grow"></div>
|
||||
{{- if not $i -}}
|
||||
<div class="backbutton">
|
||||
<a href="/reihen/?letter=A" class="no-underline">
|
||||
<i class="ri-arrow-left-long-line"></i> Alle Bände nach Reihentiteln
|
||||
</a>
|
||||
</div>
|
||||
{{- end -}}
|
||||
</div>
|
||||
{{- end -}}
|
||||
</div>
|
||||
|
||||
<div class="container-normal mt-12" id="">
|
||||
<div class="flex flex-col" id="entrydata">
|
||||
<div class="entryrow">
|
||||
<div class="fieldlabel">Almanach-Nummer</div>
|
||||
@@ -150,7 +178,7 @@
|
||||
<div class="entryrow">
|
||||
<div class="fieldlabel">Anmerkungen</div>
|
||||
<div class="fieldvalue">
|
||||
{{- Safe $model.entry.Annotation -}}
|
||||
{{- Safe (ReplaceSlashParen $model.entry.Annotation) -}}
|
||||
</div>
|
||||
</div>
|
||||
{{- end -}}
|
||||
|
||||
@@ -35,7 +35,9 @@
|
||||
</div>
|
||||
<div class="grow lg:px-0 ml-3 lg:ml-8">
|
||||
<div class="-indent-3">
|
||||
<span class="font-bold reihen-text">{{ $r.Title }}</span>
|
||||
<span class="font-bold reihen-text">
|
||||
{{ $r.Title }}
|
||||
</span>
|
||||
{{ if $r.Annotation }}
|
||||
<span> · </span>
|
||||
<span class="{{ if $marka }}reihen-text{{ end }}">{{ Safe $r.Annotation }}</span>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
{{- if $bd -}}
|
||||
<div class="flex flex-row odd:bg-zinc-100 px-3 ml-2 py-0.5 justify-between w-full">
|
||||
<a href="/almanach/{{ $bd.MusenalmID }}" class="no-underline">
|
||||
<div class="">
|
||||
<div class="{{- if eq $bd.EditState "Edited" -}}font-bold{{- end -}}">
|
||||
{{- if $bd.PreferredTitle -}}
|
||||
{{ $bd.PreferredTitle }}
|
||||
{{- else if ne $bd.Year 0 -}}
|
||||
|
||||
@@ -1 +1 @@
|
||||
<title>{{ .site.title }} – {{ .record.title }}</title>
|
||||
<title>{{ .site.title }} – {{ .record.Title }}</title>
|
||||
|
||||
@@ -1,25 +1,54 @@
|
||||
{{/* .result:
|
||||
type AgentResult struct {
|
||||
Agent *dbmodels.Agent
|
||||
|
||||
BResult []*dbmodels.Series // Sorted
|
||||
Entries map[string]*dbmodels.Entry // KEY: Entry ID
|
||||
EntriesSeries map[string][]*dbmodels.REntriesSeries // KEY: Series ID
|
||||
EntriesAgents map[string][]*dbmodels.REntriesAgents // KEY: Entry ID
|
||||
|
||||
CResult []*dbmodels.Entry /// Sorted
|
||||
Contents map[string][]*dbmodels.Content // KEY: entry ID
|
||||
ContentsAgents map[string][]*dbmodels.RContentsAgents // KEY: Content ID
|
||||
}
|
||||
*/}}
|
||||
|
||||
{{ $model := . }}
|
||||
|
||||
|
||||
<div class="container-normal font-serif">
|
||||
{{ if $model.a.CorporateBody }}
|
||||
<div class="notifier font-sans">
|
||||
<div id="breadcrumbs">
|
||||
<div>
|
||||
<div>
|
||||
Personen und Körperschaften <i class="ri-arrow-right-wide-line"></i> Einzelansicht
|
||||
<i class="ri-arrow-right-wide-line"></i> <b>{{ $model.result.Agent.Name }}</b>
|
||||
</div>
|
||||
<div class="backbutton">
|
||||
<a href="/personen/" class="no-underline">
|
||||
<i class="ri-arrow-left-long-line"></i> Alle Personen & Körperschaften
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-normal font-serif mt-12">
|
||||
{{ if $model.result.Agent.CorporateBody }}
|
||||
<div class="font-sans">
|
||||
<i class="ri-team-line"></i>
|
||||
<span class="filtercategory">Verlag, Druckerei oder Vertrieb</span>
|
||||
<span class="filtercategory">Körperschaft</span>
|
||||
</div>
|
||||
{{ else }}
|
||||
<div class="notifier font-sans">
|
||||
<div class="font-sans">
|
||||
<i class="ri-user-line"></i>
|
||||
<span class="filtercategory">Person</span>
|
||||
</div>
|
||||
{{ end }}
|
||||
<h1 class="text-3xl font-bold">{{ $model.a.Name }}</h1>
|
||||
<h1 class="text-3xl font-bold">{{ $model.result.Agent.Name }}</h1>
|
||||
<div>
|
||||
<span class="">
|
||||
{{ $model.a.BiographicalData }}
|
||||
{{ $model.result.Agent.BiographicalData }}
|
||||
</span>
|
||||
<span class="">
|
||||
{{- $arr := $model.a.ProfessionArray -}}
|
||||
{{- $arr := $model.result.Agent.ProfessionArray -}}
|
||||
{{- if $arr -}}
|
||||
{{- range $i, $p := $arr -}}
|
||||
<div
|
||||
@@ -32,10 +61,25 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ if .entries }}
|
||||
{{- if .result.BResult -}}
|
||||
<div class="container-normal flex flex-col font-serif mt-7 gap-y-6">
|
||||
<h2>Bände nach Reihentiteln</h2>
|
||||
{{ range $id, $r := .series }}
|
||||
<h2 class="font-bold">
|
||||
<i class="ri-information-2-line"></i>
|
||||
{{ if eq $model.result.LenEntries 1 }}
|
||||
Ein Band
|
||||
{{- else }}
|
||||
{{- $model.result.LenEntries }}
|
||||
Bände
|
||||
{{- end }}
|
||||
in
|
||||
{{- if eq $model.result.LenSeries 1 }}
|
||||
einer Reihe
|
||||
{{- else }}
|
||||
{{ $model.result.LenSeries }} Reihen
|
||||
{{- end }}
|
||||
gefunden:
|
||||
</h2>
|
||||
{{ range $id, $r := .result.BResult }}
|
||||
<div class="grow-0 max-w-[48rem]">
|
||||
<div>
|
||||
<span class="font-bold">{{ $r.Title }}</span>
|
||||
@@ -46,14 +90,18 @@
|
||||
</div>
|
||||
{{ end }}
|
||||
<div class="">
|
||||
{{- $bds := index $model.relations $r.Id -}}
|
||||
{{ template "reiherelations" (Arr $r $bds $model.entries true $model.relations) }}
|
||||
{{- $bds := index $model.result.EntriesSeries $r.Id -}}
|
||||
{{ template "personreiherelations" (Arr $r $bds $model.result.Entries true
|
||||
$model.result.EntriesAgents)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
|
||||
<!--
|
||||
{{ if .contents }}
|
||||
<h2>Inhalte</h2>
|
||||
{{ range $id, $c := .contents }}
|
||||
@@ -65,3 +113,4 @@
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
-->
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
{{ $reihe := index . 0 }}
|
||||
{{ $rels := index . 1 }}
|
||||
{{ $entries := index . 2 }}
|
||||
{{ $shownos := index . 3 }}
|
||||
|
||||
{{- if $rels -}}
|
||||
<div class="reiherelations flex flex-col text-base font-sans w-full pt-1 -ml-3">
|
||||
{{- range $_, $rel := $rels -}}
|
||||
{{- $bd := index $entries $rel.Entry -}}
|
||||
|
||||
{{- if $bd -}}
|
||||
<div class="flex flex-row odd:bg-zinc-100 px-3 py-0.5 justify-between w-full">
|
||||
<a href="/almanach/{{ $bd.MusenalmID }}" class="no-underline">
|
||||
<div class="">
|
||||
{{- if $bd.PreferredTitle -}}
|
||||
{{ $bd.PreferredTitle }}
|
||||
{{- else if ne $bd.Year 0 -}}
|
||||
{{- $bd.Year -}}
|
||||
{{- else -}}
|
||||
[o.J.]
|
||||
{{- end -}}
|
||||
</div>
|
||||
{{- if not (eq $rel.Type "Bevorzugter Reihentitel") -}}
|
||||
<div class="text-xs whitespace-nowrap">
|
||||
{{- if eq $rel.Type "Früherer Reihentitel" -}}
|
||||
Titelauflage aus einer anderen Reihe
|
||||
{{- else if eq $rel.Type "Späterer Reihentitel" -}}
|
||||
Titelauflage
|
||||
{{- else if eq $rel.Type "In anderer Sprache" -}}
|
||||
{{- if Contains $bd.Language "ger" -}}
|
||||
In deutscher Sprache
|
||||
{{- else -}}
|
||||
In französischer Sprache
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{ $rel.Type }}
|
||||
{{- end -}}
|
||||
</div>
|
||||
{{- end -}}
|
||||
</a>
|
||||
<div class="whitespace-nowrap align-top">
|
||||
Alm
|
||||
{{ $bd.MusenalmID }}
|
||||
</div>
|
||||
</div>
|
||||
{{- end -}}
|
||||
|
||||
{{- end -}}
|
||||
|
||||
</div>
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,4 @@
|
||||
<title>
|
||||
{{ .site.title }} –
|
||||
{{ if .result -}}{{ .result.Agent.Name }}{{ else -}}Einzelpersonenansicht{{- end -}}
|
||||
</title>
|
||||
|
||||
70
views/routes/person/personreiherelations.gohtml
Normal file
70
views/routes/person/personreiherelations.gohtml
Normal file
@@ -0,0 +1,70 @@
|
||||
{{ $reihe := index . 0 }}
|
||||
{{ $rels := index . 1 }}
|
||||
{{ $entries := index . 2 }}
|
||||
{{ $shownos := index . 3 }}
|
||||
{{ $relations := index . 4 }}
|
||||
|
||||
{{- if $rels -}}
|
||||
<div class="reiherelations flex flex-col text-base font-sans w-full pt-1 -ml-3">
|
||||
{{- range $_, $rel := $rels -}}
|
||||
{{- $bd := index $entries $rel.Entry -}}
|
||||
{{- $arels := index $relations $rel.Entry -}}
|
||||
|
||||
{{- if $bd -}}
|
||||
<div class="flex flex-row odd:bg-zinc-100 pr-3 py-0.5 w-full items-start">
|
||||
{{- if $arels -}}
|
||||
<div class="min-w-32">
|
||||
{{- range $i, $arel := $arels -}}
|
||||
<div
|
||||
class="inline font-bold text-sm font-sans bg-slate-200 pl-2 pr-3 py-0.5
|
||||
rounded-r-full mr-1.5 ">
|
||||
{{- $arel.Type -}}
|
||||
</div>
|
||||
{{- end -}}
|
||||
</div>
|
||||
{{- end -}}
|
||||
<div>
|
||||
<a
|
||||
href="/almanach/{{ $bd.MusenalmID }}"
|
||||
class="no-underline {{ if eq
|
||||
$bd.EditState "Edited"
|
||||
-}}
|
||||
font-bold
|
||||
{{- end -}}">
|
||||
{{- if $bd.PreferredTitle -}}
|
||||
{{ $bd.PreferredTitle }}
|
||||
{{- else if ne $bd.Year 0 -}}
|
||||
{{- $bd.Year -}}
|
||||
{{- else -}}
|
||||
[o.J.]
|
||||
{{- end -}}
|
||||
{{- if not (eq $rel.Type "Bevorzugter Reihentitel") -}}
|
||||
<div class="text-xs whitespace-nowrap">
|
||||
{{- if eq $rel.Type "Früherer Reihentitel" -}}
|
||||
Titelauflage aus einer anderen Reihe
|
||||
{{- else if eq $rel.Type "Späterer Reihentitel" -}}
|
||||
Titelauflage
|
||||
{{- else if eq $rel.Type "In anderer Sprache" -}}
|
||||
{{- if Contains $bd.Language "ger" -}}
|
||||
In deutscher Sprache
|
||||
{{- else -}}
|
||||
In französischer Sprache
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{ $rel.Type }}
|
||||
{{- end -}}
|
||||
</div>
|
||||
{{- end -}}
|
||||
</a>
|
||||
</div>
|
||||
<div class="whitespace-nowrap align-top grow text-right">
|
||||
Alm
|
||||
{{ $bd.MusenalmID }}
|
||||
</div>
|
||||
</div>
|
||||
{{- end -}}
|
||||
|
||||
{{- end -}}
|
||||
|
||||
</div>
|
||||
{{- end -}}
|
||||
@@ -16,9 +16,8 @@
|
||||
<!-- INFO: 4. Header -->
|
||||
<div id="personheader" class="border-t border-r border-zinc-300 relative w-full">
|
||||
{{ template "heading" . }}
|
||||
|
||||
|
||||
<div class="flex flex-row justify-end mt-12">
|
||||
<div class="flex flex-row justify-end mt-12 items-end">
|
||||
{{ template "notifier" . }}
|
||||
{{ template "professionselectbox" . }}
|
||||
{{ template "searchbox" . }}
|
||||
</div>
|
||||
@@ -35,7 +34,11 @@
|
||||
<a href="/person/{{ $agent.Id }}" class="search-result font-bold">
|
||||
{{ $agent.Name }}
|
||||
</a>
|
||||
<span class="inline-block font-sans text-sm">
|
||||
<span
|
||||
class="inline-block font-sans text-sm
|
||||
{{ if $model.FTS -}}
|
||||
search-result
|
||||
{{- end -}}">
|
||||
{{ if not $agent.CorporateBody }}
|
||||
{{ $agent.BiographicalData }}
|
||||
{{ end }}
|
||||
@@ -68,7 +71,9 @@
|
||||
{{- end -}}
|
||||
</div>
|
||||
|
||||
<div class="w-64 ml-4 shrink-0">{{ $agent.References }}</div>
|
||||
<div class="w-64 ml-4 shrink-0 {{ if $model.FTS -}}search-result{{- end -}}">
|
||||
{{ $agent.References }}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{{ $model := . }}
|
||||
|
||||
{{- if and $model.letters (not $model.search) -}}
|
||||
<div id="personalphabet" class="flex flex-col text-xl pt-[4.875rem] pb-4 relative">
|
||||
<div id="personalphabet" class="flex flex-col text-xl pt-[5.875rem] pb-4 relative">
|
||||
{{- range $id, $r := .letters -}}
|
||||
<a
|
||||
class="{{ if not $model.letter -}}inactive{{- end -}}"
|
||||
|
||||
@@ -7,14 +7,16 @@
|
||||
{{ $isOrg := and $model.filter (eq $model.filter "org") }}
|
||||
|
||||
|
||||
<h1
|
||||
class="text-3xl font-bold px-3 relative -translate-y-[55%] w-min whitespace-nowrap bg-stone-50 ml-24 z-20">
|
||||
<span x-show="!search">
|
||||
{{- if $isPerson -}}
|
||||
Personen
|
||||
{{- else if $isOrg -}}
|
||||
Verlage, Druckereien & Vertriebe
|
||||
{{- end -}}
|
||||
</span>
|
||||
<span x-show="search"> Suche · Alle Personen & Körperschaften </span>
|
||||
</h1>
|
||||
<div>
|
||||
<h1
|
||||
class="text-3xl font-bold px-3 relative -translate-y-[55%] w-min whitespace-nowrap bg-stone-50 ml-24 z-20">
|
||||
<span x-show="!search">
|
||||
{{- if $isPerson -}}
|
||||
Personen
|
||||
{{- else if $isOrg -}}
|
||||
Verlage, Druckereien & Vertriebe
|
||||
{{- end -}}
|
||||
</span>
|
||||
<span x-show="search"> Suche · Alle Personen & Körperschaften </span>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
91
views/routes/personen/components/notifier.gohtml
Normal file
91
views/routes/personen/components/notifier.gohtml
Normal file
@@ -0,0 +1,91 @@
|
||||
{{ $model := . }}
|
||||
|
||||
{{ $isPerson := and $model.filter (or (eq $model.filter "noorg") (eq $model.filter "musik") (eq $model.filter "autor") (eq $model.filter "graphik") (eq $model.filter "hrsg")) }}
|
||||
|
||||
{{ $isProfession := and $model.filter (or (eq $model.filter "musik") (eq $model.filter "autor") (eq $model.filter "graphik") (eq $model.filter "hrsg")) }}
|
||||
|
||||
{{ $isNoOrg := and $model.filter (eq $model.filter "noorg") }}
|
||||
|
||||
{{ $isOrg := and $model.filter (eq $model.filter "org") }}
|
||||
|
||||
{{ $isMusik := and $model.filter (eq $model.filter "musik") }}
|
||||
|
||||
{{ $isAutor := and $model.filter (eq $model.filter "autor") }}
|
||||
|
||||
{{ $isGraphik := and $model.filter (eq $model.filter "graphik") }}
|
||||
|
||||
{{ $isHrsg := and $model.filter (eq $model.filter "hrsg") }}
|
||||
|
||||
|
||||
<div class="justify-self-start grow flex flex-row px-3 ml-6 mt-2 mr-2">
|
||||
{{ if .letter }}
|
||||
{{- if $isNoOrg -}}
|
||||
<div class="notifier" x-show="!search">
|
||||
<i class="ri-sort-alphabet-asc"></i>
|
||||
<span class="filtercategory">Alle Personen</span> ·
|
||||
<span class="">Anfangsbuchstabe <span class="filterterm">{{ .letter }}</span></span>
|
||||
</div>
|
||||
{{- else if $isMusik -}}
|
||||
<div class="notifier" x-show="!search">
|
||||
<i class="ri-sort-alphabet-asc"></i>
|
||||
<span class="filtercategory">Musiker:innen</span> ·
|
||||
<span class="">Anfangsbuchstabe <span class="filterterm">{{ .letter }}</span></span>
|
||||
</div>
|
||||
{{- else if $isAutor -}}
|
||||
<div class="notifier" x-show="!search">
|
||||
<i class="ri-sort-alphabet-asc"></i>
|
||||
<span class="filtercategory">Autor:innen</span> ·
|
||||
<span class="">Anfangsbuchstabe <span class="filterterm">{{ .letter }}</span></span>
|
||||
</div>
|
||||
{{- else if $isGraphik -}}
|
||||
<div class="notifier" x-show="!search">
|
||||
<i class="ri-sort-alphabet-asc"></i>
|
||||
<span class="filtercategory">Graphiker:innen</span> ·
|
||||
<span class="">Anfangsbuchstabe <span class="filterterm">{{ .letter }}</span></span>
|
||||
</div>
|
||||
{{- else if $isHrsg -}}
|
||||
<div class="notifier" x-show="!search">
|
||||
<i class="ri-sort-alphabet-asc"></i>
|
||||
<span class="filtercategory">Herausgeber:innen</span> ·
|
||||
<span class="">Anfangsbuchstabe <span class="filterterm">{{ .letter }}</span></span>
|
||||
</div>
|
||||
{{- else if $isOrg -}}
|
||||
<div class="notifier" x-show="!search">
|
||||
<i class="ri-sort-alphabet-asc"></i>
|
||||
<span class="filtercategory">Verlage, Druckereien & Vertriebe</span> ·
|
||||
<span class="">Anfangsbuchstabe <span class="filterterm">{{ .letter }}</span></span>
|
||||
</div>
|
||||
{{- end -}}
|
||||
|
||||
{{ end }}
|
||||
|
||||
|
||||
<div class="notifier" x-show="search">
|
||||
<i class="ri-search-line"></i>
|
||||
<span class="filtercategory">Suche</span>
|
||||
· <span class="filterterm" x-text="search"></span>
|
||||
</div>
|
||||
|
||||
{{ if .search }}
|
||||
<div class="notifier" x-show="search">
|
||||
<i class="ri-links-line"></i>
|
||||
<span class="filtercategory">Link</span>
|
||||
· <span class="filterterm" x-text="window.location.href"></span>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ if or (not .letter) $isProfession }}
|
||||
<div class="notifier ml-2" x-show="!search">
|
||||
<a href="/personen/" class="no-underline">
|
||||
<i class="ri-arrow-left-long-line"></i> Alle Personen
|
||||
</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
|
||||
<div class="notifier ml-2" x-show="search">
|
||||
<a href="/personen/" class="no-underline">
|
||||
<i class="ri-arrow-left-long-line"></i> Alle Personen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2,22 +2,61 @@
|
||||
{{ $r := $model.series }}
|
||||
|
||||
|
||||
<div class="container-normal flex flex-col font-serif mt-16">
|
||||
<div class="grow-0 max-w-[48rem]">
|
||||
<div id="breadcrumbs">
|
||||
<div>
|
||||
<div>
|
||||
<span class="font-bold">{{ $r.Title }}</span>
|
||||
Reihen <i class="ri-arrow-right-wide-line"></i> Einzelansicht
|
||||
<i class="ri-arrow-right-wide-line"></i> <b>{{ $r.Title }}</b>
|
||||
</div>
|
||||
<div class="backbutton">
|
||||
<a href="/reihen/?letter=A" class="no-underline">
|
||||
<i class="ri-arrow-left-long-line"></i> Alle Reihen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-normal flex flex-col font-serif mt-12">
|
||||
<div class="font-sans">
|
||||
<svg
|
||||
class="w-[0.9rem] h-[0.9rem] relative bottom-[0.04rem] inline-block"
|
||||
width="65px"
|
||||
height="65px"
|
||||
viewBox="0 0 28 28"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
fill="currentColor">
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"></g>
|
||||
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
|
||||
<g id="SVGRepo_iconCarrier">
|
||||
<g id="🔍-Product-Icons" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="ic_fluent_library_28_filled" fill="currentColor" fill-rule="nonzero">
|
||||
<path
|
||||
d="M5.9897,3 C7.0937,3 7.9897,3.896 7.9897,5 L7.9897,23 C7.9897,24.104 7.0937,25 5.9897,25 L4.0007,25 C2.8957,25 2.0007,24.104 2.0007,23 L2.0007,5 C2.0007,3.896 2.8957,3 4.0007,3 L5.9897,3 Z M12.9897,3 C14.0937,3 14.9897,3.896 14.9897,5 L14.9897,23 C14.9897,24.104 14.0937,25 12.9897,25 L10.9947,25 C9.8897,25 8.9947,24.104 8.9947,23 L8.9947,5 C8.9947,3.896 9.8897,3 10.9947,3 L12.9897,3 Z M22.0701,6.5432 L25.9301,22.0262 C26.1971,23.0972 25.5441,24.1832 24.4731,24.4512 L22.5101,24.9402 C21.4391,25.2072 20.3531,24.5552 20.0861,23.4832 L16.2261,8.0002 C15.9581,6.9282 16.6111,5.8432 17.6821,5.5752 L19.6451,5.0862 C20.7161,4.8182 21.8021,5.4712 22.0701,6.5432 Z"
|
||||
id="🎨-Color"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
Reihe
|
||||
</div>
|
||||
<div class="grow-0">
|
||||
<div>
|
||||
<span class="font-bold text-3xl mr-2">{{ $r.Title }}</span>
|
||||
{{ if $r.References }}
|
||||
<div class="text-sm font-sans px-2 py-1 ml-2 bg-stone-100 w-max inline-block">
|
||||
<div class="text-sm font-sans px-2 py-1 bg-stone-100 w-max inline-block mr-2">
|
||||
{{ $r.References }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
{{ if $r.Annotation }}
|
||||
<div class="max-w-[48rem]">
|
||||
<div class="max-w-[48rem] mt-1">
|
||||
<span class="">{{ Safe $r.Annotation }}</span>
|
||||
</div>
|
||||
{{ end }}
|
||||
<div class="">
|
||||
<div class="max-w-[64rem] [&_*]:!text-lg mt-6">
|
||||
{{ template "_reiherelations" (Arr $r $model.relations $model.entries true) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
|
||||
{{ if not .letter }}
|
||||
<div class="notifier ml-2" x-show="!search">
|
||||
<a href="/reihen" class="no-underline">
|
||||
<a href="/reihen/?letter=A" class="no-underline">
|
||||
<i class="ri-arrow-left-long-line"></i> Alle Reihen anzeigen
|
||||
</a>
|
||||
</div>
|
||||
@@ -64,7 +64,7 @@
|
||||
|
||||
|
||||
<div class="notifier ml-2" x-show="search">
|
||||
<a href="/reihen" class="no-underline">
|
||||
<a href="/reihen/?letter=A" class="no-underline">
|
||||
<i class="ri-arrow-left-long-line"></i> Alle Reihen anzeigen
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -121,6 +121,13 @@
|
||||
@apply !text-gray-400;
|
||||
}
|
||||
|
||||
#alphabet a[aria-current="page"]:not(.inactive):before {
|
||||
aspect-ratio: 1;
|
||||
clip-path: polygon(100% 80%, 80% 100%, 100% 100%);
|
||||
content: " ";
|
||||
@apply bg-red-600 absolute -bottom-[1px] -right-[1px] h-full z-30;
|
||||
}
|
||||
|
||||
.headingcontainer:before {
|
||||
content: "";
|
||||
@apply bg-zinc-300 w-[50%] absolute top-0 left-[50%] h-[1px];
|
||||
@@ -138,15 +145,15 @@
|
||||
@apply border-l-4 border-zinc-300 font-bold;
|
||||
}
|
||||
|
||||
.headingcontainer .notifier {
|
||||
.notifier {
|
||||
@apply bg-stone-100 text-center text-base px-2.5 py-1 font-sans rounded;
|
||||
}
|
||||
|
||||
.headingcontainer .notifier i {
|
||||
.notifier i {
|
||||
@apply inline-block pr-0.5;
|
||||
}
|
||||
|
||||
.headingcontainer .notifier .filterterm {
|
||||
.notifier .filterterm {
|
||||
@apply font-bold;
|
||||
}
|
||||
|
||||
@@ -289,11 +296,11 @@
|
||||
}
|
||||
|
||||
#persontype a {
|
||||
@apply px-1.5 border-b-[5px] border-zinc-300 no-underline font-serif mx-2.5;
|
||||
@apply px-1.5 border-b-[5px] border-transparent hover:border-zinc-200 no-underline font-serif mx-2.5;
|
||||
}
|
||||
|
||||
#persontype a[aria-current="page"]:not(#persontype.inactive a) {
|
||||
@apply font-bold;
|
||||
@apply font-bold border-zinc-300;
|
||||
}
|
||||
|
||||
#persontype.inactive a {
|
||||
@@ -326,15 +333,15 @@
|
||||
}
|
||||
|
||||
#personalphabet a:hover:not([aria-current="page"]:not(.inactive)) {
|
||||
@apply !bg-stone-50 -ml-2 relative;
|
||||
@apply !bg-stone-50 -ml-2 relative text-stone-900;
|
||||
}
|
||||
|
||||
#personalphabet a.inactive {
|
||||
@apply !text-gray-400;
|
||||
@apply text-gray-400;
|
||||
}
|
||||
|
||||
#entrydata .fieldlabel {
|
||||
@apply font-bold text-base font-sans whitespace-nowrap w-60 grow-0 shrink-0 pt-0.5;
|
||||
@apply font-bold text-base font-sans whitespace-nowrap min-w-48 grow-0 shrink-0 pt-0.5;
|
||||
}
|
||||
|
||||
#entrydata .fieldvalue {
|
||||
@@ -342,7 +349,7 @@
|
||||
}
|
||||
|
||||
#entrydata .entryrow {
|
||||
@apply flex flex-row gap-x-3.5 items-start py-0.5 px-4;
|
||||
@apply flex flex-row gap-x-3.5 items-start py-0.5;
|
||||
}
|
||||
|
||||
#entrydata {
|
||||
@@ -351,4 +358,16 @@
|
||||
int-link {
|
||||
@apply text-slate-700 hover:text-slate-900 underline decoration-dotted hover:decoration-solid;
|
||||
}
|
||||
|
||||
#breadcrumbs {
|
||||
@apply w-full max-w-(--breakpoint-xl) mx-auto px-3 pb-4 relative pt-1.5;
|
||||
}
|
||||
|
||||
#breadcrumbs > div {
|
||||
@apply flex flex-row gap-x-2.5 justify-between;
|
||||
}
|
||||
|
||||
#breadcrumbs .backbutton {
|
||||
@apply ml-4 bg-stone-100 py-0.5 px-2.5 rounded font-sans text-base text-center mr-1.5;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user