Make the slogan user-editable and translatable

Because God forbid we have any performance; everything —**everything**—
must be user editable.
This commit is contained in:
jordi fita mas 2024-01-23 11:52:39 +01:00
parent 2db322a55c
commit e34f253620
26 changed files with 783 additions and 77 deletions

View File

@ -75,6 +75,11 @@ select add_media(52, 'wooden_lodges_carouselB.avif', 'image/avif', decode('m4_es
select add_media(52, 'wooden_lodges_carouselC.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/wooden_lodges_carouselC.avif]])', 'base64')); select add_media(52, 'wooden_lodges_carouselC.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/wooden_lodges_carouselC.avif]])', 'base64'));
select setup_home(52, 'Vine a gaudir!');
select translate_home(52, 'en', 'Come and enjoy!');
select translate_home(52, 'es', '¡Ven a disfrutar!');
select translate_home(52, 'fr', 'Venez et profitez-en !');
select add_cover_carousel_slide(62, 'Qualitat Calma Natura'); select add_cover_carousel_slide(62, 'Qualitat Calma Natura');
select add_cover_carousel_slide(63, 'El plaer dacampar en plena natura…'); select add_cover_carousel_slide(63, 'El plaer dacampar en plena natura…');
select add_cover_carousel_slide(64, '…amb serveis de 1r. classe'); select add_cover_carousel_slide(64, '…amb serveis de 1r. classe');

52
deploy/home.sql Normal file
View File

@ -0,0 +1,52 @@
-- Deploy camper:home to pg
-- requires: roles
-- requires: schema_camper
-- requires: company
-- requires: user_profile
begin;
set search_path to camper, public;
create table home (
company_id integer not null primary key references company,
slogan text not null
);
grant select on table home to guest;
grant select on table home to employee;
grant select, insert, update, delete on table home to admin;
alter table home enable row level security;
create policy guest_ok
on home
for select
using (true)
;
create policy insert_to_company
on home
for insert
with check (
company_id in (select company_id from user_profile)
)
;
create policy update_company
on home
for update
using (
company_id in (select company_id from user_profile)
)
;
create policy delete_from_company
on home
for delete
using (
company_id in (select company_id from user_profile)
)
;
commit;

21
deploy/home_i18n.sql Normal file
View File

@ -0,0 +1,21 @@
-- Deploy camper:home_i18n to pg
-- requires: roles
-- requires: schema_camper
-- requires: home
begin;
set search_path to camper, public;
create table home_i18n (
company_id integer not null references home,
lang_tag text not null references language,
slogan text not null,
primary key (company_id, lang_tag)
);
grant select on table home_i18n to guest;
grant select on table home_i18n to employee;
grant select, insert, update, delete on table home_i18n to admin;
commit;

24
deploy/setup_home.sql Normal file
View File

@ -0,0 +1,24 @@
-- Deploy camper:setup_home to pg
-- requires: roles
-- requires: schema_camper
-- requires: home
begin;
set search_path to camper, public;
create or replace function setup_home(company integer, slogan text) returns void as
$$
insert into home (company_id, slogan)
values (company, coalesce(slogan, ''))
on conflict (company_id) do update
set slogan = excluded.slogan
;
$$
language sql
;
revoke execute on function setup_home(integer, text) from public;
grant execute on function setup_home(integer, text) to admin;
commit;

25
deploy/translate_home.sql Normal file
View File

@ -0,0 +1,25 @@
-- Deploy camper:translate_home to pg
-- requires: roles
-- requires: schema_camper
-- requires: home_i18n
begin;
set search_path to camper, public;
create or replace function translate_home(company_id integer, lang_tag text, slogan text) returns void as
$$
insert into home_i18n (company_id, lang_tag, slogan)
values (company_id, lang_tag, coalesce(slogan, ''))
on conflict (company_id, lang_tag)
do update
set slogan = excluded.slogan
;
$$
language sql
;
revoke execute on function translate_home(integer, text, text) from public;
grant execute on function translate_home(integer, text, text) to admin;
commit;

View File

@ -189,3 +189,13 @@ func (c *Conn) RemoveSurroundingsHighlight(ctx context.Context, id int) error {
_, err := c.Exec(ctx, "select remove_surroundings_highlight($1)", id) _, err := c.Exec(ctx, "select remove_surroundings_highlight($1)", id)
return err return err
} }
func (tx *Tx) SetupHome(ctx context.Context, companyID int, slogan string) error {
_, err := tx.Exec(ctx, "select setup_home($1, $2)", companyID, slogan)
return err
}
func (tx *Tx) TranslateHome(ctx context.Context, companyID int, langTag language.Tag, slogan string) error {
_, err := tx.Exec(ctx, "select translate_home($1, $2, $3)", companyID, langTag, slogan)
return err
}

View File

@ -6,12 +6,17 @@
package home package home
import ( import (
"context"
"net/http" "net/http"
"github.com/jackc/pgx/v4"
"dev.tandem.ws/tandem/camper/pkg/auth" "dev.tandem.ws/tandem/camper/pkg/auth"
"dev.tandem.ws/tandem/camper/pkg/carousel" "dev.tandem.ws/tandem/camper/pkg/carousel"
"dev.tandem.ws/tandem/camper/pkg/database" "dev.tandem.ws/tandem/camper/pkg/database"
"dev.tandem.ws/tandem/camper/pkg/form"
httplib "dev.tandem.ws/tandem/camper/pkg/http" 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/template"
) )
@ -43,8 +48,10 @@ func (h *AdminHandler) Handler(user *auth.User, company *auth.Company, conn *dat
switch r.Method { switch r.Method {
case http.MethodGet: case http.MethodGet:
serveHomeIndex(w, r, user, company, conn) serveHomeIndex(w, r, user, company, conn)
case http.MethodPut:
updateHome(w, r, user, company, conn)
default: default:
httplib.MethodNotAllowed(w, r, http.MethodGet) httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut)
} }
case "cover": case "cover":
h.cover.Handler(user, company, conn).ServeHTTP(w, r) h.cover.Handler(user, company, conn).ServeHTTP(w, r)
@ -57,6 +64,14 @@ func (h *AdminHandler) Handler(user *auth.User, company *auth.Company, conn *dat
} }
func serveHomeIndex(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) { 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 {
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) cover, err := carousel.CollectSlideEntries(r.Context(), company, conn, coverName)
if err != nil { if err != nil {
panic(err) panic(err)
@ -66,6 +81,7 @@ func serveHomeIndex(w http.ResponseWriter, r *http.Request, user *auth.User, com
panic(err) panic(err)
} }
page := &homeIndex{ page := &homeIndex{
Form: f,
Cover: cover, Cover: cover,
Slides: slides, Slides: slides,
} }
@ -73,6 +89,7 @@ func serveHomeIndex(w http.ResponseWriter, r *http.Request, user *auth.User, com
} }
type homeIndex struct { type homeIndex struct {
Form *homeForm
Cover []*carousel.SlideEntry Cover []*carousel.SlideEntry
Slides []*carousel.SlideEntry Slides []*carousel.SlideEntry
} }
@ -80,3 +97,73 @@ type homeIndex struct {
func (page *homeIndex) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) { 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) 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
}

View File

