BUGFIX: keep fts5 tables syncronized

This commit is contained in:
Simon Martens
2026-01-10 23:29:26 +01:00
parent 05d4e559fe
commit 57bbd68123
15 changed files with 527 additions and 7 deletions

View File

@@ -230,3 +230,43 @@ func HasScans(contents []*dbmodels.Content) bool {
} }
return false return false
} }
func updateEntryFTS5(app core.App, entry *dbmodels.Entry) error {
if entry == nil {
return nil
}
// Load related data for FTS5
places := []*dbmodels.Place{}
for _, placeID := range entry.Places() {
place, err := dbmodels.Places_ID(app, placeID)
if err == nil && place != nil {
places = append(places, place)
}
}
agents := []*dbmodels.Agent{}
agentRelations, err := dbmodels.REntriesAgents_Entry(app, entry.Id)
if err == nil {
for _, relation := range agentRelations {
agent, err := dbmodels.Agents_ID(app, relation.Agent())
if err == nil && agent != nil {
agents = append(agents, agent)
}
}
}
series := []*dbmodels.Series{}
seriesRelations, err := dbmodels.REntriesSeries_Entry(app, entry.Id)
if err == nil {
for _, relation := range seriesRelations {
s, err := dbmodels.Series_ID(app, relation.Series())
if err == nil && s != nil {
series = append(series, s)
}
}
}
// Update entry and all related contents
return dbmodels.UpdateFTS5EntryAndRelatedContents(app, entry, places, agents, series)
}

View File

