diff --git a/controllers/person_edit.go b/controllers/person_edit.go new file mode 100644 index 0000000..af2af12 --- /dev/null +++ b/controllers/person_edit.go @@ -0,0 +1,193 @@ +package controllers + +import ( + "fmt" + "net/http" + "net/url" + "slices" + "strings" + + "github.com/Theodor-Springmann-Stiftung/musenalm/app" + "github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels" + "github.com/Theodor-Springmann-Stiftung/musenalm/middleware" + "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/types" +) + +const ( + URL_PERSON_EDIT = "edit" + TEMPLATE_PERSON_EDIT = "/person/edit/" +) + +func init() { + pep := &PersonEditPage{ + StaticPage: pagemodels.StaticPage{ + Name: pagemodels.P_PERSON_EDIT_NAME, + URL: URL_PERSON_EDIT, + Template: TEMPLATE_PERSON_EDIT, + Layout: pagemodels.LAYOUT_LOGIN_PAGES, + }, + } + app.Register(pep) +} + +type PersonEditPage struct { + pagemodels.StaticPage +} + +func (p *PersonEditPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { + rg := router.Group("/person/{id}/") + rg.BindFunc(middleware.IsAdminOrEditor()) + rg.GET(URL_PERSON_EDIT, p.GET(engine, app)) + rg.POST(URL_PERSON_EDIT, p.POST(engine, app)) + return nil +} + +type PersonEditResult struct { + Agent *dbmodels.Agent + User *dbmodels.User +} + +func NewPersonEditResult(app core.App, id string) (*PersonEditResult, error) { + agent, err := dbmodels.Agents_ID(app, id) + if err != nil { + return nil, err + } + + var user *dbmodels.User + if agent.Editor() != "" { + u, err := dbmodels.Users_ID(app, agent.Editor()) + if err == nil { + user = u + } else { + app.Logger().Error("Failed to load user for agent editor", "agent", agent.Id, "error", err) + } + } + + return &PersonEditResult{ + Agent: agent, + User: user, + }, nil +} + +func (p *PersonEditPage) GET(engine *templating.Engine, app core.App) HandleFunc { + return func(e *core.RequestEvent) error { + id := e.Request.PathValue("id") + data := make(map[string]any) + result, err := NewPersonEditResult(app, id) + if err != nil { + return engine.Response404(e, err, data) + } + data["result"] = result + + req := templating.NewRequest(e) + data["csrf_token"] = req.Session().Token + + if msg := e.Request.URL.Query().Get("saved_message"); msg != "" { + data["success"] = msg + } + + return engine.Response200(e, p.Template, data, p.Layout) + } +} + +func (p *PersonEditPage) renderError(engine *templating.Engine, app core.App, e *core.RequestEvent, message string) error { + id := e.Request.PathValue("id") + data := make(map[string]any) + result, err := NewPersonEditResult(app, id) + if err != nil { + return engine.Response404(e, err, data) + } + data["result"] = result + data["error"] = message + + req := templating.NewRequest(e) + data["csrf_token"] = req.Session().Token + + return engine.Response200(e, p.Template, data, p.Layout) +} + +type personEditForm struct { + CSRFToken string `form:"csrf_token"` + LastEdited string `form:"last_edited"` + Name string `form:"name"` + Pseudonyms string `form:"pseudonyms"` + BiographicalData string `form:"biographical_data"` + Profession string `form:"profession"` + References string `form:"references"` + Annotation string `form:"annotation"` + URI string `form:"uri"` + CorporateBody bool `form:"corporate_body"` + Fictional bool `form:"fictional"` + Status string `form:"status"` + Comment string `form:"edit_comment"` +} + +func (p *PersonEditPage) POST(engine *templating.Engine, app core.App) HandleFunc { + return func(e *core.RequestEvent) error { + id := e.Request.PathValue("id") + req := templating.NewRequest(e) + + formdata := personEditForm{} + if err := e.BindBody(&formdata); err != nil { + return p.renderError(engine, app, e, "Formulardaten ungültig.") + } + + if err := req.CheckCSRF(formdata.CSRFToken); err != nil { + return p.renderError(engine, app, e, err.Error()) + } + + agent, err := dbmodels.Agents_ID(app, id) + if err != nil { + return engine.Response404(e, err, nil) + } + + if formdata.LastEdited != "" { + lastEdited, err := types.ParseDateTime(formdata.LastEdited) + if err != nil { + return p.renderError(engine, app, e, "Ungültiger Bearbeitungszeitstempel.") + } + if !agent.Updated().Time().Equal(lastEdited.Time()) { + return p.renderError(engine, app, e, "Die Person wurde inzwischen geändert. Bitte Seite neu laden.") + } + } + + name := strings.TrimSpace(formdata.Name) + if name == "" { + return p.renderError(engine, app, e, "Name ist erforderlich.") + } + + status := strings.TrimSpace(formdata.Status) + if status == "" || !slices.Contains(dbmodels.EDITORSTATE_VALUES, status) { + return p.renderError(engine, app, e, "Ungültiger Status.") + } + + user := req.User() + if err := app.RunInTransaction(func(tx core.App) error { + agent.SetName(name) + agent.SetPseudonyms(strings.TrimSpace(formdata.Pseudonyms)) + agent.SetBiographicalData(strings.TrimSpace(formdata.BiographicalData)) + agent.SetProfession(strings.TrimSpace(formdata.Profession)) + agent.SetReferences(strings.TrimSpace(formdata.References)) + agent.SetAnnotation(strings.TrimSpace(formdata.Annotation)) + agent.SetURI(strings.TrimSpace(formdata.URI)) + agent.SetCorporateBody(formdata.CorporateBody) + agent.SetFictional(formdata.Fictional) + agent.SetEditState(status) + agent.SetComment(strings.TrimSpace(formdata.Comment)) + if user != nil { + agent.SetEditor(user.Id) + } + return tx.Save(agent) + }); err != nil { + app.Logger().Error("Failed to save agent", "agent_id", agent.Id, "error", err) + return p.renderError(engine, app, e, "Speichern fehlgeschlagen.") + } + + redirect := fmt.Sprintf("/person/%s/edit?saved_message=%s", id, url.QueryEscape("Änderungen gespeichert.")) + return e.Redirect(http.StatusSeeOther, redirect) + } +} diff --git a/controllers/reihe_edit.go b/controllers/reihe_edit.go new file mode 100644 index 0000000..4eb8f29 --- /dev/null +++ b/controllers/reihe_edit.go @@ -0,0 +1,185 @@ +package controllers + +import ( + "fmt" + "net/http" + "net/url" + "slices" + "strings" + + "github.com/Theodor-Springmann-Stiftung/musenalm/app" + "github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels" + "github.com/Theodor-Springmann-Stiftung/musenalm/middleware" + "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/types" +) + +const ( + URL_REIHE_EDIT = "edit" + TEMPLATE_REIHE_EDIT = "/reihe/edit/" +) + +func init() { + rep := &ReiheEditPage{ + StaticPage: pagemodels.StaticPage{ + Name: pagemodels.P_REIHE_EDIT_NAME, + URL: URL_REIHE_EDIT, + Template: TEMPLATE_REIHE_EDIT, + Layout: pagemodels.LAYOUT_LOGIN_PAGES, + }, + } + app.Register(rep) +} + +type ReiheEditPage struct { + pagemodels.StaticPage +} + +func (p *ReiheEditPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { + rg := router.Group(URL_REIHE) + rg.BindFunc(middleware.IsAdminOrEditor()) + rg.GET(URL_REIHE_EDIT, p.GET(engine, app)) + rg.POST(URL_REIHE_EDIT, p.POST(engine, app)) + return nil +} + +type ReiheEditResult struct { + Series *dbmodels.Series + User *dbmodels.User +} + +func NewReiheEditResult(app core.App, id string) (*ReiheEditResult, error) { + series, err := dbmodels.Series_MusenalmID(app, id) + if err != nil { + return nil, err + } + + var user *dbmodels.User + if series.Editor() != "" { + u, err := dbmodels.Users_ID(app, series.Editor()) + if err == nil { + user = u + } else { + app.Logger().Error("Failed to load user for series editor", "series", series.Id, "error", err) + } + } + + return &ReiheEditResult{ + Series: series, + User: user, + }, nil +} + +func (p *ReiheEditPage) GET(engine *templating.Engine, app core.App) HandleFunc { + return func(e *core.RequestEvent) error { + id := e.Request.PathValue("id") + data := make(map[string]any) + result, err := NewReiheEditResult(app, id) + if err != nil { + return engine.Response404(e, err, data) + } + data["result"] = result + + req := templating.NewRequest(e) + data["csrf_token"] = req.Session().Token + + if msg := e.Request.URL.Query().Get("saved_message"); msg != "" { + data["success"] = msg + } + + return engine.Response200(e, p.Template, data, p.Layout) + } +} + +func (p *ReiheEditPage) renderError(engine *templating.Engine, app core.App, e *core.RequestEvent, message string) error { + id := e.Request.PathValue("id") + data := make(map[string]any) + result, err := NewReiheEditResult(app, id) + if err != nil { + return engine.Response404(e, err, data) + } + data["result"] = result + data["error"] = message + + req := templating.NewRequest(e) + data["csrf_token"] = req.Session().Token + + return engine.Response200(e, p.Template, data, p.Layout) +} + +type reiheEditForm struct { + CSRFToken string `form:"csrf_token"` + LastEdited string `form:"last_edited"` + Title string `form:"title"` + Pseudonyms string `form:"pseudonyms"` + Annotation string `form:"annotation"` + References string `form:"references"` + Frequency string `form:"frequency"` + Status string `form:"status"` + Comment string `form:"edit_comment"` +} + +func (p *ReiheEditPage) POST(engine *templating.Engine, app core.App) HandleFunc { + return func(e *core.RequestEvent) error { + id := e.Request.PathValue("id") + req := templating.NewRequest(e) + + formdata := reiheEditForm{} + if err := e.BindBody(&formdata); err != nil { + return p.renderError(engine, app, e, "Formulardaten ungültig.") + } + + if err := req.CheckCSRF(formdata.CSRFToken); err != nil { + return p.renderError(engine, app, e, err.Error()) + } + + series, err := dbmodels.Series_MusenalmID(app, id) + if err != nil { + return engine.Response404(e, err, nil) + } + + if formdata.LastEdited != "" { + lastEdited, err := types.ParseDateTime(formdata.LastEdited) + if err != nil { + return p.renderError(engine, app, e, "Ungültiger Bearbeitungszeitstempel.") + } + if !series.Updated().Time().Equal(lastEdited.Time()) { + return p.renderError(engine, app, e, "Die Reihe wurde inzwischen geändert. Bitte Seite neu laden.") + } + } + + title := strings.TrimSpace(formdata.Title) + if title == "" { + return p.renderError(engine, app, e, "Reihentitel ist erforderlich.") + } + + status := strings.TrimSpace(formdata.Status) + if status == "" || !slices.Contains(dbmodels.EDITORSTATE_VALUES, status) { + return p.renderError(engine, app, e, "Ungültiger Status.") + } + + user := req.User() + if err := app.RunInTransaction(func(tx core.App) error { + series.SetTitle(title) + series.SetPseudonyms(strings.TrimSpace(formdata.Pseudonyms)) + series.SetAnnotation(strings.TrimSpace(formdata.Annotation)) + series.SetReferences(strings.TrimSpace(formdata.References)) + series.SetFrequency(strings.TrimSpace(formdata.Frequency)) + series.SetEditState(status) + series.SetComment(strings.TrimSpace(formdata.Comment)) + if user != nil { + series.SetEditor(user.Id) + } + return tx.Save(series) + }); err != nil { + app.Logger().Error("Failed to save series", "series_id", series.Id, "error", err) + return p.renderError(engine, app, e, "Speichern fehlgeschlagen.") + } + + redirect := fmt.Sprintf("/reihe/%s/edit?saved_message=%s", id, url.QueryEscape("Änderungen gespeichert.")) + return e.Redirect(http.StatusSeeOther, redirect) + } +} diff --git a/dbmodels/agent.go b/dbmodels/agent.go index fbc844b..59f6358 100644 --- a/dbmodels/agent.go +++ b/dbmodels/agent.go @@ -4,6 +4,7 @@ import ( "strings" "github.com/pocketbase/pocketbase/core" + "github.com/pocketbase/pocketbase/tools/types" ) var _ core.RecordProxy = (*Agent)(nil) @@ -154,3 +155,7 @@ func (a *Agent) Editor() string { func (a *Agent) SetEditor(editor string) { a.Set(EDITOR_FIELD, editor) } + +func (a *Agent) Updated() types.DateTime { + return a.GetDateTime(UPDATED_FIELD) +} diff --git a/dbmodels/series.go b/dbmodels/series.go index 41d3105..6748b65 100644 --- a/dbmodels/series.go +++ b/dbmodels/series.go @@ -2,6 +2,7 @@ package dbmodels import ( "github.com/pocketbase/pocketbase/core" + "github.com/pocketbase/pocketbase/tools/types" ) var _ core.RecordProxy = (*Series)(nil) @@ -95,3 +96,7 @@ func (s *Series) Editor() string { func (s *Series) SetEditor(editor string) { s.Set(EDITOR_FIELD, editor) } + +func (s *Series) Updated() types.DateTime { + return s.GetDateTime(UPDATED_FIELD) +} diff --git a/pagemodels/pagedata.go b/pagemodels/pagedata.go index e978f65..c2251c4 100644 --- a/pagemodels/pagedata.go +++ b/pagemodels/pagedata.go @@ -46,4 +46,6 @@ const ( P_USER_MGMT_NAME = "user_management" P_ALMANACH_EDIT_NAME = "almanach_edit" + P_REIHE_EDIT_NAME = "reihe_edit" + P_PERSON_EDIT_NAME = "person_edit" ) diff --git a/views/assets/scripts.js b/views/assets/scripts.js index 63fefd5..82b84b3 100644 --- a/views/assets/scripts.js +++ b/views/assets/scripts.js @@ -2962,29 +2962,38 @@ class ai extends HTMLElement { }); } } -const li = "filter-list", ri = "scroll-button", oi = "tool-tip", di = "abbrev-tooltips", hi = "int-link", ci = "popup-image", ui = "tab-list", mi = "filter-pill", _i = "image-reel", pi = "multi-select-places", fi = "multi-select-simple", gi = "single-select-remote", Me = "reset-button", bi = "div-manager", Ei = "items-editor", Si = "almanach-edit-page", vi = "relations-editor"; -customElements.define(hi, je); -customElements.define(di, T); -customElements.define(li, Ue); -customElements.define(ri, ze); -customElements.define(oi, Ke); -customElements.define(ci, We); -customElements.define(ui, Ge); -customElements.define(mi, He); -customElements.define(_i, Je); -customElements.define(pi, Re); -customElements.define(fi, Oe); -customElements.define(gi, Kt); +class li extends HTMLElement { + connectedCallback() { + setTimeout(() => { + const t = this.querySelector("form"); + t && typeof window.FormLoad == "function" && window.FormLoad(t); + }, 0); + } +} +const ri = "filter-list", oi = "scroll-button", di = "tool-tip", hi = "abbrev-tooltips", ci = "int-link", ui = "popup-image", mi = "tab-list", _i = "filter-pill", pi = "image-reel", fi = "multi-select-places", gi = "multi-select-simple", bi = "single-select-remote", Me = "reset-button", Ei = "div-manager", Si = "items-editor", vi = "almanach-edit-page", Li = "relations-editor", yi = "edit-page"; +customElements.define(ci, je); +customElements.define(hi, T); +customElements.define(ri, Ue); +customElements.define(oi, ze); +customElements.define(di, Ke); +customElements.define(ui, We); +customElements.define(mi, Ge); +customElements.define(_i, He); +customElements.define(pi, Je); +customElements.define(fi, Re); +customElements.define(gi, Oe); +customElements.define(bi, Kt); customElements.define(Me, It); -customElements.define(bi, xt); -customElements.define(Ei, Pt); -customElements.define(Si, Gt); -customElements.define(vi, ai); -function Li() { +customElements.define(Ei, xt); +customElements.define(Si, Pt); +customElements.define(vi, Gt); +customElements.define(Li, ai); +customElements.define(yi, li); +function Ai() { const l = window.location.pathname, t = window.location.search, e = l + t; return encodeURIComponent(e); } -function yi(l = 5e3, t = 100) { +function Ii(l = 5e3, t = 100) { return new Promise((e, i) => { let s = 0; const n = setInterval(() => { @@ -2992,8 +3001,8 @@ function yi(l = 5e3, t = 100) { }, t); }); } -async function Ai(l) { - const t = await yi(), e = document.getElementById("qr"); +async function Ci(l) { + const t = await Ii(), e = document.getElementById("qr"); e && (e.innerHTML = "", e.classList.add("hidden"), new t(e, { text: l, width: 1280, @@ -3005,7 +3014,7 @@ async function Ai(l) { e.classList.remove("hidden"); }, 20)); } -function Ii(l) { +function Ti(l) { l && (l.addEventListener("focus", (t) => { t.preventDefault(), l.select(); }), l.addEventListener("mousedown", (t) => { @@ -3018,7 +3027,7 @@ function Ii(l) { l.select(); })); } -function Ci() { +function wi() { document.body.addEventListener("htmx:responseError", function(l) { const t = l.detail.requestConfig; if (t.boosted) { @@ -3028,7 +3037,7 @@ function Ci() { } }); } -function Ti(l, t) { +function xi(l, t) { if (!(l instanceof HTMLElement)) { console.warn("Target must be an HTMLElement."); return; @@ -3073,7 +3082,7 @@ function E(l) { function Ne(l) { l.key === "Enter" && l.preventDefault(); } -function wi(l) { +function ki(l) { if (!(l instanceof HTMLTextAreaElement)) { console.warn("HookupTextareaAutoResize: Provided element is not a textarea."); return; @@ -3082,7 +3091,7 @@ function wi(l) { E(l); }); } -function xi(l) { +function Ri(l) { if (!(l instanceof HTMLTextAreaElement)) { console.warn("DisconnectTextareaAutoResize: Provided element is not a textarea."); return; @@ -3091,23 +3100,23 @@ function xi(l) { E(l); }); } -function ki(l) { +function Oi(l) { !(l instanceof HTMLTextAreaElement) && l.classList.contains("no-enter") || l.addEventListener("keydown", Ne); } -function Ri(l) { +function Bi(l) { !(l instanceof HTMLTextAreaElement) && l.classList.contains("no-enter") || l.removeEventListener("keydown", Ne); } -function Oi(l, t) { +function Mi(l, t) { const e = !$e(); for (const i of l) if (i.type === "childList") { for (const s of i.addedNodes) - s.nodeType === Node.ELEMENT_NODE && s.matches("textarea") && e && (wi(s), E(s)); + s.nodeType === Node.ELEMENT_NODE && s.matches("textarea") && e && (ki(s), E(s)); for (const s of i.removedNodes) - s.nodeType === Node.ELEMENT_NODE && s.matches("textarea") && (Ri(s), e && xi(s)); + s.nodeType === Node.ELEMENT_NODE && s.matches("textarea") && (Bi(s), e && Ri(s)); } } -function Bi(l) { +function $i(l) { if (console.log("=== FormLoad CALLED ==="), !(l instanceof HTMLFormElement)) { console.warn("FormLoad: Provided element is not a form."); return; @@ -3125,8 +3134,8 @@ function Bi(l) { }, 200); const e = document.querySelectorAll("textarea.no-enter"); for (const n of e) - ki(n); - new MutationObserver(Oi).observe(l, { + Oi(n); + new MutationObserver(Mi).observe(l, { childList: !0, subtree: !0 }), new MutationObserver((n) => { @@ -3151,16 +3160,17 @@ document.addEventListener("keydown", (l) => { const t = l.target; t instanceof HTMLElement && t.matches("textarea.no-enter") && l.preventDefault(); }); -window.ShowBoostedErrors = Ci; -window.GenQRCode = Ai; -window.SelectableInput = Ii; -window.PathPlusQuery = Li; -window.HookupRBChange = Ti; -window.FormLoad = Bi; +window.ShowBoostedErrors = wi; +window.GenQRCode = Ci; +window.SelectableInput = Ti; +window.PathPlusQuery = Ai; +window.HookupRBChange = xi; +window.FormLoad = $i; window.TextareaAutoResize = E; export { T as AbbreviationTooltips, Gt as AlmanachEditPage, + li as EditPage, Ue as FilterList, He as FilterPill, Je as ImageReel, diff --git a/views/routes/person/body.gohtml b/views/routes/person/body.gohtml index 7b9f23e..3fe804e 100644 --- a/views/routes/person/body.gohtml +++ b/views/routes/person/body.gohtml @@ -41,6 +41,12 @@ Person {{ end }} + {{- if (IsAdminOrEditor $model.request.user) -}} +
+ + Bearbeiten +
+ {{- end -}}

{{ $model.result.Agent.Name }}

{{- if $model.result.Agent.Pseudonyms -}}

diff --git a/views/routes/person/edit/body.gohtml b/views/routes/person/edit/body.gohtml new file mode 100644 index 0000000..a9fa184 --- /dev/null +++ b/views/routes/person/edit/body.gohtml @@ -0,0 +1,147 @@ +{{ $model := . }} +{{ $agent := $model.result.Agent }} + + +

+
+
+

{{ $agent.Name }}

+
+
+ + Anschauen + +
+ · +
+ + Reset + +
+
+
+
+
+
+
+ Datenbank-ID +
+
{{ $agent.Id }}
+
+
+
+
+
Zuletzt bearbeitet
+
+
+ {{ GermanDate $agent.Updated }}, + {{ GermanTime $agent.Updated }}h +
+
+ + {{- if $model.result.User -}}{{ $model.result.User.Name }}{{- end -}} +
+
+
+
+
+
+
+ +
+ {{ template "_usermessage" $model }} +
+ + + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ + +
+
+
+ +
+
+ + +
+
+ + +
+
+
+ +
+

+
+ + + Abbrechen + + + + Reset + + +
+
+
+
+ diff --git a/views/routes/person/edit/head.gohtml b/views/routes/person/edit/head.gohtml new file mode 100644 index 0000000..ae87328 --- /dev/null +++ b/views/routes/person/edit/head.gohtml @@ -0,0 +1,8 @@ +{{ $model := . }} + +{{- if $model.result -}} + Bearbeiten: {{ $model.result.Agent.Name }} - Musenalm +{{- else -}} + Person bearbeiten - Musenalm +{{- end -}} + diff --git a/views/routes/reihe/body.gohtml b/views/routes/reihe/body.gohtml index 1d90847..689e649 100644 --- a/views/routes/reihe/body.gohtml +++ b/views/routes/reihe/body.gohtml @@ -18,7 +18,7 @@
- {{/* - */}} + */}} Reihe
+ {{- if (IsAdminOrEditor $model.request.user) -}} +
+ + Bearbeiten +
+ {{- end -}}
{{ $r.Title }} diff --git a/views/routes/reihe/edit/body.gohtml b/views/routes/reihe/edit/body.gohtml new file mode 100644 index 0000000..68ef9fa --- /dev/null +++ b/views/routes/reihe/edit/body.gohtml @@ -0,0 +1,126 @@ +{{ $model := . }} +{{ $series := $model.result.Series }} + + +
+
+
+

{{ $series.Title }}

+
+ + · + +
+
+
+
+
+
+ Datenbank-ID +
+
{{ $series.Id }}
+
+
+
+
+
Zuletzt bearbeitet
+
+
+ {{ GermanDate $series.Updated }}, + {{ GermanTime $series.Updated }}h +
+
+ + {{- if $model.result.User -}}{{ $model.result.User.Name }}{{- end -}} +
+
+
+
+
+
+
+ +
+ {{ template "_usermessage" $model }} +
+ + + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+
+ +
+

+
+ + + Abbrechen + + + + Reset + + +
+
+
+
+
diff --git a/views/routes/reihe/edit/head.gohtml b/views/routes/reihe/edit/head.gohtml new file mode 100644 index 0000000..a33bac6 --- /dev/null +++ b/views/routes/reihe/edit/head.gohtml @@ -0,0 +1,8 @@ +{{ $model := . }} + +{{- if $model.result -}} + Bearbeiten: {{ $model.result.Series.Title }} - Musenalm +{{- else -}} + Reihe bearbeiten - Musenalm +{{- end -}} + diff --git a/views/transform/edit-page.js b/views/transform/edit-page.js new file mode 100644 index 0000000..d9fa0ef --- /dev/null +++ b/views/transform/edit-page.js @@ -0,0 +1,10 @@ +export class EditPage extends HTMLElement { + connectedCallback() { + setTimeout(() => { + const form = this.querySelector("form"); + if (form && typeof window.FormLoad === "function") { + window.FormLoad(form); + } + }, 0); + } +} diff --git a/views/transform/main.js b/views/transform/main.js index 61440e8..bf8f2ac 100644 --- a/views/transform/main.js +++ b/views/transform/main.js @@ -18,6 +18,7 @@ import { ItemsEditor } from "./items-editor.js"; import { SingleSelectRemote } from "./single-select-remote.js"; import { AlmanachEditPage } from "./almanach-edit.js"; import { RelationsEditor } from "./relations-editor.js"; +import { EditPage } from "./edit-page.js"; const FILTER_LIST_ELEMENT = "filter-list"; const SCROLL_BUTTON_ELEMENT = "scroll-button"; @@ -36,6 +37,7 @@ const DIV_MANAGER_ELEMENT = "div-manager"; const ITEMS_EDITOR_ELEMENT = "items-editor"; const ALMANACH_EDIT_PAGE_ELEMENT = "almanach-edit-page"; const RELATIONS_EDITOR_ELEMENT = "relations-editor"; +const EDIT_PAGE_ELEMENT = "edit-page"; customElements.define(INT_LINK_ELEMENT, IntLink); customElements.define(ABBREV_TOOLTIPS_ELEMENT, AbbreviationTooltips); @@ -54,6 +56,7 @@ customElements.define(DIV_MANAGER_ELEMENT, DivManager); customElements.define(ITEMS_EDITOR_ELEMENT, ItemsEditor); customElements.define(ALMANACH_EDIT_PAGE_ELEMENT, AlmanachEditPage); customElements.define(RELATIONS_EDITOR_ELEMENT, RelationsEditor); +customElements.define(EDIT_PAGE_ELEMENT, EditPage); function PathPlusQuery() { const path = window.location.pathname; @@ -406,4 +409,21 @@ window.HookupRBChange = HookupRBChange; window.FormLoad = FormLoad; window.TextareaAutoResize = TextareaAutoResize; -export { FilterList, ScrollButton, AbbreviationTooltips, MultiSelectSimple, MultiSelectRole, ToolTip, PopupImage, TabList, FilterPill, ImageReel, IntLink, ItemsEditor, SingleSelectRemote, AlmanachEditPage, RelationsEditor }; +export { + FilterList, + ScrollButton, + AbbreviationTooltips, + MultiSelectSimple, + MultiSelectRole, + ToolTip, + PopupImage, + TabList, + FilterPill, + ImageReel, + IntLink, + ItemsEditor, + SingleSelectRemote, + AlmanachEditPage, + RelationsEditor, + EditPage, +};