@ -41,6 +41,7 @@ type homePage struct {
Cover []*carousel.Slide Cover []*carousel.Slide
CampsiteTypes []*campsiteType CampsiteTypes []*campsiteType
Carousel []*carousel.Slide Carousel []*carousel.Slide
Slogan string
} }
func newHomePage() *homePage { func newHomePage() *homePage {
@ -52,6 +53,7 @@ func (p *homePage) MustRender(w http.ResponseWriter, r *http.Request, user *auth
p.CampsiteTypes = mustCollectCampsiteTypes(r.Context(), company, conn, user.Locale) p.CampsiteTypes = mustCollectCampsiteTypes(r.Context(), company, conn, user.Locale)
p.Cover = carousel.MustCollectSlides(r.Context(), company, conn, user.Locale, coverName) p.Cover = carousel.MustCollectSlides(r.Context(), company, conn, user.Locale, coverName)
p.Carousel = carousel.MustCollectSlides(r.Context(), company, conn, user.Locale, carouselName) p.Carousel = carousel.MustCollectSlides(r.Context(), company, conn, user.Locale, carouselName)
p.Slogan = conn.MustGetText(r.Context(), "select coalesce(i18n.slogan, home.slogan) from home left join camper.home_i18n as i18n on i18n.company_id = home.company_id and i18n.lang_tag = $1 where home.company_id = $2", user.Locale.Language, company.ID)
template.MustRenderPublic(w, r, user, company, "home.gohtml", p) template.MustRenderPublic(w, r, user, company, "home.gohtml", p)
} }

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: camper\n" "Project-Id-Version: camper\n"
"Report-Msgid-Bugs-To: jordi@tandem.blog\n" "Report-Msgid-Bugs-To: jordi@tandem.blog\n"
"POT-Creation-Date: 2024-01-22 20:50+0100\n" "POT-Creation-Date: 2024-01-23 11:46+0100\n"
"PO-Revision-Date: 2023-07-22 23:45+0200\n" "PO-Revision-Date: 2023-07-22 23:45+0200\n"
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n" "Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
"Language-Team: Catalan <ca@dodds.net>\n" "Language-Team: Catalan <ca@dodds.net>\n"
@ -80,10 +80,6 @@ msgstr "El plaer dacampar en plena natura…"
msgid "Our services" msgid "Our services"
msgstr "Els nostres serveis" msgstr "Els nostres serveis"
#: web/templates/public/home.gohtml:42
msgid "Come and enjoy!"
msgstr "Vine a gaudir!"
#: web/templates/public/home.gohtml:44 #: web/templates/public/home.gohtml:44
#: web/templates/public/surroundings.gohtml:7 #: web/templates/public/surroundings.gohtml:7
#: web/templates/public/surroundings.gohtml:12 #: web/templates/public/surroundings.gohtml:12
@ -479,6 +475,7 @@ msgstr "Contingut"
#: web/templates/admin/season/form.gohtml:73 #: web/templates/admin/season/form.gohtml:73
#: web/templates/admin/services/form.gohtml:80 #: web/templates/admin/services/form.gohtml:80
#: web/templates/admin/surroundings/form.gohtml:69 #: web/templates/admin/surroundings/form.gohtml:69
#: web/templates/admin/home/index.gohtml:34
#: web/templates/admin/media/form.gohtml:39 #: web/templates/admin/media/form.gohtml:39
msgctxt "action" msgctxt "action"
msgid "Update" msgid "Update"
@ -632,7 +629,7 @@ msgstr "Carrusel del tipus dallotjament"
#: web/templates/admin/campsite/carousel/index.gohtml:17 #: web/templates/admin/campsite/carousel/index.gohtml:17
#: web/templates/admin/services/index.gohtml:15 #: web/templates/admin/services/index.gohtml:15
#: web/templates/admin/home/index.gohtml:60 #: web/templates/admin/home/index.gohtml:84
msgctxt "action" msgctxt "action"
msgid "Add slide" msgid "Add slide"
msgstr "Afegeix diapositiva" msgstr "Afegeix diapositiva"
@ -640,16 +637,16 @@ msgstr "Afegeix diapositiva"
#: web/templates/admin/campsite/carousel/index.gohtml:30 #: web/templates/admin/campsite/carousel/index.gohtml:30
#: web/templates/admin/services/index.gohtml:28 #: web/templates/admin/services/index.gohtml:28
#: web/templates/admin/surroundings/index.gohtml:28 #: web/templates/admin/surroundings/index.gohtml:28
#: web/templates/admin/home/index.gohtml:28 #: web/templates/admin/home/index.gohtml:52
#: web/templates/admin/home/index.gohtml:73 #: web/templates/admin/home/index.gohtml:97
msgctxt "header" msgctxt "header"
msgid "Image" msgid "Image"
msgstr "Imatge" msgstr "Imatge"
#: web/templates/admin/campsite/carousel/index.gohtml:31 #: web/templates/admin/campsite/carousel/index.gohtml:31
#: web/templates/admin/services/index.gohtml:29 #: web/templates/admin/services/index.gohtml:29
#: web/templates/admin/home/index.gohtml:29 #: web/templates/admin/home/index.gohtml:53
#: web/templates/admin/home/index.gohtml:74 #: web/templates/admin/home/index.gohtml:98
msgctxt "header" msgctxt "header"
msgid "Caption" msgid "Caption"
msgstr "Llegenda" msgstr "Llegenda"
@ -660,15 +657,15 @@ msgstr "Llegenda"
#: web/templates/admin/services/index.gohtml:75 #: web/templates/admin/services/index.gohtml:75
#: web/templates/admin/user/index.gohtml:23 #: web/templates/admin/user/index.gohtml:23
#: web/templates/admin/surroundings/index.gohtml:30 #: web/templates/admin/surroundings/index.gohtml:30
#: web/templates/admin/home/index.gohtml:30 #: web/templates/admin/home/index.gohtml:54
#: web/templates/admin/home/index.gohtml:75 #: web/templates/admin/home/index.gohtml:99
msgctxt "header" msgctxt "header"
msgid "Actions" msgid "Actions"
msgstr "Accions" msgstr "Accions"
#: web/templates/admin/campsite/carousel/index.gohtml:36 #: web/templates/admin/campsite/carousel/index.gohtml:36
#: web/templates/admin/services/index.gohtml:34 #: web/templates/admin/services/index.gohtml:34
#: web/templates/admin/home/index.gohtml:79 #: web/templates/admin/home/index.gohtml:103
msgid "Are you sure you wish to delete this slide?" msgid "Are you sure you wish to delete this slide?"
msgstr "Esteu segur de voler esborrar aquesta diapositiva?" msgstr "Esteu segur de voler esborrar aquesta diapositiva?"
@ -678,15 +675,15 @@ msgstr "Esteu segur de voler esborrar aquesta diapositiva?"
#: web/templates/admin/services/index.gohtml:91 #: web/templates/admin/services/index.gohtml:91
#: web/templates/admin/user/index.gohtml:37 #: web/templates/admin/user/index.gohtml:37
#: web/templates/admin/surroundings/index.gohtml:47 #: web/templates/admin/surroundings/index.gohtml:47
#: web/templates/admin/home/index.gohtml:47 #: web/templates/admin/home/index.gohtml:71
#: web/templates/admin/home/index.gohtml:92 #: web/templates/admin/home/index.gohtml:116
msgctxt "action" msgctxt "action"
msgid "Delete" msgid "Delete"
msgstr "Esborra" msgstr "Esborra"
#: web/templates/admin/campsite/carousel/index.gohtml:59 #: web/templates/admin/campsite/carousel/index.gohtml:59
#: web/templates/admin/services/index.gohtml:56 #: web/templates/admin/services/index.gohtml:56
#: web/templates/admin/home/index.gohtml:101 #: web/templates/admin/home/index.gohtml:125
msgid "No slides added yet." msgid "No slides added yet."
msgstr "No sha afegit cap diapositiva encara." msgstr "No sha afegit cap diapositiva encara."
@ -1003,7 +1000,7 @@ msgid "Services Page"
msgstr "Pàgina de serveis" msgstr "Pàgina de serveis"
#: web/templates/admin/services/index.gohtml:14 #: web/templates/admin/services/index.gohtml:14
#: web/templates/admin/home/index.gohtml:59 #: web/templates/admin/home/index.gohtml:83
msgctxt "title" msgctxt "title"
msgid "Carousel" msgid "Carousel"
msgstr "Carrusel" msgstr "Carrusel"
@ -1279,21 +1276,31 @@ msgstr "Fil dAriadna"
msgid "Camper Version: %s" msgid "Camper Version: %s"
msgstr "Camper versió: %s" msgstr "Camper versió: %s"
#: web/templates/admin/home/index.gohtml:14 #: web/templates/admin/home/index.gohtml:15
msgctxt "title"
msgid "Slogan"
msgstr "Eslògan"
#: web/templates/admin/home/index.gohtml:21
msgctxt "input"
msgid "Slogan"
msgstr "Eslògan"
#: web/templates/admin/home/index.gohtml:38
msgctxt "title" msgctxt "title"
msgid "Cover" msgid "Cover"
msgstr "Portada" msgstr "Portada"
#: web/templates/admin/home/index.gohtml:15 #: web/templates/admin/home/index.gohtml:39
msgctxt "action" msgctxt "action"
msgid "Add cover image" msgid "Add cover image"
msgstr "Afegeix imatge de portada" msgstr "Afegeix imatge de portada"
#: web/templates/admin/home/index.gohtml:34 #: web/templates/admin/home/index.gohtml:58
msgid "Are you sure you wish to delete this cover image?" msgid "Are you sure you wish to delete this cover image?"
msgstr "Esteu segur de voler esborrar aquesta imatge de portada?" msgstr "Esteu segur de voler esborrar aquesta imatge de portada?"
#: web/templates/admin/home/index.gohtml:56 #: web/templates/admin/home/index.gohtml:80
msgid "No images added to the cover yet." msgid "No images added to the cover yet."
msgstr "No sha afegit cap imatge de portada encara." msgstr "No sha afegit cap imatge de portada encara."
@ -1443,22 +1450,22 @@ msgstr "No podeu deixar el nom en blanc."
msgid "Name must have at least one letter." msgid "Name must have at least one letter."
msgstr "El nom ha de tenir com a mínim una lletra." msgstr "El nom ha de tenir com a mínim una lletra."
#: pkg/carousel/admin.go:275 pkg/campsite/types/carousel.go:223 #: pkg/carousel/admin.go:276 pkg/campsite/types/carousel.go:225
msgctxt "input" msgctxt "input"
msgid "Slide image" msgid "Slide image"
msgstr "Imatge de la diapositiva" msgstr "Imatge de la diapositiva"
#: pkg/carousel/admin.go:276 pkg/campsite/types/carousel.go:224 #: pkg/carousel/admin.go:277 pkg/campsite/types/carousel.go:226
msgctxt "action" msgctxt "action"
msgid "Set slide image" msgid "Set slide image"
msgstr "Estableix la imatge de la diapositiva" msgstr "Estableix la imatge de la diapositiva"
#: pkg/carousel/admin.go:345 pkg/campsite/types/carousel.go:297 #: pkg/carousel/admin.go:346 pkg/campsite/types/carousel.go:299
#: pkg/surroundings/admin.go:316 #: pkg/surroundings/admin.go:316
msgid "Slide image can not be empty." msgid "Slide image can not be empty."
msgstr "No podeu deixar la imatge de la diapositiva en blanc." msgstr "No podeu deixar la imatge de la diapositiva en blanc."
#: pkg/carousel/admin.go:346 pkg/campsite/types/carousel.go:298 #: pkg/carousel/admin.go:347 pkg/campsite/types/carousel.go:300
#: pkg/surroundings/admin.go:317 #: pkg/surroundings/admin.go:317
msgid "Slide image must be an image media type." msgid "Slide image must be an image media type."
msgstr "La imatge de la diapositiva ha de ser un mèdia de tipus imatge." msgstr "La imatge de la diapositiva ha de ser un mèdia de tipus imatge."

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: camper\n" "Project-Id-Version: camper\n"
"Report-Msgid-Bugs-To: jordi@tandem.blog\n" "Report-Msgid-Bugs-To: jordi@tandem.blog\n"
"POT-Creation-Date: 2024-01-22 20:50+0100\n" "POT-Creation-Date: 2024-01-23 11:46+0100\n"
"PO-Revision-Date: 2023-07-22 23:46+0200\n" "PO-Revision-Date: 2023-07-22 23:46+0200\n"
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n" "Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
"Language-Team: Spanish <es@tp.org.es>\n" "Language-Team: Spanish <es@tp.org.es>\n"
@ -80,10 +80,6 @@ msgstr "El placer de acampar en plena naturaleza…"
msgid "Our services" msgid "Our services"
msgstr "Nuestros servicios" msgstr "Nuestros servicios"
#: web/templates/public/home.gohtml:42
msgid "Come and enjoy!"
msgstr "¡Ven a disfrutar!"
#: web/templates/public/home.gohtml:44 #: web/templates/public/home.gohtml:44
#: web/templates/public/surroundings.gohtml:7 #: web/templates/public/surroundings.gohtml:7
#: web/templates/public/surroundings.gohtml:12 #: web/templates/public/surroundings.gohtml:12
@ -479,6 +475,7 @@ msgstr "Contenido"
#: web/templates/admin/season/form.gohtml:73 #: web/templates/admin/season/form.gohtml:73
#: web/templates/admin/services/form.gohtml:80 #: web/templates/admin/services/form.gohtml:80
#: web/templates/admin/surroundings/form.gohtml:69 #: web/templates/admin/surroundings/form.gohtml:69
#: web/templates/admin/home/index.gohtml:34
#: web/templates/admin/media/form.gohtml:39 #: web/templates/admin/media/form.gohtml:39
msgctxt "action" msgctxt "action"
msgid "Update" msgid "Update"
@ -632,7 +629,7 @@ msgstr "Carrusel del tipo de alojamiento"
#: web/templates/admin/campsite/carousel/index.gohtml:17 #: web/templates/admin/campsite/carousel/index.gohtml:17
#: web/templates/admin/services/index.gohtml:15 #: web/templates/admin/services/index.gohtml:15
#: web/templates/admin/home/index.gohtml:60 #: web/templates/admin/home/index.gohtml:84
msgctxt "action" msgctxt "action"
msgid "Add slide" msgid "Add slide"
msgstr "Añadir diapositiva" msgstr "Añadir diapositiva"
@ -640,16 +637,16 @@ msgstr "Añadir diapositiva"
#: web/templates/admin/campsite/carousel/index.gohtml:30 #: web/templates/admin/campsite/carousel/index.gohtml:30
#: web/templates/admin/services/index.gohtml:28 #: web/templates/admin/services/index.gohtml:28
#: web/templates/admin/surroundings/index.gohtml:28 #: web/templates/admin/surroundings/index.gohtml:28
#: web/templates/admin/home/index.gohtml:28 #: web/templates/admin/home/index.gohtml:52
#: web/templates/admin/home/index.gohtml:73 #: web/templates/admin/home/index.gohtml:97
msgctxt "header" msgctxt "header"
msgid "Image" msgid "Image"
msgstr "Imagen" msgstr "Imagen"
#: web/templates/admin/campsite/carousel/index.gohtml:31 #: web/templates/admin/campsite/carousel/index.gohtml:31
#: web/templates/admin/services/index.gohtml:29 #: web/templates/admin/services/index.gohtml:29
#: web/templates/admin/home/index.gohtml:29 #: web/templates/admin/home/index.gohtml:53
#: web/templates/admin/home/index.gohtml:74 #: web/templates/admin/home/index.gohtml:98
msgctxt "header" msgctxt "header"
msgid "Caption" msgid "Caption"
msgstr "Leyenda" msgstr "Leyenda"
@ -660,15 +657,15 @@ msgstr "Leyenda"
#: web/templates/admin/services/index.gohtml:75 #: web/templates/admin/services/index.gohtml:75
#: web/templates/admin/user/index.gohtml:23 #: web/templates/admin/user/index.gohtml:23
#: web/templates/admin/surroundings/index.gohtml:30 #: web/templates/admin/surroundings/index.gohtml:30
#: web/templates/admin/home/index.gohtml:30 #: web/templates/admin/home/index.gohtml:54
#: web/templates/admin/home/index.gohtml:75 #: web/templates/admin/home/index.gohtml:99
msgctxt "header" msgctxt "header"
msgid "Actions" msgid "Actions"
msgstr "Acciones" msgstr "Acciones"
#: web/templates/admin/campsite/carousel/index.gohtml:36 #: web/templates/admin/campsite/carousel/index.gohtml:36
#: web/templates/admin/services/index.gohtml:34 #: web/templates/admin/services/index.gohtml:34
#: web/templates/admin/home/index.gohtml:79 #: web/templates/admin/home/index.gohtml:103
msgid "Are you sure you wish to delete this slide?" msgid "Are you sure you wish to delete this slide?"
msgstr "¿Estáis seguro de querer borrar esta diapositiva?" msgstr "¿Estáis seguro de querer borrar esta diapositiva?"
@ -678,15 +675,15 @@ msgstr "¿Estáis seguro de querer borrar esta diapositiva?"
#: web/templates/admin/services/index.gohtml:91 #: web/templates/admin/services/index.gohtml:91
#: web/templates/admin/user/index.gohtml:37 #: web/templates/admin/user/index.gohtml:37
#: web/templates/admin/surroundings/index.gohtml:47 #: web/templates/admin/surroundings/index.gohtml:47
#: web/templates/admin/home/index.gohtml:47 #: web/templates/admin/home/index.gohtml:71
#: web/templates/admin/home/index.gohtml:92 #: web/templates/admin/home/index.gohtml:116
msgctxt "action" msgctxt "action"
msgid "Delete" msgid "Delete"
msgstr "Borrar" msgstr "Borrar"
#: web/templates/admin/campsite/carousel/index.gohtml:59 #: web/templates/admin/campsite/carousel/index.gohtml:59
#: web/templates/admin/services/index.gohtml:56 #: web/templates/admin/services/index.gohtml:56
#: web/templates/admin/home/index.gohtml:101 #: web/templates/admin/home/index.gohtml:125
msgid "No slides added yet." msgid "No slides added yet."
msgstr "No se ha añadido ninguna diapositiva todavía." msgstr "No se ha añadido ninguna diapositiva todavía."
@ -1003,7 +1000,7 @@ msgid "Services Page"
msgstr "Página de servicios" msgstr "Página de servicios"
#: web/templates/admin/services/index.gohtml:14 #: web/templates/admin/services/index.gohtml:14
#: web/templates/admin/home/index.gohtml:59 #: web/templates/admin/home/index.gohtml:83
msgctxt "title" msgctxt "title"
msgid "Carousel" msgid "Carousel"
msgstr "Carrusel" msgstr "Carrusel"
@ -1279,21 +1276,31 @@ msgstr "Migas de pan"
msgid "Camper Version: %s" msgid "Camper Version: %s"
msgstr "Camper versión: %s" msgstr "Camper versión: %s"
#: web/templates/admin/home/index.gohtml:14 #: web/templates/admin/home/index.gohtml:15
msgctxt "title"
msgid "Slogan"
msgstr "Eslogan"
#: web/templates/admin/home/index.gohtml:21
msgctxt "input"
msgid "Slogan"
msgstr "Eslogan"
#: web/templates/admin/home/index.gohtml:38
msgctxt "title" msgctxt "title"
msgid "Cover" msgid "Cover"
msgstr "Portada" msgstr "Portada"
#: web/templates/admin/home/index.gohtml:15 #: web/templates/admin/home/index.gohtml:39
msgctxt "action" msgctxt "action"
msgid "Add cover image" msgid "Add cover image"
msgstr "Añadir imagen de portada" msgstr "Añadir imagen de portada"
#: web/templates/admin/home/index.gohtml:34 #: web/templates/admin/home/index.gohtml:58
msgid "Are you sure you wish to delete this cover image?" msgid "Are you sure you wish to delete this cover image?"
msgstr "¿Estáis seguro de querer borrar esta imagen de portada?" msgstr "¿Estáis seguro de querer borrar esta imagen de portada?"
#: web/templates/admin/home/index.gohtml:56 #: web/templates/admin/home/index.gohtml:80
msgid "No images added to the cover yet." msgid "No images added to the cover yet."
msgstr "No se ha añadido ninguna imagen de portada todavía." msgstr "No se ha añadido ninguna imagen de portada todavía."
@ -1443,22 +1450,22 @@ msgstr "No podéis dejar el nombre en blanco."
msgid "Name must have at least one letter." msgid "Name must have at least one letter."
msgstr "El nombre tiene que tener como mínimo una letra." msgstr "El nombre tiene que tener como mínimo una letra."
#: pkg/carousel/admin.go:275 pkg/campsite/types/carousel.go:223 #: pkg/carousel/admin.go:276 pkg/campsite/types/carousel.go:225
msgctxt "input" msgctxt "input"
msgid "Slide image" msgid "Slide image"
msgstr "Imagen de la diapositiva" msgstr "Imagen de la diapositiva"
#: pkg/carousel/admin.go:276 pkg/campsite/types/carousel.go:224 #: pkg/carousel/admin.go:277 pkg/campsite/types/carousel.go:226
msgctxt "action" msgctxt "action"
msgid "Set slide image" msgid "Set slide image"
msgstr "Establecer la imagen de la diapositiva" msgstr "Establecer la imagen de la diapositiva"
#: pkg/carousel/admin.go:345 pkg/campsite/types/carousel.go:297 #: pkg/carousel/admin.go:346 pkg/campsite/types/carousel.go:299
#: pkg/surroundings/admin.go:316 #: pkg/surroundings/admin.go:316
msgid "Slide image can not be empty." msgid "Slide image can not be empty."
msgstr "No podéis dejar la imagen de la diapositiva en blanco." msgstr "No podéis dejar la imagen de la diapositiva en blanco."
#: pkg/carousel/admin.go:346 pkg/campsite/types/carousel.go:298 #: pkg/carousel/admin.go:347 pkg/campsite/types/carousel.go:300
#: pkg/surroundings/admin.go:317 #: pkg/surroundings/admin.go:317
msgid "Slide image must be an image media type." msgid "Slide image must be an image media type."
msgstr "La imagen de la diapositiva tiene que ser un medio de tipo imagen." msgstr "La imagen de la diapositiva tiene que ser un medio de tipo imagen."

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: camper\n" "Project-Id-Version: camper\n"
"Report-Msgid-Bugs-To: jordi@tandem.blog\n" "Report-Msgid-Bugs-To: jordi@tandem.blog\n"
"POT-Creation-Date: 2024-01-22 20:50+0100\n" "POT-Creation-Date: 2024-01-23 11:46+0100\n"
"PO-Revision-Date: 2023-12-20 10:13+0100\n" "PO-Revision-Date: 2023-12-20 10:13+0100\n"
"Last-Translator: Oriol Carbonell <info@oriolcarbonell.cat>\n" "Last-Translator: Oriol Carbonell <info@oriolcarbonell.cat>\n"
"Language-Team: French <traduc@traduc.org>\n" "Language-Team: French <traduc@traduc.org>\n"
@ -81,10 +81,6 @@ msgstr "Le plaisir de camper en pleine nature…"
msgid "Our services" msgid "Our services"
msgstr "Nos services" msgstr "Nos services"
#: web/templates/public/home.gohtml:42
msgid "Come and enjoy!"
msgstr "Venez et profitez-en !"
#: web/templates/public/home.gohtml:44 #: web/templates/public/home.gohtml:44
#: web/templates/public/surroundings.gohtml:7 #: web/templates/public/surroundings.gohtml:7
#: web/templates/public/surroundings.gohtml:12 #: web/templates/public/surroundings.gohtml:12
@ -480,6 +476,7 @@ msgstr "Contenu"
#: web/templates/admin/season/form.gohtml:73 #: web/templates/admin/season/form.gohtml:73
#: web/templates/admin/services/form.gohtml:80 #: web/templates/admin/services/form.gohtml:80
#: web/templates/admin/surroundings/form.gohtml:69 #: web/templates/admin/surroundings/form.gohtml:69
#: web/templates/admin/home/index.gohtml:34
#: web/templates/admin/media/form.gohtml:39 #: web/templates/admin/media/form.gohtml:39
msgctxt "action" msgctxt "action"
msgid "Update" msgid "Update"
@ -633,7 +630,7 @@ msgstr "Type de camping Carrousel"
#: web/templates/admin/campsite/carousel/index.gohtml:17 #: web/templates/admin/campsite/carousel/index.gohtml:17
#: web/templates/admin/services/index.gohtml:15 #: web/templates/admin/services/index.gohtml:15
#: web/templates/admin/home/index.gohtml:60 #: web/templates/admin/home/index.gohtml:84
msgctxt "action" msgctxt "action"
msgid "Add slide" msgid "Add slide"
msgstr "Ajouter la diapositive" msgstr "Ajouter la diapositive"
@ -641,16 +638,16 @@ msgstr "Ajouter la diapositive"
#: web/templates/admin/campsite/carousel/index.gohtml:30 #: web/templates/admin/campsite/carousel/index.gohtml:30
#: web/templates/admin/services/index.gohtml:28 #: web/templates/admin/services/index.gohtml:28
#: web/templates/admin/surroundings/index.gohtml:28 #: web/templates/admin/surroundings/index.gohtml:28
#: web/templates/admin/home/index.gohtml:28 #: web/templates/admin/home/index.gohtml:52
#: web/templates/admin/home/index.gohtml:73 #: web/templates/admin/home/index.gohtml:97
msgctxt "header" msgctxt "header"
msgid "Image" msgid "Image"
msgstr "Image" msgstr "Image"
#: web/templates/admin/campsite/carousel/index.gohtml:31 #: web/templates/admin/campsite/carousel/index.gohtml:31
#: web/templates/admin/services/index.gohtml:29 #: web/templates/admin/services/index.gohtml:29
#: web/templates/admin/home/index.gohtml:29 #: web/templates/admin/home/index.gohtml:53
#: web/templates/admin/home/index.gohtml:74 #: web/templates/admin/home/index.gohtml:98
msgctxt "header" msgctxt "header"
msgid "Caption" msgid "Caption"
msgstr "Légende" msgstr "Légende"
@ -661,15 +658,15 @@ msgstr "Légende"
#: web/templates/admin/services/index.gohtml:75 #: web/templates/admin/services/index.gohtml:75
#: web/templates/admin/user/index.gohtml:23 #: web/templates/admin/user/index.gohtml:23
#: web/templates/admin/surroundings/index.gohtml:30 #: web/templates/admin/surroundings/index.gohtml:30
#: web/templates/admin/home/index.gohtml:30 #: web/templates/admin/home/index.gohtml:54
#: web/templates/admin/home/index.gohtml:75 #: web/templates/admin/home/index.gohtml:99
msgctxt "header" msgctxt "header"
msgid "Actions" msgid "Actions"
msgstr "Actions" msgstr "Actions"
#: web/templates/admin/campsite/carousel/index.gohtml:36 #: web/templates/admin/campsite/carousel/index.gohtml:36
#: web/templates/admin/services/index.gohtml:34 #: web/templates/admin/services/index.gohtml:34
#: web/templates/admin/home/index.gohtml:79 #: web/templates/admin/home/index.gohtml:103
msgid "Are you sure you wish to delete this slide?" msgid "Are you sure you wish to delete this slide?"
msgstr "Êtes-vous sûr de vouloir supprimer cette diapositive ?" msgstr "Êtes-vous sûr de vouloir supprimer cette diapositive ?"
@ -679,15 +676,15 @@ msgstr "Êtes-vous sûr de vouloir supprimer cette diapositive ?"
#: web/templates/admin/services/index.gohtml:91 #: web/templates/admin/services/index.gohtml:91
#: web/templates/admin/user/index.gohtml:37 #: web/templates/admin/user/index.gohtml:37
#: web/templates/admin/surroundings/index.gohtml:47 #: web/templates/admin/surroundings/index.gohtml:47
#: web/templates/admin/home/index.gohtml:47 #: web/templates/admin/home/index.gohtml:71
#: web/templates/admin/home/index.gohtml:92 #: web/templates/admin/home/index.gohtml:116
msgctxt "action" msgctxt "action"
msgid "Delete" msgid "Delete"
msgstr "Supprimer" msgstr "Supprimer"
#: web/templates/admin/campsite/carousel/index.gohtml:59 #: web/templates/admin/campsite/carousel/index.gohtml:59
#: web/templates/admin/services/index.gohtml:56 #: web/templates/admin/services/index.gohtml:56
#: web/templates/admin/home/index.gohtml:101 #: web/templates/admin/home/index.gohtml:125
msgid "No slides added yet." msgid "No slides added yet."
msgstr "Aucune diapositive na encore été ajoutée." msgstr "Aucune diapositive na encore été ajoutée."
@ -1004,7 +1001,7 @@ msgid "Services Page"
msgstr "La page des services" msgstr "La page des services"
#: web/templates/admin/services/index.gohtml:14 #: web/templates/admin/services/index.gohtml:14
#: web/templates/admin/home/index.gohtml:59 #: web/templates/admin/home/index.gohtml:83
msgctxt "title" msgctxt "title"
msgid "Carousel" msgid "Carousel"
msgstr "Carrousel" msgstr "Carrousel"
@ -1280,21 +1277,31 @@ msgstr "Fil dAriane"
msgid "Camper Version: %s" msgid "Camper Version: %s"
msgstr "Camper version: %s" msgstr "Camper version: %s"
#: web/templates/admin/home/index.gohtml:14 #: web/templates/admin/home/index.gohtml:15
msgctxt "title"
msgid "Slogan"
msgstr "Slogan"
#: web/templates/admin/home/index.gohtml:21
msgctxt "input"
msgid "Slogan"
msgstr "Slogan"
#: web/templates/admin/home/index.gohtml:38
msgctxt "title" msgctxt "title"
msgid "Cover" msgid "Cover"
msgstr "Couverture" msgstr "Couverture"
#: web/templates/admin/home/index.gohtml:15 #: web/templates/admin/home/index.gohtml:39
msgctxt "action" msgctxt "action"
msgid "Add cover image" msgid "Add cover image"
msgstr "Ajouter une image de couverture" msgstr "Ajouter une image de couverture"
#: web/templates/admin/home/index.gohtml:34 #: web/templates/admin/home/index.gohtml:58
msgid "Are you sure you wish to delete this cover image?" msgid "Are you sure you wish to delete this cover image?"
msgstr "Êtes-vous sûr de vouloir supprimer cette image de couverture ?" msgstr "Êtes-vous sûr de vouloir supprimer cette image de couverture ?"
#: web/templates/admin/home/index.gohtml:56 #: web/templates/admin/home/index.gohtml:80
msgid "No images added to the cover yet." msgid "No images added to the cover yet."
msgstr "Aucune image de couverture na encore été ajoutée." msgstr "Aucune image de couverture na encore été ajoutée."
@ -1444,22 +1451,22 @@ msgstr "Le nom ne peut pas être laissé vide."
msgid "Name must have at least one letter." msgid "Name must have at least one letter."
msgstr "Le nom doit comporter au moins une lettre." msgstr "Le nom doit comporter au moins une lettre."
#: pkg/carousel/admin.go:275 pkg/campsite/types/carousel.go:223 #: pkg/carousel/admin.go:276 pkg/campsite/types/carousel.go:225
msgctxt "input" msgctxt "input"
msgid "Slide image" msgid "Slide image"
msgstr "Image du diaporama" msgstr "Image du diaporama"
#: pkg/carousel/admin.go:276 pkg/campsite/types/carousel.go:224 #: pkg/carousel/admin.go:277 pkg/campsite/types/carousel.go:226
msgctxt "action" msgctxt "action"
msgid "Set slide image" msgid "Set slide image"
msgstr "Définir limage de la diapositive" msgstr "Définir limage de la diapositive"
#: pkg/carousel/admin.go:345 pkg/campsite/types/carousel.go:297 #: pkg/carousel/admin.go:346 pkg/campsite/types/carousel.go:299
#: pkg/surroundings/admin.go:316 #: pkg/surroundings/admin.go:316
msgid "Slide image can not be empty." msgid "Slide image can not be empty."
msgstr "Limage de la diapositive ne peut pas être vide." msgstr "Limage de la diapositive ne peut pas être vide."
#: pkg/carousel/admin.go:346 pkg/campsite/types/carousel.go:298 #: pkg/carousel/admin.go:347 pkg/campsite/types/carousel.go:300
#: pkg/surroundings/admin.go:317 #: pkg/surroundings/admin.go:317
msgid "Slide image must be an image media type." msgid "Slide image must be an image media type."
msgstr "Limage de la diapositive doit être de type média dimage." msgstr "Limage de la diapositive doit être de type média dimage."

7
revert/home.sql Normal file
View File

@ -0,0 +1,7 @@
-- Revert camper:home from pg
begin;
drop table if exists camper.home;
commit;

7
revert/home_i18n.sql Normal file
View File

@ -0,0 +1,7 @@
-- Revert camper:home_i18n from pg
begin;
drop table if exists camper.home_i18n;
commit;

7
revert/setup_home.sql Normal file
View File

@ -0,0 +1,7 @@
-- Revert camper:setup_home from pg
begin;
drop function if exists camper.setup_home(integer, text);
commit;

View File

@ -0,0 +1,7 @@
-- Revert camper:translate_home from pg
begin;
drop function if exists camper.translate_home(integer, text, text);
commit;

View File

@ -168,3 +168,7 @@ edit_campsite_type [edit_campsite_type@v1 campsite_type__check_in_out] 2024-01-2
campsite_type_i18n__check_in_out [campsite_type_i18n] 2024-01-22T18:07:21Z jordi fita mas <jordi@tandem.blog> # Add check_in and check_out fields to campsite_type_i18n campsite_type_i18n__check_in_out [campsite_type_i18n] 2024-01-22T18:07:21Z jordi fita mas <jordi@tandem.blog> # Add check_in and check_out fields to campsite_type_i18n
translate_campsite_type [translate_campsite_type@v1 campsite_type_i18n__check_in_out] 2024-01-22T18:14:26Z jordi fita mas <jordi@tandem.blog> # Add check_in and check_out parameters to translate_campsite_type function translate_campsite_type [translate_campsite_type@v1 campsite_type_i18n__check_in_out] 2024-01-22T18:14:26Z jordi fita mas <jordi@tandem.blog> # Add check_in and check_out parameters to translate_campsite_type function
remove_campsite_type_option [roles schema_camper campsite_type_option campsite_type_option_i18n campsite_type_option_cost] 2024-01-22T19:25:03Z jordi fita mas <jordi@tandem.blog> # Add function to remove campsite type options remove_campsite_type_option [roles schema_camper campsite_type_option campsite_type_option_i18n campsite_type_option_cost] 2024-01-22T19:25:03Z jordi fita mas <jordi@tandem.blog> # Add function to remove campsite type options
home [roles schema_camper company user_profile] 2024-01-23T10:02:08Z jordi fita mas <jordi@tandem.blog> # Add table to hold texts for home page
setup_home [roles schema_camper home] 2024-01-23T10:14:14Z jordi fita mas <jordi@tandem.blog> # Add function to set up home page
home_i18n [roles schema_camper home] 2024-01-23T10:19:47Z jordi fita mas <jordi@tandem.blog> # Add table to hold translated texts for home page
translate_home [roles schema_camper home_i18n] 2024-01-23T10:24:02Z jordi fita mas <jordi@tandem.blog> # Add function to translate home texts

167
test/home.sql Normal file
View File

@ -0,0 +1,167 @@
-- Test home
set client_min_messages to warning;
create extension if not exists pgtap;
reset client_min_messages;
begin;
select plan(30);
set search_path to camper, public;
select has_table('home');
select has_pk('home');
select table_privs_are('home', 'guest', array['SELECT']);
select table_privs_are('home', 'employee', array['SELECT']);
select table_privs_are('home', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']);
select table_privs_are('home', 'authenticator', array[]::text[]);
select has_column('home', 'company_id');
select col_is_pk('home', 'company_id');
select col_is_fk('home', 'company_id');
select fk_ok('home', 'company_id', 'company', 'company_id');
select col_type_is('home', 'company_id', 'integer');
select col_not_null('home', 'company_id');
select col_hasnt_default('home', 'company_id');
select has_column('home', 'slogan');
select col_type_is('home', 'slogan', 'text');
select col_not_null('home', 'slogan');
select col_hasnt_default('home', 'slogan');
set client_min_messages to warning;
truncate home cascade;
truncate company_host cascade;
truncate company_user cascade;
truncate company cascade;
truncate auth."user" cascade;
reset client_min_messages;
insert into auth."user" (user_id, email, name, password, cookie, cookie_expires_at)
values (1, 'demo@tandem.blog', 'Demo', 'test', '44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e', current_timestamp + interval '1 month')
, (5, 'admin@tandem.blog', 'Demo', 'test', '12af4c88b528c2ad4222e3740496ecbc58e76e26f087657524', current_timestamp + interval '1 month')
;
insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag)
values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca')
, (4, 'Company 4', 'XX234', '', '666-666-666', 'b@b', '', '', '', '', '', '', 60, 'FR', 'USD', 'ca')
, (6, 'Company 5', 'XX345', '', '777-777-777', 'c@c', '', '', '', '', '', '', 60, 'FR', 'USD', 'ca')
;
insert into company_user (company_id, user_id, role)
values (2, 1, 'admin')
, (4, 5, 'admin')
;
insert into company_host (company_id, host)
values (2, 'co2')
, (4, 'co4')
;
insert into home (company_id, slogan)
values (2, 'Slogan 2')
, (4, 'Slogan 4')
;
prepare home_data as
select company_id, slogan
from home
order by company_id, slogan;
set role guest;
select bag_eq(
'home_data',
$$ values (2, 'Slogan 2')
, (4, 'Slogan 4')
$$,
'Everyone should be able to list all home texts across all companies'
);
reset role;
select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'co2');
select lives_ok(
$$ delete from home where company_id = 2 $$,
'Admin from company 2 should be able to delete home texts from that company.'
);
select bag_eq(
'home_data',
$$ values (4, 'Slogan 4')
$$,
'The row should have been deleted.'
);
select lives_ok(
$$ insert into home(company_id, slogan) values (2, 'Another Slogan') $$,
'Admin from company 2 should be able to insert a new home texts to that company.'
);
select bag_eq(
'home_data',
$$ values (2, 'Another Slogan')
, (4, 'Slogan 4')
$$,
'The new row should have been added'
);
select lives_ok(
$$ update home set slogan = 'Slogan 2' where company_id = 2 $$,
'Admin from company 2 should be able to update home texts of that company.'
);
select bag_eq(
'home_data',
$$ values (2, 'Slogan 2')
, (4, 'Slogan 4')
$$,
'The row should have been updated.'
);
select throws_ok(
$$ insert into home (company_id, slogan) values (6, 'Slogan 6') $$,
'42501', 'new row violates row-level security policy for table "home"',
'Admin from company 2 should NOT be able to insert new home texts to company 6.'
);
select lives_ok(
$$ update home set slogan = 'Nope' where company_id = 4 $$,
'Admin from company 2 should not be able to update new home texts of company 4, but no error if company_id is not changed.'
);
select bag_eq(
'home_data',
$$ values (2, 'Slogan 2')
, (4, 'Slogan 4')
$$,
'No row should have been changed.'
);
select throws_ok(
$$ update home set company_id = 6 where company_id = 2 $$,
'42501', 'new row violates row-level security policy for table "home"',
'Admin from company 2 should NOT be able to move home texts to company 6'
);
select lives_ok(
$$ delete from home where company_id = 4 $$,
'Admin from company 2 should NOT be able to delete home texts from company 4, but not error is thrown'
);
select bag_eq(
'home_data',
$$ values (2, 'Slogan 2')
, (4, 'Slogan 4')
$$,
'No row should have been changed'
);
reset role;
select *
from finish();
rollback;