@@ -214,6 +214,18 @@ func (p *AlmanachEditPage) POSTSave(engine *templating.Engine, app core.App) Han
}) })
} }
// Update FTS5 index asynchronously
go func(appInstance core.App, entryID string) {
freshEntry, err := dbmodels.Entries_ID(appInstance, entryID)
if err != nil {
appInstance.Logger().Error("Failed to load entry for FTS5 update", "entry_id", entryID, "error", err)
return
}
if err := updateEntryFTS5(appInstance, freshEntry); err != nil {
appInstance.Logger().Error("Failed to update FTS5 index for entry", "entry_id", entryID, "error", err)
}
}(app, entry.Id)
freshEntry, err := dbmodels.Entries_MusenalmID(app, id) freshEntry, err := dbmodels.Entries_MusenalmID(app, id)
if err == nil { if err == nil {
entry = freshEntry entry = freshEntry
@@ -297,6 +309,13 @@ func (p *AlmanachEditPage) POSTDelete(engine *templating.Engine, app core.App) H
}) })
} }
// Delete from FTS5 index asynchronously
go func(appInstance core.App, entryID string) {
if err := dbmodels.DeleteFTS5Entry(appInstance, entryID); err != nil {
appInstance.Logger().Error("Failed to delete FTS5 entry", "entry_id", entryID, "error", err)
}
}(app, entry.Id)
return e.JSON(http.StatusOK, map[string]any{ return e.JSON(http.StatusOK, map[string]any{
"success": true, "success": true,
"redirect": "/suche/baende", "redirect": "/suche/baende",

View File

@@ -151,6 +151,18 @@ func (p *AlmanachNewPage) POSTSave(engine *templating.Engine, app core.App) Hand
}) })
} }
// Update FTS5 index asynchronously
go func(appInstance core.App, entryID string) {
freshEntry, err := dbmodels.Entries_ID(appInstance, entryID)
if err != nil {
appInstance.Logger().Error("Failed to load entry for FTS5 update", "entry_id", entryID, "error", err)
return
}
if err := updateEntryFTS5(appInstance, freshEntry); err != nil {
appInstance.Logger().Error("Failed to update FTS5 index for new entry", "entry_id", entryID, "error", err)
}
}(app, entry.Id)
redirect := "/" redirect := "/"
if entry != nil { if entry != nil {
redirect = "/almanach/" + strconv.Itoa(entry.MusenalmID()) + "/edit?saved_message=" + url.QueryEscape("Änderungen gespeichert.") redirect = "/almanach/" + strconv.Itoa(entry.MusenalmID()) + "/edit?saved_message=" + url.QueryEscape("Änderungen gespeichert.")

View File

@@ -206,6 +206,18 @@ func (p *OrtEditPage) POST(engine *templating.Engine, app core.App) HandleFunc {
return p.renderError(engine, app, e, "Speichern fehlgeschlagen.") return p.renderError(engine, app, e, "Speichern fehlgeschlagen.")
} }
// Update FTS5 index for place and all related entries asynchronously
go func(appInstance core.App, placeID string) {
freshPlace, err := dbmodels.Places_ID(appInstance, placeID)
if err != nil {
appInstance.Logger().Error("Failed to load place for FTS5 update", "place_id", placeID, "error", err)
return
}
if err := dbmodels.UpdateFTS5PlaceAndRelatedEntries(appInstance, freshPlace); err != nil {
appInstance.Logger().Error("Failed to update FTS5 index for place and related records", "place_id", placeID, "error", err)
}
}(app, place.Id)
redirect := fmt.Sprintf("/ort/%s/edit?saved_message=%s", id, url.QueryEscape("Änderungen gespeichert.")) redirect := fmt.Sprintf("/ort/%s/edit?saved_message=%s", id, url.QueryEscape("Änderungen gespeichert."))
return e.Redirect(http.StatusSeeOther, redirect) return e.Redirect(http.StatusSeeOther, redirect)
} }
@@ -288,6 +300,20 @@ func (p *OrtEditPage) POSTDelete(engine *templating.Engine, app core.App) Handle
}) })
} }
// Delete place from FTS5 and update all affected entries asynchronously
go func(appInstance core.App, placeID string, affectedEntries []*dbmodels.Entry) {
if err := dbmodels.DeleteFTS5Place(appInstance, placeID); err != nil {
appInstance.Logger().Error("Failed to delete place from FTS5", "place_id", placeID, "error", err)
}
// Update FTS5 for all entries that had this place
for _, entry := range affectedEntries {
if err := updateEntryFTS5(appInstance, entry); err != nil {
appInstance.Logger().Error("Failed to update FTS5 for entry after place deletion", "entry_id", entry.Id, "error", err)
}
}
}(app, place.Id, entries)
return e.JSON(http.StatusOK, map[string]any{ return e.JSON(http.StatusOK, map[string]any{
"success": true, "success": true,
"redirect": "/orte", "redirect": "/orte",

View File

@@ -130,6 +130,18 @@ func (p *OrtNewPage) POST(engine *templating.Engine, app core.App) HandleFunc {
return p.renderPage(engine, app, e, req, "Speichern fehlgeschlagen.") return p.renderPage(engine, app, e, req, "Speichern fehlgeschlagen.")
} }
// Update FTS5 index for new place (no related entries yet) asynchronously
go func(appInstance core.App, placeID string) {
freshPlace, err := dbmodels.Places_ID(appInstance, placeID)
if err != nil {
appInstance.Logger().Error("Failed to load place for FTS5 update", "place_id", placeID, "error", err)
return
}
if err := dbmodels.UpdateFTS5Place(appInstance, freshPlace); err != nil {
appInstance.Logger().Error("Failed to update FTS5 index for new place", "place_id", placeID, "error", err)
}
}(app, createdPlace.Id)
redirect := fmt.Sprintf( redirect := fmt.Sprintf(
"/ort/%s/edit?saved_message=%s", "/ort/%s/edit?saved_message=%s",
createdPlace.Id, createdPlace.Id,

View File

@@ -312,6 +312,18 @@ func (p *PersonEditPage) POST(engine *templating.Engine, app core.App) HandleFun
return p.renderError(engine, app, e, "Speichern fehlgeschlagen.") return p.renderError(engine, app, e, "Speichern fehlgeschlagen.")
} }
// Update FTS5 index for agent and all related entries/contents asynchronously
go func(appInstance core.App, agentID string) {
freshAgent, err := dbmodels.Agents_ID(appInstance, agentID)
if err != nil {
appInstance.Logger().Error("Failed to load agent for FTS5 update", "agent_id", agentID, "error", err)
return
}
if err := dbmodels.UpdateFTS5AgentAndRelated(appInstance, freshAgent); err != nil {
appInstance.Logger().Error("Failed to update FTS5 index for agent and related records", "agent_id", agentID, "error", err)
}
}(app, agent.Id)
redirect := fmt.Sprintf("/person/%s/edit?saved_message=%s", id, url.QueryEscape("Änderungen gespeichert.")) redirect := fmt.Sprintf("/person/%s/edit?saved_message=%s", id, url.QueryEscape("Änderungen gespeichert."))
return e.Redirect(http.StatusSeeOther, redirect) return e.Redirect(http.StatusSeeOther, redirect)
} }

View File

@@ -134,6 +134,18 @@ func (p *PersonNewPage) POST(engine *templating.Engine, app core.App) HandleFunc
return p.renderPage(engine, app, e, req, "Speichern fehlgeschlagen.") return p.renderPage(engine, app, e, req, "Speichern fehlgeschlagen.")
} }
// Update FTS5 index for agent (no related records for new agent) asynchronously
go func(appInstance core.App, agentID string) {
freshAgent, err := dbmodels.Agents_ID(appInstance, agentID)
if err != nil {
appInstance.Logger().Error("Failed to load agent for FTS5 update", "agent_id", agentID, "error", err)
return
}
if err := dbmodels.UpdateFTS5Agent(appInstance, freshAgent); err != nil {
appInstance.Logger().Error("Failed to update FTS5 index for new agent", "agent_id", agentID, "error", err)
}
}(app, createdAgent.Id)
redirect := fmt.Sprintf( redirect := fmt.Sprintf(
"/person/%s/edit?saved_message=%s", "/person/%s/edit?saved_message=%s",
createdAgent.Id, createdAgent.Id,

View File

@@ -253,6 +253,19 @@ func (p *ReiheEditPage) POSTDelete(engine *templating.Engine, app core.App) Hand
}) })
} }
// Delete series and entries from FTS5 asynchronously
go func(appInstance core.App, seriesID string, deletedEntries []*dbmodels.Entry) {
if err := dbmodels.DeleteFTS5Series(appInstance, seriesID); err != nil {
appInstance.Logger().Error("Failed to delete series from FTS5", "series_id", seriesID, "error", err)
}
for _, entry := range deletedEntries {
if err := dbmodels.DeleteFTS5Entry(appInstance, entry.Id); err != nil {
appInstance.Logger().Error("Failed to delete FTS5 entry", "entry_id", entry.Id, "error", err)
}
}
}(app, series.Id, preferredEntries)
return e.JSON(http.StatusOK, map[string]any{ return e.JSON(http.StatusOK, map[string]any{
"success": true, "success": true,
"redirect": "/reihen", "redirect": "/reihen",
@@ -405,6 +418,18 @@ func (p *ReiheEditPage) POST(engine *templating.Engine, app core.App) HandleFunc
return p.renderError(engine, app, e, "Speichern fehlgeschlagen.") return p.renderError(engine, app, e, "Speichern fehlgeschlagen.")
} }
// Update FTS5 index for series and all related entries asynchronously
go func(appInstance core.App, seriesID string) {
freshSeries, err := dbmodels.Series_ID(appInstance, seriesID)
if err != nil {
appInstance.Logger().Error("Failed to load series for FTS5 update", "series_id", seriesID, "error", err)
return
}
if err := dbmodels.UpdateFTS5SeriesAndRelatedEntries(appInstance, freshSeries); err != nil {
appInstance.Logger().Error("Failed to update FTS5 index for series and related records", "series_id", seriesID, "error", err)
}
}(app, series.Id)
redirect := fmt.Sprintf("/reihe/%s/edit?saved_message=%s", id, url.QueryEscape("Änderungen gespeichert.")) redirect := fmt.Sprintf("/reihe/%s/edit?saved_message=%s", id, url.QueryEscape("Änderungen gespeichert."))
return e.Redirect(http.StatusSeeOther, redirect) return e.Redirect(http.StatusSeeOther, redirect)
} }

