Add public page for campsite type, and function to edit them
Had to export and move PublicPage struct to template because i can not import app from campsites/types: app already imports campsite for the http handler, and it, in turn, imports the types package for its own http handler; an import loop. Also had to replace PublicPage.MustRender with a Setup function because the page passed down to html/template was the PublicPage struct, not whatever struct embeds it. I was thinking more of Java inheritance here rather than struct embedding.
This commit is contained in:
parent
866af09b50
commit
d117ce5027
|
@ -0,0 +1,25 @@
|
|||
-- Deploy camper:edit_campsite_type to pg
|
||||
-- requires: roles
|
||||
-- requires: schema_camper
|
||||
-- requires: campsite_type
|
||||
-- requires: company
|
||||
|
||||
begin;
|
||||
|
||||
set search_path to camper, public;
|
||||
|
||||
create or replace function edit_campsite_type(slug uuid, name text, description text) returns uuid as
|
||||
$$
|
||||
update campsite_type
|
||||
set name = edit_campsite_type.name
|
||||
, description = xmlparse(content edit_campsite_type.description)
|
||||
where slug = edit_campsite_type.slug
|
||||
returning slug;
|
||||
$$
|
||||
language sql
|
||||
;
|
||||
|
||||
revoke execute on function edit_campsite_type(uuid, text, text) from public;
|
||||
grant execute on function edit_campsite_type(uuid, text, text) to admin;
|
||||
|
||||
commit;
|
|
@ -16,12 +16,12 @@ import (
|
|||
)
|
||||
|
||||
type adminHandler struct {
|
||||
campsite *campsite.Handler
|
||||
campsite *campsite.AdminHandler
|
||||
}
|
||||
|
||||
func newAdminHandler() *adminHandler {
|
||||
return &adminHandler{
|
||||
campsite: campsite.NewHandler(),
|
||||
campsite: campsite.NewAdminHandler(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,19 +6,23 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"dev.tandem.ws/tandem/camper/pkg/auth"
|
||||
"dev.tandem.ws/tandem/camper/pkg/campsite"
|
||||
"dev.tandem.ws/tandem/camper/pkg/database"
|
||||
httplib "dev.tandem.ws/tandem/camper/pkg/http"
|
||||
"dev.tandem.ws/tandem/camper/pkg/template"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type publicHandler struct{}
|
||||
type publicHandler struct {
|
||||
campsite *campsite.PublicHandler
|
||||
}
|
||||
|
||||
func newPublicHandler() *publicHandler {
|
||||
return &publicHandler{}
|
||||
return &publicHandler{
|
||||
campsite: campsite.NewPublicHandler(),
|
||||
}
|
||||
}
|
||||
|
||||
func (h *publicHandler) Handler(user *auth.User, company *auth.Company, conn *database.Conn) http.Handler {
|
||||
|
@ -28,7 +32,9 @@ func (h *publicHandler) Handler(user *auth.User, company *auth.Company, conn *da
|
|||
switch head {
|
||||
case "":
|
||||
page := newHomePage()
|
||||
page.MustRender(w, r, user, company)
|
||||
page.MustRender(w, r, user, company, conn)
|
||||
case "campsites":
|
||||
h.campsite.Handler(user, company, conn).ServeHTTP(w, r)
|
||||
default:
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
|
@ -36,41 +42,14 @@ func (h *publicHandler) Handler(user *auth.User, company *auth.Company, conn *da
|
|||
}
|
||||
|
||||
type homePage struct {
|
||||
*PublicPage
|
||||
*template.PublicPage
|
||||
}
|
||||
|
||||
func newHomePage() *homePage {
|
||||
return &homePage{newPublicPage("home.gohtml")}
|
||||
return &homePage{template.NewPublicPage()}
|
||||
}
|
||||
|
||||
type PublicPage struct {
|
||||
template string
|
||||
LocalizedAlternates []*LocalizedAlternate
|
||||
}
|
||||
|
||||
func newPublicPage(template string) *PublicPage {
|
||||
return &PublicPage{
|
||||
template: template,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PublicPage) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
|
||||
schema := httplib.Protocol(r)
|
||||
authority := httplib.Host(r)
|
||||
_, path := httplib.ShiftPath(r.RequestURI)
|
||||
for _, l := range company.Locales {
|
||||
p.LocalizedAlternates = append(p.LocalizedAlternates, &LocalizedAlternate{
|
||||
Lang: l.Language.String(),
|
||||
Endonym: l.Endonym,
|
||||
HRef: fmt.Sprintf("%s://%s/%s%s", schema, authority, l.Language, path),
|
||||
})
|
||||
}
|
||||
sort.Slice(p.LocalizedAlternates, func(i, j int) bool { return p.LocalizedAlternates[i].Lang < p.LocalizedAlternates[j].Lang })
|
||||
template.MustRenderPublic(w, r, user, company, p.template, p)
|
||||
}
|
||||
|
||||
type LocalizedAlternate struct {
|
||||
Lang string
|
||||
HRef string
|
||||
Endonym string
|
||||
func (p *homePage) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) {
|
||||
p.Setup(r, user, company, conn)
|
||||
template.MustRenderPublic(w, r, user, company, "home.gohtml", p)
|
||||
}
|
||||
|
|
|
@ -9,21 +9,22 @@ import (
|
|||
"net/http"
|
||||
|
||||
"dev.tandem.ws/tandem/camper/pkg/auth"
|
||||
"dev.tandem.ws/tandem/camper/pkg/campsite/types"
|
||||
"dev.tandem.ws/tandem/camper/pkg/database"
|
||||
httplib "dev.tandem.ws/tandem/camper/pkg/http"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
types *typeHandler
|
||||
type AdminHandler struct {
|
||||
types *types.AdminHandler
|
||||
}
|
||||
|
||||
func NewHandler() *Handler {
|
||||
return &Handler{
|
||||
types: &typeHandler{},
|
||||
func NewAdminHandler() *AdminHandler {
|
||||
return &AdminHandler{
|
||||
types: &types.AdminHandler{},
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) Handler(user *auth.User, company *auth.Company, conn *database.Conn) http.HandlerFunc {
|
||||
func (h *AdminHandler) Handler(user *auth.User, company *auth.Company, conn *database.Conn) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var head string
|
||||
head, r.URL.Path = httplib.ShiftPath(r.URL.Path)
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 jordi fita mas <jfita@peritasoft.com>
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package campsite
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"dev.tandem.ws/tandem/camper/pkg/auth"
|
||||
"dev.tandem.ws/tandem/camper/pkg/campsite/types"
|
||||
"dev.tandem.ws/tandem/camper/pkg/database"
|
||||
httplib "dev.tandem.ws/tandem/camper/pkg/http"
|
||||
)
|
||||
|
||||
type PublicHandler struct {
|
||||
types *types.PublicHandler
|
||||
}
|
||||
|
||||
func NewPublicHandler() *PublicHandler {
|
||||
return &PublicHandler{
|
||||
types: &types.PublicHandler{},
|
||||
}
|
||||
}
|
||||
|
||||
func (h *PublicHandler) 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 "types":
|
||||
h.types.Handler(user, company, conn).ServeHTTP(w, r)
|
||||
default:
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
})
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package campsite
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
@ -15,12 +15,13 @@ import (
|
|||
httplib "dev.tandem.ws/tandem/camper/pkg/http"
|
||||
"dev.tandem.ws/tandem/camper/pkg/locale"
|
||||
"dev.tandem.ws/tandem/camper/pkg/template"
|
||||
"dev.tandem.ws/tandem/camper/pkg/uuid"
|
||||
)
|
||||
|
||||
type typeHandler struct {
|
||||
type AdminHandler struct {
|
||||
}
|
||||
|
||||
func (h *typeHandler) Handler(user *auth.User, company *auth.Company, conn *database.Conn) http.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)
|
||||
|
@ -44,7 +45,26 @@ func (h *typeHandler) Handler(user *auth.User, company *auth.Company, conn *data
|
|||
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPost)
|
||||
}
|
||||
default:
|
||||
http.NotFound(w, r)
|
||||
if !uuid.Valid(head) {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
f := newTypeForm()
|
||||
if err := f.FillFromDatabase(r.Context(), conn, head); err != nil {
|
||||
if database.ErrorIsNotFound(err) {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
f.MustRender(w, r, user, company)
|
||||
case http.MethodPut:
|
||||
editType(w, r, user, company, conn, f)
|
||||
default:
|
||||
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -110,10 +130,31 @@ func addType(w http.ResponseWriter, r *http.Request, user *auth.User, company *a
|
|||
return
|
||||
}
|
||||
conn.MustExec(r.Context(), "select add_campsite_type($1, $2, $3)", company.ID, f.Name, f.Description)
|
||||
httplib.Redirect(w, r, "/campsites/types", http.StatusSeeOther)
|
||||
httplib.Redirect(w, r, "/admin/campsites/types", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func editType(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, f *typeForm) {
|
||||
if err := f.Parse(r); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err := user.VerifyCSRFToken(r); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
if !f.Valid(user.Locale) {
|
||||
if !httplib.IsHTMxRequest(r) {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
}
|
||||
f.MustRender(w, r, user, company)
|
||||
return
|
||||
}
|
||||
conn.MustExec(r.Context(), "select edit_campsite_type($1, $2, $3)", f.Slug, f.Name, f.Description)
|
||||
httplib.Redirect(w, r, "/admin/campsites/types", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
type typeForm struct {
|
||||
Slug string
|
||||
Name *form.Input
|
||||
Description *form.Input
|
||||
}
|
||||
|
@ -129,6 +170,12 @@ func newTypeForm() *typeForm {
|
|||
}
|
||||
}
|
||||
|
||||
func (f *typeForm) FillFromDatabase(ctx context.Context, conn *database.Conn, slug string) error {
|
||||
f.Slug = slug
|
||||
row := conn.QueryRow(ctx, "select name, description from campsite_type where slug = $1", slug)
|
||||
return row.Scan(&f.Name.Val, &f.Description.Val)
|
||||
}
|
||||
|
||||
func (f *typeForm) Parse(r *http.Request) error {
|
||||
if err := r.ParseForm(); err != nil {
|
||||
return err
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 jordi fita mas <jfita@peritasoft.com>
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
gotemplate "html/template"
|
||||
"net/http"
|
||||
|
||||
"dev.tandem.ws/tandem/camper/pkg/auth"
|
||||
"dev.tandem.ws/tandem/camper/pkg/database"
|
||||
httplib "dev.tandem.ws/tandem/camper/pkg/http"
|
||||
"dev.tandem.ws/tandem/camper/pkg/template"
|
||||
"dev.tandem.ws/tandem/camper/pkg/uuid"
|
||||
)
|
||||
|
||||
type PublicHandler struct {
|
||||
}
|
||||
|
||||
func (h *PublicHandler) 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 r.Method {
|
||||
case http.MethodGet:
|
||||
if !uuid.Valid(head) {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
page, err := newPublicPage(r.Context(), conn, head)
|
||||
if database.ErrorIsNotFound(err) {
|
||||
http.NotFound(w, r)
|
||||
} else if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
page.MustRender(w, r, user, company, conn)
|
||||
default:
|
||||
httplib.MethodNotAllowed(w, r, http.MethodGet)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
type publicPage struct {
|
||||
*template.PublicPage
|
||||
Name string
|
||||
Description gotemplate.HTML
|
||||
}
|
||||
|
||||
func newPublicPage(ctx context.Context, conn *database.Conn, slug string) (*publicPage, error) {
|
||||
page := &publicPage{
|
||||
PublicPage: template.NewPublicPage(),
|
||||
}
|
||||
row := conn.QueryRow(ctx, "select name, description::text from campsite_type where slug = $1", slug)
|
||||
if err := row.Scan(&page.Name, &page.Description); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return page, nil
|
||||
}
|
||||
|
||||
func (p *publicPage) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) {
|
||||
p.Setup(r, user, company, conn)
|
||||
template.MustRenderPublic(w, r, user, company, "campsite/type.gohtml", p)
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 jordi fita mas <jfita@peritasoft.com>
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package template
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sort"
|
||||
|
||||
"dev.tandem.ws/tandem/camper/pkg/auth"
|
||||
"dev.tandem.ws/tandem/camper/pkg/database"
|
||||
httplib "dev.tandem.ws/tandem/camper/pkg/http"
|
||||
"dev.tandem.ws/tandem/camper/pkg/locale"
|
||||
)
|
||||
|
||||
type PublicPage struct {
|
||||
LocalizedAlternates []*LocalizedAlternate
|
||||
Menu *siteMenu
|
||||
}
|
||||
|
||||
func NewPublicPage() *PublicPage {
|
||||
return &PublicPage{}
|
||||
}
|
||||
|
||||
func (p *PublicPage) Setup(r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) {
|
||||
schema := httplib.Protocol(r)
|
||||
authority := httplib.Host(r)
|
||||
_, path := httplib.ShiftPath(r.RequestURI)
|
||||
for _, l := range company.Locales {
|
||||
p.LocalizedAlternates = append(p.LocalizedAlternates, &LocalizedAlternate{
|
||||
Lang: l.Language.String(),
|
||||
Endonym: l.Endonym,
|
||||
HRef: fmt.Sprintf("%s://%s/%s%s", schema, authority, l.Language, path),
|
||||
})
|
||||
}
|
||||
sort.Slice(p.LocalizedAlternates, func(i, j int) bool { return p.LocalizedAlternates[i].Lang < p.LocalizedAlternates[j].Lang })
|
||||
|
||||
p.Menu = &siteMenu{
|
||||
CampsiteTypes: mustCollectMenuItems(r.Context(), conn, user.Locale, "select name, '/campsites/types/' || slug from campsite_type where company_id = $1", company.ID),
|
||||
}
|
||||
}
|
||||
|
||||
type LocalizedAlternate struct {
|
||||
Lang string
|
||||
HRef string
|
||||
Endonym string
|
||||
}
|
||||
|
||||
type siteMenu struct {
|
||||
CampsiteTypes []*menuItem
|
||||
}
|
||||
|
||||
type menuItem struct {
|
||||
Label string
|
||||
HRef string
|
||||
}
|
||||
|
||||
func mustCollectMenuItems(ctx context.Context, conn *database.Conn, loc *locale.Locale, sql string, args ...interface{}) []*menuItem {
|
||||
rows, err := conn.Query(ctx, sql, args...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
localePath := "/" + loc.Language.String()
|
||||
var items []*menuItem
|
||||
for rows.Next() {
|
||||
item := &menuItem{}
|
||||
err = rows.Scan(&item.Label, &item.HRef)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
item.HRef = localePath + item.HRef
|
||||
items = append(items, item)
|
||||
}
|
||||
if rows.Err() != nil {
|
||||
panic(rows.Err())
|
||||
}
|
||||
|
||||
return items
|
||||
}
|
45
po/ca.po
45
po/ca.po
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: camper\n"
|
||||
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
||||
"POT-Creation-Date: 2023-08-05 03:23+0200\n"
|
||||
"POT-Creation-Date: 2023-08-08 02:43+0200\n"
|
||||
"PO-Revision-Date: 2023-07-22 23:45+0200\n"
|
||||
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
||||
"Language-Team: Catalan <ca@dodds.net>\n"
|
||||
|
@ -23,32 +23,47 @@ msgctxt "title"
|
|||
msgid "Home"
|
||||
msgstr "Inici"
|
||||
|
||||
#: web/templates/public/layout.gohtml:10 web/templates/public/layout.gohtml:17
|
||||
#: web/templates/public/layout.gohtml:11 web/templates/public/layout.gohtml:21
|
||||
msgid "Campsite Montagut"
|
||||
msgstr "Càmping Montagut"
|
||||
|
||||
#: web/templates/public/layout.gohtml:16 web/templates/admin/layout.gohtml:18
|
||||
#: web/templates/public/layout.gohtml:20 web/templates/admin/layout.gohtml:18
|
||||
msgid "Skip to main content"
|
||||
msgstr "Salta al contingut principal"
|
||||
|
||||
#: web/templates/admin/campsite/type/new.gohtml:14
|
||||
#: web/templates/admin/campsite/type/new.gohtml:20
|
||||
#: web/templates/public/layout.gohtml:38
|
||||
msgid "Singular Lodges"
|
||||
msgstr "Allotjaments singulars"
|
||||
|
||||
#: web/templates/admin/campsite/type/new.gohtml:16
|
||||
#: web/templates/admin/campsite/type/new.gohtml:33
|
||||
msgctxt "title"
|
||||
msgid "Edit Campsite Type"
|
||||
msgstr "Edició del tipus d’allotjament"
|
||||
|
||||
#: web/templates/admin/campsite/type/new.gohtml:18
|
||||
#: web/templates/admin/campsite/type/new.gohtml:35
|
||||
msgctxt "title"
|
||||
msgid "New Campsite Type"
|
||||
msgstr "Nou tipus d’allotjament"
|
||||
|
||||
#: web/templates/admin/campsite/type/new.gohtml:25
|
||||
#: web/templates/admin/campsite/type/new.gohtml:42
|
||||
#: web/templates/admin/profile.gohtml:26
|
||||
msgctxt "input"
|
||||
msgid "Name"
|
||||
msgstr "Nom"
|
||||
|
||||
#: web/templates/admin/campsite/type/new.gohtml:33
|
||||
#: web/templates/admin/campsite/type/new.gohtml:50
|
||||
msgctxt "input"
|
||||
msgid "Description"
|
||||
msgstr "Descripció"
|
||||
|
||||
#: web/templates/admin/campsite/type/new.gohtml:40
|
||||
#: web/templates/admin/campsite/type/new.gohtml:59
|
||||
msgctxt "action"
|
||||
msgid "Update"
|
||||
msgstr "Actualitza"
|
||||
|
||||
#: web/templates/admin/campsite/type/new.gohtml:61
|
||||
msgctxt "action"
|
||||
msgid "Add"
|
||||
msgstr "Afegeix"
|
||||
|
@ -140,11 +155,11 @@ msgctxt "action"
|
|||
msgid "Logout"
|
||||
msgstr "Surt"
|
||||
|
||||
#: pkg/app/login.go:56 pkg/app/user.go:245
|
||||
#: pkg/app/login.go:56 pkg/app/user.go:246
|
||||
msgid "Email can not be empty."
|
||||
msgstr "No podeu deixar el correu en blanc."
|
||||
|
||||
#: pkg/app/login.go:57 pkg/app/user.go:246
|
||||
#: pkg/app/login.go:57 pkg/app/user.go:247
|
||||
msgid "This email is not valid. It should be like name@domain.com."
|
||||
msgstr "Aquest correu-e no és vàlid. Hauria de ser similar a nom@domini.com."
|
||||
|
||||
|
@ -156,24 +171,24 @@ msgstr "No podeu deixar la contrasenya en blanc."
|
|||
msgid "Invalid user or password."
|
||||
msgstr "Nom d’usuari o contrasenya incorrectes."
|
||||
|
||||
#: pkg/app/user.go:196
|
||||
#: pkg/app/user.go:197
|
||||
msgctxt "language option"
|
||||
msgid "Automatic"
|
||||
msgstr "Automàtic"
|
||||
|
||||
#: pkg/app/user.go:248 pkg/campsite/type.go:143
|
||||
#: pkg/app/user.go:249 pkg/campsite/types/admin.go:190
|
||||
msgid "Name can not be empty."
|
||||
msgstr "No podeu deixar el nom en blanc."
|
||||
|
||||
#: pkg/app/user.go:249
|
||||
#: pkg/app/user.go:250
|
||||
msgid "Confirmation does not match password."
|
||||
msgstr "La confirmació no es correspon amb la contrasenya."
|
||||
|
||||
#: pkg/app/user.go:250
|
||||
#: pkg/app/user.go:251
|
||||
msgid "Selected language is not valid."
|
||||
msgstr "L’idioma escollit no és vàlid."
|
||||
|
||||
#: pkg/app/user.go:252
|
||||
#: pkg/app/user.go:253
|
||||
msgid "File must be a valid PNG or JPEG image."
|
||||
msgstr "El fitxer has de ser una imatge PNG o JPEG vàlida."
|
||||
|
||||
|
|
45
po/es.po
45
po/es.po
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: camper\n"
|
||||
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
||||
"POT-Creation-Date: 2023-08-05 03:23+0200\n"
|
||||
"POT-Creation-Date: 2023-08-08 02:43+0200\n"
|
||||
"PO-Revision-Date: 2023-07-22 23:46+0200\n"
|
||||
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
||||
"Language-Team: Spanish <es@tp.org.es>\n"
|
||||
|
@ -23,32 +23,47 @@ msgctxt "title"
|
|||
msgid "Home"
|
||||
msgstr "Inicio"
|
||||
|
||||
#: web/templates/public/layout.gohtml:10 web/templates/public/layout.gohtml:17
|
||||
#: web/templates/public/layout.gohtml:11 web/templates/public/layout.gohtml:21
|
||||
msgid "Campsite Montagut"
|
||||
msgstr "Camping Montagut"
|
||||
|
||||
#: web/templates/public/layout.gohtml:16 web/templates/admin/layout.gohtml:18
|
||||
#: web/templates/public/layout.gohtml:20 web/templates/admin/layout.gohtml:18
|
||||
msgid "Skip to main content"
|
||||
msgstr "Saltar al contenido principal"
|
||||
|
||||
#: web/templates/admin/campsite/type/new.gohtml:14
|
||||
#: web/templates/admin/campsite/type/new.gohtml:20
|
||||
#: web/templates/public/layout.gohtml:38
|
||||
msgid "Singular Lodges"
|
||||
msgstr "Alojamientos singulares"
|
||||
|
||||
#: web/templates/admin/campsite/type/new.gohtml:16
|
||||
#: web/templates/admin/campsite/type/new.gohtml:33
|
||||
msgctxt "title"
|
||||
msgid "Edit Campsite Type"
|
||||
msgstr "Edición del tipo de alojamientos"
|
||||
|
||||
#: web/templates/admin/campsite/type/new.gohtml:18
|
||||
#: web/templates/admin/campsite/type/new.gohtml:35
|
||||
msgctxt "title"
|
||||
msgid "New Campsite Type"
|
||||
msgstr "Nuevo tipo de alojamiento"
|
||||
|
||||
#: web/templates/admin/campsite/type/new.gohtml:25
|
||||
#: web/templates/admin/campsite/type/new.gohtml:42
|
||||
#: web/templates/admin/profile.gohtml:26
|
||||
msgctxt "input"
|
||||
msgid "Name"
|
||||
msgstr "Nombre"
|
||||
|
||||
#: web/templates/admin/campsite/type/new.gohtml:33
|
||||
#: web/templates/admin/campsite/type/new.gohtml:50
|
||||
msgctxt "input"
|
||||
msgid "Description"
|
||||
msgstr "Descripción"
|
||||
|
||||
#: web/templates/admin/campsite/type/new.gohtml:40
|
||||
#: web/templates/admin/campsite/type/new.gohtml:59
|
||||
msgctxt "action"
|
||||
msgid "Update"
|
||||
msgstr "Actualitzar"
|
||||
|
||||
#: web/templates/admin/campsite/type/new.gohtml:61
|
||||
msgctxt "action"
|
||||
msgid "Add"
|
||||
msgstr "Añadir"
|
||||
|
@ -140,11 +155,11 @@ msgctxt "action"
|
|||
msgid "Logout"
|
||||
msgstr "Salir"
|
||||
|
||||
#: pkg/app/login.go:56 pkg/app/user.go:245
|
||||
#: pkg/app/login.go:56 pkg/app/user.go:246
|
||||
msgid "Email can not be empty."
|
||||
msgstr "No podéis dejar el correo-e en blanco."
|
||||
|
||||
#: pkg/app/login.go:57 pkg/app/user.go:246
|
||||
#: pkg/app/login.go:57 pkg/app/user.go:247
|
||||
msgid "This email is not valid. It should be like name@domain.com."
|
||||
msgstr "Este correo-e no es válido. Tiene que ser parecido a nombre@dominio.com."
|
||||
|
||||
|
@ -156,24 +171,24 @@ msgstr "No podéis dejar la contraseña en blanco."
|
|||
msgid "Invalid user or password."
|
||||
msgstr "Usuario o contraseña incorrectos."
|
||||
|
||||
#: pkg/app/user.go:196
|
||||
#: pkg/app/user.go:197
|
||||
msgctxt "language option"
|
||||
msgid "Automatic"
|
||||
msgstr "Automático"
|
||||
|
||||
#: pkg/app/user.go:248 pkg/campsite/type.go:143
|
||||
#: pkg/app/user.go:249 pkg/campsite/types/admin.go:190
|
||||
msgid "Name can not be empty."
|
||||
msgstr "No podéis dejar el nombre en blanco."
|
||||
|
||||
#: pkg/app/user.go:249
|
||||
#: pkg/app/user.go:250
|
||||
msgid "Confirmation does not match password."
|
||||
msgstr "La confirmación no se corresponde con la contraseña."
|
||||
|
||||
#: pkg/app/user.go:250
|
||||
#: pkg/app/user.go:251
|
||||
msgid "Selected language is not valid."
|
||||
msgstr "El idioma escogido no es válido."
|
||||
|
||||
#: pkg/app/user.go:252
|
||||
#: pkg/app/user.go:253
|
||||
msgid "File must be a valid PNG or JPEG image."
|
||||
msgstr "El archivo tiene que ser una imagen PNG o JPEG válida."
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
-- Revert camper:edit_campsite_type from pg
|
||||
|
||||
begin;
|
||||
|
||||
drop function if exists camper.edit_campsite_type(uuid, text, text);
|
||||
|
||||
commit;
|
|
@ -41,3 +41,4 @@ policies_company [company user_profile] 2023-08-07T20:04:26Z jordi fita mas <jor
|
|||
change_password [roles schema_auth schema_camper user] 2023-07-21T23:54:52Z jordi fita mas <jordi@tandem.blog> # Add function to change the current user’s password
|
||||
campsite_type [roles schema_camper company user_profile] 2023-07-31T11:20:29Z jordi fita mas <jordi@tandem.blog> # Add relation of campsite type
|
||||
add_campsite_type [roles schema_camper campsite_type company] 2023-08-04T16:14:48Z jordi fita mas <jordi@tandem.blog> # Add function to create campsite types
|
||||
edit_campsite_type [roles schema_camper campsite_type company] 2023-08-07T22:21:34Z jordi fita mas <jordi@tandem.blog> # Add function to edit campsite types
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
-- Test edit_campsite_type
|
||||
set client_min_messages to warning;
|
||||
create extension if not exists pgtap;
|
||||
reset client_min_messages;
|
||||
|
||||
begin;
|
||||
|
||||
set search_path to camper, public;
|
||||
|
||||
select plan(12);
|
||||
|
||||
select has_function('camper', 'edit_campsite_type', array ['uuid', 'text', 'text']);
|
||||
select function_lang_is('camper', 'edit_campsite_type', array ['uuid', 'text', 'text'], 'sql');
|
||||
select function_returns('camper', 'edit_campsite_type', array ['uuid', 'text', 'text'], 'uuid');
|
||||
select isnt_definer('camper', 'edit_campsite_type', array ['uuid', 'text', 'text']);
|
||||
select volatility_is('camper', 'edit_campsite_type', array ['uuid', 'text', 'text'], 'volatile');
|
||||
select function_privs_are('camper', 'edit_campsite_type', array ['uuid', 'text', 'text'], 'guest', array[]::text[]);
|
||||
select function_privs_are('camper', 'edit_campsite_type', array ['uuid', 'text', 'text'], 'employee', array[]::text[]);
|
||||
select function_privs_are('camper', 'edit_campsite_type', array ['uuid', 'text', 'text'], 'admin', array['EXECUTE']);
|
||||
select function_privs_are('camper', 'edit_campsite_type', array ['uuid', 'text', 'text'], 'authenticator', array[]::text[]);
|
||||
|
||||
set client_min_messages to warning;
|
||||
truncate campsite_type cascade;
|
||||
truncate company cascade;
|
||||
reset client_min_messages;
|
||||
|
||||
|
||||
insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, country_code, currency_code, default_lang_tag)
|
||||
values (1, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', 'ES', 'EUR', 'ca')
|
||||
;
|
||||
|
||||
insert into campsite_type (company_id, slug, name, description)
|
||||
values (1, '87452b88-b48f-48d3-bb6c-0296de64164e', 'Type A', '<p>A</p>')
|
||||
, (1, '9b6370f7-f941-46f2-bc6e-de455675bd0a', 'Type B', '<p>B</p>')
|
||||
;
|
||||
|
||||
select lives_ok(
|
||||
$$ select edit_campsite_type('87452b88-b48f-48d3-bb6c-0296de64164e', 'Type 1', '<p>1</p>') $$,
|
||||
'Should be ablo to edit the first type'
|
||||
);
|
||||
|
||||
select lives_ok(
|
||||
$$ select edit_campsite_type('9b6370f7-f941-46f2-bc6e-de455675bd0a', 'Type 2', '<p>2</p>') $$,
|
||||
'Should be ablo to edit the second type'
|
||||
);
|
||||
|
||||
select bag_eq(
|
||||
$$ select slug::text, name, description::text from campsite_type $$,
|
||||
$$ values ('87452b88-b48f-48d3-bb6c-0296de64164e', 'Type 1', '<p>1</p>')
|
||||
, ('9b6370f7-f941-46f2-bc6e-de455675bd0a', 'Type 2', '<p>2</p>')
|
||||
$$,
|
||||
'Should have updated all campsite types.'
|
||||
);
|
||||
|
||||
|
||||
select *
|
||||
from finish();
|
||||
|
||||
rollback;
|
|
@ -0,0 +1,7 @@
|
|||
-- Verify camper:edit_campsite_type on pg
|
||||
|
||||
begin;
|
||||
|
||||
select has_function_privilege('camper.edit_campsite_type(uuid, text, text)', 'execute');
|
||||
|
||||
rollback;
|
|
@ -7,7 +7,7 @@
|
|||
{{- end }}
|
||||
|
||||
{{ define "content" -}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite.typeIndex*/ -}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.typeIndex*/ -}}
|
||||
<a href="/admin/campsites/types/new">{{( pgettext "Add Type" "action" )}}</a>
|
||||
<h2>{{( pgettext "Campsite Types" "title" )}}</h2>
|
||||
{{ if .Types -}}
|
||||
|
@ -20,7 +20,7 @@
|
|||
<tbody>
|
||||
{{ range .Types -}}
|
||||
<tr>
|
||||
<td><a href="/admin/campsites/type/{{ .Slug }}">{{ .Name }}</a></td>
|
||||
<td><a href="/admin/campsites/types/{{ .Slug }}">{{ .Name }}</a></td>
|
||||
</tr>
|
||||
{{- end }}
|
||||
</tbody>
|
||||
|
|
|
@ -11,13 +11,30 @@
|
|||
{{- end }}
|
||||
|
||||
{{ define "title" -}}
|
||||
{{( pgettext "New Campsite Type" "title" )}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.typeForm*/ -}}
|
||||
{{ if .Slug}}
|
||||
{{( pgettext "Edit Campsite Type" "title" )}}
|
||||
{{ else }}
|
||||
{{( pgettext "New Campsite Type" "title" )}}
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
|
||||
{{ define "content" -}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite.typeForm*/ -}}
|
||||
<form action="/admin/campsites/types" method="post">
|
||||
<h2>{{( pgettext "New Campsite Type" "title" )}}</h2>
|
||||
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.typeForm*/ -}}
|
||||
<form
|
||||
{{ if .Slug }}
|
||||
data-hx-put="/admin/campsites/types/{{ .Slug }}"
|
||||
{{ else }}
|
||||
action="/admin/campsites/types" method="post"
|
||||
{{ end }}
|
||||
>
|
||||
<h2>
|
||||
{{ if .Slug }}
|
||||
{{( pgettext "Edit Campsite Type" "title" )}}
|
||||
{{ else }}
|
||||
{{( pgettext "New Campsite Type" "title" )}}
|
||||
{{ end }}
|
||||
</h2>
|
||||
{{ CSRFInput }}
|
||||
<fieldset>
|
||||
{{ with .Name -}}
|
||||
|
@ -37,7 +54,13 @@
|
|||
{{- end }}
|
||||
</fieldset>
|
||||
<footer>
|
||||
<button type="submit">{{( pgettext "Add" "action" )}}</button>
|
||||
<button type="submit">
|
||||
{{ if .Slug }}
|
||||
{{( pgettext "Update" "action" )}}
|
||||
{{ else }}
|
||||
{{( pgettext "Add" "action" )}}
|
||||
{{ end }}
|
||||
</button>
|
||||
</footer>
|
||||
</form>
|
||||
{{- end }}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<!--
|
||||
SPDX-FileCopyrightText: 2023 jordi fita mas <jordi@tandem.blog>
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
{{ define "title" -}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.publicPage*/ -}}
|
||||
{{ .Name }}
|
||||
{{- end }}
|
||||
|
||||
{{ define "content" -}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.publicPage*/ -}}
|
||||
<h2>{{ .Name }}</h2>
|
||||
{{ .Description }}
|
||||
{{- end }}
|
|
@ -29,6 +29,23 @@
|
|||
</ul>
|
||||
</nav>
|
||||
{{- end }}
|
||||
{{ with .Menu -}}
|
||||
<nav>
|
||||
<ul>
|
||||
{{ if .CampsiteTypes -}}
|
||||
<li>
|
||||
<button type="button" aria-expanded="false" aria-controls="campsite-types-menu"
|
||||
>{{( gettext "Singular Lodges" )}}</button>
|
||||
<ul id="campsite-types-menu">
|
||||
{{ range .CampsiteTypes -}}
|
||||
<li><a href="{{ .HRef }}">{{ .Label }}</a></li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</li>
|
||||
{{- end }}
|
||||
</ul>
|
||||
</nav>
|
||||
{{- end }}
|
||||
</header>
|
||||
<main id="content">
|
||||
{{- template "content" . }}
|
||||
|
|
Loading…
Reference in New Issue