44
test/home_i18n.sql Normal file
View File

@ -0,0 +1,44 @@
-- Test home_i18n
set client_min_messages to warning;
create extension if not exists pgtap;
reset client_min_messages;
begin;
select plan(23);
set search_path to camper, public;
select has_table('home_i18n');
select has_pk('home_i18n');
select col_is_pk('home_i18n', array['company_id', 'lang_tag']);
select table_privs_are('home_i18n', 'guest', array['SELECT']);
select table_privs_are('home_i18n', 'employee', array['SELECT']);
select table_privs_are('home_i18n', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']);
select table_privs_are('home_i18n', 'authenticator', array[]::text[]);
select has_column('home_i18n', 'company_id');
select col_is_fk('home_i18n', 'company_id');
select fk_ok('home_i18n', 'company_id', 'home', 'company_id');
select col_type_is('home_i18n', 'company_id', 'integer');
select col_not_null('home_i18n', 'company_id');
select col_hasnt_default('home_i18n', 'company_id');
select has_column('home_i18n', 'lang_tag');
select col_is_fk('home_i18n', 'lang_tag');
select fk_ok('home_i18n', 'lang_tag', 'language', 'lang_tag');
select col_type_is('home_i18n', 'lang_tag', 'text');
select col_not_null('home_i18n', 'lang_tag');
select col_hasnt_default('home_i18n', 'lang_tag');
select has_column('home_i18n', 'slogan');
select col_type_is('home_i18n', 'slogan', 'text');
select col_not_null('home_i18n', 'slogan');
select col_hasnt_default('home_i18n', 'slogan');
select *
from finish();
rollback;

78
test/setup_home.sql Normal file
View File

@ -0,0 +1,78 @@
-- Test setup_home
set client_min_messages to warning;
create extension if not exists pgtap;
reset client_min_messages;
begin;
select plan(15);
set search_path to camper, public;
select has_function('camper', 'setup_home', array['integer', 'text']);
select function_lang_is('camper', 'setup_home', array['integer', 'text'], 'sql');
select function_returns('camper', 'setup_home', array['integer', 'text'], 'void');
select isnt_definer('camper', 'setup_home', array['integer', 'text']);
select volatility_is('camper', 'setup_home', array['integer', 'text'], 'volatile');
select function_privs_are('camper', 'setup_home', array ['integer', 'text'], 'guest', array[]::text[]);
select function_privs_are('camper', 'setup_home', array ['integer', 'text'], 'employee', array[]::text[]);
select function_privs_are('camper', 'setup_home', array ['integer', 'text'], 'admin', array['EXECUTE']);
select function_privs_are('camper', 'setup_home', array ['integer', 'text'], 'authenticator', array[]::text[]);
set client_min_messages to warning;
truncate home 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, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag)
values (1, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca')
, (2, 'Company 4', 'XX234', '', '666-666-666', 'b@b', '', '', '', '', '', '', 60, 'FR', 'USD', 'ca')
;
prepare home_data as
select company_id, slogan
from home
;
select lives_ok(
$$ select setup_home(1, 'Enjoy!') $$,
'Should be able to setup home for the first company'
);
select lives_ok(
$$ select setup_home(2, 'Go Away!') $$,
'Should be able to setup home for the second company'
);
select bag_eq(
'home_data',
$$ values (1, 'Enjoy!')
, (2, 'Go Away!')
$$,
'Should have inserted all home texts'
);
select lives_ok(
$$ select setup_home(1, 'Come Back!') $$,
'Should be able to update home for the first company'
);
select lives_ok(
$$ select setup_home(2, 'Quoi?') $$,
'Should be able to update home for the second company'
);
select bag_eq(
'home_data',
$$ values (1, 'Come Back!')
, (2, 'Quoi?')
$$,
'Should have updated all home texts'
);
select *
from finish();
rollback;

73
test/translate_home.sql Normal file
View File

@ -0,0 +1,73 @@
-- Test translate_home
set client_min_messages to warning;
create extension if not exists pgtap;
reset client_min_messages;
begin;
select plan(13);
set search_path to camper, public;
select has_function('camper', 'translate_home', array['integer', 'text', 'text']);
select function_lang_is('camper', 'translate_home', array['integer', 'text', 'text'], 'sql');
select function_returns('camper', 'translate_home', array['integer', 'text', 'text'], 'void');
select isnt_definer('camper', 'translate_home', array['integer', 'text', 'text']);
select volatility_is('camper', 'translate_home', array['integer', 'text', 'text'], 'volatile');
select function_privs_are('camper', 'translate_home', array['integer', 'text', 'text'], 'guest', array[]::text[]);
select function_privs_are('camper', 'translate_home', array['integer', 'text', 'text'], 'employee', array[]::text[]);
select function_privs_are('camper', 'translate_home', array['integer', 'text', 'text'], 'admin', array['EXECUTE']);
select function_privs_are('camper', 'translate_home', array['integer', 'text', 'text'], 'authenticator', array[]::text[]);
set client_min_messages to warning;
truncate home_i18n cascade;
truncate home 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, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag)
values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca')
, (4, 'Company 4', 'XX234', '', '666-666-666', 'b@b', '', '', '', '', '', '', 60, 'FR', 'USD', 'ca')
;
insert into home (company_id, slogan)
values (2, 'Enjoy')
, (4, 'Away')
;
insert into home_i18n (company_id, lang_tag, slogan)
values (2, 'ca', 'Hola')
, (4, 'ca', 'Hola')
;
select lives_ok(
$$ select translate_home(2, 'es', 'Disfruta') $$,
'Should be able to translate the home of the first company to a new language'
);
select lives_ok(
$$ select translate_home(2, 'ca', 'Gaudeix') $$,
'Should be able to overwrite a homes translation'
);
select lives_ok(
$$ select translate_home(4, 'ca', null) $$,
'Should be able to “translate” a home to empty strings'
);
select bag_eq(
$$ select company_id, lang_tag, slogan from home_i18n $$,
$$ values (2, 'ca', 'Gaudeix')
, (2, 'es', 'Disfruta')
, (4, 'ca', '')
$$,
'Should have translated all home texts'
);
select *
from finish();
rollback;