View File

@@ -134,6 +134,18 @@ func (p *ReiheNewPage) POST(engine *templating.Engine, app core.App) HandleFunc
return p.renderPage(engine, app, e, req, "Speichern fehlgeschlagen.") return p.renderPage(engine, app, e, req, "Speichern fehlgeschlagen.")
} }
// Update FTS5 index for new series (no related entries yet) asynchronously
go func(appInstance core.App, seriesID string) {
freshSeries, err := dbmodels.Series_ID(appInstance, seriesID)
if err != nil {
appInstance.Logger().Error("Failed to load series for FTS5 update", "series_id", seriesID, "error", err)
return
}
if err := dbmodels.UpdateFTS5Series(appInstance, freshSeries); err != nil {
appInstance.Logger().Error("Failed to update FTS5 index for new series", "series_id", seriesID, "error", err)
}
}(app, createdSeries.Id)
redirect := fmt.Sprintf( redirect := fmt.Sprintf(
"/reihe/%d/edit?saved_message=%s", "/reihe/%d/edit?saved_message=%s",
createdSeries.MusenalmID(), createdSeries.MusenalmID(),

View File

@@ -562,3 +562,306 @@ func deleteTableContents(app core.App, table string) error {
} }
return nil return nil
} }
func DeleteFTS5Entry(app core.App, entryID string) error {
query := "DELETE FROM " + FTS5TableName(ENTRIES_TABLE) + " WHERE " + ID_FIELD + " = {:id}"
_, err := app.DB().NewQuery(query).Bind(dbx.Params{"id": entryID}).Execute()
return err
}
func UpdateFTS5Entry(app core.App, entry *Entry, places []*Place, agents []*Agent, series []*Series) error {
if err := DeleteFTS5Entry(app, entry.Id); err != nil {
return err
}
return InsertFTS5Entry(app, entry, places, agents, series)
}
func UpdateFTS5EntryAndRelatedContents(app core.App, entry *Entry, places []*Place, agents []*Agent, series []*Series) error {
// Update the entry itself
if err := UpdateFTS5Entry(app, entry, places, agents, series); err != nil {
return err
}
// Update all contents that belong to this entry
contents, err := Contents_Entry(app, entry.Id)
if err == nil {
for _, content := range contents {
// Load all agents for this content
contentAgents := []*Agent{}
agentRels, err := RContentsAgents_Content(app, content.Id)
if err == nil {
for _, rel := range agentRels {
agent, err := Agents_ID(app, rel.Agent())
if err == nil && agent != nil {
contentAgents = append(contentAgents, agent)
}
}
}
if err := UpdateFTS5Content(app, content, entry, contentAgents); err != nil {
app.Logger().Error("Failed to update FTS5 for content", "content_id", content.Id, "error", err)
}
}
}
return nil
}
func DeleteFTS5Agent(app core.App, agentID string) error {
query := "DELETE FROM " + FTS5TableName(AGENTS_TABLE) + " WHERE " + ID_FIELD + " = {:id}"
_, err := app.DB().NewQuery(query).Bind(dbx.Params{"id": agentID}).Execute()
return err
}
func UpdateFTS5Agent(app core.App, agent *Agent) error {
if err := DeleteFTS5Agent(app, agent.Id); err != nil {
return err
}
return InsertFTS5Agent(app, agent)
}
func UpdateFTS5AgentAndRelated(app core.App, agent *Agent) error {
// Update the agent itself
if err := UpdateFTS5Agent(app, agent); err != nil {
return err
}
// Update all entries related to this agent
entryRelations, err := REntriesAgents_Agent(app, agent.Id)
if err == nil {
for _, relation := range entryRelations {
entry, err := Entries_ID(app, relation.Entry())
if err != nil {
app.Logger().Error("Failed to load entry for FTS5 update", "entry_id", relation.Entry(), "error", err)
continue
}
// Load all related data for this entry
places := []*Place{}
for _, placeID := range entry.Places() {
place, err := Places_ID(app, placeID)
if err == nil && place != nil {
places = append(places, place)
}
}
agents := []*Agent{}
agentRels, err := REntriesAgents_Entry(app, entry.Id)
if err == nil {
for _, rel := range agentRels {
ag, err := Agents_ID(app, rel.Agent())
if err == nil && ag != nil {
agents = append(agents, ag)
}
}
}
series := []*Series{}
seriesRels, err := REntriesSeries_Entry(app, entry.Id)
if err == nil {
for _, rel := range seriesRels {
s, err := Series_ID(app, rel.Series())
if err == nil && s != nil {
series = append(series, s)
}
}
}
if err := UpdateFTS5Entry(app, entry, places, agents, series); err != nil {
app.Logger().Error("Failed to update FTS5 for entry", "entry_id", entry.Id, "error", err)
}
}
}
// Update all contents related to this agent
contentRelations, err := RContentsAgents_Agent(app, agent.Id)
if err == nil {
for _, relation := range contentRelations {
contents, err := Contents_IDs(app, []any{relation.Content()})
if err != nil || len(contents) == 0 {
app.Logger().Error("Failed to load content for FTS5 update", "content_id", relation.Content(), "error", err)
continue
}
content := contents[0]
// Load the parent entry
entry, err := Entries_ID(app, content.Entry())
if err != nil {
app.Logger().Error("Failed to load entry for content FTS5 update", "entry_id", content.Entry(), "error", err)
continue
}
// Load all agents for this content
agents := []*Agent{}
agentRels, err := RContentsAgents_Content(app, content.Id)
if err == nil {
for _, rel := range agentRels {
ag, err := Agents_ID(app, rel.Agent())
if err == nil && ag != nil {
agents = append(agents, ag)
}
}
}
if err := UpdateFTS5Content(app, content, entry, agents); err != nil {
app.Logger().Error("Failed to update FTS5 for content", "content_id", content.Id, "error", err)
}
}
}
return nil
}
func DeleteFTS5Content(app core.App, contentID string) error {
query := "DELETE FROM " + FTS5TableName(CONTENTS_TABLE) + " WHERE " + ID_FIELD + " = {:id}"
_, err := app.DB().NewQuery(query).Bind(dbx.Params{"id": contentID}).Execute()
return err
}
func UpdateFTS5Content(app core.App, content *Content, entry *Entry, agents []*Agent) error {
if err := DeleteFTS5Content(app, content.Id); err != nil {
return err
}
return InsertFTS5Content(app, content, entry, agents)
}
func DeleteFTS5Place(app core.App, placeID string) error {
query := "DELETE FROM " + FTS5TableName(PLACES_TABLE) + " WHERE " + ID_FIELD + " = {:id}"
_, err := app.DB().NewQuery(query).Bind(dbx.Params{"id": placeID}).Execute()
return err
}
func UpdateFTS5Place(app core.App, place *Place) error {
if err := DeleteFTS5Place(app, place.Id); err != nil {
return err
}
return InsertFTS5Place(app, place)
}
func UpdateFTS5PlaceAndRelatedEntries(app core.App, place *Place) error {
// Update the place itself
if err := UpdateFTS5Place(app, place); err != nil {
return err
}
// Find all entries that reference this place
entries := []*Entry{}
err := app.RecordQuery(ENTRIES_TABLE).
Where(dbx.NewExp(
PLACES_TABLE+" = {:id} OR (json_valid("+PLACES_TABLE+") = 1 AND EXISTS (SELECT 1 FROM json_each("+PLACES_TABLE+") WHERE value = {:id}))",
dbx.Params{"id": place.Id},
)).
All(&entries)
if err == nil {
for _, entry := range entries {
// Load all related data for this entry
places := []*Place{}
for _, placeID := range entry.Places() {
p, err := Places_ID(app, placeID)
if err == nil && p != nil {
places = append(places, p)
}
}
agents := []*Agent{}
agentRels, err := REntriesAgents_Entry(app, entry.Id)
if err == nil {
for _, rel := range agentRels {
agent, err := Agents_ID(app, rel.Agent())
if err == nil && agent != nil {
agents = append(agents, agent)
}
}
}
series := []*Series{}
seriesRels, err := REntriesSeries_Entry(app, entry.Id)
if err == nil {
for _, rel := range seriesRels {
s, err := Series_ID(app, rel.Series())
if err == nil && s != nil {
series = append(series, s)
}
}
}
// Only update the entry itself, not contents (contents don't store place data)
if err := UpdateFTS5Entry(app, entry, places, agents, series); err != nil {
app.Logger().Error("Failed to update FTS5 for entry", "entry_id", entry.Id, "error", err)
}
}
}
return nil
}
func DeleteFTS5Series(app core.App, seriesID string) error {
query := "DELETE FROM " + FTS5TableName(SERIES_TABLE) + " WHERE " + ID_FIELD + " = {:id}"
_, err := app.DB().NewQuery(query).Bind(dbx.Params{"id": seriesID}).Execute()
return err
}
func UpdateFTS5Series(app core.App, series *Series) error {
if err := DeleteFTS5Series(app, series.Id); err != nil {
return err
}
return InsertFTS5Series(app, series)
}
func UpdateFTS5SeriesAndRelatedEntries(app core.App, series *Series) error {
// Update the series itself
if err := UpdateFTS5Series(app, series); err != nil {
return err
}
// Find all entries that reference this series
relations, err := REntriesSeries_Seriess(app, []any{series.Id})
if err == nil {
for _, relation := range relations {
entry, err := Entries_ID(app, relation.Entry())
if err != nil {
app.Logger().Error("Failed to load entry for FTS5 update", "entry_id", relation.Entry(), "error", err)
continue
}
// Load all related data for this entry
places := []*Place{}
for _, placeID := range entry.Places() {
place, err := Places_ID(app, placeID)
if err == nil && place != nil {
places = append(places, place)
}
}
agents := []*Agent{}
agentRels, err := REntriesAgents_Entry(app, entry.Id)
if err == nil {
for _, rel := range agentRels {
agent, err := Agents_ID(app, rel.Agent())
if err == nil && agent != nil {
agents = append(agents, agent)
}
}
}
allSeries := []*Series{}
seriesRels, err := REntriesSeries_Entry(app, entry.Id)
if err == nil {
for _, rel := range seriesRels {
s, err := Series_ID(app, rel.Series())
if err == nil && s != nil {
allSeries = append(allSeries, s)
}
}
}
// Only update the entry itself, not contents (contents don't store series data)
if err := UpdateFTS5Entry(app, entry, places, agents, allSeries); err != nil {
app.Logger().Error("Failed to update FTS5 for entry", "entry_id", entry.Id, "error", err)
}
}
}
return nil
}

