From b1e3f5017fd16ef4aeb70a72dccb93f79215cf1d Mon Sep 17 00:00:00 2001 From: jordi fita mas Date: Tue, 16 Jan 2024 21:05:52 +0100 Subject: [PATCH] =?UTF-8?q?Add=20home=E2=80=99s=20cover=20carousel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a separate carousel from the one displayed at the bottom with location info; it is, i suppose, a carousel for the hero image. For the database, it works exactly as the home carousel, but on the front had to use AlpineJS instead of Slick because it needs to show a text popping up from the bottom when the slide is show, something i do not know how to do in Slick. It now makes no sense to have the carousel inside the “nature” section, because the heading is no longer in there, and moved it out into a new “hero” div. Since i now have two carousels in home, i had to add additional attributes to carousel.AdminHandler to know which URL to point to when POSTing, PUTting, or redirecting. --- demo/demo.sql | 16 ++ deploy/add_cover_carousel_slide.sql | 25 +++ deploy/cover_carousel.sql | 54 ++++++ deploy/cover_carousel_i18n.sql | 22 +++ deploy/order_cover_carousel.sql | 24 +++ deploy/remove_cover_carousel_slide.sql | 22 +++ deploy/translate_cover_carousel_slide.sql | 23 +++ pkg/carousel/admin.go | 24 ++- pkg/home/admin.go | 16 +- pkg/home/public.go | 2 + po/ca.po | 134 ++++++++------- po/es.po | 134 ++++++++------- po/fr.po | 134 ++++++++------- revert/add_cover_carousel_slide.sql | 7 + revert/cover_carousel.sql | 7 + revert/cover_carousel_i18n.sql | 7 + revert/order_cover_carousel.sql | 7 + revert/remove_cover_carousel_slide.sql | 7 + revert/translate_cover_carousel_slide.sql | 7 + sqitch.plan | 6 + test/add_cover_carousel_slide.sql | 82 +++++++++ test/cover_carousel.sql | 192 ++++++++++++++++++++++ test/cover_carousel_i18n.sql | 44 +++++ test/order_cover_carousel.sql | 79 +++++++++ test/remove_cover_carousel_slide.sql | 87 ++++++++++ test/translate_cover_carousel_slide.sql | 85 ++++++++++ verify/add_cover_carousel_slide.sql | 7 + verify/cover_carousel.sql | 17 ++ verify/cover_carousel_i18n.sql | 11 ++ verify/order_cover_carousel.sql | 7 + verify/remove_cover_carousel_slide.sql | 7 + verify/translate_cover_carousel_slide.sql | 7 + web/static/public.css | 116 +++++++++---- web/templates/admin/carousel/form.gohtml | 4 +- web/templates/admin/home/index.gohtml | 45 +++++ web/templates/public/campsite/type.gohtml | 2 +- web/templates/public/home.gohtml | 19 ++- web/templates/public/layout.gohtml | 4 + 38 files changed, 1276 insertions(+), 217 deletions(-) create mode 100644 deploy/add_cover_carousel_slide.sql create mode 100644 deploy/cover_carousel.sql create mode 100644 deploy/cover_carousel_i18n.sql create mode 100644 deploy/order_cover_carousel.sql create mode 100644 deploy/remove_cover_carousel_slide.sql create mode 100644 deploy/translate_cover_carousel_slide.sql create mode 100644 revert/add_cover_carousel_slide.sql create mode 100644 revert/cover_carousel.sql create mode 100644 revert/cover_carousel_i18n.sql create mode 100644 revert/order_cover_carousel.sql create mode 100644 revert/remove_cover_carousel_slide.sql create mode 100644 revert/translate_cover_carousel_slide.sql create mode 100644 test/add_cover_carousel_slide.sql create mode 100644 test/cover_carousel.sql create mode 100644 test/cover_carousel_i18n.sql create mode 100644 test/order_cover_carousel.sql create mode 100644 test/remove_cover_carousel_slide.sql create mode 100644 test/translate_cover_carousel_slide.sql create mode 100644 verify/add_cover_carousel_slide.sql create mode 100644 verify/cover_carousel.sql create mode 100644 verify/cover_carousel_i18n.sql create mode 100644 verify/order_cover_carousel.sql create mode 100644 verify/remove_cover_carousel_slide.sql create mode 100644 verify/translate_cover_carousel_slide.sql diff --git a/demo/demo.sql b/demo/demo.sql index 55775d2..05b065b 100644 --- a/demo/demo.sql +++ b/demo/demo.sql @@ -74,6 +74,22 @@ select add_media(52, 'wooden_lodges_carouselA.avif', 'image/avif', decode('m4_es select add_media(52, 'wooden_lodges_carouselB.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/wooden_lodges_carouselB.avif]])', 'base64')); select add_media(52, 'wooden_lodges_carouselC.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/wooden_lodges_carouselC.avif]])', 'base64')); + +select add_cover_carousel_slide(62, 'Qualitat Calma Natura'); +select add_cover_carousel_slide(63, 'El plaer d’acampar en plena natura…'); +select add_cover_carousel_slide(64, '…amb serveis de 1r. classe'); +select order_cover_carousel('{62, 63, 64}'); + +select translate_cover_carousel_slide(62, 'en', 'Quality Calm Nature'); +select translate_cover_carousel_slide(63, 'en', 'The pleasure to camp in the middle of nature…'); +select translate_cover_carousel_slide(64, 'en', '…with 1st. class services'); +select translate_cover_carousel_slide(62, 'es', 'Calidad Calma Naturaleza'); +select translate_cover_carousel_slide(63, 'es', 'El placer de acampar en medio de la naturaleza…'); +select translate_cover_carousel_slide(64, 'es', '…con servicios de 1ª categoría.'); +select translate_cover_carousel_slide(62, 'fr', 'Qualité Calme Nature'); +select translate_cover_carousel_slide(63, 'fr', 'Le plaisir de camper en pleine nature …'); +select translate_cover_carousel_slide(64, 'fr', '… services de 1ère. ordre'); + select add_home_carousel_slide(67, 'Volcà de Santa Margarida'); select add_home_carousel_slide(68, 'Gorga fosca Sadernes'); select add_home_carousel_slide(69, 'Castellfollit de la Roca'); diff --git a/deploy/add_cover_carousel_slide.sql b/deploy/add_cover_carousel_slide.sql new file mode 100644 index 0000000..29913de --- /dev/null +++ b/deploy/add_cover_carousel_slide.sql @@ -0,0 +1,25 @@ +-- Deploy camper:add_cover_carousel_slide to pg +-- requires: roles +-- requires: schema_camper +-- requires: cover_carousel + +begin; + +set search_path to camper, public; + +create or replace function add_cover_carousel_slide(media_id integer, caption text) returns integer as +$$ + insert into cover_carousel (media_id, caption) + values (media_id, coalesce(caption, '')) + on conflict (media_id) do update + set caption = excluded.caption + returning media_id + ; +$$ + language sql +; + +revoke execute on function add_cover_carousel_slide(integer, text) from public; +grant execute on function add_cover_carousel_slide(integer, text) to admin; + +commit; diff --git a/deploy/cover_carousel.sql b/deploy/cover_carousel.sql new file mode 100644 index 0000000..af43ae4 --- /dev/null +++ b/deploy/cover_carousel.sql @@ -0,0 +1,54 @@ +-- Deploy camper:cover_carousel to pg +-- requires: roles +-- requires: schema_camper +-- requires: company +-- requires: media +-- requires: user_profile + +begin; + +set search_path to camper, public; + +create table cover_carousel ( + media_id integer not null references media primary key, + caption text not null, + position integer not null default 2147483647 +); + +grant select on table cover_carousel to guest; +grant select on table cover_carousel to employee; +grant select, insert, update, delete on table cover_carousel to admin; + +alter table cover_carousel enable row level security; + +create policy guest_ok +on cover_carousel +for select +using (true) +; + +create policy insert_to_company +on cover_carousel +for insert +with check ( + exists (select 1 from media join user_profile using (company_id) where media.media_id = cover_carousel.media_id) +) +; + +create policy update_company +on cover_carousel +for update +using ( + exists (select 1 from media join user_profile using (company_id) where media.media_id = cover_carousel.media_id) +) +; + +create policy delete_from_company +on cover_carousel +for delete +using ( + exists (select 1 from media join user_profile using (company_id) where media.media_id = cover_carousel.media_id) +) +; + +commit; diff --git a/deploy/cover_carousel_i18n.sql b/deploy/cover_carousel_i18n.sql new file mode 100644 index 0000000..26c037f --- /dev/null +++ b/deploy/cover_carousel_i18n.sql @@ -0,0 +1,22 @@ +-- Deploy camper:cover_carousel_i18n to pg +-- requires: roles +-- requires: schema_camper +-- requires: cover_carousel +-- requires: language + +begin; + +set search_path to camper, public; + +create table cover_carousel_i18n ( + media_id integer not null references cover_carousel, + lang_tag text not null references language, + caption text not null, + primary key (media_id, lang_tag) +); + +grant select on table cover_carousel_i18n to guest; +grant select on table cover_carousel_i18n to employee; +grant select, insert, update, delete on table cover_carousel_i18n to admin; + +commit; diff --git a/deploy/order_cover_carousel.sql b/deploy/order_cover_carousel.sql new file mode 100644 index 0000000..8620af1 --- /dev/null +++ b/deploy/order_cover_carousel.sql @@ -0,0 +1,24 @@ +-- Deploy camper:order_cover_carousel to pg +-- requires: schema_camper +-- requires: roles +-- requires: cover_carousel + +begin; + +set search_path to camper, public; + +create or replace function order_cover_carousel(positions integer[]) returns void as +$$ + update cover_carousel + set position = cast(temp.position as integer) + from unnest(positions) with ordinality as temp(media_id, position) + where cover_carousel.media_id = temp.media_id + ; +$$ + language sql +; + +revoke execute on function order_cover_carousel(integer[]) from public; +grant execute on function order_cover_carousel(integer[]) to admin; + +commit; diff --git a/deploy/remove_cover_carousel_slide.sql b/deploy/remove_cover_carousel_slide.sql new file mode 100644 index 0000000..2cad52b --- /dev/null +++ b/deploy/remove_cover_carousel_slide.sql @@ -0,0 +1,22 @@ +-- Deploy camper:remove_cover_carousel_slide to pg +-- requires: roles +-- requires: schema_camper +-- requires: cover_carousel +-- requires: cover_carousel_i18n + +begin; + +set search_path to camper, public; + +create or replace function remove_cover_carousel_slide (media_id integer) returns void as +$$ + delete from cover_carousel_i18n where media_id = $1; + delete from cover_carousel where media_id = $1; +$$ + language sql +; + +revoke execute on function remove_cover_carousel_slide (integer) from public; +grant execute on function remove_cover_carousel_slide (integer) to admin; + +commit; diff --git a/deploy/translate_cover_carousel_slide.sql b/deploy/translate_cover_carousel_slide.sql new file mode 100644 index 0000000..5c195ef --- /dev/null +++ b/deploy/translate_cover_carousel_slide.sql @@ -0,0 +1,23 @@ +-- Deploy camper:translate_cover_carousel_slide to pg +-- requires: roles +-- requires: schema_camper +-- requires: cover_carousel_i18n + +begin; + +set search_path to camper, public; + +create or replace function translate_cover_carousel_slide (media_id integer, lang_tag text, caption text) returns void as +$$ + insert into cover_carousel_i18n (media_id, lang_tag, caption) + values (media_id, lang_tag, coalesce(caption, '')) + on conflict (media_id, lang_tag) do update + set caption = excluded.caption +$$ + language sql +; + +revoke execute on function translate_cover_carousel_slide(integer, text, text) from public; +grant execute on function translate_cover_carousel_slide(integer, text, text) to admin; + +commit; diff --git a/pkg/carousel/admin.go b/pkg/carousel/admin.go index b1817e3..352526d 100644 --- a/pkg/carousel/admin.go +++ b/pkg/carousel/admin.go @@ -22,6 +22,8 @@ import ( ) type AdminHandler struct { + IndexURL string + SlidesURL string name string indexHandler IndexHandler } @@ -30,6 +32,8 @@ type IndexHandler func(w http.ResponseWriter, r *http.Request, user *auth.User, func NewAdminHandler(name string, indexHandler IndexHandler) *AdminHandler { return &AdminHandler{ + IndexURL: "/admin/" + name, + SlidesURL: "/admin/" + name + "/slides", name: name, indexHandler: indexHandler, } @@ -44,14 +48,14 @@ func (h *AdminHandler) Handler(user *auth.User, company *auth.Company, conn *dat case "": switch r.Method { case http.MethodPost: - addSlide(w, r, user, company, conn, h.name) + addSlide(w, r, user, company, conn, h.name, h.IndexURL, h.SlidesURL) default: httplib.MethodNotAllowed(w, r, http.MethodPost) } case "new": switch r.Method { case http.MethodGet: - f := newSlideForm(h.name, company) + f := newSlideForm(h.name, h.IndexURL, h.SlidesURL, company) f.MustRender(w, r, user, company) default: httplib.MethodNotAllowed(w, r, http.MethodGet) @@ -69,7 +73,7 @@ func (h *AdminHandler) Handler(user *auth.User, company *auth.Company, conn *dat http.NotFound(w, r) return } - f := newSlideForm(h.name, company) + f := newSlideForm(h.name, h.IndexURL, h.SlidesURL, company) if err := f.FillFromDatabase(r.Context(), conn, id); err != nil { if database.ErrorIsNotFound(err) { http.NotFound(w, r) @@ -194,8 +198,8 @@ func CollectSlideEntries(ctx context.Context, company *auth.Company, conn *datab return slides, nil } -func addSlide(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, carouselName string) { - f := newSlideForm(carouselName, company) +func addSlide(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, carouselName string, indexURL, baseURL string) { + f := newSlideForm(carouselName, indexURL, baseURL, company) f.process(w, r, user, company, conn, func(ctx context.Context, tx *database.Tx) error { var err error if f.ID, err = tx.GetInt(ctx, fmt.Sprintf("select add_%s_carousel_slide($1, $2)", f.CarouselName), f.Media, f.Caption[f.DefaultLang]); err != nil { @@ -245,21 +249,25 @@ func (h *AdminHandler) deleteSlide(w http.ResponseWriter, r *http.Request, user return } conn.MustExec(r.Context(), fmt.Sprintf("select remove_%s_carousel_slide($1)", h.name), id) - httplib.Redirect(w, r, "/admin/"+h.name, http.StatusSeeOther) + httplib.Redirect(w, r, h.IndexURL, http.StatusSeeOther) } type slideForm struct { DefaultLang string CarouselName string + IndexURL string + SlidesURL string ID int Media *form.Media Caption form.I18nInput } -func newSlideForm(carouselName string, company *auth.Company) *slideForm { +func newSlideForm(carouselName string, indexURL string, baseURL string, company *auth.Company) *slideForm { return &slideForm{ DefaultLang: company.DefaultLanguage.String(), CarouselName: carouselName, + IndexURL: indexURL, + SlidesURL: baseURL, Media: &form.Media{ Input: &form.Input{ Name: "media", @@ -320,7 +328,7 @@ func (f *slideForm) process(w http.ResponseWriter, r *http.Request, user *auth.U } panic(err) } - httplib.Redirect(w, r, "/admin/"+f.CarouselName, http.StatusSeeOther) + httplib.Redirect(w, r, f.IndexURL, http.StatusSeeOther) } func (f *slideForm) Parse(r *http.Request) error { diff --git a/pkg/home/admin.go b/pkg/home/admin.go index 297e4db..feff8c0 100644 --- a/pkg/home/admin.go +++ b/pkg/home/admin.go @@ -15,16 +15,22 @@ import ( "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 { - return &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 { @@ -40,6 +46,8 @@ func (h *AdminHandler) Handler(user *auth.User, company *auth.Company, conn *dat default: httplib.MethodNotAllowed(w, r, http.MethodGet) } + case "cover": + h.cover.Handler(user, company, conn).ServeHTTP(w, r) case "slides": h.carousel.Handler(user, company, conn).ServeHTTP(w, r) default: @@ -49,17 +57,23 @@ 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) { + 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{ + Cover: cover, Slides: slides, } page.MustRender(w, r, user, company) } type homeIndex struct { + Cover []*carousel.SlideEntry Slides []*carousel.SlideEntry } diff --git a/pkg/home/public.go b/pkg/home/public.go index 347a3b9..9c21394 100644 --- a/pkg/home/public.go +++ b/pkg/home/public.go @@ -38,6 +38,7 @@ func (h *PublicHandler) Handler(user *auth.User, company *auth.Company, conn *da type homePage struct { *template.PublicPage + Cover []*carousel.Slide CampsiteTypes []*campsiteType Carousel []*carousel.Slide } @@ -49,6 +50,7 @@ func newHomePage() *homePage { 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) p.CampsiteTypes = mustCollectCampsiteTypes(r.Context(), company, conn, user.Locale) + p.Cover = carousel.MustCollectSlides(r.Context(), company, conn, user.Locale, coverName) p.Carousel = carousel.MustCollectSlides(r.Context(), company, conn, user.Locale, carouselName) template.MustRenderPublic(w, r, user, company, "home.gohtml", p) } diff --git a/po/ca.po b/po/ca.po index 63779b8..d85ecaf 100644 --- a/po/ca.po +++ b/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: 2024-01-16 00:48+0100\n" +"POT-Creation-Date: 2024-01-16 20:32+0100\n" "PO-Revision-Date: 2023-07-22 23:45+0200\n" "Last-Translator: jordi fita mas \n" "Language-Team: Catalan \n" @@ -41,71 +41,71 @@ msgctxt "title" msgid "Payment Failed" msgstr "Ha fallat el pagament" -#: web/templates/public/services.gohtml:6 -#: web/templates/public/services.gohtml:15 -#: web/templates/public/layout.gohtml:66 web/templates/public/layout.gohtml:94 +#: web/templates/public/services.gohtml:7 +#: web/templates/public/services.gohtml:16 +#: web/templates/public/layout.gohtml:67 web/templates/public/layout.gohtml:95 #: web/templates/admin/services/index.gohtml:56 msgctxt "title" msgid "Services" msgstr "Serveis" -#: web/templates/public/services.gohtml:18 +#: web/templates/public/services.gohtml:19 msgid "The campsite offers many different services." msgstr "El càmping disposa de diversos serveis." -#: web/templates/public/location.gohtml:6 -#: web/templates/public/location.gohtml:12 -#: web/templates/public/layout.gohtml:68 web/templates/public/layout.gohtml:96 +#: web/templates/public/location.gohtml:7 +#: web/templates/public/location.gohtml:13 +#: web/templates/public/layout.gohtml:69 web/templates/public/layout.gohtml:97 #: web/templates/admin/layout.gohtml:61 msgctxt "title" msgid "Location" msgstr "Com arribar" -#: web/templates/public/home.gohtml:6 web/templates/public/layout.gohtml:52 -#: web/templates/public/layout.gohtml:92 +#: web/templates/public/home.gohtml:7 web/templates/public/layout.gohtml:53 +#: web/templates/public/layout.gohtml:93 msgctxt "title" msgid "Home" msgstr "Inici" -#: web/templates/public/home.gohtml:17 -msgid "The pleasure of camping in the middle of nature…" -msgstr "El plaer d’acampar en plena natura…" - -#: web/templates/public/home.gohtml:18 +#: web/templates/public/home.gohtml:24 msgctxt "link" msgid "Booking" msgstr "Reserva" #: web/templates/public/home.gohtml:31 +msgid "The pleasure of camping in the middle of nature…" +msgstr "El plaer d’acampar en plena natura…" + +#: web/templates/public/home.gohtml:43 msgid "Our services" msgstr "Els nostres serveis" -#: web/templates/public/home.gohtml:33 +#: web/templates/public/home.gohtml:45 msgid "Come and enjoy!" msgstr "Vine a gaudir!" -#: web/templates/public/home.gohtml:35 -#: web/templates/public/surroundings.gohtml:6 -#: web/templates/public/surroundings.gohtml:11 -#: web/templates/public/layout.gohtml:67 web/templates/public/layout.gohtml:95 +#: web/templates/public/home.gohtml:47 +#: web/templates/public/surroundings.gohtml:7 +#: web/templates/public/surroundings.gohtml:12 +#: web/templates/public/layout.gohtml:68 web/templates/public/layout.gohtml:96 #: web/templates/admin/layout.gohtml:64 msgctxt "title" msgid "Surroundings" msgstr "L’entorn" -#: web/templates/public/home.gohtml:38 +#: web/templates/public/home.gohtml:50 msgid "Located in Alta Garrotxa, between the Pyrenees and the Costa Brava." msgstr "Situats a l’Alta Garrotxa, entre els Pirineus i la Costa Brava." -#: web/templates/public/home.gohtml:39 +#: web/templates/public/home.gohtml:51 msgid "Nearby there are the gorges of Sadernes, volcanoes, La Fageda d’en Jordà, the Jewish quarter of Besalú, the basaltic cliff of Castellfollit de la Roca… much to see and much to do." msgstr "A prop teniu els gorgs de Sadernes, volcans, La Fageda d’en Jordà, el call jueu de Besalú, la cinglera basàltica de Castellfollit de la Roca… molt per veure i molt per fer." -#: web/templates/public/home.gohtml:40 +#: web/templates/public/home.gohtml:52 msgid "Less than an hour from Girona, one from La Bisbal d’Empordà, and two from Barcelona." msgstr "A menys d’una hora de Girona, a una de La Bisbal d’Empordà i a dues de Barcelona." -#: web/templates/public/home.gohtml:41 +#: web/templates/public/home.gohtml:53 msgid "Discover the surroundings" msgstr "Descobreix l’entorn" @@ -252,57 +252,57 @@ msgctxt "day" msgid "Sun" msgstr "dg" -#: web/templates/public/surroundings.gohtml:31 +#: web/templates/public/surroundings.gohtml:32 msgctxt "title" msgid "What to Do Outside the Campsite?" msgstr "Què fer des del càmping?" -#: web/templates/public/surroundings.gohtml:51 +#: web/templates/public/surroundings.gohtml:52 msgctxt "title" msgid "Once at the Campsite, We Can Inform You about What Activities are Available" msgstr "Un cop en el càmping, us podem informar de quines activitats fer" -#: web/templates/public/surroundings.gohtml:54 +#: web/templates/public/surroundings.gohtml:55 msgid "Cycle routes" msgstr "Rutes amb bicicleta" -#: web/templates/public/surroundings.gohtml:55 +#: web/templates/public/surroundings.gohtml:56 msgid "There are many bicycle rental companies in Olot." msgstr "A Olot podeu trobar empreses de lloguer de bicicletes." -#: web/templates/public/surroundings.gohtml:59 +#: web/templates/public/surroundings.gohtml:60 msgid "Routes" msgstr "Rutes" -#: web/templates/public/surroundings.gohtml:60 +#: web/templates/public/surroundings.gohtml:61 msgid "Routes of all kinds, climbing, mountain passes, for all levels." msgstr "Rutes de tota mena, escalada, ports de muntanya, per a tots els nivells." -#: web/templates/public/surroundings.gohtml:64 +#: web/templates/public/surroundings.gohtml:65 msgid "Family outing" msgstr "Excursions familiars" -#: web/templates/public/surroundings.gohtml:65 +#: web/templates/public/surroundings.gohtml:66 msgid "Many outing possibilities, for all ages." msgstr "Múltiples excursions per a totes les edats." -#: web/templates/public/surroundings.gohtml:69 +#: web/templates/public/surroundings.gohtml:70 msgid "Kayak" msgstr "Caiac" -#: web/templates/public/surroundings.gohtml:70 +#: web/templates/public/surroundings.gohtml:71 msgid "There are several points where you can go by kayak, from sections of the Ter river as well as on the coast…." msgstr "Hi ha diversos punts on poder anar amb caiac, des de trams del riu Ter com també a la costa…." -#: web/templates/public/campground.gohtml:6 -#: web/templates/public/campground.gohtml:15 -#: web/templates/public/layout.gohtml:53 web/templates/public/layout.gohtml:93 +#: web/templates/public/campground.gohtml:7 +#: web/templates/public/campground.gohtml:16 +#: web/templates/public/layout.gohtml:54 web/templates/public/layout.gohtml:94 msgctxt "title" msgid "Campground" msgstr "El càmping" #: web/templates/public/booking.gohtml:6 web/templates/public/booking.gohtml:11 -#: web/templates/public/layout.gohtml:69 +#: web/templates/public/layout.gohtml:70 msgctxt "title" msgid "Booking" msgstr "Reserva" @@ -390,20 +390,20 @@ msgctxt "input" msgid "I have read and I accept the reservation conditions" msgstr "He llegit i accepto les condicions de reserves" -#: web/templates/public/layout.gohtml:11 web/templates/public/layout.gohtml:47 -#: web/templates/public/layout.gohtml:130 +#: web/templates/public/layout.gohtml:12 web/templates/public/layout.gohtml:48 +#: web/templates/public/layout.gohtml:131 msgid "Campsite Montagut" msgstr "Càmping Montagut" -#: web/templates/public/layout.gohtml:23 web/templates/admin/layout.gohtml:21 +#: web/templates/public/layout.gohtml:24 web/templates/admin/layout.gohtml:21 msgid "Skip to main content" msgstr "Salta al contingut principal" -#: web/templates/public/layout.gohtml:49 +#: web/templates/public/layout.gohtml:50 msgid "Menu" msgstr "Menú" -#: web/templates/public/layout.gohtml:57 web/templates/public/layout.gohtml:103 +#: web/templates/public/layout.gohtml:58 web/templates/public/layout.gohtml:104 #: web/templates/admin/campsite/index.gohtml:6 #: web/templates/admin/campsite/index.gohtml:12 #: web/templates/admin/layout.gohtml:46 web/templates/admin/layout.gohtml:86 @@ -411,17 +411,17 @@ msgctxt "title" msgid "Campsites" msgstr "Allotjaments" -#: web/templates/public/layout.gohtml:90 +#: web/templates/public/layout.gohtml:91 msgctxt "title" msgid "Sections" msgstr "Apartats" -#: web/templates/public/layout.gohtml:114 +#: web/templates/public/layout.gohtml:115 msgctxt "title" msgid "Opening" msgstr "Obertura" -#: web/templates/public/layout.gohtml:121 +#: web/templates/public/layout.gohtml:122 msgid "RTC #%s" msgstr "Núm. RTC %s" @@ -612,7 +612,7 @@ msgstr "Carrusel del tipus d’allotjament" #: web/templates/admin/campsite/carousel/index.gohtml:12 #: web/templates/admin/services/index.gohtml:12 -#: web/templates/admin/home/index.gohtml:12 +#: web/templates/admin/home/index.gohtml:57 msgctxt "action" msgid "Add slide" msgstr "Afegeix diapositiva" @@ -621,6 +621,7 @@ msgstr "Afegeix diapositiva" #: web/templates/admin/services/index.gohtml:25 #: web/templates/admin/surroundings/index.gohtml:25 #: web/templates/admin/home/index.gohtml:25 +#: web/templates/admin/home/index.gohtml:70 msgctxt "header" msgid "Image" msgstr "Imatge" @@ -628,6 +629,7 @@ msgstr "Imatge" #: web/templates/admin/campsite/carousel/index.gohtml:26 #: web/templates/admin/services/index.gohtml:26 #: web/templates/admin/home/index.gohtml:26 +#: web/templates/admin/home/index.gohtml:71 msgctxt "header" msgid "Caption" msgstr "Llegenda" @@ -637,13 +639,14 @@ msgstr "Llegenda" #: web/templates/admin/services/index.gohtml:72 #: web/templates/admin/surroundings/index.gohtml:27 #: web/templates/admin/home/index.gohtml:27 +#: web/templates/admin/home/index.gohtml:72 msgctxt "header" msgid "Actions" msgstr "Accions" #: web/templates/admin/campsite/carousel/index.gohtml:31 #: web/templates/admin/services/index.gohtml:31 -#: web/templates/admin/home/index.gohtml:31 +#: web/templates/admin/home/index.gohtml:76 msgid "Are you sure you wish to delete this slide?" msgstr "Esteu segur de voler esborrar aquesta diapositiva?" @@ -652,13 +655,14 @@ msgstr "Esteu segur de voler esborrar aquesta diapositiva?" #: web/templates/admin/services/index.gohtml:88 #: web/templates/admin/surroundings/index.gohtml:44 #: web/templates/admin/home/index.gohtml:44 +#: web/templates/admin/home/index.gohtml:89 msgctxt "action" msgid "Delete" msgstr "Esborra" #: web/templates/admin/campsite/carousel/index.gohtml:54 #: web/templates/admin/services/index.gohtml:53 -#: web/templates/admin/home/index.gohtml:53 +#: web/templates/admin/home/index.gohtml:98 msgid "No slides added yet." msgstr "No s’ha afegit cap diapositiva encara." @@ -1000,7 +1004,7 @@ msgid "Services Page" msgstr "Pàgina de serveis" #: web/templates/admin/services/index.gohtml:11 -#: web/templates/admin/home/index.gohtml:11 +#: web/templates/admin/home/index.gohtml:56 msgctxt "title" msgid "Carousel" msgstr "Carrusel" @@ -1198,6 +1202,24 @@ msgctxt "action" msgid "Logout" msgstr "Surt" +#: web/templates/admin/home/index.gohtml:11 +msgctxt "title" +msgid "Cover" +msgstr "Portada" + +#: web/templates/admin/home/index.gohtml:12 +msgctxt "action" +msgid "Add cover image" +msgstr "Afegeix imatge de portada" + +#: web/templates/admin/home/index.gohtml:31 +msgid "Are you sure you wish to delete this cover image?" +msgstr "Esteu segur de voler esborrar aquesta imatge de portada?" + +#: web/templates/admin/home/index.gohtml:53 +msgid "No images added to the cover yet." +msgstr "No s’ha afegit cap imatge de portada encara." + #: web/templates/admin/media/picker.gohtml:8 msgctxt "title" msgid "Media Picker" @@ -1265,7 +1287,7 @@ msgstr "Pujada de mèdia" #: pkg/legal/admin.go:258 pkg/app/user.go:249 pkg/campsite/types/option.go:344 #: pkg/campsite/types/feature.go:259 pkg/campsite/types/admin.go:463 -#: pkg/season/admin.go:412 pkg/services/admin.go:314 +#: pkg/season/admin.go:412 pkg/services/admin.go:316 #: pkg/surroundings/admin.go:321 msgid "Name can not be empty." msgstr "No podeu deixar el nom en blanc." @@ -1275,22 +1297,22 @@ msgstr "No podeu deixar el nom en blanc." msgid "Name must have at least one letter." msgstr "El nom ha de tenir com a mínim una lletra." -#: pkg/carousel/admin.go:267 pkg/campsite/types/carousel.go:223 +#: pkg/carousel/admin.go:275 pkg/campsite/types/carousel.go:223 msgctxt "input" msgid "Slide image" msgstr "Imatge de la diapositiva" -#: pkg/carousel/admin.go:268 pkg/campsite/types/carousel.go:224 +#: pkg/carousel/admin.go:276 pkg/campsite/types/carousel.go:224 msgctxt "action" msgid "Set slide image" msgstr "Estableix la imatge de la diapositiva" -#: pkg/carousel/admin.go:337 pkg/campsite/types/carousel.go:297 +#: pkg/carousel/admin.go:345 pkg/campsite/types/carousel.go:297 #: pkg/surroundings/admin.go:316 msgid "Slide image can not be empty." msgstr "No podeu deixar la imatge de la diapositiva en blanc." -#: pkg/carousel/admin.go:338 pkg/campsite/types/carousel.go:298 +#: pkg/carousel/admin.go:346 pkg/campsite/types/carousel.go:298 #: pkg/surroundings/admin.go:317 msgid "Slide image must be an image media type." msgstr "La imatge de la diapositiva ha de ser un mèdia de tipus imatge." @@ -1370,7 +1392,7 @@ msgstr "El preu per nit ha de ser un número decimal." msgid "Price per night must be zero or greater." msgstr "El preu per nit ha de ser com a mínim zero." -#: pkg/campsite/types/feature.go:258 pkg/services/admin.go:313 +#: pkg/campsite/types/feature.go:258 pkg/services/admin.go:315 msgid "Selected icon is not valid." msgstr "La icona escollida no és vàlida." diff --git a/po/es.po b/po/es.po index 1f58f23..db83867 100644 --- a/po/es.po +++ b/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: 2024-01-16 00:48+0100\n" +"POT-Creation-Date: 2024-01-16 20:32+0100\n" "PO-Revision-Date: 2023-07-22 23:46+0200\n" "Last-Translator: jordi fita mas \n" "Language-Team: Spanish \n" @@ -41,71 +41,71 @@ msgctxt "title" msgid "Payment Failed" msgstr "Pago fallido" -#: web/templates/public/services.gohtml:6 -#: web/templates/public/services.gohtml:15 -#: web/templates/public/layout.gohtml:66 web/templates/public/layout.gohtml:94 +#: web/templates/public/services.gohtml:7 +#: web/templates/public/services.gohtml:16 +#: web/templates/public/layout.gohtml:67 web/templates/public/layout.gohtml:95 #: web/templates/admin/services/index.gohtml:56 msgctxt "title" msgid "Services" msgstr "Servicios" -#: web/templates/public/services.gohtml:18 +#: web/templates/public/services.gohtml:19 msgid "The campsite offers many different services." msgstr "El camping dispone de varios servicios." -#: web/templates/public/location.gohtml:6 -#: web/templates/public/location.gohtml:12 -#: web/templates/public/layout.gohtml:68 web/templates/public/layout.gohtml:96 +#: web/templates/public/location.gohtml:7 +#: web/templates/public/location.gohtml:13 +#: web/templates/public/layout.gohtml:69 web/templates/public/layout.gohtml:97 #: web/templates/admin/layout.gohtml:61 msgctxt "title" msgid "Location" msgstr "Cómo llegar" -#: web/templates/public/home.gohtml:6 web/templates/public/layout.gohtml:52 -#: web/templates/public/layout.gohtml:92 +#: web/templates/public/home.gohtml:7 web/templates/public/layout.gohtml:53 +#: web/templates/public/layout.gohtml:93 msgctxt "title" msgid "Home" msgstr "Inicio" -#: web/templates/public/home.gohtml:17 -msgid "The pleasure of camping in the middle of nature…" -msgstr "El placer de acampar en plena naturaleza…" - -#: web/templates/public/home.gohtml:18 +#: web/templates/public/home.gohtml:24 msgctxt "link" msgid "Booking" msgstr "Reservar" #: web/templates/public/home.gohtml:31 +msgid "The pleasure of camping in the middle of nature…" +msgstr "El placer de acampar en plena naturaleza…" + +#: web/templates/public/home.gohtml:43 msgid "Our services" msgstr "Nuestros servicios" -#: web/templates/public/home.gohtml:33 +#: web/templates/public/home.gohtml:45 msgid "Come and enjoy!" msgstr "¡Ven a disfrutar!" -#: web/templates/public/home.gohtml:35 -#: web/templates/public/surroundings.gohtml:6 -#: web/templates/public/surroundings.gohtml:11 -#: web/templates/public/layout.gohtml:67 web/templates/public/layout.gohtml:95 +#: web/templates/public/home.gohtml:47 +#: web/templates/public/surroundings.gohtml:7 +#: web/templates/public/surroundings.gohtml:12 +#: web/templates/public/layout.gohtml:68 web/templates/public/layout.gohtml:96 #: web/templates/admin/layout.gohtml:64 msgctxt "title" msgid "Surroundings" msgstr "El entorno" -#: web/templates/public/home.gohtml:38 +#: web/templates/public/home.gohtml:50 msgid "Located in Alta Garrotxa, between the Pyrenees and the Costa Brava." msgstr "Situados en la Alta Garrotxa, entre los Pirineos y la Costa Brava." -#: web/templates/public/home.gohtml:39 +#: web/templates/public/home.gohtml:51 msgid "Nearby there are the gorges of Sadernes, volcanoes, La Fageda d’en Jordà, the Jewish quarter of Besalú, the basaltic cliff of Castellfollit de la Roca… much to see and much to do." msgstr "Cerca tenéis los piletones de Sadernes, volcanes, La Fageda d’en Jordà, la judería de Besalú, el riscal basáltico de Castellfollit de la Roca… mucho por ver y mucho por hacer." -#: web/templates/public/home.gohtml:40 +#: web/templates/public/home.gohtml:52 msgid "Less than an hour from Girona, one from La Bisbal d’Empordà, and two from Barcelona." msgstr "A menos de una hora de Girona, a una de La Bisbal d’Empordà y a dos de Barcelona." -#: web/templates/public/home.gohtml:41 +#: web/templates/public/home.gohtml:53 msgid "Discover the surroundings" msgstr "Descubre el entorno" @@ -252,57 +252,57 @@ msgctxt "day" msgid "Sun" msgstr "do" -#: web/templates/public/surroundings.gohtml:31 +#: web/templates/public/surroundings.gohtml:32 msgctxt "title" msgid "What to Do Outside the Campsite?" msgstr "¿Qué hacer desde el camping?" -#: web/templates/public/surroundings.gohtml:51 +#: web/templates/public/surroundings.gohtml:52 msgctxt "title" msgid "Once at the Campsite, We Can Inform You about What Activities are Available" msgstr "Una vez en el camping, os podemos informar de qué actividades hacer" -#: web/templates/public/surroundings.gohtml:54 +#: web/templates/public/surroundings.gohtml:55 msgid "Cycle routes" msgstr "Rutas en bicicleta" -#: web/templates/public/surroundings.gohtml:55 +#: web/templates/public/surroundings.gohtml:56 msgid "There are many bicycle rental companies in Olot." msgstr "A Olot podéis encontrar empresas de alquiler de bicicletas." -#: web/templates/public/surroundings.gohtml:59 +#: web/templates/public/surroundings.gohtml:60 msgid "Routes" msgstr "Rutas" -#: web/templates/public/surroundings.gohtml:60 +#: web/templates/public/surroundings.gohtml:61 msgid "Routes of all kinds, climbing, mountain passes, for all levels." msgstr "Rutas de todo tipo, escalada, puertos de montaña, para todos los niveles." -#: web/templates/public/surroundings.gohtml:64 +#: web/templates/public/surroundings.gohtml:65 msgid "Family outing" msgstr "Excusiones familiares" -#: web/templates/public/surroundings.gohtml:65 +#: web/templates/public/surroundings.gohtml:66 msgid "Many outing possibilities, for all ages." msgstr "Múltiples excursiones para todas las edades." -#: web/templates/public/surroundings.gohtml:69 +#: web/templates/public/surroundings.gohtml:70 msgid "Kayak" msgstr "Kayak" -#: web/templates/public/surroundings.gohtml:70 +#: web/templates/public/surroundings.gohtml:71 msgid "There are several points where you can go by kayak, from sections of the Ter river as well as on the coast…." msgstr "Hay diversos puntos dónde podéis ir en kayak, desde tramos del río Ter como también en la costa…." -#: web/templates/public/campground.gohtml:6 -#: web/templates/public/campground.gohtml:15 -#: web/templates/public/layout.gohtml:53 web/templates/public/layout.gohtml:93 +#: web/templates/public/campground.gohtml:7 +#: web/templates/public/campground.gohtml:16 +#: web/templates/public/layout.gohtml:54 web/templates/public/layout.gohtml:94 msgctxt "title" msgid "Campground" msgstr "El camping" #: web/templates/public/booking.gohtml:6 web/templates/public/booking.gohtml:11 -#: web/templates/public/layout.gohtml:69 +#: web/templates/public/layout.gohtml:70 msgctxt "title" msgid "Booking" msgstr "Reserva" @@ -390,20 +390,20 @@ msgctxt "input" msgid "I have read and I accept the reservation conditions" msgstr "He leído y acepto las condiciones de reserva" -#: web/templates/public/layout.gohtml:11 web/templates/public/layout.gohtml:47 -#: web/templates/public/layout.gohtml:130 +#: web/templates/public/layout.gohtml:12 web/templates/public/layout.gohtml:48 +#: web/templates/public/layout.gohtml:131 msgid "Campsite Montagut" msgstr "Camping Montagut" -#: web/templates/public/layout.gohtml:23 web/templates/admin/layout.gohtml:21 +#: web/templates/public/layout.gohtml:24 web/templates/admin/layout.gohtml:21 msgid "Skip to main content" msgstr "Saltar al contenido principal" -#: web/templates/public/layout.gohtml:49 +#: web/templates/public/layout.gohtml:50 msgid "Menu" msgstr "Menú" -#: web/templates/public/layout.gohtml:57 web/templates/public/layout.gohtml:103 +#: web/templates/public/layout.gohtml:58 web/templates/public/layout.gohtml:104 #: web/templates/admin/campsite/index.gohtml:6 #: web/templates/admin/campsite/index.gohtml:12 #: web/templates/admin/layout.gohtml:46 web/templates/admin/layout.gohtml:86 @@ -411,17 +411,17 @@ msgctxt "title" msgid "Campsites" msgstr "Alojamientos" -#: web/templates/public/layout.gohtml:90 +#: web/templates/public/layout.gohtml:91 msgctxt "title" msgid "Sections" msgstr "Apartados" -#: web/templates/public/layout.gohtml:114 +#: web/templates/public/layout.gohtml:115 msgctxt "title" msgid "Opening" msgstr "Apertura" -#: web/templates/public/layout.gohtml:121 +#: web/templates/public/layout.gohtml:122 msgid "RTC #%s" msgstr " RTC %s" @@ -612,7 +612,7 @@ msgstr "Carrusel del tipo de alojamiento" #: web/templates/admin/campsite/carousel/index.gohtml:12 #: web/templates/admin/services/index.gohtml:12 -#: web/templates/admin/home/index.gohtml:12 +#: web/templates/admin/home/index.gohtml:57 msgctxt "action" msgid "Add slide" msgstr "Añadir diapositiva" @@ -621,6 +621,7 @@ msgstr "Añadir diapositiva" #: web/templates/admin/services/index.gohtml:25 #: web/templates/admin/surroundings/index.gohtml:25 #: web/templates/admin/home/index.gohtml:25 +#: web/templates/admin/home/index.gohtml:70 msgctxt "header" msgid "Image" msgstr "Imagen" @@ -628,6 +629,7 @@ msgstr "Imagen" #: web/templates/admin/campsite/carousel/index.gohtml:26 #: web/templates/admin/services/index.gohtml:26 #: web/templates/admin/home/index.gohtml:26 +#: web/templates/admin/home/index.gohtml:71 msgctxt "header" msgid "Caption" msgstr "Leyenda" @@ -637,13 +639,14 @@ msgstr "Leyenda" #: web/templates/admin/services/index.gohtml:72 #: web/templates/admin/surroundings/index.gohtml:27 #: web/templates/admin/home/index.gohtml:27 +#: web/templates/admin/home/index.gohtml:72 msgctxt "header" msgid "Actions" msgstr "Acciones" #: web/templates/admin/campsite/carousel/index.gohtml:31 #: web/templates/admin/services/index.gohtml:31 -#: web/templates/admin/home/index.gohtml:31 +#: web/templates/admin/home/index.gohtml:76 msgid "Are you sure you wish to delete this slide?" msgstr "¿Estáis seguro de querer borrar esta diapositiva?" @@ -652,13 +655,14 @@ msgstr "¿Estáis seguro de querer borrar esta diapositiva?" #: web/templates/admin/services/index.gohtml:88 #: web/templates/admin/surroundings/index.gohtml:44 #: web/templates/admin/home/index.gohtml:44 +#: web/templates/admin/home/index.gohtml:89 msgctxt "action" msgid "Delete" msgstr "Borrar" #: web/templates/admin/campsite/carousel/index.gohtml:54 #: web/templates/admin/services/index.gohtml:53 -#: web/templates/admin/home/index.gohtml:53 +#: web/templates/admin/home/index.gohtml:98 msgid "No slides added yet." msgstr "No se ha añadido ninguna diapositiva todavía." @@ -1000,7 +1004,7 @@ msgid "Services Page" msgstr "Página de servicios" #: web/templates/admin/services/index.gohtml:11 -#: web/templates/admin/home/index.gohtml:11 +#: web/templates/admin/home/index.gohtml:56 msgctxt "title" msgid "Carousel" msgstr "Carrusel" @@ -1198,6 +1202,24 @@ msgctxt "action" msgid "Logout" msgstr "Salir" +#: web/templates/admin/home/index.gohtml:11 +msgctxt "title" +msgid "Cover" +msgstr "Portada" + +#: web/templates/admin/home/index.gohtml:12 +msgctxt "action" +msgid "Add cover image" +msgstr "Añadir imagen de portada" + +#: web/templates/admin/home/index.gohtml:31 +msgid "Are you sure you wish to delete this cover image?" +msgstr "¿Estáis seguro de querer borrar esta imagen de portada?" + +#: web/templates/admin/home/index.gohtml:53 +msgid "No images added to the cover yet." +msgstr "No se ha añadido ninguna imagen de portada todavía." + #: web/templates/admin/media/picker.gohtml:8 msgctxt "title" msgid "Media Picker" @@ -1265,7 +1287,7 @@ msgstr "Subida de medio" #: pkg/legal/admin.go:258 pkg/app/user.go:249 pkg/campsite/types/option.go:344 #: pkg/campsite/types/feature.go:259 pkg/campsite/types/admin.go:463 -#: pkg/season/admin.go:412 pkg/services/admin.go:314 +#: pkg/season/admin.go:412 pkg/services/admin.go:316 #: pkg/surroundings/admin.go:321 msgid "Name can not be empty." msgstr "No podéis dejar el nombre en blanco." @@ -1275,22 +1297,22 @@ msgstr "No podéis dejar el nombre en blanco." msgid "Name must have at least one letter." msgstr "El nombre tiene que tener como mínimo una letra." -#: pkg/carousel/admin.go:267 pkg/campsite/types/carousel.go:223 +#: pkg/carousel/admin.go:275 pkg/campsite/types/carousel.go:223 msgctxt "input" msgid "Slide image" msgstr "Imagen de la diapositiva" -#: pkg/carousel/admin.go:268 pkg/campsite/types/carousel.go:224 +#: pkg/carousel/admin.go:276 pkg/campsite/types/carousel.go:224 msgctxt "action" msgid "Set slide image" msgstr "Establecer la imagen de la diapositiva" -#: pkg/carousel/admin.go:337 pkg/campsite/types/carousel.go:297 +#: pkg/carousel/admin.go:345 pkg/campsite/types/carousel.go:297 #: pkg/surroundings/admin.go:316 msgid "Slide image can not be empty." msgstr "No podéis dejar la imagen de la diapositiva en blanco." -#: pkg/carousel/admin.go:338 pkg/campsite/types/carousel.go:298 +#: pkg/carousel/admin.go:346 pkg/campsite/types/carousel.go:298 #: pkg/surroundings/admin.go:317 msgid "Slide image must be an image media type." msgstr "La imagen de la diapositiva tiene que ser un medio de tipo imagen." @@ -1370,7 +1392,7 @@ msgstr "El precio por noche tiene que ser un número decimal." msgid "Price per night must be zero or greater." msgstr "El precio por noche tiene que ser como mínimo cero." -#: pkg/campsite/types/feature.go:258 pkg/services/admin.go:313 +#: pkg/campsite/types/feature.go:258 pkg/services/admin.go:315 msgid "Selected icon is not valid." msgstr "El icono escogido no es válido." diff --git a/po/fr.po b/po/fr.po index 4996ee1..e94fa97 100644 --- a/po/fr.po +++ b/po/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: camper\n" "Report-Msgid-Bugs-To: jordi@tandem.blog\n" -"POT-Creation-Date: 2024-01-16 00:48+0100\n" +"POT-Creation-Date: 2024-01-16 20:32+0100\n" "PO-Revision-Date: 2023-12-20 10:13+0100\n" "Last-Translator: Oriol Carbonell \n" "Language-Team: French \n" @@ -42,71 +42,71 @@ msgctxt "title" msgid "Payment Failed" msgstr "Le paiement a échoué" -#: web/templates/public/services.gohtml:6 -#: web/templates/public/services.gohtml:15 -#: web/templates/public/layout.gohtml:66 web/templates/public/layout.gohtml:94 +#: web/templates/public/services.gohtml:7 +#: web/templates/public/services.gohtml:16 +#: web/templates/public/layout.gohtml:67 web/templates/public/layout.gohtml:95 #: web/templates/admin/services/index.gohtml:56 msgctxt "title" msgid "Services" msgstr "Services" -#: web/templates/public/services.gohtml:18 +#: web/templates/public/services.gohtml:19 msgid "The campsite offers many different services." msgstr "Le camping propose de nombreux services différents." -#: web/templates/public/location.gohtml:6 -#: web/templates/public/location.gohtml:12 -#: web/templates/public/layout.gohtml:68 web/templates/public/layout.gohtml:96 +#: web/templates/public/location.gohtml:7 +#: web/templates/public/location.gohtml:13 +#: web/templates/public/layout.gohtml:69 web/templates/public/layout.gohtml:97 #: web/templates/admin/layout.gohtml:61 msgctxt "title" msgid "Location" msgstr "Comment nous rejoindre" -#: web/templates/public/home.gohtml:6 web/templates/public/layout.gohtml:52 -#: web/templates/public/layout.gohtml:92 +#: web/templates/public/home.gohtml:7 web/templates/public/layout.gohtml:53 +#: web/templates/public/layout.gohtml:93 msgctxt "title" msgid "Home" msgstr "Accueil" -#: web/templates/public/home.gohtml:17 -msgid "The pleasure of camping in the middle of nature…" -msgstr "Le plaisir de camper en pleine nature…" - -#: web/templates/public/home.gohtml:18 +#: web/templates/public/home.gohtml:24 msgctxt "link" msgid "Booking" msgstr "Réservation" #: web/templates/public/home.gohtml:31 +msgid "The pleasure of camping in the middle of nature…" +msgstr "Le plaisir de camper en pleine nature…" + +#: web/templates/public/home.gohtml:43 msgid "Our services" msgstr "Nos services" -#: web/templates/public/home.gohtml:33 +#: web/templates/public/home.gohtml:45 msgid "Come and enjoy!" msgstr "Venez et profitez-en !" -#: web/templates/public/home.gohtml:35 -#: web/templates/public/surroundings.gohtml:6 -#: web/templates/public/surroundings.gohtml:11 -#: web/templates/public/layout.gohtml:67 web/templates/public/layout.gohtml:95 +#: web/templates/public/home.gohtml:47 +#: web/templates/public/surroundings.gohtml:7 +#: web/templates/public/surroundings.gohtml:12 +#: web/templates/public/layout.gohtml:68 web/templates/public/layout.gohtml:96 #: web/templates/admin/layout.gohtml:64 msgctxt "title" msgid "Surroundings" msgstr "Entourage" -#: web/templates/public/home.gohtml:38 +#: web/templates/public/home.gohtml:50 msgid "Located in Alta Garrotxa, between the Pyrenees and the Costa Brava." msgstr "Situé dans l’Alta Garrotxa, entre les Pyrénées et la Costa Brava." -#: web/templates/public/home.gohtml:39 +#: web/templates/public/home.gohtml:51 msgid "Nearby there are the gorges of Sadernes, volcanoes, La Fageda d’en Jordà, the Jewish quarter of Besalú, the basaltic cliff of Castellfollit de la Roca… much to see and much to do." msgstr "A proximité il y a les gorges de Sadernes, les volcans, La Fageda dâen Jordã , le quartier juif de Besalú, la falaise basaltique de Castellfollit de la Roca… beaucoup à voir et beaucoup à faire." -#: web/templates/public/home.gohtml:40 +#: web/templates/public/home.gohtml:52 msgid "Less than an hour from Girona, one from La Bisbal d’Empordà, and two from Barcelona." msgstr "À moins d’une heure de Gérone, un de La Bisbal d’Empordàet deux de Barcelone." -#: web/templates/public/home.gohtml:41 +#: web/templates/public/home.gohtml:53 msgid "Discover the surroundings" msgstr "Découvrir les environs" @@ -253,57 +253,57 @@ msgctxt "day" msgid "Sun" msgstr "Dim." -#: web/templates/public/surroundings.gohtml:31 +#: web/templates/public/surroundings.gohtml:32 msgctxt "title" msgid "What to Do Outside the Campsite?" msgstr "Que faire à l’extérieur du camping ?" -#: web/templates/public/surroundings.gohtml:51 +#: web/templates/public/surroundings.gohtml:52 msgctxt "title" msgid "Once at the Campsite, We Can Inform You about What Activities are Available" msgstr "Une fois au camping, nous pourrons vous informer sur les activités disponibles" -#: web/templates/public/surroundings.gohtml:54 +#: web/templates/public/surroundings.gohtml:55 msgid "Cycle routes" msgstr "Pistes cyclables" -#: web/templates/public/surroundings.gohtml:55 +#: web/templates/public/surroundings.gohtml:56 msgid "There are many bicycle rental companies in Olot." msgstr "Il existe de nombreuses sociétés de location de vélos à Olot." -#: web/templates/public/surroundings.gohtml:59 +#: web/templates/public/surroundings.gohtml:60 msgid "Routes" msgstr "Itinéraires" -#: web/templates/public/surroundings.gohtml:60 +#: web/templates/public/surroundings.gohtml:61 msgid "Routes of all kinds, climbing, mountain passes, for all levels." msgstr "Itinéraires de toutes sortes, escalade, cols de montagne, pour tous les niveaux." -#: web/templates/public/surroundings.gohtml:64 +#: web/templates/public/surroundings.gohtml:65 msgid "Family outing" msgstr "Sortie en famille" -#: web/templates/public/surroundings.gohtml:65 +#: web/templates/public/surroundings.gohtml:66 msgid "Many outing possibilities, for all ages." msgstr "Nombreuses possibilités de sorties, pour tous les âges." -#: web/templates/public/surroundings.gohtml:69 +#: web/templates/public/surroundings.gohtml:70 msgid "Kayak" msgstr "Kayak" -#: web/templates/public/surroundings.gohtml:70 +#: web/templates/public/surroundings.gohtml:71 msgid "There are several points where you can go by kayak, from sections of the Ter river as well as on the coast…." msgstr "Il y a plusieurs points où vous pouvez aller en kayak, à partir de sections de la rivière Ter ainsi que sur la côte…." -#: web/templates/public/campground.gohtml:6 -#: web/templates/public/campground.gohtml:15 -#: web/templates/public/layout.gohtml:53 web/templates/public/layout.gohtml:93 +#: web/templates/public/campground.gohtml:7 +#: web/templates/public/campground.gohtml:16 +#: web/templates/public/layout.gohtml:54 web/templates/public/layout.gohtml:94 msgctxt "title" msgid "Campground" msgstr "Camping" #: web/templates/public/booking.gohtml:6 web/templates/public/booking.gohtml:11 -#: web/templates/public/layout.gohtml:69 +#: web/templates/public/layout.gohtml:70 msgctxt "title" msgid "Booking" msgstr "Reservation" @@ -391,20 +391,20 @@ msgctxt "input" msgid "I have read and I accept the reservation conditions" msgstr "J’ai lu et j’accepte les conditions de réservation" -#: web/templates/public/layout.gohtml:11 web/templates/public/layout.gohtml:47 -#: web/templates/public/layout.gohtml:130 +#: web/templates/public/layout.gohtml:12 web/templates/public/layout.gohtml:48 +#: web/templates/public/layout.gohtml:131 msgid "Campsite Montagut" msgstr "Camping Montagut" -#: web/templates/public/layout.gohtml:23 web/templates/admin/layout.gohtml:21 +#: web/templates/public/layout.gohtml:24 web/templates/admin/layout.gohtml:21 msgid "Skip to main content" msgstr "Passer au contenu principal" -#: web/templates/public/layout.gohtml:49 +#: web/templates/public/layout.gohtml:50 msgid "Menu" msgstr "Menu" -#: web/templates/public/layout.gohtml:57 web/templates/public/layout.gohtml:103 +#: web/templates/public/layout.gohtml:58 web/templates/public/layout.gohtml:104 #: web/templates/admin/campsite/index.gohtml:6 #: web/templates/admin/campsite/index.gohtml:12 #: web/templates/admin/layout.gohtml:46 web/templates/admin/layout.gohtml:86 @@ -412,17 +412,17 @@ msgctxt "title" msgid "Campsites" msgstr "Locatifs" -#: web/templates/public/layout.gohtml:90 +#: web/templates/public/layout.gohtml:91 msgctxt "title" msgid "Sections" msgstr "Sections" -#: web/templates/public/layout.gohtml:114 +#: web/templates/public/layout.gohtml:115 msgctxt "title" msgid "Opening" msgstr "Ouverture" -#: web/templates/public/layout.gohtml:121 +#: web/templates/public/layout.gohtml:122 msgid "RTC #%s" msgstr "# RTC %s" @@ -613,7 +613,7 @@ msgstr "Type de camping Carrousel" #: web/templates/admin/campsite/carousel/index.gohtml:12 #: web/templates/admin/services/index.gohtml:12 -#: web/templates/admin/home/index.gohtml:12 +#: web/templates/admin/home/index.gohtml:57 msgctxt "action" msgid "Add slide" msgstr "Ajouter la diapositive" @@ -622,6 +622,7 @@ msgstr "Ajouter la diapositive" #: web/templates/admin/services/index.gohtml:25 #: web/templates/admin/surroundings/index.gohtml:25 #: web/templates/admin/home/index.gohtml:25 +#: web/templates/admin/home/index.gohtml:70 msgctxt "header" msgid "Image" msgstr "Image" @@ -629,6 +630,7 @@ msgstr "Image" #: web/templates/admin/campsite/carousel/index.gohtml:26 #: web/templates/admin/services/index.gohtml:26 #: web/templates/admin/home/index.gohtml:26 +#: web/templates/admin/home/index.gohtml:71 msgctxt "header" msgid "Caption" msgstr "Légende" @@ -638,13 +640,14 @@ msgstr "Légende" #: web/templates/admin/services/index.gohtml:72 #: web/templates/admin/surroundings/index.gohtml:27 #: web/templates/admin/home/index.gohtml:27 +#: web/templates/admin/home/index.gohtml:72 msgctxt "header" msgid "Actions" msgstr "Actions" #: web/templates/admin/campsite/carousel/index.gohtml:31 #: web/templates/admin/services/index.gohtml:31 -#: web/templates/admin/home/index.gohtml:31 +#: web/templates/admin/home/index.gohtml:76 msgid "Are you sure you wish to delete this slide?" msgstr "Êtes-vous sûr de vouloir supprimer cette diapositive ?" @@ -653,13 +656,14 @@ msgstr "Êtes-vous sûr de vouloir supprimer cette diapositive ?" #: web/templates/admin/services/index.gohtml:88 #: web/templates/admin/surroundings/index.gohtml:44 #: web/templates/admin/home/index.gohtml:44 +#: web/templates/admin/home/index.gohtml:89 msgctxt "action" msgid "Delete" msgstr "Supprimer" #: web/templates/admin/campsite/carousel/index.gohtml:54 #: web/templates/admin/services/index.gohtml:53 -#: web/templates/admin/home/index.gohtml:53 +#: web/templates/admin/home/index.gohtml:98 msgid "No slides added yet." msgstr "Aucune diapositive n’a encore été ajoutée." @@ -1001,7 +1005,7 @@ msgid "Services Page" msgstr "La page des services" #: web/templates/admin/services/index.gohtml:11 -#: web/templates/admin/home/index.gohtml:11 +#: web/templates/admin/home/index.gohtml:56 msgctxt "title" msgid "Carousel" msgstr "Carrousel" @@ -1199,6 +1203,24 @@ msgctxt "action" msgid "Logout" msgstr "Déconnexion" +#: web/templates/admin/home/index.gohtml:11 +msgctxt "title" +msgid "Cover" +msgstr "Couverture" + +#: web/templates/admin/home/index.gohtml:12 +msgctxt "action" +msgid "Add cover image" +msgstr "Ajouter une image de couverture" + +#: web/templates/admin/home/index.gohtml:31 +msgid "Are you sure you wish to delete this cover image?" +msgstr "Êtes-vous sûr de vouloir supprimer cette image de couverture ?" + +#: web/templates/admin/home/index.gohtml:53 +msgid "No images added to the cover yet." +msgstr "Aucune image de couverture n’a encore été ajoutée." + #: web/templates/admin/media/picker.gohtml:8 msgctxt "title" msgid "Media Picker" @@ -1266,7 +1288,7 @@ msgstr "Envoyer un fichier" #: pkg/legal/admin.go:258 pkg/app/user.go:249 pkg/campsite/types/option.go:344 #: pkg/campsite/types/feature.go:259 pkg/campsite/types/admin.go:463 -#: pkg/season/admin.go:412 pkg/services/admin.go:314 +#: pkg/season/admin.go:412 pkg/services/admin.go:316 #: pkg/surroundings/admin.go:321 msgid "Name can not be empty." msgstr "Le nom ne peut pas être laissé vide." @@ -1276,22 +1298,22 @@ msgstr "Le nom ne peut pas être laissé vide." msgid "Name must have at least one letter." msgstr "Le nom doit comporter au moins une lettre." -#: pkg/carousel/admin.go:267 pkg/campsite/types/carousel.go:223 +#: pkg/carousel/admin.go:275 pkg/campsite/types/carousel.go:223 msgctxt "input" msgid "Slide image" msgstr "Image du diaporama" -#: pkg/carousel/admin.go:268 pkg/campsite/types/carousel.go:224 +#: pkg/carousel/admin.go:276 pkg/campsite/types/carousel.go:224 msgctxt "action" msgid "Set slide image" msgstr "Définir l’image de la diapositive" -#: pkg/carousel/admin.go:337 pkg/campsite/types/carousel.go:297 +#: pkg/carousel/admin.go:345 pkg/campsite/types/carousel.go:297 #: pkg/surroundings/admin.go:316 msgid "Slide image can not be empty." msgstr "L’image de la diapositive ne peut pas être vide." -#: pkg/carousel/admin.go:338 pkg/campsite/types/carousel.go:298 +#: pkg/carousel/admin.go:346 pkg/campsite/types/carousel.go:298 #: pkg/surroundings/admin.go:317 msgid "Slide image must be an image media type." msgstr "L’image de la diapositive doit être de type média d’image." @@ -1371,7 +1393,7 @@ msgstr "Le prix par nuit doit être un nombre décimal." msgid "Price per night must be zero or greater." msgstr "Le prix par nuit doit être égal ou supérieur." -#: pkg/campsite/types/feature.go:258 pkg/services/admin.go:313 +#: pkg/campsite/types/feature.go:258 pkg/services/admin.go:315 msgid "Selected icon is not valid." msgstr "L’icône sélectionnée n’est pas valide." diff --git a/revert/add_cover_carousel_slide.sql b/revert/add_cover_carousel_slide.sql new file mode 100644 index 0000000..7902a2f --- /dev/null +++ b/revert/add_cover_carousel_slide.sql @@ -0,0 +1,7 @@ +-- Revert camper:add_cover_carousel_slide from pg + +begin; + +drop function if exists camper.add_cover_carousel_slide(integer, text); + +commit; diff --git a/revert/cover_carousel.sql b/revert/cover_carousel.sql new file mode 100644 index 0000000..d66efbe --- /dev/null +++ b/revert/cover_carousel.sql @@ -0,0 +1,7 @@ +-- Revert camper:cover_carousel from pg + +begin; + +drop table if exists camper.cover_carousel; + +commit; diff --git a/revert/cover_carousel_i18n.sql b/revert/cover_carousel_i18n.sql new file mode 100644 index 0000000..245189a --- /dev/null +++ b/revert/cover_carousel_i18n.sql @@ -0,0 +1,7 @@ +-- Revert camper:cover_carousel_i18n from pg + +begin; + +drop table if exists camper.cover_carousel_i18n; + +commit; diff --git a/revert/order_cover_carousel.sql b/revert/order_cover_carousel.sql new file mode 100644 index 0000000..c65053a --- /dev/null +++ b/revert/order_cover_carousel.sql @@ -0,0 +1,7 @@ +-- Revert camper:order_cover_carousel from pg + +begin; + +drop function if exists camper.order_cover_carousel(integer[]); + +commit; diff --git a/revert/remove_cover_carousel_slide.sql b/revert/remove_cover_carousel_slide.sql new file mode 100644 index 0000000..63c8b62 --- /dev/null +++ b/revert/remove_cover_carousel_slide.sql @@ -0,0 +1,7 @@ +-- Revert camper:remove_cover_carousel_slide from pg + +begin; + +drop function if exists camper.remove_cover_carousel_slide(integer); + +commit; diff --git a/revert/translate_cover_carousel_slide.sql b/revert/translate_cover_carousel_slide.sql new file mode 100644 index 0000000..d2088d5 --- /dev/null +++ b/revert/translate_cover_carousel_slide.sql @@ -0,0 +1,7 @@ +-- Revert camper:translate_cover_carousel_slide from pg + +begin; + +drop function if exists camper.translate_cover_carousel_slide(integer, text, text); + +commit; diff --git a/sqitch.plan b/sqitch.plan index 088e1f5..bf299de 100644 --- a/sqitch.plan +++ b/sqitch.plan @@ -148,3 +148,9 @@ surroundings_highlight_i18n [roles schema_camper surroundings_highlight language translate_surroundings_highlight [roles schema_camper surroundings_highlight_i18n] 2024-01-15T20:09:40Z jordi fita mas # Add function to translate surroundings highlights remove_surroundings_highlight [roles schema_camper surroundings_highlight surroundings_highlight_i18n] 2024-01-15T20:19:37Z jordi fita mas # Add function to delete surroundings highlight and their translations order_surroundings_highlights [roles schema_camper surroundings_highlight] 2024-01-15T20:29:59Z jordi fita mas # Add function to order surrounding highlights +cover_carousel [roles schema_camper company media user_profile] 2024-01-16T17:16:34Z jordi fita mas # Add relation for cover page’s image carousel +cover_carousel_i18n [roles schema_camper cover_carousel language] 2024-01-16T17:22:42Z jordi fita mas # Add relation for cover carousel translations +add_cover_carousel_slide [roles schema_camper cover_carousel] 2024-01-16T17:49:21Z jordi fita mas # Add function to create slides for the cover carousel +translate_cover_carousel_slide [roles schema_camper cover_carousel_i18n] 2024-01-16T18:17:36Z jordi fita mas # Add function to translate a cover carousel slider +remove_cover_carousel_slide [roles schema_camper cover_carousel cover_carousel_i18n] 2024-01-16T18:27:48Z jordi fita mas # Add function to remove sliders from the cover carousel +order_cover_carousel [schema_camper roles cover_carousel] 2024-01-16T18:40:12Z jordi fita mas # Add function to order cover carousel diff --git a/test/add_cover_carousel_slide.sql b/test/add_cover_carousel_slide.sql new file mode 100644 index 0000000..1e0f204 --- /dev/null +++ b/test/add_cover_carousel_slide.sql @@ -0,0 +1,82 @@ +-- Test add_cover_carousel_slide +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(14); + +select has_function('camper', 'add_cover_carousel_slide', array['integer', 'text']); +select function_lang_is('camper', 'add_cover_carousel_slide', array['integer', 'text'], 'sql'); +select function_returns('camper', 'add_cover_carousel_slide', array['integer', 'text'], 'integer'); +select isnt_definer('camper', 'add_cover_carousel_slide', array['integer', 'text']); +select volatility_is('camper', 'add_cover_carousel_slide', array['integer', 'text'], 'volatile'); +select function_privs_are('camper', 'add_cover_carousel_slide', array['integer', 'text'], 'guest', array[]::text[]); +select function_privs_are('camper', 'add_cover_carousel_slide', array['integer', 'text'], 'employee', array[]::text[]); +select function_privs_are('camper', 'add_cover_carousel_slide', array['integer', 'text'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'add_cover_carousel_slide', array['integer', 'text'], 'authenticator', array[]::text[]); + +set client_min_messages to warning; +truncate cover_carousel_i18n cascade; +truncate cover_carousel cascade; +truncate media cascade; +truncate media_content 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') +; + +insert into media_content (media_type, bytes) +values ('text/plain', 'hello, world!') + , ('image/svg+xml', '') + , ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values (5, 1, 'text.txt', sha256('hello, world!')) + , (6, 1, 'image.svg', sha256('')) + , (7, 1, 'cover4.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) +; + +insert into cover_carousel (media_id, caption) +values (5, 'Previous caption') +; + +select lives_ok( + $$ select add_cover_carousel_slide(6, 'A caption') $$, + 'Should be able to add a carousel slide with a caption' +); + +select lives_ok( + $$ select add_cover_carousel_slide(7, null) $$, + 'Should be able to add a carousel slide without caption' +); + +select lives_ok( + $$ select add_cover_carousel_slide(5, 'New caption') $$, + 'Should be able to overwrite a slide with a new caption' +); + +select bag_eq( + $$ select media_id, caption from cover_carousel $$, + $$ values (5, 'New caption') + , (6, 'A caption') + , (7, '') + $$, + 'Should have all three slides' +); + +select is_empty( + $$ select * from cover_carousel_i18n $$, + 'Should not have added any translation' +); + +select * +from finish(); + +rollback; diff --git a/test/cover_carousel.sql b/test/cover_carousel.sql new file mode 100644 index 0000000..748dd99 --- /dev/null +++ b/test/cover_carousel.sql @@ -0,0 +1,192 @@ +-- Test cover_carousel +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(35); + +set search_path to camper, public; + +select has_table('cover_carousel'); +select has_pk('cover_carousel'); +select table_privs_are('cover_carousel', 'guest', array['SELECT']); +select table_privs_are('cover_carousel', 'employee', array['SELECT']); +select table_privs_are('cover_carousel', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']); +select table_privs_are('cover_carousel', 'authenticator', array[]::text[]); + +select has_column('cover_carousel', 'media_id'); +select col_is_pk('cover_carousel', 'media_id'); +select col_is_fk('cover_carousel', 'media_id'); +select fk_ok('cover_carousel', 'media_id', 'media', 'media_id'); +select col_type_is('cover_carousel', 'media_id', 'integer'); +select col_not_null('cover_carousel', 'media_id'); +select col_hasnt_default('cover_carousel', 'media_id'); + +select has_column('cover_carousel', 'caption'); +select col_type_is('cover_carousel', 'caption', 'text'); +select col_not_null('cover_carousel', 'caption'); +select col_hasnt_default('cover_carousel', 'caption'); + +select has_column('cover_carousel', 'position'); +select col_type_is('cover_carousel', 'position', 'integer'); +select col_not_null('cover_carousel', 'position'); +select col_has_default('cover_carousel', 'position'); +select col_default_is('cover_carousel', 'position', '2147483647'); + +set client_min_messages to warning; +truncate cover_carousel cascade; +truncate media cascade; +truncate media_content 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') +; + +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 media_content (media_type, bytes) +values ('text/plain', 'content2') + , ('text/plain', 'content3') + , ('text/plain', 'content4') + , ('text/plain', 'content5') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values ( 7, 2, 'text2.txt', sha256('content2')) + , ( 8, 2, 'text3.txt', sha256('content3')) + , ( 9, 4, 'text4.txt', sha256('content4')) + , (10, 4, 'text5.txt', sha256('content5')) +; + +insert into cover_carousel (media_id, caption) +values (7, 'Caption 7') + , (9, 'Caption 9') +; + +prepare carousel_data as +select media_id, caption +from cover_carousel +order by media_id, caption; + +set role guest; +select bag_eq( + 'carousel_data', + $$ values (7, 'Caption 7') + , (9, 'Caption 9') + $$, + 'Everyone should be able to list all carousel media across all companies' +); +reset role; + +select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'co2'); + +select lives_ok( + $$ insert into cover_carousel(media_id, caption) + values (8, 'Caption 8') $$, + 'Admin from company 2 should be able to insert a new carousel media to that company.' +); + +select bag_eq( + 'carousel_data', + $$ values (7, 'Caption 7') + , (8, 'Caption 8') + , (9, 'Caption 9') + $$, + 'The new row should have been added' +); + +select lives_ok( + $$ update cover_carousel set caption = 'Caption 8.8' where media_id = 8 $$, + 'Admin from company 2 should be able to update carousel media of that company.' +); + +select bag_eq( + 'carousel_data', + $$ values (7, 'Caption 7') + , (8, 'Caption 8.8') + , (9, 'Caption 9') + $$, + 'The row should have been updated.' +); + +select lives_ok( + $$ delete from cover_carousel where media_id = 8 $$, + 'Admin from company 2 should be able to delete carousel media from that company.' +); + +select bag_eq( + 'carousel_data', + $$ values (7, 'Caption 7') + , (9, 'Caption 9') + $$, + 'The row should have been deleted.' +); + +select throws_ok( + $$ insert into cover_carousel (media_id, caption) + values (10, 'Caption 10') $$, + '42501', 'new row violates row-level security policy for table "cover_carousel"', + 'Admin from company 2 should NOT be able to insert new media to company 4.' +); + +select lives_ok( + $$ update cover_carousel set caption = 'Nope' where media_id = 9 $$, + 'Admin from company 2 should not be able to update new carousel media of company 4, but no error if media_id is not changed.' +); + +select bag_eq( + 'carousel_data', + $$ values (7, 'Caption 7') + , (9, 'Caption 9') + $$, + 'No row should have been changed.' +); + +select throws_ok( + $$ update cover_carousel set media_id = 10 where media_id = 7 $$, + '42501', 'new row violates row-level security policy for table "cover_carousel"', + 'Admin from company 2 should NOT be able to move carousel media to company 4' +); + +select lives_ok( + $$ delete from cover_carousel where media_id = 9 $$, + 'Admin from company 2 should NOT be able to delete carousel media from company 4, but no error is thrown' +); + +select bag_eq( + 'carousel_data', + $$ values (7, 'Caption 7') + , (9, 'Caption 9') + $$, + 'No row should have been changed' +); + +reset role; + +select * +from finish(); + +rollback; + diff --git a/test/cover_carousel_i18n.sql b/test/cover_carousel_i18n.sql new file mode 100644 index 0000000..cc9f4ae --- /dev/null +++ b/test/cover_carousel_i18n.sql @@ -0,0 +1,44 @@ +-- Test cover_carousel_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('cover_carousel_i18n'); +select has_pk('cover_carousel_i18n'); +select col_is_pk('cover_carousel_i18n', array['media_id', 'lang_tag']); +select table_privs_are('cover_carousel_i18n', 'guest', array['SELECT']); +select table_privs_are('cover_carousel_i18n', 'employee', array['SELECT']); +select table_privs_are('cover_carousel_i18n', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']); +select table_privs_are('cover_carousel_i18n', 'authenticator', array[]::text[]); + +select has_column('cover_carousel_i18n', 'media_id'); +select col_is_fk('cover_carousel_i18n', 'media_id'); +select fk_ok('cover_carousel_i18n', 'media_id', 'cover_carousel', 'media_id'); +select col_type_is('cover_carousel_i18n', 'media_id', 'integer'); +select col_not_null('cover_carousel_i18n', 'media_id'); +select col_hasnt_default('cover_carousel_i18n', 'media_id'); + +select has_column('cover_carousel_i18n', 'lang_tag'); +select col_is_fk('cover_carousel_i18n', 'lang_tag'); +select fk_ok('cover_carousel_i18n', 'lang_tag', 'language', 'lang_tag'); +select col_type_is('cover_carousel_i18n', 'lang_tag', 'text'); +select col_not_null('cover_carousel_i18n', 'lang_tag'); +select col_hasnt_default('cover_carousel_i18n', 'lang_tag'); + +select has_column('cover_carousel_i18n', 'caption'); +select col_type_is('cover_carousel_i18n', 'caption', 'text'); +select col_not_null('cover_carousel_i18n', 'caption'); +select col_hasnt_default('cover_carousel_i18n', 'caption'); + + +select * +from finish(); + +rollback; + diff --git a/test/order_cover_carousel.sql b/test/order_cover_carousel.sql new file mode 100644 index 0000000..d8121d0 --- /dev/null +++ b/test/order_cover_carousel.sql @@ -0,0 +1,79 @@ +-- Test order_cover_carousel +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(11); + +set search_path to camper, public; + +select has_function('camper', 'order_cover_carousel', array['integer[]']); +select function_lang_is('camper', 'order_cover_carousel', array['integer[]'], 'sql'); +select function_returns('camper', 'order_cover_carousel', array['integer[]'], 'void'); +select isnt_definer('camper', 'order_cover_carousel', array['integer[]']); +select volatility_is('camper', 'order_cover_carousel', array['integer[]'], 'volatile'); +select function_privs_are('camper', 'order_cover_carousel', array ['integer[]'], 'guest', array[]::text[]); +select function_privs_are('camper', 'order_cover_carousel', array ['integer[]'], 'employee', array[]::text[]); +select function_privs_are('camper', 'order_cover_carousel', array ['integer[]'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'order_cover_carousel', array ['integer[]'], 'authenticator', array[]::text[]); + + +set client_min_messages to warning; +truncate cover_carousel_i18n cascade; +truncate cover_carousel cascade; +truncate media cascade; +truncate media_content 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') +; + +insert into media_content (media_type, bytes) +values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};') + , ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ff00ff","a"};') + , ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffff00","a"};') + , ('text/plain', 'hello, world!') + , ('image/svg+xml', '') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values (2, 1, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) + , (3, 1, 'cover3.xpm', sha256('static char *s[]={"1 1 1 1","a c #ff00ff","a"};')) + , (4, 1, 'cover4.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffff00","a"};')) + , (5, 1, 'text.txt', sha256('hello, world!')) + , (6, 1, 'image.svg', sha256('')) +; + +insert into cover_carousel (media_id, caption) +values (2, '1') + , (3, '2') + , (4, '3') + , (5, '4') + , (6, '5') +; + +select lives_ok( + $$ select order_cover_carousel('{4,6,5,2,3}') $$, + 'Should be able to sort cover slides using their ID' +); + +select bag_eq( + $$ select media_id, position from cover_carousel $$, + $$ values (4, 1) + , (6, 2) + , (5, 3) + , (2, 4) + , (3, 5) + $$, + 'Should have sorted all cover slides.' +); + + +select * +from finish(); + +rollback; diff --git a/test/remove_cover_carousel_slide.sql b/test/remove_cover_carousel_slide.sql new file mode 100644 index 0000000..2c92abd --- /dev/null +++ b/test/remove_cover_carousel_slide.sql @@ -0,0 +1,87 @@ +-- Test remove_cover_carousel_slide +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(12); + +set search_path to camper, public; + +select has_function('camper', 'remove_cover_carousel_slide', array['integer']); +select function_lang_is('camper', 'remove_cover_carousel_slide', array['integer'], 'sql'); +select function_returns('camper', 'remove_cover_carousel_slide', array['integer'], 'void'); +select isnt_definer('camper', 'remove_cover_carousel_slide', array['integer']); +select volatility_is('camper', 'remove_cover_carousel_slide', array['integer'], 'volatile'); +select function_privs_are('camper', 'remove_cover_carousel_slide', array['integer'], 'guest', array[]::text[]); +select function_privs_are('camper', 'remove_cover_carousel_slide', array['integer'], 'employee', array[]::text[]); +select function_privs_are('camper', 'remove_cover_carousel_slide', array['integer'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'remove_cover_carousel_slide', array['integer'], 'authenticator', array[]::text[]); + +set client_min_messages to warning; +truncate cover_carousel_i18n cascade; +truncate cover_carousel cascade; +truncate media cascade; +truncate media_content 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') +; + +insert into media_content (media_type, bytes) +values ('text/plain', 'hello, world!') + , ('image/svg+xml', '') + , ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values (5, 1, 'text.txt', sha256('hello, world!')) + , (6, 1, 'image.svg', sha256('')) + , (7, 1, 'cover4.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) +; + +insert into cover_carousel (media_id, caption) +values (5, 'Source caption') + , (6, 'Another caption') + , (7, 'N/A') +; + +insert into cover_carousel_i18n (media_id, lang_tag, caption) +values (5, 'en', 'Target caption') + , (5, 'es', 'Target caption (spanish)') + , (6, 'en', 'Target caption') + , (6, 'es', 'Target caption (spanish)') + , (7, 'en', 'Target caption') + , (7, 'es', 'Target caption (spanish)') +; + +select lives_ok( + $$ select remove_cover_carousel_slide(6) $$, + 'Should be able to delete a slide' +); + +select bag_eq( + $$ select media_id, caption from cover_carousel $$, + $$ values (5, 'Source caption') + , (7, 'N/A') + $$, + 'Should have removed the slide' +); + +select bag_eq( + $$ select media_id, lang_tag, caption from cover_carousel_i18n $$, + $$ values (5, 'en', 'Target caption') + , (5, 'es', 'Target caption (spanish)') + , (7, 'en', 'Target caption') + , (7, 'es', 'Target caption (spanish)') + $$, + 'Should have removed the slide’s translations' +); + +select * +from finish(); + +rollback; diff --git a/test/translate_cover_carousel_slide.sql b/test/translate_cover_carousel_slide.sql new file mode 100644 index 0000000..6a54bfb --- /dev/null +++ b/test/translate_cover_carousel_slide.sql @@ -0,0 +1,85 @@ +-- Test translate_cover_carousel_slide +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_cover_carousel_slide', array['integer', 'text', 'text']); +select function_lang_is('camper', 'translate_cover_carousel_slide', array['integer', 'text', 'text'], 'sql'); +select function_returns('camper', 'translate_cover_carousel_slide', array['integer', 'text', 'text'], 'void'); +select isnt_definer('camper', 'translate_cover_carousel_slide', array['integer', 'text', 'text']); +select volatility_is('camper', 'translate_cover_carousel_slide', array['integer', 'text', 'text'], 'volatile'); +select function_privs_are('camper', 'translate_cover_carousel_slide', array['integer', 'text', 'text'], 'guest', array[]::text[]); +select function_privs_are('camper', 'translate_cover_carousel_slide', array['integer', 'text', 'text'], 'employee', array[]::text[]); +select function_privs_are('camper', 'translate_cover_carousel_slide', array['integer', 'text', 'text'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'translate_cover_carousel_slide', array['integer', 'text', 'text'], 'authenticator', array[]::text[]); + + +set client_min_messages to warning; +truncate cover_carousel_i18n cascade; +truncate cover_carousel cascade; +truncate media cascade; +truncate media_content 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') +; + +insert into media_content (media_type, bytes) +values ('text/plain', 'hello, world!') + , ('image/svg+xml', '') + , ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values (5, 1, 'text.txt', sha256('hello, world!')) + , (6, 1, 'image.svg', sha256('')) + , (7, 1, 'cover4.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) +; + +insert into cover_carousel (media_id, caption) +values (5, 'Source caption') + , (6, 'Another caption') + , (7, 'N/A') +; + +insert into cover_carousel_i18n (media_id, lang_tag, caption) +values (5, 'en', 'Target caption') +; + +select lives_ok( + $$ select translate_cover_carousel_slide(5, 'ca', 'Traducció') $$, + 'Should be able to translate a carousel slide' +); + +select lives_ok( + $$ select translate_cover_carousel_slide(6, 'es', null) $$, + 'Should be able to “translate” a carousel slide to the empty string' +); + +select lives_ok( + $$ select translate_cover_carousel_slide(5, 'en', 'Not anymore') $$, + 'Should be able to overwrite a slide’s translation' +); + +select bag_eq( + $$ select media_id, lang_tag, caption from cover_carousel_i18n $$, + $$ values (5, 'ca', 'Traducció') + , (5, 'en', 'Not anymore') + , (6, 'es', '') + $$, + 'Should have all three slides' +); + + +select * +from finish(); + +rollback; diff --git a/verify/add_cover_carousel_slide.sql b/verify/add_cover_carousel_slide.sql new file mode 100644 index 0000000..7078594 --- /dev/null +++ b/verify/add_cover_carousel_slide.sql @@ -0,0 +1,7 @@ +-- Verify camper:add_cover_carousel_slide on pg + +begin; + +select has_function_privilege('camper.add_cover_carousel_slide(integer, text)', 'execute'); + +rollback; diff --git a/verify/cover_carousel.sql b/verify/cover_carousel.sql new file mode 100644 index 0000000..27fccc7 --- /dev/null +++ b/verify/cover_carousel.sql @@ -0,0 +1,17 @@ +-- Verify camper:cover_carousel on pg + +begin; + +select media_id + , caption + , position +from camper.cover_carousel +where false; + +select 1 / count(*) from pg_class where oid = 'camper.cover_carousel'::regclass and relrowsecurity; +select 1 / count(*) from pg_policy where polname = 'guest_ok' and polrelid = 'camper.cover_carousel'::regclass; +select 1 / count(*) from pg_policy where polname = 'insert_to_company' and polrelid = 'camper.cover_carousel'::regclass; +select 1 / count(*) from pg_policy where polname = 'update_company' and polrelid = 'camper.cover_carousel'::regclass; +select 1 / count(*) from pg_policy where polname = 'delete_from_company' and polrelid = 'camper.cover_carousel'::regclass; + +rollback; diff --git a/verify/cover_carousel_i18n.sql b/verify/cover_carousel_i18n.sql new file mode 100644 index 0000000..51413ea --- /dev/null +++ b/verify/cover_carousel_i18n.sql @@ -0,0 +1,11 @@ +-- Verify camper:cover_carousel_i18n on pg + +begin; + +select media_id + , lang_tag + , caption +from camper.cover_carousel_i18n +where false; + +rollback; diff --git a/verify/order_cover_carousel.sql b/verify/order_cover_carousel.sql new file mode 100644 index 0000000..37117f3 --- /dev/null +++ b/verify/order_cover_carousel.sql @@ -0,0 +1,7 @@ +-- Verify camper:order_cover_carousel on pg + +begin; + +select has_function_privilege('camper.order_cover_carousel(integer[])', 'execute'); + +rollback; diff --git a/verify/remove_cover_carousel_slide.sql b/verify/remove_cover_carousel_slide.sql new file mode 100644 index 0000000..28aab47 --- /dev/null +++ b/verify/remove_cover_carousel_slide.sql @@ -0,0 +1,7 @@ +-- Verify camper:remove_cover_carousel_slide on pg + +begin; + +select has_function_privilege('camper.remove_cover_carousel_slide(integer)', 'execute'); + +rollback; diff --git a/verify/translate_cover_carousel_slide.sql b/verify/translate_cover_carousel_slide.sql new file mode 100644 index 0000000..ca8dee8 --- /dev/null +++ b/verify/translate_cover_carousel_slide.sql @@ -0,0 +1,7 @@ +-- Verify camper:translate_cover_carousel_slide on pg + +begin; + +select has_function_privilege('camper.translate_cover_carousel_slide(integer, text, text)', 'execute'); + +rollback; diff --git a/web/static/public.css b/web/static/public.css index 7b4fbdd..84760fb 100644 --- a/web/static/public.css +++ b/web/static/public.css @@ -155,7 +155,7 @@ address { font-style: normal; } -body > a[href="#content"], .sr-only { +body > a[href="#content"], .sr-only, .hero button span { border: 0; clip: rect(1px, 1px, 1px, 1px); clip-path: inset(50%); @@ -418,25 +418,70 @@ nav:last-of-type > ul > li:last-child { padding: 2.5rem; } -.nature div, .nature section a { +.hero div, .nature section a { background: var(--background-image) center center no-repeat; background-size: cover; } -.nature div, .services { +.hero, .nature, .services { margin-bottom: 5rem; } -.nature div:first-child, .nature section, .services { +.hero div, .nature section, .services { border-radius: 5px; } -.nature div:first-child { - min-height: 65vh; +.hero { + height: 65vh; + position: relative; + overflow: hidden; +} + +.hero div { + position: absolute; + inset: 0; display: flex; align-items: flex-end; + justify-content: space-between; gap: 5rem; padding: 5rem; + transition: opacity 1s ease-in-out; +} + +.hero div[aria-hidden] { + opacity: 0; +} + +.hero button { + position: absolute; + top: 50%; + opacity: 0; + z-index: 10; + transition: opacity .5s, transform .5s; + width: 3.2rem; + aspect-ratio: 1; + background-color: transparent; + background-repeat: no-repeat; + background-position: center center; + background-size: 3.2rem; + border: none; +} + +.hero button:first-of-type { + left: 1rem; + transform: translate(-150%, -50%); + background-image: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"%3E%3Crect width="256" height="256" fill="none"/%3E%3Cpolyline points="160 208 80 128 160 48" fill="none" stroke="white" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/%3E%3C/svg%3E'); +} + +.hero button:last-of-type { + right: 1rem; + transform: translate(150%, -50%); + background-image: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"%3E%3Crect width="256" height="256" fill="none"/%3E%3Cpolyline points="96 48 176 128 96 208" fill="none" stroke="white" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/%3E%3C/svg%3E'); +} + +.hero:hover button { + transform: translate(0, -50%); + opacity: 1; } .services { @@ -447,48 +492,59 @@ nav:last-of-type > ul > li:last-child { padding: 5rem; } -.nature div:first-child { - justify-content: space-between; -} - -.nature h2, .nature div:first-child a, .services h2, .surroundings .spiel a { +.hero div > span, .hero a, .services h2, .surroundings .spiel a { font-weight: bold; line-height: .9em; } -.nature h2, .nature div:first-child a { +.hero div > span, .hero a { border-radius: 5px; background-color: var(--clar); } -.nature h2 { +.hero div > span { width: 50%; - min-height: 100%; margin-bottom: 0; font-size: calc(2rem + 4vw); display: block; - background: transparent; + background: transparent; color: var(--base); + text-shadow: 0 1px 0 black; + transition: transform 1s 1s; } -.nature div:first-child a, .services h2, .surroundings .spiel a { +.hero div[aria-hidden] > span { + transform: translateY(200%); +} + +.hero a, .services h2, .surroundings .spiel a { font-size: calc(1rem + 1.2vw); } -.nature div:first-child a, .services a { +.hero a, .services a { padding: 1.5rem 2rem; } -.nature div:first-child a span, .services a span, .surroundings .spiel a:hover span, .campsite_type_booking button span { +.hero a span, .services a span, .surroundings .spiel a:hover span, .campsite_type_booking button span { display: inline-block; transition: transform 0.5s ease; } -.nature div:first-child a:hover span, .services a:hover span, .spiel a:hover span, .campsite_type_booking button:hover span { +.hero a:hover span, .services a:hover span, .spiel a:hover span, .campsite_type_booking button:hover span { transform: translateX(1.3rem); } -dl, .nature div + div, .outside_activities > div { +@media (max-width: 48rem) { + .hero div { + flex-direction: column; + } + + .hero div > span { + width: 100%; + } +} + +dl, .nature > div, .outside_activities > div { display: flex; gap: 5rem; } @@ -512,27 +568,17 @@ dl, .nature div + div, .outside_activities > div { z-index: 2; padding: .55rem 1.5rem 1rem; background-color: var(--accent); - color: var(--base); + color: var(--base); border-top-left-radius: 5px; border-bottom-right-radius: 5px; } @media (max-width: 64rem) { - .nature div + div { + .nature > div { flex-direction: column; } } -@media (max-width: 48rem) { - .nature div:first-child { - flex-direction: column; - } - - .nature h2 { - width: 100%; - } -} - .services { justify-content: end; background-color: var(--accent); @@ -1411,7 +1457,7 @@ address { /* camping map */ #campground_map { - border-radius: 5px; + border-radius: 5px; } #arbres { @@ -1522,3 +1568,7 @@ dt { color: var(--accent); text-decoration: var(--accent) wavy underline; } + +[x-cloak] { + display: none !important; +} diff --git a/web/templates/admin/carousel/form.gohtml b/web/templates/admin/carousel/form.gohtml index 2d67406..c74cc8d 100644 --- a/web/templates/admin/carousel/form.gohtml +++ b/web/templates/admin/carousel/form.gohtml @@ -15,9 +15,9 @@ {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/carousel.slideForm*/ -}}