16
verify/home.sql Normal file
View File

@ -0,0 +1,16 @@
-- Verify camper:home on pg
begin;
select company_id
, slogan
from camper.home
where false;
select 1 / count(*) from pg_class where oid = 'camper.home'::regclass and relrowsecurity;
select 1 / count(*) from pg_policy where polname = 'guest_ok' and polrelid = 'camper.home'::regclass;
select 1 / count(*) from pg_policy where polname = 'insert_to_company' and polrelid = 'camper.home'::regclass;
select 1 / count(*) from pg_policy where polname = 'update_company' and polrelid = 'camper.home'::regclass;
select 1 / count(*) from pg_policy where polname = 'delete_from_company' and polrelid = 'camper.home'::regclass;
rollback;

11
verify/home_i18n.sql Normal file
View File

@ -0,0 +1,11 @@
-- Verify camper:home_i18n on pg
begin;
select company_id
, lang_tag
, slogan
from camper.home_i18n
where false;
rollback;

7
verify/setup_home.sql Normal file
View File

@ -0,0 +1,7 @@
-- Verify camper:setup_home on pg
begin;
select has_function_privilege('camper.setup_home(integer, text)', 'execute');
rollback;

View File

@ -0,0 +1,7 @@
-- Verify camper:translate_home on pg
begin;
select has_function_privilege('camper.translate_home(integer, text, text)', 'execute');
rollback;