View File

@@ -4,9 +4,8 @@ TODO danach:
- Zeilenumbrüche in Reihen-Annotationen (EVTL. fix in TinyMCE) - Zeilenumbrüche in Reihen-Annotationen (EVTL. fix in TinyMCE)
- Status: Auopsiert, Erfasst etc. - Status: Auopsiert, Erfasst etc.
- Status farbig - Status farbig
- Deprecated Fields display
- TinyMCE f. Annotationen
- Lsite verknüpfter Bände ind Inhalte wie in Personen (Reihen, Orte)
- Rolle anzeigen bei Reihen
- Lösch-Links in Liste, Übersicht u.s.w. (? CSRF-Token fehlt) - Lösch-Links in Liste, Übersicht u.s.w. (? CSRF-Token fehlt)
- Löschen von Personen: werden relationen zu Inhalten mitgelöscht? optional inhalte löschen? - Löschen von Personen: werden relationen zu Inhalten mitgelöscht? optional inhalte löschen?
- Display von Status u. Bearbeitungsvermerk in Almanach-Ansicht für eingeloggte Nutzer
- ACHTUNG! FTS5-Tabellen müssen beim Speichern (und löschen) synchronisiert werden!
- Hilfe-Texte für Felder

File diff suppressed because one or more lines are too long