diff --git a/web/templates/admin/home/index.gohtml b/web/templates/admin/home/index.gohtml index 5304e60..4bcf1c2 100644 --- a/web/templates/admin/home/index.gohtml +++ b/web/templates/admin/home/index.gohtml @@ -8,6 +8,51 @@ {{ define "content" -}} {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/home.homeIndex*/ -}} +

{{( pgettext "Cover" "title" )}}

+ {{( pgettext "Add cover image" "action" )}} + {{ if .Cover -}} + + {{ CSRFInput }} + + + + + + + + + + {{ $confirm := (gettext "Are you sure you wish to delete this cover image?")}} + {{ range $slide := .Cover -}} + + + + + + {{- end }} + +
{{( pgettext "Image" "header" )}}{{( pgettext "Caption" "header" )}}{{( pgettext "Actions" "header" )}}
+ + + + {{ .Caption }} + +
+
+ {{ else -}} +

{{( gettext "No images added to the cover yet." )}}

+ {{- end }} +

{{( pgettext "Carousel" "title" )}}

{{( pgettext "Add slide" "action" )}} {{ if .Slides -}} diff --git a/web/templates/public/campsite/type.gohtml b/web/templates/public/campsite/type.gohtml index f938567..136b1f0 100644 --- a/web/templates/public/campsite/type.gohtml +++ b/web/templates/public/campsite/type.gohtml @@ -9,7 +9,7 @@ {{ define "head" -}} {{ template "carouselStyle" }} - + {{ template "alpineScript" }} {{- end }} {{ define "content" -}} diff --git a/web/templates/public/home.gohtml b/web/templates/public/home.gohtml index 1ad5b39..21e53fb 100644 --- a/web/templates/public/home.gohtml +++ b/web/templates/public/home.gohtml @@ -9,15 +9,26 @@ {{ define "head" -}} {{ template "carouselStyle" }} + {{ template "alpineScript" }} {{- end }} {{ define "content" -}} {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/home.homePage*/ -}} +
+ {{ range $index, $slide := .Cover -}} + + {{- end }} + + +
-
-

{{ (gettext "The pleasure of camping in the middle of nature…")}}

- {{( pgettext "Booking" "link" )}} -
+

{{ (gettext "The pleasure of camping in the middle of nature…")}}

{{ with .CampsiteTypes -}}
{{ range . -}} diff --git a/web/templates/public/layout.gohtml b/web/templates/public/layout.gohtml index 09e57a0..db5fff2 100644 --- a/web/templates/public/layout.gohtml +++ b/web/templates/public/layout.gohtml @@ -152,6 +152,10 @@ {{- end }} +{{ define "alpineScript" -}} + +{{- end }} + {{ define "carouselInit" -}}