View File

@ -11,6 +11,30 @@
{{ define "content" -}} {{ define "content" -}}
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/home.homeIndex*/ -}} {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/home.homeIndex*/ -}}
{{ with .Form }}
<h2>{{( pgettext "Slogan" "title")}}</h2>
<form data-hx-put="/admin/home">
{{ CSRFInput }}
<fieldset {{ template "init-lang" . }}>
{{ with .Slogan -}}
<fieldset>
<legend>{{( pgettext "Slogan" "input")}}</legend>
{{ template "lang-selector" . }}
{{ range $lang, $input := . -}}
<label x-cloak x-show="lang === '{{ $lang }}'"><span>{{ $lang }}</span><br>
<input type="text" name="{{ $input.Name }}" value="{{ $input.Val }}"
{{ template "error-attrs" . }}><br>
</label>
{{- end }}
{{ template "error-message" . }}
</fieldset>
{{- end }}
</fieldset>
<footer>
<button type="submit">{{( pgettext "Update" "action" )}}</button>
</footer>
</form>
{{- end }}
<h2>{{( pgettext "Cover" "title" )}}</h2> <h2>{{( pgettext "Cover" "title" )}}</h2>
<a href="/admin/home/cover/new">{{( pgettext "Add cover image" "action" )}}</a> <a href="/admin/home/cover/new">{{( pgettext "Add cover image" "action" )}}</a>
{{ if .Cover -}} {{ if .Cover -}}

View File

@ -39,7 +39,7 @@
<section class="services"> <section class="services">
<h2><a href="/{{ currentLocale }}/services">{{( gettext "Our services")}} <span>→</span></a></h2> <h2><a href="/{{ currentLocale }}/services">{{( gettext "Our services")}} <span>→</span></a></h2>
</section> </section>
<p class="enjoy">{{( gettext "Come and enjoy!")}}</p> <p class="enjoy">{{ .Slogan }}</p>
<section class="surroundings"> <section class="surroundings">
<h2 class="sr-only">{{( pgettext "Surroundings" "title" )}}</h2> <h2 class="sr-only">{{( pgettext "Surroundings" "title" )}}</h2>
<div class="carousel"> <div class="carousel">