View File

@@ -715,6 +715,41 @@ type AlmanachResult struct {
<div id="physical"></div> <div id="physical"></div>
</div> </div>
</div> </div>
{{- $deprecated := $model.result.Entry.Deprecated -}}
{{- if or $deprecated.Reihentitel $deprecated.Norm (gt $deprecated.BiblioID 0) $deprecated.Status $deprecated.Gesichtet $deprecated.Erfasst -}}
<details class="mt-4">
<summary class="flex items-center gap-2 text-lg font-bold text-stone-700 cursor-pointer select-none rounded-xs py-1 hover:bg-stone-50 hover:text-stone-900">
<i class="ri-history-line"></i>
<span>Abgekündigte Access-DB-Felder</span>
<i class="ri-arrow-down-s-line text-base legacy-toggle-icon"></i>
</summary>
<hr class="border-slate-400 mt-2 mb-3" />
<div class="text-xs leading-relaxed font-mono bg-slate-50 text-gray-600 border border-slate-200 rounded-xs px-3 py-2">
<div class="grid grid-cols-[7.5rem_1fr] gap-x-3 gap-y-1">
{{- if $deprecated.Reihentitel -}}
<div class="text-gray-500">Reihentitel</div>
<div>{{ $deprecated.Reihentitel }}</div>
{{- end -}}
{{- if $deprecated.Norm -}}
<div class="text-gray-500">Norm</div>
<div>{{ $deprecated.Norm }}</div>
{{- end -}}
{{- if gt $deprecated.BiblioID 0 -}}
<div class="text-gray-500">Biblio-ID</div>
<div>{{ $deprecated.BiblioID }}</div>
{{- end -}}
{{- if $deprecated.Status -}}
<div class="text-gray-500">Status</div>
<div>{{- range $i, $s := $deprecated.Status -}}{{- if $i }}, {{ end -}}{{- $s -}}{{- end -}}</div>
{{- end -}}
<div class="text-gray-500">Gesichtet</div>
<div>{{ if $deprecated.Gesichtet }}Ja{{ else }}Nein{{ end }}</div>
<div class="text-gray-500">Erfasst</div>
<div>{{ if $deprecated.Erfasst }}Ja{{ else }}Nein{{ end }}</div>
</div>
</div>
</details>
{{- end -}}
<!-- Exemplare --> <!-- Exemplare -->
<div class=""> <div class="">
<items-editor class="block mt-4"> <items-editor class="block mt-4">

View File

@@ -52,12 +52,12 @@
</div> </div>
<h1 class="text-3xl font-bold">{{ $model.result.Agent.Name }}</h1> <h1 class="text-3xl font-bold">{{ $model.result.Agent.Name }}</h1>
{{- if $model.result.Agent.Pseudonyms -}} {{- if $model.result.Agent.Pseudonyms -}}
<p class="italic"> <p class="mt-1 italic">
auch: auch:
<span class="">{{ $model.result.Agent.Pseudonyms }}</span> <span class="">{{ $model.result.Agent.Pseudonyms }}</span>
</p> </p>
{{- end -}} {{- end -}}
<div> <div class="mt-1">
<span class=""> <span class="">
{{ $model.result.Agent.BiographicalData }} {{ $model.result.Agent.BiographicalData }}
</span> </span>
@@ -80,6 +80,11 @@
{{- end -}} {{- end -}}
</span> </span>
</div> </div>
{{ if $model.result.Agent.Annotation }}
<div class="max-w-[48rem] mt-1 annotation-content">
<span class="">{{ Safe $model.result.Agent.Annotation }}</span>
</div>
{{ end }}
</div> </div>
{{- if .result.BResult -}} {{- if .result.BResult -}}

View File

@@ -161,6 +161,14 @@
@apply border-l-4 border-zinc-300 font-bold; @apply border-l-4 border-zinc-300 font-bold;
} }
.legacy-toggle-icon {
transition: transform 150ms ease;
}
details[open] .legacy-toggle-icon {
transform: rotate(180deg);
}
.notifier { .notifier {
@apply bg-stone-100 text-center text-base px-2.5 py-1 font-sans rounded; @apply bg-stone-100 text-center text-base px-2.5 py-1 font-sans rounded;
} }