/* * SPDX-FileCopyrightText: 2023 jordi fita mas * SPDX-License-Identifier: AGPL-3.0-only */ package home import ( "context" "net/http" "github.com/jackc/pgx/v4" "dev.tandem.ws/tandem/camper/pkg/auth" "dev.tandem.ws/tandem/camper/pkg/carousel" "dev.tandem.ws/tandem/camper/pkg/database" "dev.tandem.ws/tandem/camper/pkg/form" httplib "dev.tandem.ws/tandem/camper/pkg/http" "dev.tandem.ws/tandem/camper/pkg/locale" "dev.tandem.ws/tandem/camper/pkg/template" ) const coverName = "cover" const carouselName = "home" type AdminHandler struct { cover *carousel.AdminHandler carousel *carousel.AdminHandler } func NewAdminHandler() *AdminHandler { handler := &AdminHandler{ cover: carousel.NewAdminHandler(coverName, serveHomeIndex), carousel: carousel.NewAdminHandler(carouselName, serveHomeIndex), } handler.cover.IndexURL = "/admin/home" handler.cover.SlidesURL = "/admin/home/cover" return handler } func (h *AdminHandler) Handler(user *auth.User, company *auth.Company, conn *database.Conn) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var head string head, r.URL.Path = httplib.ShiftPath(r.URL.Path) switch head { case "": switch r.Method { case http.MethodGet: serveHomeIndex(w, r, user, company, conn) case http.MethodPut: updateHome(w, r, user, company, conn) default: httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut) } case "cover": h.cover.Handler(user, company, conn).ServeHTTP(w, r) case "slides": h.carousel.Handler(user, company, conn).ServeHTTP(w, r) default: http.NotFound(w, r) } }) } func serveHomeIndex(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) { f := newHomeForm(company) if err := f.FillFromDatabase(r.Context(), company, conn); err != nil && !database.ErrorIsNotFound(err) { panic(err) } serveHomeIndexWithForm(w, r, user, company, conn, f) } func serveHomeIndexWithForm(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, f *homeForm) { cover, err := carousel.CollectSlideEntries(r.Context(), company, conn, coverName) if err != nil { panic(err) } slides, err := carousel.CollectSlideEntries(r.Context(), company, conn, carouselName) if err != nil { panic(err) } page := &homeIndex{ Form: f, Cover: cover, Slides: slides, } page.MustRender(w, r, user, company) } type homeIndex struct { Form *homeForm Cover []*carousel.SlideEntry Slides []*carousel.SlideEntry } func (page *homeIndex) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) { template.MustRenderAdmin(w, r, user, company, "home/index.gohtml", page) } func updateHome(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) { f := newHomeForm(company) if ok, err := form.Handle(f, w, r, user); err != nil { return } else if !ok { serveHomeIndexWithForm(w, r, user, company, conn, f) return } tx := conn.MustBegin(r.Context()) defer tx.Rollback(r.Context()) if err := tx.SetupHome(r.Context(), company.ID, f.Slogan[f.DefaultLang].Val); err != nil { panic(err) } for lang := range company.Locales { l := lang.String() if l == f.DefaultLang { continue } if err := tx.TranslateHome(r.Context(), company.ID, lang, f.Slogan[l].Val); err != nil { panic(err) } } tx.MustCommit(r.Context()) httplib.Redirect(w, r, "/admin/home", http.StatusSeeOther) } type homeForm struct { DefaultLang string Slogan form.I18nInput } func newHomeForm(company *auth.Company) *homeForm { return &homeForm{ DefaultLang: company.DefaultLanguage.String(), Slogan: form.NewI18nInput(company.Locales, "slogan"), } } func (f *homeForm) FillFromDatabase(ctx context.Context, company *auth.Company, conn *database.Conn) error { var slogans database.RecordArray err := conn.QueryRow(ctx, ` select home.slogan , array_agg((lang_tag, i18n.slogan)) from home left join home_i18n as i18n using (company_id) where company_id = $1 group by home.slogan `, pgx.QueryResultFormats{pgx.BinaryFormatCode}, company.ID).Scan(&f.Slogan[f.DefaultLang].Val, &slogans) if err != nil { return err } if err := f.Slogan.FillArray(slogans); err != nil { return err } return nil } func (f *homeForm) Parse(r *http.Request) error { if err := r.ParseForm(); err != nil { return err } f.Slogan.FillValue(r) return nil } func (f *homeForm) Valid(l *locale.Locale) bool { v := form.NewValidator(l) return v.AllOK }