FIX: edit pages for contents could not be reached bc of trtailing slash error

This commit is contained in:
Simon Martens
2026-01-24 14:36:17 +01:00
parent 87dc77e990
commit a869dd8676
15 changed files with 116 additions and 29 deletions

View File

@@ -1,7 +1,9 @@
package controllers
import (
"net/http"
"sort"
"strings"
"sync"
"github.com/Theodor-Springmann-Stiftung/musenalm/app"
@@ -16,9 +18,9 @@ import (
const (
URL_ALMANACH = "/almanach/{id}/"
URL_ALMANACH_CONTENTS = "/almanach/{id}/contents/"
URL_ALMANACH_CONTENTS = "/almanach/{id}/contents-view/"
TEMPLATE_ALMANACH = "/almanach/"
TEMPLATE_ALMANACH_CONTENTS = "/almanach/contents/"
TEMPLATE_ALMANACH_CONTENTS = "/almanach/contents-view/"
)
// Simple in-memory cache for sorted entries
@@ -92,6 +94,11 @@ func (p *AlmanachPage) Setup(router *router.Router[*core.RequestEvent], ia pagem
func (p *AlmanachPage) GET(engine *templating.Engine, app core.App) HandleFunc {
return func(e *core.RequestEvent) error {
path := e.Request.URL.Path
if strings.Contains(path, "/contents/") && strings.HasSuffix(path, "/edit/") {
return e.Redirect(http.StatusTemporaryRedirect, strings.TrimSuffix(path, "/"))
}
id := e.Request.PathValue("id")
data := make(map[string]any)
filters := NewBeitraegeFilterParameters(e)

View File

@@ -17,21 +17,21 @@ import (
"github.com/Theodor-Springmann-Stiftung/musenalm/pagemodels"
"github.com/Theodor-Springmann-Stiftung/musenalm/templating"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/tools/router"
"github.com/pocketbase/pocketbase/tools/filesystem"
"github.com/pocketbase/pocketbase/tools/router"
)
const (
URL_ALMANACH_CONTENTS_EDIT = "contents/edit"
URL_ALMANACH_CONTENTS_NEW = "contents/new"
URL_ALMANACH_CONTENTS_ITEM_EDIT = "contents/{contentMusenalmId}/edit"
URL_ALMANACH_CONTENTS_DELETE = "contents/delete"
URL_ALMANACH_CONTENTS_EDIT_EXTENT = "contents/edit/extent"
URL_ALMANACH_CONTENTS_UPLOAD = "contents/upload"
URL_ALMANACH_CONTENTS_DELETE_SCAN = "contents/scan/delete"
TEMPLATE_ALMANACH_CONTENTS_EDIT = "/almanach/contents/edit/"
TEMPLATE_ALMANACH_CONTENTS_ITEM_EDIT = "/almanach/contents/edit_item/"
TEMPLATE_ALMANACH_CONTENTS_IMAGES_PANEL = "/almanach/contents/images_panel/"
URL_ALMANACH_CONTENTS_EDIT = "contents/edit"
URL_ALMANACH_CONTENTS_NEW = "contents/new"
URL_ALMANACH_CONTENTS_ITEM_EDIT = "contents/{contentMusenalmId}/edit"
URL_ALMANACH_CONTENTS_DELETE = "contents/delete"
URL_ALMANACH_CONTENTS_EDIT_EXTENT = "contents/edit/extent"
URL_ALMANACH_CONTENTS_UPLOAD = "contents/upload"
URL_ALMANACH_CONTENTS_DELETE_SCAN = "contents/scan/delete"
TEMPLATE_ALMANACH_CONTENTS_EDIT = "/contents/edit/"
TEMPLATE_ALMANACH_CONTENTS_ITEM_EDIT = "/contents/edit_item/"
TEMPLATE_ALMANACH_CONTENTS_IMAGES_PANEL = "/contents/images_panel/"
)
func init() {
@@ -955,9 +955,9 @@ type contentAgentRelationPayload struct {
}
type contentAgentRelationsPayload struct {
Relations []contentAgentRelationPayload
Relations []contentAgentRelationPayload
NewRelations []contentAgentRelationPayload
DeletedIDs []string
DeletedIDs []string
}
type contentAgentRender struct {

View File

@@ -63,7 +63,7 @@
{{- if $model.result.HasContents -}}
<div
id="almanachcontents"
hx-get="/almanach/{{ $model.result.Entry.MusenalmID }}/contents/{{- if $model.request.query -}}?{{- $model.request.query -}}{{- end -}}"
hx-get="/almanach/{{ $model.result.Entry.MusenalmID }}/contents-view/{{- if $model.request.query -}}?{{- $model.request.query -}}{{- end -}}"
hx-trigger="load"
hx-target="this"
hx-swap="outerHTML"

View File

@@ -0,0 +1,80 @@
{{ $model := . }}
<div class="container-oversize mt-0 pt-0" id="almanachcontents">
<div class="flex relative justify-center">
<div class="-translate-y-[50%] flex flex-col items-center">
<h2 class="relative bg-stone-50 px-5 font-bold text-3xl w-max mb-1">Inhalt</h2>
<div class="flex flex-row justify-center">
<div class="bg-stone-200 text-sm px-3 py-0.5 rounded mt-1">
{{- if $model.filters.Type -}}
{{- $i := len $model.result.Contents -}}
{{- if eq $i 1 -}}
<b>{{- $i }}</b> Beitrag der Kategorie <b>{{ $model.filters.Type }}</b> &middot;
{{- else -}}
<b>{{- $i }}</b> Beiträge der Kategorie <b>{{ $model.filters.Type }}</b> &middot;
{{- end -}}
{{- else if $model.filters.OnlyScans -}}
<i class="ri-image-line"></i>&nbsp;
{{- $i := len $model.result.Contents -}}
{{- if eq $i 1 -}}
<b>{{- $i }} Digitalisat &middot; </b>
{{- else -}}
<b>{{- $i }} Digitalisate &middot;</b>
{{- end -}}
{{- else -}}
{{- if eq (len $model.result.Contents) 1 -}}
<b>{{- len $model.result.Contents }}</b> erfasster Beitrag &middot;
{{- else -}}
<b>{{- len $model.result.Contents }}</b> erfasste Beiträge &middot;
{{- end -}}
{{- end -}}
<i class="ri-sort-number-asc"></i> Anzeige nach Reihenfolge
</div>
{{- if or $model.filters.Type $model.filters.OnlyScans -}}
<div class="flex flex-row items-center justify-center ml-2.5">
<div class="block bg-stone-200 text-sm px-3 py-0.5 rounded mt-1">
<i class="ri-arrow-left-long-line"></i>
<a href="/almanach/{{ $model.result.Entry.MusenalmID }}/contents-view/" hx-target="#almanachcontents" hx-select="#almanachcontents" hx-swap="outerHTML show:none" hx-indicator="body"> Alle Beiträge anzeigen </a>
</div>
</div>
{{- end -}}
</div>
</div>
</div>
<div>
<div class="flex flex-row justify-end">
{{- if gt (len $model.result.Types) 1 -}}
<div>
<form method="GET" hx-boost="false" x-target="almanachcontents" aria-label="Filter für Beitragstypen">
<label for="typefilter" class="align-baseline h-min self-end pb-1 mr-1.5 text-sm font-sans text-stone-700"> Kategorie </label>
<select class="h-min pb-1 border-b-4 border-zinc-300 px-1.5 mr-8" name="typefilter" id="typefilter" autocomplete="off" @change.debounce="$el.form.requestSubmit()">
<option value="">Alle</option>
{{- range $i, $t := $model.result.Types -}}
<option value="{{- $t -}}" {{- if eq $model.filters.Type $t -}}selected{{- end -}}>
{{- $t -}}
</option>
{{- end -}}
</select>
<button x-show="false">Filtern</button>
</form>
</div>
{{- end -}}
{{- if $model.result.HasScans -}}
<div>
<form method="GET" hx-boost="false" x-target="almanachcontents" aria-label="Filter für digialisierte Beiträge">
<label for="onlyscans" class="align-baseline h-min self-end pb-1 mr-1.5 text-sm font-sans text-stone-700"> Nur Digitalisate anzeigen </label>
<input class="" type="checkbox" id="onlyscans" name="onlyscans" autocomplete="off" @change.debounce="$el.form.requestSubmit()" {{ if $model.filters.OnlyScans -}}checked{{- end -}} />
<button x-show="false">Filtern</button>
</form>
</div>
{{- end -}}
</div>
<div class="mt-8">
{{- range $i, $c := $model.result.Contents -}}
{{- $rels := index $model.result.ContentsAgents $c.Id -}}
{{- template "_content" Arr $c $model.result.Entry $rels $model.result.Agents false false false $model.request -}}
{{- end -}}
</div>
</div>
</div>

View File

@@ -57,7 +57,7 @@
</div>
<div>
<i class="ri-file-edit-line"></i>
<a href="/almanach/{{ $model.result.Entry.MusenalmID }}/contents/edit/">Beiträge bearbeiten</a>
<a href="/almanach/{{ $model.result.Entry.MusenalmID }}/contents/edit">Beiträge bearbeiten</a>
</div>
{{- end -}}
</div>

View File

@@ -45,7 +45,7 @@ type AlmanachResult struct {
<i class="ri-book-line"></i> Almanach
</span>
{{- if not $model.is_new -}}
<a href="/almanach/{{- $model.result.Entry.MusenalmID -}}/contents/edit/" class="header-tab">
<a href="/almanach/{{- $model.result.Entry.MusenalmID -}}/contents/edit" class="header-tab">
<i class="ri-file-list-3-line"></i> Beiträge
</a>
{{- else -}}

View File

@@ -36,7 +36,7 @@
<div class="form-action-bar">
<div class="form-action-bar-inner">
<div class="form-action-bar-actions">
<a href="/almanach/{{ $entry.MusenalmID }}/contents/edit/" class="resetbutton w-40 flex items-center gap-2 justify-center">
<a href="/almanach/{{ $entry.MusenalmID }}/contents/edit" class="resetbutton w-40 flex items-center gap-2 justify-center">
<i class="ri-close-line"></i>
<span>Zurueck</span>
</a>

View File

@@ -40,7 +40,7 @@
<div class="flex flex-row">
{{- if $model.result.PrevByID -}}
<div>
<a href="/almanach/{{ $model.result.PrevByID.MusenalmID }}/contents/edit/" class="text-gray-700 hover:text-slate-950 no-underline block">
<a href="/almanach/{{ $model.result.PrevByID.MusenalmID }}/contents/edit" class="text-gray-700 hover:text-slate-950 no-underline block">
<i class="ri-arrow-left-s-line"></i>
</a>
</div>
@@ -50,7 +50,7 @@
</div>
{{- if $model.result.NextByID -}}
<div>
<a href="/almanach/{{ $model.result.NextByID.MusenalmID }}/contents/edit/" class="text-gray-700 hover:text-slate-950 no-underline block">
<a href="/almanach/{{ $model.result.NextByID.MusenalmID }}/contents/edit" class="text-gray-700 hover:text-slate-950 no-underline block">
<i class="ri-arrow-right-s-line"></i>
</a>
</div>
@@ -71,7 +71,7 @@
<tool-tip position="top" class="!inline">
<div class="data-tip">{{ $model.result.PrevByTitle.PreferredTitle }}</div>
<a
href="/almanach/{{ $model.result.PrevByTitle.MusenalmID }}/contents/edit/"
href="/almanach/{{ $model.result.PrevByTitle.MusenalmID }}/contents/edit"
class="text-gray-700 hover:text-slate-950 no-underline">
<i class="ri-arrow-left-s-line"></i>
</a>
@@ -88,7 +88,7 @@
<tool-tip position="top" class="!inline">
<div class="data-tip">{{ $model.result.NextByTitle.PreferredTitle }}</div>
<a
href="/almanach/{{ $model.result.NextByTitle.MusenalmID }}/contents/edit/"
href="/almanach/{{ $model.result.NextByTitle.MusenalmID }}/contents/edit"
class="text-gray-700 hover:text-slate-950 no-underline">
<i class="ri-arrow-right-s-line"></i>
</a>

View File

@@ -15,7 +15,7 @@
<i class="ri-book-line"></i> Almanach
</span>
{{- end -}}
<a href="/almanach/{{- $model.result.Entry.MusenalmID -}}/contents/edit/" class="header-tab">
<a href="/almanach/{{- $model.result.Entry.MusenalmID -}}/contents/edit" class="header-tab">
<i class="ri-file-list-3-line"></i> Beiträge
</a>
<span class="header-tab-sep" aria-hidden="true">
@@ -52,7 +52,7 @@
<div class="flex flex-row">
{{- if $model.prev_content -}}
<div>
<a href="/almanach/{{ $model.result.Entry.MusenalmID }}/contents/{{ $model.prev_content.MusenalmID }}/edit/" class="text-gray-700 hover:text-slate-950 no-underline block">
<a href="/almanach/{{ $model.result.Entry.MusenalmID }}/contents/{{ $model.prev_content.MusenalmID }}/edit" class="text-gray-700 hover:text-slate-950 no-underline block">
<i class="ri-arrow-left-s-line"></i>
</a>
</div>
@@ -62,7 +62,7 @@
</div>
{{- if $model.next_content -}}
<div>
<a href="/almanach/{{ $model.result.Entry.MusenalmID }}/contents/{{ $model.next_content.MusenalmID }}/edit/" class="text-gray-700 hover:text-slate-950 no-underline block">
<a href="/almanach/{{ $model.result.Entry.MusenalmID }}/contents/{{ $model.next_content.MusenalmID }}/edit" class="text-gray-700 hover:text-slate-950 no-underline block">
<i class="ri-arrow-right-s-line"></i>
</a>
</div>
@@ -93,7 +93,7 @@
{{- end -}}
</div>
<a
href="/almanach/{{ $model.result.Entry.MusenalmID }}/contents/{{ $model.prev_content.MusenalmID }}/edit/"
href="/almanach/{{ $model.result.Entry.MusenalmID }}/contents/{{ $model.prev_content.MusenalmID }}/edit"
class="text-gray-700 hover:text-slate-950 no-underline">
<i class="ri-arrow-left-s-line"></i>
</a>
@@ -118,7 +118,7 @@
{{- end -}}
</div>
<a
href="/almanach/{{ $model.result.Entry.MusenalmID }}/contents/{{ $model.next_content.MusenalmID }}/edit/"
href="/almanach/{{ $model.result.Entry.MusenalmID }}/contents/{{ $model.next_content.MusenalmID }}/edit"
class="text-gray-700 hover:text-slate-950 no-underline">
<i class="ri-arrow-right-s-line"></i>
</a>
@@ -266,7 +266,7 @@
{{- end -}}
</p>
<div class="form-action-bar-actions">
<a href="/almanach/{{ $model.result.Entry.MusenalmID }}/contents/edit/" class="resetbutton w-40 flex items-center gap-2 justify-center">
<a href="/almanach/{{ $model.result.Entry.MusenalmID }}/contents/edit" class="resetbutton w-40 flex items-center gap-2 justify-center">
<i class="ri-arrow-left-line"></i>
<span>Liste</span>
</a>