diff --git a/demo/demo.sql b/demo/demo.sql index 2cc51bf..008aba6 100644 --- a/demo/demo.sql +++ b/demo/demo.sql @@ -595,4 +595,56 @@ values (72, 77, 'en', 'Legend') , (76, 103, 'es', 'Leyenda') ; +alter table surroundings_highlight alter column surroundings_highlight_id restart with 112; + +select add_surroundings_highlight(52, 62, 'El Pont del Llierca', '

Pont d’estil romànic i bany natural a 400 m del càmping.

'); +select add_surroundings_highlight(52, 63, 'Alta Garrotxa', '

Excursions pels voltants que no us podeu perdre:

'); +select add_surroundings_highlight(52, 64, 'Sadernes', '

Zona d’escalada de Sadernes a 5 km del càmping

Escalada esportiva.

Descens de barrancs.

'); +select add_surroundings_highlight(52, 65, 'Besalú', '

Vila comtal medieval a 15 minuts

besalu.cat

'); +select add_surroundings_highlight(52, 65, 'Parc natural de la zona volcànica de la Garrotxa', '

El millor exponent de paisatge volcànic de la península a només 20 minuts.

turismegarrotxa.com

itinerannia.net

'); +select add_surroundings_highlight(52, 66, 'Les millors platges a només una hora', '

costabrava.org

'); +select add_surroundings_highlight(52, 67, 'Empordà', '

Esplèndida comarca entre el Pirineu i el Mediterrani. Figueres i el Museu Dalí a només 30 minuts.

visitfigueres.cat
salvador-dali.org

'); +select add_surroundings_highlight(52, 68, 'Denominació d’Orígen Empordà', '

Una experiència inoblidable, la Ruta del vi DO Empordà.

doemporda.cat

Autor de la foto: Rafael Lopez-Monné

'); +select add_surroundings_highlight(52, 69, 'Pirineus', '

Pirineu de Girona

Cims de quasi 3.000 metres, valls i paratges màgics com la Vall de Núria.

valldenuria.com

'); +select add_surroundings_highlight(52, 70, 'Girona', '

Val la pena visitar Girona: us recomanem visitar el Call Jueu, les Rambles, la catedral i els jardins que l’envolten…

Turisme Girona

'); +select add_surroundings_highlight(52, 71, 'Barcelona', '

Barcelona és més que botigues o el Barça… Descobreix els seus barris i les seves «joies» i respira el seu ambient.

Turisme Barcelona

'); + +select order_surroundings_highlights('{112,113,114,115,116,117,118,119,120,121,122}'); + +select translate_surroundings_highlight(112, 'en', 'Bridge of Llierca', '

Romanesque style bridge and natural bath at only 400 m from the camp site.

'); +select translate_surroundings_highlight(113, 'en', 'Alta Garrotxa', '

Walks in the neighbourhood that nobody should miss:

'); +select translate_surroundings_highlight(114, 'en', 'Sadernes', '

The Sadernes climbing area only 5 km from the camp site

Sport climbing.

Canyoning.

'); +select translate_surroundings_highlight(115, 'en', 'Besalú', '

County medieval village only 15 minutes distance

besalu.cat

'); +select translate_surroundings_highlight(116, 'en', 'La Garrotxa volcanic zone natural park', '

The best exponent of volcanic scenery in the Iberian Peninsula at 20 minutes.

turismegarrotxa.com

itinerannia.net

'); +select translate_surroundings_highlight(117, 'en', 'The best beaches at only one hour', '

costabrava.org

'); +select translate_surroundings_highlight(118, 'en', 'Empordà', '

Splendid region between the Pyrenees and the Mediterranean sea. Figueres and the Dalí Museum at only 30 minutes.

visitfigueres.cat
salvador-dali.org

'); +select translate_surroundings_highlight(119, 'en', 'Empordà Designation of Origin', '

An unforgetable experience, the DO Empordà wine rute.

doemporda.cat

Photo author: Rafael Lopez-Monné

'); +select translate_surroundings_highlight(120, 'en', 'Pyrenees', '

The Girona Pyrenees

With mountains of up to 3.000 meters, valleys and magic places as the Núria Valley.

valldenuria.com

'); +select translate_surroundings_highlight(121, 'en', 'Girona', '

Girona is worthwhile: we recommend to visit the Jewis Call, the Rambles, the cathedral and the gardens nearby…

Turisme Girona

'); +select translate_surroundings_highlight(122, 'en', 'Barcelona', '

Barcelona is more than shops or Barça… Discover the quarters, their “jewels” and breathe the ambiance.

Turisme Barcelona

'); + +select translate_surroundings_highlight(112, 'es', 'El Puente del Llierca', '

Puente de estilo románico y baño natural a 400 m del camping.

'); +select translate_surroundings_highlight(113, 'es', 'Alta Garrotxa', '

Excursiones por los alrededores que no os podéis perder:

'); +select translate_surroundings_highlight(114, 'es', 'Sadernes', '

Zona de escalada de Sadernes a 5 km del camping Escalada deportiva Descenso de barrancos.

'); +select translate_surroundings_highlight(115, 'es', 'Besalú', '

Villa condal medieval a 15 minutos.

besalu.cat

'); +select translate_surroundings_highlight(116, 'es', 'Parque Natural de la Zona Volcánica de la Garrotxa', '

El mejor exponente de paisaje volcánico de la península a sólo 20 minutos.

turismegarrotxa.com

itinerannia.net

'); +select translate_surroundings_highlight(117, 'es', 'Las mejores playas a sólo una hora', '

costabrava.org

'); +select translate_surroundings_highlight(118, 'es', 'Empordà', '

Espléndida comarca entre los Pirineos y el Mediterráneo. Figueres y el Museo Dalí a sólo 30 minutos.

visitfigueres.cat
salvador-dali.org

'); +select translate_surroundings_highlight(119, 'es', 'Denominación de Orígen Empordà', '

Una experiéncia inolvidable, la Ruta del vino DO Empordà.

doemporda.cat

Autor de la foto: Rafael Lopez-Monné

'); +select translate_surroundings_highlight(120, 'es', 'Pirineos', '

Pirineos de Girona

Cimas de casi 3.000 metros, valles y parajes mágicos como el Valle de Núria.

valldenuria.com

'); +select translate_surroundings_highlight(121, 'es', 'Girona', '

Girona vale una visita: os recomendamos visitar el Call Judío, las Ramblas, la catedral y los jardines que la rodean…

Turismo Girona

'); +select translate_surroundings_highlight(122, 'es', 'Barcelona', '

Barcelona es más que tiendas o el Barça… Descubre sus barrios y sus «joyas» y respira su ambiente.

Turismo Barcelona

'); + +select translate_surroundings_highlight(112, 'fr', 'Le Pont de Llierca', '

Pont de style romain et bain naturel à 400 m du camping.

'); +select translate_surroundings_highlight(113, 'fr', 'Haute Garrotxa', '

Randonnées incontournables:

'); +select translate_surroundings_highlight(114, 'fr', 'Sadernes', '

Zone d’escalade de Sadernes a 5 km du camping.

Escalade sportive.

Canyoning.

'); +select translate_surroundings_highlight(115, 'fr', 'Besalú', '

Village médiévale à 15 minutes.

besalu.cat

'); +select translate_surroundings_highlight(116, 'fr', 'Parc naturel de la zone volcanique de la Garrotxa', '

Un magnifique paysage volcanique à seulement 20 minutes.

turismegarrotxa.com

itinerannia.net

'); +select translate_surroundings_highlight(117, 'fr', 'Les plus belles plages à moins d’une heure', '

costabrava.org

'); +select translate_surroundings_highlight(118, 'fr', 'Empordà', '

Magnifique région entre Pyrénées et Méditerranée.

Figueres et le musée Dalí a seulement 30 minutes.

visitfigueres.cat
salvador-dali.org

'); +select translate_surroundings_highlight(119, 'fr', 'Appellation d’origine Empordà', '

Une expérience inoubliable, la route des Vin DO Empordà

doemporda.cat

Auteur de la photo: Rafael Lopez-Monné

'); +select translate_surroundings_highlight(120, 'fr', 'Pyrénées', '

Pyrénées de Gérone.

Sommet de prêt de 3.000 mètres, vallées et lieux magiques comme la Vall de Núria.

valldenuria.com

'); +select translate_surroundings_highlight(121, 'fr', 'Gérone', '

Visite incontournable, principalement: le quartier juifs, les Rambles, la cathédrale et les jardins qui l’entourent … Sans oublier ses nombreuses boutiques !

Turisme Girona

'); +select translate_surroundings_highlight(122, 'fr', 'Barcelone', '

Barcelone c’est plus que des boutiques et le Barça … Découvrez la richesse de ces quartiers: Gràcia, Barceloneta, …

Turisme Barcelona

'); + commit; diff --git a/deploy/add_surroundings_highlight.sql b/deploy/add_surroundings_highlight.sql new file mode 100644 index 0000000..d50e729 --- /dev/null +++ b/deploy/add_surroundings_highlight.sql @@ -0,0 +1,23 @@ +-- Deploy camper:add_surroundings_highlight to pg +-- requires: roles +-- requires: schema_camper +-- requires: surroundings_highlight + +begin; + +set search_path to camper, public; + +create or replace function add_surroundings_highlight(company integer, media_id integer, name text, description text) returns integer as +$$ + insert into surroundings_highlight (company_id, media_id, name, description) + values (company, media_id, name, xmlparse(content description)) + returning surroundings_highlight_id + ; +$$ + language sql +; + +revoke execute on function add_surroundings_highlight(integer, integer, text, text) from public; +grant execute on function add_surroundings_highlight(integer, integer, text, text) to admin; + +commit; diff --git a/deploy/edit_surroundings_highlight.sql b/deploy/edit_surroundings_highlight.sql new file mode 100644 index 0000000..bdee7f8 --- /dev/null +++ b/deploy/edit_surroundings_highlight.sql @@ -0,0 +1,25 @@ +-- Deploy camper:edit_surroundings_highlight to pg +-- requires: roles +-- requires: schema_camper +-- requires: surroundings_highlight + +begin; + +set search_path to camper, public; + +create or replace function edit_surroundings_highlight(highlight_id integer, media_id integer, name text, description text) returns integer as +$$ + update surroundings_highlight + set media_id = coalesce(edit_surroundings_highlight.media_id, surroundings_highlight.media_id) + , name = edit_surroundings_highlight.name + , description = xmlparse(content edit_surroundings_highlight.description) + where surroundings_highlight_id = highlight_id + returning surroundings_highlight_id; +$$ + language sql +; + +revoke execute on function edit_surroundings_highlight(integer, integer, text, text) from public; +grant execute on function edit_surroundings_highlight(integer, integer, text, text) to admin; + +commit; diff --git a/deploy/order_surroundings_highlights.sql b/deploy/order_surroundings_highlights.sql new file mode 100644 index 0000000..08b6243 --- /dev/null +++ b/deploy/order_surroundings_highlights.sql @@ -0,0 +1,24 @@ +-- Deploy camper:order_surroundings_highlights to pg +-- requires: roles +-- requires: schema_camper +-- requires: surroundings_highlight + +begin; + +set search_path to camper, public; + +create or replace function order_surroundings_highlights(positions integer[]) returns void as +$$ + update surroundings_highlight + set position = cast(temp.position as integer) + from unnest(positions) with ordinality as temp(surroundings_highlight_id, position) + where surroundings_highlight.surroundings_highlight_id = temp.surroundings_highlight_id + ; +$$ + language sql +; + +revoke execute on function order_surroundings_highlights(integer[]) from public; +grant execute on function order_surroundings_highlights(integer[]) to admin; + +commit; diff --git a/deploy/remove_surroundings_highlight.sql b/deploy/remove_surroundings_highlight.sql new file mode 100644 index 0000000..5ac863b --- /dev/null +++ b/deploy/remove_surroundings_highlight.sql @@ -0,0 +1,22 @@ +-- Deploy camper:remove_surroundings_highlight to pg +-- requires: roles +-- requires: schema_camper +-- requires: surroundings_highlight +-- requires: surroundings_highlight_i18n + +begin; + +set search_path to camper, public; + +create or replace function remove_surroundings_highlight(highlight_id integer) returns void as +$$ + delete from surroundings_highlight_i18n where surroundings_highlight_id = highlight_id; + delete from surroundings_highlight where surroundings_highlight_id = highlight_id; +$$ + language sql +; + +revoke execute on function remove_surroundings_highlight(integer) from public; +grant execute on function remove_surroundings_highlight(integer) to admin; + +commit; diff --git a/deploy/surroundings_highlight.sql b/deploy/surroundings_highlight.sql new file mode 100644 index 0000000..05eea3b --- /dev/null +++ b/deploy/surroundings_highlight.sql @@ -0,0 +1,58 @@ +-- Deploy camper:surroundings_highlight to pg +-- requires: roles +-- requires: schema_camper +-- requires: company +-- requires: media +-- requires: user_profile + +begin; + +set search_path to camper, public; + +create table surroundings_highlight ( + surroundings_highlight_id integer generated by default as identity primary key, + company_id integer not null references company, + media_id integer not null references media, + name text not null constraint name_not_empty check(length(trim(name)) > 0), + description xml not null, + position integer not null default 2147483647 +); + +grant select on table surroundings_highlight to guest; +grant select on table surroundings_highlight to employee; +grant select, insert, update, delete on table surroundings_highlight to admin; + + +alter table surroundings_highlight enable row level security; + +create policy guest_ok +on surroundings_highlight +for select +using (true) +; + +create policy insert_to_company +on surroundings_highlight +for insert +with check ( + company_id in (select company_id from user_profile) +) +; + +create policy update_company +on surroundings_highlight +for update +using ( + company_id in (select company_id from user_profile) +) +; + +create policy delete_from_company +on surroundings_highlight +for delete +using ( + company_id in (select company_id from user_profile) +) +; + +commit; diff --git a/deploy/surroundings_highlight_i18n.sql b/deploy/surroundings_highlight_i18n.sql new file mode 100644 index 0000000..1802fa4 --- /dev/null +++ b/deploy/surroundings_highlight_i18n.sql @@ -0,0 +1,23 @@ +-- Deploy camper:surroundings_highlight_i18n to pg +-- requires: roles +-- requires: schema_camper +-- requires: surroundings_highlight +-- requires: language + +begin; + +set search_path to camper, public; + +create table surroundings_highlight_i18n ( + surroundings_highlight_id integer not null references surroundings_highlight, + lang_tag text not null references language, + name text not null, + description xml not null, + primary key (surroundings_highlight_id, lang_tag) +); + +grant select on table surroundings_highlight_i18n to guest; +grant select on table surroundings_highlight_i18n to employee; +grant select, insert, update, delete on table surroundings_highlight_i18n to admin; + +commit; diff --git a/deploy/translate_surroundings_highlight.sql b/deploy/translate_surroundings_highlight.sql new file mode 100644 index 0000000..0ef3b6f --- /dev/null +++ b/deploy/translate_surroundings_highlight.sql @@ -0,0 +1,25 @@ +-- Deploy camper:translate_surroundings_highlight to pg +-- requires: roles +-- requires: schema_camper +-- requires: surroundings_highlight_i18n + +begin; + +set search_path to camper, public; + +create or replace function translate_surroundings_highlight(highlight_id integer, lang_tag text, name text, description text) returns void as +$$ + insert into surroundings_highlight_i18n (surroundings_highlight_id, lang_tag, name, description) + values (highlight_id, lang_tag, name, xmlparse(content coalesce(description, ''))) + on conflict (surroundings_highlight_id, lang_tag) do update + set name = excluded.name + , description = excluded.description + ; +$$ + language sql +; + +revoke execute on function translate_surroundings_highlight(integer, text, text, text) from public; +grant execute on function translate_surroundings_highlight(integer, text, text, text) to admin; + +commit; diff --git a/pkg/app/admin.go b/pkg/app/admin.go index 7ddf4f6..8846a9b 100644 --- a/pkg/app/admin.go +++ b/pkg/app/admin.go @@ -20,32 +20,35 @@ import ( "dev.tandem.ws/tandem/camper/pkg/media" "dev.tandem.ws/tandem/camper/pkg/season" "dev.tandem.ws/tandem/camper/pkg/services" + "dev.tandem.ws/tandem/camper/pkg/surroundings" "dev.tandem.ws/tandem/camper/pkg/template" ) type adminHandler struct { - campsite *campsite.AdminHandler - company *company.AdminHandler - home *home.AdminHandler - legal *legal.AdminHandler - location *location.AdminHandler - media *media.AdminHandler - payment *booking.AdminHandler - season *season.AdminHandler - services *services.AdminHandler + campsite *campsite.AdminHandler + company *company.AdminHandler + home *home.AdminHandler + legal *legal.AdminHandler + location *location.AdminHandler + media *media.AdminHandler + payment *booking.AdminHandler + season *season.AdminHandler + services *services.AdminHandler + surroundings *surroundings.AdminHandler } func newAdminHandler(mediaDir string) *adminHandler { return &adminHandler{ - campsite: campsite.NewAdminHandler(), - company: company.NewAdminHandler(), - home: home.NewAdminHandler(), - legal: legal.NewAdminHandler(), - location: location.NewAdminHandler(), - media: media.NewAdminHandler(mediaDir), - payment: booking.NewAdminHandler(), - season: season.NewAdminHandler(), - services: services.NewAdminHandler(), + campsite: campsite.NewAdminHandler(), + company: company.NewAdminHandler(), + home: home.NewAdminHandler(), + legal: legal.NewAdminHandler(), + location: location.NewAdminHandler(), + media: media.NewAdminHandler(mediaDir), + payment: booking.NewAdminHandler(), + season: season.NewAdminHandler(), + services: services.NewAdminHandler(), + surroundings: surroundings.NewAdminHandler(), } } @@ -83,6 +86,8 @@ func (h *adminHandler) Handle(user *auth.User, company *auth.Company, conn *data h.season.Handler(user, company, conn).ServeHTTP(w, r) case "services": h.services.Handler(user, company, conn).ServeHTTP(w, r) + case "surroundings": + h.surroundings.Handler(user, company, conn).ServeHTTP(w, r) case "": switch r.Method { case http.MethodGet: diff --git a/pkg/app/public.go b/pkg/app/public.go index 5b10661..b7c2c0b 100644 --- a/pkg/app/public.go +++ b/pkg/app/public.go @@ -6,7 +6,6 @@ package app import ( - "dev.tandem.ws/tandem/camper/pkg/legal" "net/http" "dev.tandem.ws/tandem/camper/pkg/auth" @@ -15,28 +14,32 @@ import ( "dev.tandem.ws/tandem/camper/pkg/database" "dev.tandem.ws/tandem/camper/pkg/home" httplib "dev.tandem.ws/tandem/camper/pkg/http" + "dev.tandem.ws/tandem/camper/pkg/legal" "dev.tandem.ws/tandem/camper/pkg/location" "dev.tandem.ws/tandem/camper/pkg/services" + "dev.tandem.ws/tandem/camper/pkg/surroundings" "dev.tandem.ws/tandem/camper/pkg/template" ) type publicHandler struct { - home *home.PublicHandler - booking *booking.PublicHandler - campsite *campsite.PublicHandler - legal *legal.PublicHandler - location *location.PublicHandler - services *services.PublicHandler + home *home.PublicHandler + booking *booking.PublicHandler + campsite *campsite.PublicHandler + legal *legal.PublicHandler + location *location.PublicHandler + services *services.PublicHandler + surroundings *surroundings.PublicHandler } func newPublicHandler() *publicHandler { return &publicHandler{ - home: home.NewPublicHandler(), - booking: booking.NewPublicHandler(), - campsite: campsite.NewPublicHandler(), - legal: legal.NewPublicHandler(), - location: location.NewPublicHandler(), - services: services.NewPublicHandler(), + home: home.NewPublicHandler(), + booking: booking.NewPublicHandler(), + campsite: campsite.NewPublicHandler(), + legal: legal.NewPublicHandler(), + location: location.NewPublicHandler(), + services: services.NewPublicHandler(), + surroundings: surroundings.NewPublicHandler(), } } @@ -60,27 +63,7 @@ func (h *publicHandler) Handler(user *auth.User, company *auth.Company, conn *da case "services": h.services.Handler(user, company, conn).ServeHTTP(w, r) case "surroundings": - surroundingsHandler(user, company, conn).ServeHTTP(w, r) - default: - http.NotFound(w, r) - } - }) -} - -func surroundingsHandler(user *auth.User, company *auth.Company, conn *database.Conn) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - var head string - head, r.URL.Path = httplib.ShiftPath(r.URL.Path) - switch head { - case "": - switch r.Method { - case http.MethodGet: - page := template.NewPublicPage() - page.Setup(r, user, company, conn) - template.MustRenderPublic(w, r, user, company, "surroundings.gohtml", page) - default: - httplib.MethodNotAllowed(w, r, http.MethodGet) - } + h.surroundings.Handler(user, company, conn).ServeHTTP(w, r) default: http.NotFound(w, r) } diff --git a/pkg/database/funcs.go b/pkg/database/funcs.go index 3616342..2f68f2f 100644 --- a/pkg/database/funcs.go +++ b/pkg/database/funcs.go @@ -150,3 +150,27 @@ func (c *Conn) OrderServices(ctx context.Context, ids []int) error { _, err := c.Exec(ctx, "select order_services($1)", ids) return err } + +func (tx *Tx) AddSurroundingsHighlight(ctx context.Context, companyID int, mediaID int, name string, description string) (int, error) { + return tx.GetInt(ctx, "select add_surroundings_highlight($1, $2, $3, $4)", companyID, mediaID, name, description) +} + +func (tx *Tx) EditSurroundingsHighlight(ctx context.Context, id int, mediaID int, name string, description string) error { + _, err := tx.Exec(ctx, "select edit_surroundings_highlight($1, $2, $3, $4)", id, mediaID, name, description) + return err +} + +func (tx *Tx) TranslateSurroundingsHighlight(ctx context.Context, id int, langTag language.Tag, name string, description string) error { + _, err := tx.Exec(ctx, "select translate_surroundings_highlight($1, $2, $3, $4)", id, langTag, name, description) + return err +} + +func (c *Conn) OrderSurroundingsHighlights(ctx context.Context, ids []int) error { + _, err := c.Exec(ctx, "select order_surroundings_highlights($1)", ids) + return err +} + +func (c *Conn) RemoveSurroundingsHighlight(ctx context.Context, id int) error { + _, err := c.Exec(ctx, "select remove_surroundings_highlight($1)", id) + return err +} diff --git a/pkg/surroundings/admin.go b/pkg/surroundings/admin.go new file mode 100644 index 0000000..14349c5 --- /dev/null +++ b/pkg/surroundings/admin.go @@ -0,0 +1,327 @@ +/* + * SPDX-FileCopyrightText: 2023 jordi fita mas + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package surroundings + +import ( + "context" + "net/http" + "strconv" + + "github.com/jackc/pgx/v4" + + "dev.tandem.ws/tandem/camper/pkg/auth" + "dev.tandem.ws/tandem/camper/pkg/database" + "dev.tandem.ws/tandem/camper/pkg/form" + httplib "dev.tandem.ws/tandem/camper/pkg/http" + "dev.tandem.ws/tandem/camper/pkg/locale" + "dev.tandem.ws/tandem/camper/pkg/template" +) + +type AdminHandler struct { +} + +func NewAdminHandler() *AdminHandler { + return &AdminHandler{} +} + +func (h *AdminHandler) Handler(user *auth.User, company *auth.Company, conn *database.Conn) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var head string + head, r.URL.Path = httplib.ShiftPath(r.URL.Path) + + switch head { + case "": + switch r.Method { + case http.MethodGet: + serveHighlightsIndex(w, r, user, company, conn) + case http.MethodPost: + addHighlight(w, r, user, company, conn) + default: + httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPost) + } + case "new": + switch r.Method { + case http.MethodGet: + f := newHighlightForm(company) + f.MustRender(w, r, user, company) + default: + httplib.MethodNotAllowed(w, r, http.MethodGet) + } + case "order": + switch r.Method { + case http.MethodPost: + orderHighlights(w, r, user, company, conn) + default: + httplib.MethodNotAllowed(w, r, http.MethodPost) + } + default: + id, err := strconv.Atoi(head) + if err != nil { + http.NotFound(w, r) + return + } + f := newHighlightForm(company) + if err := f.FillFromDatabase(r.Context(), conn, id); err != nil { + if database.ErrorIsNotFound(err) { + http.NotFound(w, r) + return + } + panic(err) + } + + head, r.URL.Path = httplib.ShiftPath(r.URL.Path) + switch head { + case "": + switch r.Method { + case http.MethodGet: + f.MustRender(w, r, user, company) + case http.MethodPut: + editHighlight(w, r, user, company, conn, f) + case http.MethodDelete: + deleteHighlight(w, r, user, conn, id) + default: + httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut, http.MethodDelete) + } + default: + http.NotFound(w, r) + } + } + }) +} + +func orderHighlights(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) { + if err := r.ParseForm(); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + if err := user.VerifyCSRFToken(r); err != nil { + http.Error(w, err.Error(), http.StatusForbidden) + return + } + input := r.PostForm["highlight_id"] + if len(input) > 0 { + var ids []int + for _, s := range input { + if id, err := strconv.Atoi(s); err == nil { + ids = append(ids, id) + } else { + http.Error(w, err.Error(), http.StatusUnprocessableEntity) + return + } + } + if err := conn.OrderSurroundingsHighlights(r.Context(), ids); err != nil { + panic(err) + } + } + serveHighlightsIndex(w, r, user, company, conn) +} + +func serveHighlightsIndex(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) { + highlights, err := collectHighlightEntries(r.Context(), company, conn) + if err != nil { + panic(err) + } + page := &highlightIndex{ + Highlights: highlights, + } + page.MustRender(w, r, user, company) +} + +type highlightIndex struct { + Highlights []*highlightEntry +} + +func (page *highlightIndex) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) { + template.MustRenderAdmin(w, r, user, company, "surroundings/index.gohtml", page) +} + +type highlightEntry struct { + ID int + URL string + Media string + Name string +} + +func collectHighlightEntries(ctx context.Context, company *auth.Company, conn *database.Conn) ([]*highlightEntry, error) { + rows, err := conn.Query(ctx, ` + select surroundings_highlight_id + , '/admin/surroundings/' || surroundings_highlight_id + , media.path + , name + from surroundings_highlight as highlight + join media using (media_id) + where highlight.company_id = $1 + order by position + , name + `, company.ID) + if err != nil { + return nil, err + } + defer rows.Close() + + var highlights []*highlightEntry + for rows.Next() { + entry := &highlightEntry{} + if err = rows.Scan(&entry.ID, &entry.URL, &entry.Media, &entry.Name); err != nil { + return nil, err + } + highlights = append(highlights, entry) + } + + return highlights, nil +} + +func addHighlight(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) { + f := newHighlightForm(company) + processHighlightForm(w, r, user, company, conn, f, func(ctx context.Context, tx *database.Tx) error { + var err error + if f.ID, err = tx.AddSurroundingsHighlight(ctx, company.ID, f.Media.Int(), f.Name[f.DefaultLang].Val, f.Description[f.DefaultLang].Val); err != nil { + return err + } + return translateHighlight(ctx, tx, company, f) + }) +} + +func processHighlightForm(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, f *highlightForm, act func(context.Context, *database.Tx) error) { + if err := f.Parse(r); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + if err := user.VerifyCSRFToken(r); err != nil { + http.Error(w, err.Error(), http.StatusForbidden) + return + } + if ok, err := f.Valid(r.Context(), conn, user.Locale); err != nil { + panic(err) + } else if !ok { + if !httplib.IsHTMxRequest(r) { + w.WriteHeader(http.StatusUnprocessableEntity) + } + f.MustRender(w, r, user, company) + return + } + tx := conn.MustBegin(r.Context()) + if err := act(r.Context(), tx); err == nil { + tx.MustCommit(r.Context()) + } else { + if rErr := tx.Rollback(r.Context()); rErr != nil { + err = rErr + } + panic(err) + } + httplib.Redirect(w, r, "/admin/surroundings", http.StatusSeeOther) +} + +func translateHighlight(ctx context.Context, tx *database.Tx, company *auth.Company, f *highlightForm) error { + for lang := range company.Locales { + l := lang.String() + if l == f.DefaultLang { + continue + } + if err := tx.TranslateSurroundingsHighlight(ctx, f.ID, lang, f.Name[l].Val, f.Description[l].Val); err != nil { + return err + } + } + return nil +} + +func editHighlight(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, f *highlightForm) { + processHighlightForm(w, r, user, company, conn, f, func(ctx context.Context, tx *database.Tx) error { + if err := tx.EditSurroundingsHighlight(ctx, f.ID, f.Media.Int(), f.Name[f.DefaultLang].Val, f.Description[f.DefaultLang].Val); err != nil { + return err + } + return translateHighlight(ctx, tx, company, f) + }) + httplib.Redirect(w, r, "/admin/surroundings", http.StatusSeeOther) +} + +func deleteHighlight(w http.ResponseWriter, r *http.Request, user *auth.User, conn *database.Conn, id int) { + if err := user.VerifyCSRFToken(r); err != nil { + http.Error(w, err.Error(), http.StatusForbidden) + return + } + if err := conn.RemoveSurroundingsHighlight(r.Context(), id); err != nil { + panic(err) + } + httplib.Redirect(w, r, "/admin/surroundings", http.StatusSeeOther) +} + +type highlightForm struct { + DefaultLang string + ID int + Media *form.Media + Name form.I18nInput + Description form.I18nInput +} + +func newHighlightForm(company *auth.Company) *highlightForm { + return &highlightForm{ + DefaultLang: company.DefaultLanguage.String(), + Media: &form.Media{ + Input: &form.Input{ + Name: "media", + }, + Label: locale.PgettextNoop("Highlight image", "input"), + Prompt: locale.PgettextNoop("Set highlight image", "action"), + }, + Name: form.NewI18nInput(company.Locales, "name"), + Description: form.NewI18nInput(company.Locales, "description"), + } +} + +func (f *highlightForm) FillFromDatabase(ctx context.Context, conn *database.Conn, id int) error { + f.ID = id + var name database.RecordArray + var description database.RecordArray + row := conn.QueryRow(ctx, ` + select media_id::text + , highlight.name + , highlight.description::text + , array_agg((lang_tag, i18n.name)) + , array_agg((lang_tag, i18n.description::text)) + from surroundings_highlight as highlight + left join surroundings_highlight_i18n as i18n using (surroundings_highlight_id) + where surroundings_highlight_id = $1 + group by media_id::text + , highlight.name + , highlight.description::text + `, pgx.QueryResultFormats{pgx.BinaryFormatCode}, id) + if err := row.Scan(&f.Media.Val, &f.Name[f.DefaultLang].Val, &f.Description[f.DefaultLang].Val, &name, &description); err != nil { + return err + } + if err := f.Name.FillArray(name); err != nil { + return err + } + if err := f.Description.FillArray(description); err != nil { + return err + } + return nil +} + +func (f *highlightForm) Parse(r *http.Request) error { + if err := r.ParseForm(); err != nil { + return err + } + f.Media.FillValue(r) + f.Name.FillValue(r) + f.Description.FillValue(r) + return nil +} + +func (f *highlightForm) Valid(ctx context.Context, conn *database.Conn, l *locale.Locale) (bool, error) { + v := form.NewValidator(l) + if v.CheckRequired(f.Media.Input, l.GettextNoop("Slide image can not be empty.")) { + if _, err := v.CheckImageMedia(ctx, conn, f.Media.Input, l.GettextNoop("Slide image must be an image media type.")); err != nil { + return false, err + } + } + v.CheckRequired(f.Name[f.DefaultLang], l.GettextNoop("Name can not be empty.")) + return v.AllOK, nil +} + +func (f *highlightForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) { + template.MustRenderAdmin(w, r, user, company, "surroundings/form.gohtml", f) +} diff --git a/pkg/surroundings/public.go b/pkg/surroundings/public.go new file mode 100644 index 0000000..16ff5d2 --- /dev/null +++ b/pkg/surroundings/public.go @@ -0,0 +1,98 @@ +/* + * SPDX-FileCopyrightText: 2023 jordi fita mas + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package surroundings + +import ( + "context" + gotemplate "html/template" + "net/http" + + "dev.tandem.ws/tandem/camper/pkg/auth" + "dev.tandem.ws/tandem/camper/pkg/database" + httplib "dev.tandem.ws/tandem/camper/pkg/http" + "dev.tandem.ws/tandem/camper/pkg/locale" + "dev.tandem.ws/tandem/camper/pkg/template" +) + +type PublicHandler struct { +} + +func NewPublicHandler() *PublicHandler { + return &PublicHandler{} +} + +func (h *PublicHandler) Handler(user *auth.User, company *auth.Company, conn *database.Conn) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var head string + head, r.URL.Path = httplib.ShiftPath(r.URL.Path) + switch head { + case "": + switch r.Method { + case http.MethodGet: + page := newSurroundingsPage() + page.MustRender(w, r, user, company, conn) + default: + httplib.MethodNotAllowed(w, r, http.MethodGet) + } + default: + http.NotFound(w, r) + } + }) +} + +type surroundingsPage struct { + *template.PublicPage + Highlights []*highlight +} + +func newSurroundingsPage() *surroundingsPage { + return &surroundingsPage{PublicPage: template.NewPublicPage()} +} + +func (p *surroundingsPage) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) { + p.Setup(r, user, company, conn) + p.Highlights = mustCollectSurroundings(r.Context(), company, conn, user.Locale) + template.MustRenderPublic(w, r, user, company, "surroundings.gohtml", p) +} + +type highlight struct { + Media string + Name string + Description gotemplate.HTML +} + +func mustCollectSurroundings(ctx context.Context, company *auth.Company, conn *database.Conn, loc *locale.Locale) []*highlight { + rows, err := conn.Query(ctx, ` + select media.path + , coalesce(i18n.name, highlight.name) as l10_name + , coalesce(i18n.description, highlight.description)::text as l10_description + from surroundings_highlight as highlight + join media using (media_id) + left join surroundings_highlight_i18n as i18n on highlight.surroundings_highlight_id = i18n.surroundings_highlight_id and lang_tag = $1 + where highlight.company_id = $2 + order by position + , l10_name + `, loc.Language, company.ID) + if err != nil { + panic(err) + } + defer rows.Close() + + var items []*highlight + for rows.Next() { + item := &highlight{} + err = rows.Scan(&item.Media, &item.Name, &item.Description) + if err != nil { + panic(err) + } + items = append(items, item) + } + if rows.Err() != nil { + panic(rows.Err()) + } + + return items +} diff --git a/po/ca.po b/po/ca.po index 87e4172..63779b8 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-15 02:00+0100\n" +"POT-Creation-Date: 2024-01-16 00:48+0100\n" "PO-Revision-Date: 2023-07-22 23:45+0200\n" "Last-Translator: jordi fita mas \n" "Language-Team: Catalan \n" @@ -56,7 +56,7 @@ 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/admin/layout.gohtml:60 +#: web/templates/admin/layout.gohtml:61 msgctxt "title" msgid "Location" msgstr "Com arribar" @@ -86,8 +86,9 @@ msgstr "Vine a gaudir!" #: web/templates/public/home.gohtml:35 #: web/templates/public/surroundings.gohtml:6 -#: web/templates/public/surroundings.gohtml:10 +#: web/templates/public/surroundings.gohtml:11 #: web/templates/public/layout.gohtml:67 web/templates/public/layout.gohtml:95 +#: web/templates/admin/layout.gohtml:64 msgctxt "title" msgid "Surroundings" msgstr "L’entorn" @@ -251,61 +252,45 @@ msgctxt "day" msgid "Sun" msgstr "dg" -#: web/templates/public/surroundings.gohtml:28 +#: web/templates/public/surroundings.gohtml:31 msgctxt "title" msgid "What to Do Outside the Campsite?" msgstr "Què fer des del càmping?" -#: web/templates/public/surroundings.gohtml:31 -msgid "Campsite Montagut is an ideal starting point for quiet outings, climbing, swimming in the river and gorges, volcanoes, the Fageda d’en Jordà, cycle tours for all ages…." -msgstr "El Càmping Montagut és ideal com a punt de partida d’excursions tranquil·les, escalada, banyar-se en el riu i gorgues, volcans, la Fageda d’en Jordà, sortides amb bicicleta per a tots els nivells…." - -#: web/templates/public/surroundings.gohtml:38 -msgid "Get to the Costa Brava and enjoy the beaches, the gastronomy or go kayaking…." -msgstr "Arribar fins a la costa brava i gaudir de les platges, la gastronomia o anar amb caiac…." - -#: web/templates/public/surroundings.gohtml:47 -msgid "You will also find museums in Olot, Figures, Girona." -msgstr "També trobareu museus a Olot, Figueres, Girona." - -#: web/templates/public/surroundings.gohtml:48 -msgid "As well as music festivals, dance, theater…." -msgstr "Com festivals de música, dansa, teatre…." - -#: web/templates/public/surroundings.gohtml:54 +#: web/templates/public/surroundings.gohtml:51 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:57 +#: web/templates/public/surroundings.gohtml:54 msgid "Cycle routes" msgstr "Rutes amb bicicleta" -#: web/templates/public/surroundings.gohtml:58 +#: web/templates/public/surroundings.gohtml:55 msgid "There are many bicycle rental companies in Olot." msgstr "A Olot podeu trobar empreses de lloguer de bicicletes." -#: web/templates/public/surroundings.gohtml:62 +#: web/templates/public/surroundings.gohtml:59 msgid "Routes" msgstr "Rutes" -#: web/templates/public/surroundings.gohtml:63 +#: web/templates/public/surroundings.gohtml:60 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:67 +#: web/templates/public/surroundings.gohtml:64 msgid "Family outing" msgstr "Excursions familiars" -#: web/templates/public/surroundings.gohtml:68 +#: web/templates/public/surroundings.gohtml:65 msgid "Many outing possibilities, for all ages." msgstr "Múltiples excursions per a totes les edats." -#: web/templates/public/surroundings.gohtml:72 +#: web/templates/public/surroundings.gohtml:69 msgid "Kayak" msgstr "Caiac" -#: web/templates/public/surroundings.gohtml:73 +#: web/templates/public/surroundings.gohtml:70 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…." @@ -410,7 +395,7 @@ msgstr "He llegit i accepto les condicions de r msgid "Campsite Montagut" msgstr "Càmping Montagut" -#: web/templates/public/layout.gohtml:23 web/templates/admin/layout.gohtml:20 +#: web/templates/public/layout.gohtml:23 web/templates/admin/layout.gohtml:21 msgid "Skip to main content" msgstr "Salta al contingut principal" @@ -421,7 +406,7 @@ msgstr "Menú" #: web/templates/public/layout.gohtml:57 web/templates/public/layout.gohtml:103 #: web/templates/admin/campsite/index.gohtml:6 #: web/templates/admin/campsite/index.gohtml:12 -#: web/templates/admin/layout.gohtml:45 web/templates/admin/layout.gohtml:82 +#: web/templates/admin/layout.gohtml:46 web/templates/admin/layout.gohtml:86 msgctxt "title" msgid "Campsites" msgstr "Allotjaments" @@ -464,6 +449,7 @@ msgstr "Àlies" #: web/templates/admin/season/form.gohtml:46 #: web/templates/admin/services/form.gohtml:52 #: web/templates/admin/profile.gohtml:26 +#: web/templates/admin/surroundings/form.gohtml:37 msgctxt "input" msgid "Name" msgstr "Nom" @@ -482,6 +468,7 @@ msgstr "Contingut" #: web/templates/admin/campsite/type/form.gohtml:171 #: web/templates/admin/season/form.gohtml:69 #: web/templates/admin/services/form.gohtml:80 +#: web/templates/admin/surroundings/form.gohtml:65 #: web/templates/admin/media/form.gohtml:35 msgctxt "action" msgid "Update" @@ -496,13 +483,14 @@ msgstr "Actualitza" #: web/templates/admin/campsite/type/form.gohtml:173 #: web/templates/admin/season/form.gohtml:71 #: web/templates/admin/services/form.gohtml:82 +#: web/templates/admin/surroundings/form.gohtml:67 msgctxt "action" msgid "Add" msgstr "Afegeix" #: web/templates/admin/legal/index.gohtml:6 #: web/templates/admin/legal/index.gohtml:12 -#: web/templates/admin/layout.gohtml:63 +#: web/templates/admin/layout.gohtml:67 msgctxt "title" msgid "Legal Texts" msgstr "Texts legals" @@ -517,6 +505,7 @@ msgstr "Afegeix text legal" #: web/templates/admin/campsite/option/index.gohtml:25 #: web/templates/admin/campsite/type/index.gohtml:25 #: web/templates/admin/season/index.gohtml:26 +#: web/templates/admin/surroundings/index.gohtml:26 msgctxt "header" msgid "Name" msgstr "Nom" @@ -630,6 +619,7 @@ msgstr "Afegeix diapositiva" #: web/templates/admin/campsite/carousel/index.gohtml:25 #: web/templates/admin/services/index.gohtml:25 +#: web/templates/admin/surroundings/index.gohtml:25 #: web/templates/admin/home/index.gohtml:25 msgctxt "header" msgid "Image" @@ -645,6 +635,7 @@ msgstr "Llegenda" #: web/templates/admin/campsite/carousel/index.gohtml:27 #: web/templates/admin/services/index.gohtml:27 #: web/templates/admin/services/index.gohtml:72 +#: web/templates/admin/surroundings/index.gohtml:27 #: web/templates/admin/home/index.gohtml:27 msgctxt "header" msgid "Actions" @@ -659,6 +650,7 @@ msgstr "Esteu segur de voler esborrar aquesta diapositiva?" #: web/templates/admin/campsite/carousel/index.gohtml:45 #: web/templates/admin/services/index.gohtml:44 #: web/templates/admin/services/index.gohtml:88 +#: web/templates/admin/surroundings/index.gohtml:44 #: web/templates/admin/home/index.gohtml:44 msgctxt "action" msgid "Delete" @@ -826,6 +818,7 @@ msgstr "Equipaments" #: web/templates/admin/campsite/type/form.gohtml:143 #: web/templates/admin/services/form.gohtml:65 +#: web/templates/admin/surroundings/form.gohtml:50 msgctxt "input" msgid "Description" msgstr "Descripció" @@ -837,7 +830,7 @@ msgstr "Informació addicional" #: web/templates/admin/campsite/type/index.gohtml:6 #: web/templates/admin/campsite/type/index.gohtml:12 -#: web/templates/admin/layout.gohtml:42 +#: web/templates/admin/layout.gohtml:43 msgctxt "title" msgid "Campsite Types" msgstr "Tipus d’allotjaments" @@ -906,7 +899,7 @@ msgstr "Color" #: web/templates/admin/season/index.gohtml:6 #: web/templates/admin/season/index.gohtml:12 -#: web/templates/admin/layout.gohtml:48 +#: web/templates/admin/layout.gohtml:49 msgctxt "title" msgid "Seasons" msgstr "Temporades" @@ -932,7 +925,7 @@ msgid "Cancel" msgstr "Canceŀla" #: web/templates/admin/payment.gohtml:6 web/templates/admin/payment.gohtml:12 -#: web/templates/admin/layout.gohtml:39 +#: web/templates/admin/layout.gohtml:40 msgctxt "title" msgid "Payment Settings" msgstr "Paràmetres de pagament" @@ -968,7 +961,7 @@ msgid "Integration" msgstr "Integració" #: web/templates/admin/dashboard.gohtml:6 -#: web/templates/admin/dashboard.gohtml:10 web/templates/admin/layout.gohtml:79 +#: web/templates/admin/dashboard.gohtml:10 web/templates/admin/layout.gohtml:83 msgctxt "title" msgid "Dashboard" msgstr "Tauler" @@ -1001,7 +994,7 @@ msgid "New Service" msgstr "Nou servei" #: web/templates/admin/services/index.gohtml:6 -#: web/templates/admin/layout.gohtml:57 +#: web/templates/admin/layout.gohtml:58 msgctxt "title" msgid "Services Page" msgstr "Pàgina de serveis" @@ -1036,7 +1029,7 @@ msgid "No services added yet." msgstr "No s’ha afegit cap servei encara." #: web/templates/admin/profile.gohtml:6 web/templates/admin/profile.gohtml:12 -#: web/templates/admin/layout.gohtml:32 +#: web/templates/admin/layout.gohtml:33 msgctxt "title" msgid "Profile" msgstr "Perfil" @@ -1143,29 +1136,64 @@ msgctxt "input" msgid "Legal Disclaimer" msgstr "Nota legal" -#: web/templates/admin/layout.gohtml:28 +#: web/templates/admin/surroundings/form.gohtml:8 +#: web/templates/admin/surroundings/form.gohtml:25 +msgctxt "title" +msgid "Edit Highlight" +msgstr "Edició del punt d’interès" + +#: web/templates/admin/surroundings/form.gohtml:10 +#: web/templates/admin/surroundings/form.gohtml:27 +msgctxt "title" +msgid "New Highlight" +msgstr "Nou punt d’interès" + +#: web/templates/admin/surroundings/index.gohtml:6 +msgctxt "title" +msgid "Surroundings Page" +msgstr "Pàgina de l’entorn" + +#: web/templates/admin/surroundings/index.gohtml:11 +msgctxt "title" +msgid "Highlights" +msgstr "Punts d’interès" + +#: web/templates/admin/surroundings/index.gohtml:12 +msgctxt "action" +msgid "Add highlight" +msgstr "Afegeix punt d’interès" + +#: web/templates/admin/surroundings/index.gohtml:31 +msgid "Are you sure you wish to delete this highlight?" +msgstr "Esteu segur de voler esborrar aquest punt d’interès?" + +#: web/templates/admin/surroundings/index.gohtml:53 +msgid "No highlights added yet." +msgstr "No s’ha afegit cap punt d’interès encara." + +#: web/templates/admin/layout.gohtml:29 msgctxt "title" msgid "User Menu" msgstr "Menú d’usuari" -#: web/templates/admin/layout.gohtml:36 +#: web/templates/admin/layout.gohtml:37 msgctxt "title" msgid "Company Settings" msgstr "Paràmetres de l’empresa" -#: web/templates/admin/layout.gohtml:51 +#: web/templates/admin/layout.gohtml:52 #: web/templates/admin/media/index.gohtml:6 #: web/templates/admin/media/index.gohtml:11 msgctxt "title" msgid "Media" msgstr "Mèdia" -#: web/templates/admin/layout.gohtml:54 web/templates/admin/home/index.gohtml:6 +#: web/templates/admin/layout.gohtml:55 web/templates/admin/home/index.gohtml:6 msgctxt "title" msgid "Home Page" msgstr "Pàgina d’inici" -#: web/templates/admin/layout.gohtml:68 +#: web/templates/admin/layout.gohtml:72 msgctxt "action" msgid "Logout" msgstr "Surt" @@ -1236,31 +1264,34 @@ msgid "Upload Media" 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:464 -#: pkg/season/admin.go:415 pkg/services/admin.go:319 +#: pkg/campsite/types/feature.go:259 pkg/campsite/types/admin.go:463 +#: pkg/season/admin.go:412 pkg/services/admin.go:314 +#: pkg/surroundings/admin.go:321 msgid "Name can not be empty." msgstr "No podeu deixar el nom en blanc." #: pkg/legal/admin.go:259 pkg/campsite/types/option.go:345 -#: pkg/campsite/types/feature.go:260 pkg/campsite/types/admin.go:465 +#: pkg/campsite/types/feature.go:260 pkg/campsite/types/admin.go:464 msgid "Name must have at least one letter." msgstr "El nom ha de tenir com a mínim una lletra." -#: pkg/carousel/admin.go:269 pkg/campsite/types/carousel.go:223 +#: pkg/carousel/admin.go:267 pkg/campsite/types/carousel.go:223 msgctxt "input" msgid "Slide image" msgstr "Imatge de la diapositiva" -#: pkg/carousel/admin.go:270 pkg/campsite/types/carousel.go:224 +#: pkg/carousel/admin.go:268 pkg/campsite/types/carousel.go:224 msgctxt "action" msgid "Set slide image" msgstr "Estableix la imatge de la diapositiva" -#: pkg/carousel/admin.go:339 pkg/campsite/types/carousel.go:297 +#: pkg/carousel/admin.go:337 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:340 pkg/campsite/types/carousel.go:298 +#: pkg/carousel/admin.go:338 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." @@ -1299,7 +1330,7 @@ msgstr "L’idioma escollit no és vàlid." msgid "File must be a valid PNG or JPEG image." msgstr "El fitxer has de ser una imatge PNG o JPEG vàlida." -#: pkg/app/admin.go:62 +#: pkg/app/admin.go:64 msgid "Access forbidden" msgstr "Accés prohibit" @@ -1327,61 +1358,61 @@ msgstr "El valor del màxim ha de ser un número enter." msgid "Maximum must be equal or greater than minimum." msgstr "El valor del màxim ha de ser igual o superir al del mínim." -#: pkg/campsite/types/option.go:361 pkg/campsite/types/admin.go:478 +#: pkg/campsite/types/option.go:361 pkg/campsite/types/admin.go:477 msgid "Price per night can not be empty." msgstr "No podeu deixar el preu per nit en blanc." -#: pkg/campsite/types/option.go:362 pkg/campsite/types/admin.go:479 +#: pkg/campsite/types/option.go:362 pkg/campsite/types/admin.go:478 msgid "Price per night must be a decimal number." msgstr "El preu per nit ha de ser un número decimal." -#: pkg/campsite/types/option.go:363 pkg/campsite/types/admin.go:480 +#: pkg/campsite/types/option.go:363 pkg/campsite/types/admin.go:479 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:318 +#: pkg/campsite/types/feature.go:258 pkg/services/admin.go:313 msgid "Selected icon is not valid." msgstr "La icona escollida no és vàlida." -#: pkg/campsite/types/admin.go:306 +#: pkg/campsite/types/admin.go:305 msgctxt "input" msgid "Cover image" msgstr "Imatge de portada" -#: pkg/campsite/types/admin.go:307 +#: pkg/campsite/types/admin.go:306 msgctxt "action" msgid "Set campsite type cover" msgstr "Estableix la portada del tipus d’allotjament" -#: pkg/campsite/types/admin.go:467 +#: pkg/campsite/types/admin.go:466 msgid "Cover image can not be empty." msgstr "No podeu deixar la imatge de portada en blanc." -#: pkg/campsite/types/admin.go:468 +#: pkg/campsite/types/admin.go:467 msgid "Cover image must be an image media type." msgstr "La imatge de portada ha de ser un mèdia de tipus imatge." -#: pkg/campsite/types/admin.go:472 +#: pkg/campsite/types/admin.go:471 msgid "Maximum number of campers can not be empty." msgstr "No podeu deixar el número màxim de persones en blanc." -#: pkg/campsite/types/admin.go:473 +#: pkg/campsite/types/admin.go:472 msgid "Maximum number of campers must be an integer number." msgstr "El número màxim de persones ha de ser enter." -#: pkg/campsite/types/admin.go:474 +#: pkg/campsite/types/admin.go:473 msgid "Maximum number of campers must be one or greater." msgstr "El número màxim de persones no pot ser zero." -#: pkg/campsite/types/admin.go:483 +#: pkg/campsite/types/admin.go:482 msgid "Minimum number of nights can not be empty." msgstr "No podeu deixar el número mínim de nits en blanc." -#: pkg/campsite/types/admin.go:484 +#: pkg/campsite/types/admin.go:483 msgid "Minimum number of nights must be an integer." msgstr "El número mínim de nits ha de ser enter." -#: pkg/campsite/types/admin.go:485 +#: pkg/campsite/types/admin.go:484 msgid "Minimum number of nights must be one or greater." msgstr "El número mínim de nits no pot ser zero." @@ -1393,95 +1424,105 @@ msgstr "El tipus d’allotjament escollit no és vàlid." msgid "Label can not be empty." msgstr "No podeu deixar l’etiqueta en blanc." -#: pkg/season/admin.go:186 +#: pkg/season/admin.go:183 msgctxt "month" msgid "January" msgstr "gener" -#: pkg/season/admin.go:187 +#: pkg/season/admin.go:184 msgctxt "month" msgid "February" msgstr "febrer" -#: pkg/season/admin.go:188 +#: pkg/season/admin.go:185 msgctxt "month" msgid "March" msgstr "març" -#: pkg/season/admin.go:189 +#: pkg/season/admin.go:186 msgctxt "month" msgid "April" msgstr "abril" -#: pkg/season/admin.go:190 +#: pkg/season/admin.go:187 msgctxt "month" msgid "May" msgstr "maig" -#: pkg/season/admin.go:191 +#: pkg/season/admin.go:188 msgctxt "month" msgid "June" msgstr "juny" -#: pkg/season/admin.go:192 +#: pkg/season/admin.go:189 msgctxt "month" msgid "July" msgstr "juliol" -#: pkg/season/admin.go:193 +#: pkg/season/admin.go:190 msgctxt "month" msgid "August" msgstr "agost" -#: pkg/season/admin.go:194 +#: pkg/season/admin.go:191 msgctxt "month" msgid "September" msgstr "setembre" -#: pkg/season/admin.go:195 +#: pkg/season/admin.go:192 msgctxt "month" msgid "October" msgstr "octubre" -#: pkg/season/admin.go:196 +#: pkg/season/admin.go:193 msgctxt "month" msgid "November" msgstr "novembre" -#: pkg/season/admin.go:197 +#: pkg/season/admin.go:194 msgctxt "month" msgid "December" msgstr "desembre" -#: pkg/season/admin.go:416 +#: pkg/season/admin.go:413 msgid "Color can not be empty." msgstr "No podeu deixar el color en blanc." -#: pkg/season/admin.go:417 +#: pkg/season/admin.go:414 msgid "This color is not valid. It must be like #123abc." msgstr "Aquest color no és vàlid. Hauria de ser similar a #123abc." -#: pkg/season/admin.go:517 +#: pkg/season/admin.go:514 msgctxt "action" msgid "Unset" msgstr "Desassigna" -#: pkg/season/admin.go:548 +#: pkg/season/admin.go:545 msgid "Start date can not be empty." msgstr "No podeu deixar la data d’inici en blanc." -#: pkg/season/admin.go:549 +#: pkg/season/admin.go:546 msgid "Start date must be a valid date." msgstr "La data d’inici ha de ser una data vàlida." -#: pkg/season/admin.go:551 +#: pkg/season/admin.go:548 msgid "End date can not be empty." msgstr "No podeu deixar la data de fi en blanc." -#: pkg/season/admin.go:552 +#: pkg/season/admin.go:549 msgid "End date must be a valid date." msgstr "La data de fi ha de ser una data vàlida." +#: pkg/surroundings/admin.go:267 +msgctxt "input" +msgid "Highlight image" +msgstr "Imatge del punt d’interès" + +#: pkg/surroundings/admin.go:268 +msgctxt "action" +msgid "Set highlight image" +msgstr "Estableix la imatge del punt d’interès" + #: pkg/company/admin.go:200 pkg/booking/public.go:256 msgid "Selected country is not valid." msgstr "El país escollit no és vàlid." @@ -1562,11 +1603,11 @@ msgstr "No podeu deixar el format del número de factura en blanc." msgid "Cross-site request forgery detected." msgstr "S’ha detectat un intent de falsificació de petició a llocs creuats." -#: pkg/media/admin.go:265 +#: pkg/media/admin.go:312 msgid "Uploaded file can not be empty." msgstr "No podeu deixar el fitxer del mèdia en blanc." -#: pkg/media/admin.go:324 +#: pkg/media/admin.go:371 msgid "Filename can not be empty." msgstr "No podeu deixar el nom del fitxer en blanc." @@ -1674,6 +1715,18 @@ msgstr "El valor de %s ha de ser com a mínim %d." msgid "%s must be at most %d." msgstr "El valor de %s ha de ser com a màxim %d." +#~ msgid "Campsite Montagut is an ideal starting point for quiet outings, climbing, swimming in the river and gorges, volcanoes, the Fageda d’en Jordà, cycle tours for all ages…." +#~ msgstr "El Càmping Montagut és ideal com a punt de partida d’excursions tranquil·les, escalada, banyar-se en el riu i gorgues, volcans, la Fageda d’en Jordà, sortides amb bicicleta per a tots els nivells…." + +#~ msgid "Get to the Costa Brava and enjoy the beaches, the gastronomy or go kayaking…." +#~ msgstr "Arribar fins a la costa brava i gaudir de les platges, la gastronomia o anar amb caiac…." + +#~ msgid "You will also find museums in Olot, Figures, Girona." +#~ msgstr "També trobareu museus a Olot, Figueres, Girona." + +#~ msgid "As well as music festivals, dance, theater…." +#~ msgstr "Com festivals de música, dansa, teatre…." + #~ msgctxt "header" #~ msgid "Translations" #~ msgstr "Traduccions" diff --git a/po/es.po b/po/es.po index 6a95bdd..1f58f23 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-15 02:00+0100\n" +"POT-Creation-Date: 2024-01-16 00:48+0100\n" "PO-Revision-Date: 2023-07-22 23:46+0200\n" "Last-Translator: jordi fita mas \n" "Language-Team: Spanish \n" @@ -56,7 +56,7 @@ 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/admin/layout.gohtml:60 +#: web/templates/admin/layout.gohtml:61 msgctxt "title" msgid "Location" msgstr "Cómo llegar" @@ -86,8 +86,9 @@ msgstr "¡Ven a disfrutar!" #: web/templates/public/home.gohtml:35 #: web/templates/public/surroundings.gohtml:6 -#: web/templates/public/surroundings.gohtml:10 +#: web/templates/public/surroundings.gohtml:11 #: web/templates/public/layout.gohtml:67 web/templates/public/layout.gohtml:95 +#: web/templates/admin/layout.gohtml:64 msgctxt "title" msgid "Surroundings" msgstr "El entorno" @@ -251,61 +252,45 @@ msgctxt "day" msgid "Sun" msgstr "do" -#: web/templates/public/surroundings.gohtml:28 +#: web/templates/public/surroundings.gohtml:31 msgctxt "title" msgid "What to Do Outside the Campsite?" msgstr "¿Qué hacer desde el camping?" -#: web/templates/public/surroundings.gohtml:31 -msgid "Campsite Montagut is an ideal starting point for quiet outings, climbing, swimming in the river and gorges, volcanoes, the Fageda d’en Jordà, cycle tours for all ages…." -msgstr "El Camping Montagut es ideal como punto de salida de excursiones tranquilas, escalada, bañarse en el río y piletones, volcanes, la Fageda d’en Jordà, salidas en bicicleta para todos los niveles…." - -#: web/templates/public/surroundings.gohtml:38 -msgid "Get to the Costa Brava and enjoy the beaches, the gastronomy or go kayaking…." -msgstr "Llegar hasta la Costa Brava y disfrutar de las playas, la gastronomía o ir en kayak…." - -#: web/templates/public/surroundings.gohtml:47 -msgid "You will also find museums in Olot, Figures, Girona." -msgstr "También encontraréis museos en Olot, Figueres, Girona." - -#: web/templates/public/surroundings.gohtml:48 -msgid "As well as music festivals, dance, theater…." -msgstr "Como festivales de música, danza, teatro…." - -#: web/templates/public/surroundings.gohtml:54 +#: web/templates/public/surroundings.gohtml:51 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:57 +#: web/templates/public/surroundings.gohtml:54 msgid "Cycle routes" msgstr "Rutas en bicicleta" -#: web/templates/public/surroundings.gohtml:58 +#: web/templates/public/surroundings.gohtml:55 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:62 +#: web/templates/public/surroundings.gohtml:59 msgid "Routes" msgstr "Rutas" -#: web/templates/public/surroundings.gohtml:63 +#: web/templates/public/surroundings.gohtml:60 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:67 +#: web/templates/public/surroundings.gohtml:64 msgid "Family outing" msgstr "Excusiones familiares" -#: web/templates/public/surroundings.gohtml:68 +#: web/templates/public/surroundings.gohtml:65 msgid "Many outing possibilities, for all ages." msgstr "Múltiples excursiones para todas las edades." -#: web/templates/public/surroundings.gohtml:72 +#: web/templates/public/surroundings.gohtml:69 msgid "Kayak" msgstr "Kayak" -#: web/templates/public/surroundings.gohtml:73 +#: web/templates/public/surroundings.gohtml:70 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…." @@ -410,7 +395,7 @@ msgstr "He leído y acepto las condiciones de r msgid "Campsite Montagut" msgstr "Camping Montagut" -#: web/templates/public/layout.gohtml:23 web/templates/admin/layout.gohtml:20 +#: web/templates/public/layout.gohtml:23 web/templates/admin/layout.gohtml:21 msgid "Skip to main content" msgstr "Saltar al contenido principal" @@ -421,7 +406,7 @@ msgstr "Menú" #: web/templates/public/layout.gohtml:57 web/templates/public/layout.gohtml:103 #: web/templates/admin/campsite/index.gohtml:6 #: web/templates/admin/campsite/index.gohtml:12 -#: web/templates/admin/layout.gohtml:45 web/templates/admin/layout.gohtml:82 +#: web/templates/admin/layout.gohtml:46 web/templates/admin/layout.gohtml:86 msgctxt "title" msgid "Campsites" msgstr "Alojamientos" @@ -464,6 +449,7 @@ msgstr "Álias" #: web/templates/admin/season/form.gohtml:46 #: web/templates/admin/services/form.gohtml:52 #: web/templates/admin/profile.gohtml:26 +#: web/templates/admin/surroundings/form.gohtml:37 msgctxt "input" msgid "Name" msgstr "Nombre" @@ -482,6 +468,7 @@ msgstr "Contenido" #: web/templates/admin/campsite/type/form.gohtml:171 #: web/templates/admin/season/form.gohtml:69 #: web/templates/admin/services/form.gohtml:80 +#: web/templates/admin/surroundings/form.gohtml:65 #: web/templates/admin/media/form.gohtml:35 msgctxt "action" msgid "Update" @@ -496,13 +483,14 @@ msgstr "Actualizar" #: web/templates/admin/campsite/type/form.gohtml:173 #: web/templates/admin/season/form.gohtml:71 #: web/templates/admin/services/form.gohtml:82 +#: web/templates/admin/surroundings/form.gohtml:67 msgctxt "action" msgid "Add" msgstr "Añadir" #: web/templates/admin/legal/index.gohtml:6 #: web/templates/admin/legal/index.gohtml:12 -#: web/templates/admin/layout.gohtml:63 +#: web/templates/admin/layout.gohtml:67 msgctxt "title" msgid "Legal Texts" msgstr "Textos legales" @@ -517,6 +505,7 @@ msgstr "Añadir texto legal" #: web/templates/admin/campsite/option/index.gohtml:25 #: web/templates/admin/campsite/type/index.gohtml:25 #: web/templates/admin/season/index.gohtml:26 +#: web/templates/admin/surroundings/index.gohtml:26 msgctxt "header" msgid "Name" msgstr "Nombre" @@ -630,6 +619,7 @@ msgstr "Añadir diapositiva" #: web/templates/admin/campsite/carousel/index.gohtml:25 #: web/templates/admin/services/index.gohtml:25 +#: web/templates/admin/surroundings/index.gohtml:25 #: web/templates/admin/home/index.gohtml:25 msgctxt "header" msgid "Image" @@ -645,6 +635,7 @@ msgstr "Leyenda" #: web/templates/admin/campsite/carousel/index.gohtml:27 #: web/templates/admin/services/index.gohtml:27 #: web/templates/admin/services/index.gohtml:72 +#: web/templates/admin/surroundings/index.gohtml:27 #: web/templates/admin/home/index.gohtml:27 msgctxt "header" msgid "Actions" @@ -659,6 +650,7 @@ msgstr "¿Estáis seguro de querer borrar esta diapositiva?" #: web/templates/admin/campsite/carousel/index.gohtml:45 #: web/templates/admin/services/index.gohtml:44 #: web/templates/admin/services/index.gohtml:88 +#: web/templates/admin/surroundings/index.gohtml:44 #: web/templates/admin/home/index.gohtml:44 msgctxt "action" msgid "Delete" @@ -826,6 +818,7 @@ msgstr "Equipamento" #: web/templates/admin/campsite/type/form.gohtml:143 #: web/templates/admin/services/form.gohtml:65 +#: web/templates/admin/surroundings/form.gohtml:50 msgctxt "input" msgid "Description" msgstr "Descripción" @@ -837,7 +830,7 @@ msgstr "Información adicional" #: web/templates/admin/campsite/type/index.gohtml:6 #: web/templates/admin/campsite/type/index.gohtml:12 -#: web/templates/admin/layout.gohtml:42 +#: web/templates/admin/layout.gohtml:43 msgctxt "title" msgid "Campsite Types" msgstr "Tipos de alojamientos" @@ -906,7 +899,7 @@ msgstr "Color" #: web/templates/admin/season/index.gohtml:6 #: web/templates/admin/season/index.gohtml:12 -#: web/templates/admin/layout.gohtml:48 +#: web/templates/admin/layout.gohtml:49 msgctxt "title" msgid "Seasons" msgstr "Temporadas" @@ -932,7 +925,7 @@ msgid "Cancel" msgstr "Cancelar" #: web/templates/admin/payment.gohtml:6 web/templates/admin/payment.gohtml:12 -#: web/templates/admin/layout.gohtml:39 +#: web/templates/admin/layout.gohtml:40 msgctxt "title" msgid "Payment Settings" msgstr "Parámetros de pago" @@ -968,7 +961,7 @@ msgid "Integration" msgstr "Integración" #: web/templates/admin/dashboard.gohtml:6 -#: web/templates/admin/dashboard.gohtml:10 web/templates/admin/layout.gohtml:79 +#: web/templates/admin/dashboard.gohtml:10 web/templates/admin/layout.gohtml:83 msgctxt "title" msgid "Dashboard" msgstr "Panel" @@ -1001,7 +994,7 @@ msgid "New Service" msgstr "Nuevo servicio" #: web/templates/admin/services/index.gohtml:6 -#: web/templates/admin/layout.gohtml:57 +#: web/templates/admin/layout.gohtml:58 msgctxt "title" msgid "Services Page" msgstr "Página de servicios" @@ -1036,7 +1029,7 @@ msgid "No services added yet." msgstr "No se ha añadido ningún servicio todavía." #: web/templates/admin/profile.gohtml:6 web/templates/admin/profile.gohtml:12 -#: web/templates/admin/layout.gohtml:32 +#: web/templates/admin/layout.gohtml:33 msgctxt "title" msgid "Profile" msgstr "Perfil" @@ -1143,29 +1136,64 @@ msgctxt "input" msgid "Legal Disclaimer" msgstr "Nota legal" -#: web/templates/admin/layout.gohtml:28 +#: web/templates/admin/surroundings/form.gohtml:8 +#: web/templates/admin/surroundings/form.gohtml:25 +msgctxt "title" +msgid "Edit Highlight" +msgstr "Edición del punto de interés" + +#: web/templates/admin/surroundings/form.gohtml:10 +#: web/templates/admin/surroundings/form.gohtml:27 +msgctxt "title" +msgid "New Highlight" +msgstr "Nuevo punto de interés" + +#: web/templates/admin/surroundings/index.gohtml:6 +msgctxt "title" +msgid "Surroundings Page" +msgstr "Página del entorno" + +#: web/templates/admin/surroundings/index.gohtml:11 +msgctxt "title" +msgid "Highlights" +msgstr "Puntos de interés" + +#: web/templates/admin/surroundings/index.gohtml:12 +msgctxt "action" +msgid "Add highlight" +msgstr "Añadir punto de interés" + +#: web/templates/admin/surroundings/index.gohtml:31 +msgid "Are you sure you wish to delete this highlight?" +msgstr "¿Estáis seguro de querer borrar este punto de interés?" + +#: web/templates/admin/surroundings/index.gohtml:53 +msgid "No highlights added yet." +msgstr "No se ha añadido ningún punto de interés todavía." + +#: web/templates/admin/layout.gohtml:29 msgctxt "title" msgid "User Menu" msgstr "Menú de usuario" -#: web/templates/admin/layout.gohtml:36 +#: web/templates/admin/layout.gohtml:37 msgctxt "title" msgid "Company Settings" msgstr "Parámetros de la empresa" -#: web/templates/admin/layout.gohtml:51 +#: web/templates/admin/layout.gohtml:52 #: web/templates/admin/media/index.gohtml:6 #: web/templates/admin/media/index.gohtml:11 msgctxt "title" msgid "Media" msgstr "Medios" -#: web/templates/admin/layout.gohtml:54 web/templates/admin/home/index.gohtml:6 +#: web/templates/admin/layout.gohtml:55 web/templates/admin/home/index.gohtml:6 msgctxt "title" msgid "Home Page" msgstr "Página de inicio" -#: web/templates/admin/layout.gohtml:68 +#: web/templates/admin/layout.gohtml:72 msgctxt "action" msgid "Logout" msgstr "Salir" @@ -1236,31 +1264,34 @@ msgid "Upload Media" 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:464 -#: pkg/season/admin.go:415 pkg/services/admin.go:319 +#: pkg/campsite/types/feature.go:259 pkg/campsite/types/admin.go:463 +#: pkg/season/admin.go:412 pkg/services/admin.go:314 +#: pkg/surroundings/admin.go:321 msgid "Name can not be empty." msgstr "No podéis dejar el nombre en blanco." #: pkg/legal/admin.go:259 pkg/campsite/types/option.go:345 -#: pkg/campsite/types/feature.go:260 pkg/campsite/types/admin.go:465 +#: pkg/campsite/types/feature.go:260 pkg/campsite/types/admin.go:464 msgid "Name must have at least one letter." msgstr "El nombre tiene que tener como mínimo una letra." -#: pkg/carousel/admin.go:269 pkg/campsite/types/carousel.go:223 +#: pkg/carousel/admin.go:267 pkg/campsite/types/carousel.go:223 msgctxt "input" msgid "Slide image" msgstr "Imagen de la diapositiva" -#: pkg/carousel/admin.go:270 pkg/campsite/types/carousel.go:224 +#: pkg/carousel/admin.go:268 pkg/campsite/types/carousel.go:224 msgctxt "action" msgid "Set slide image" msgstr "Establecer la imagen de la diapositiva" -#: pkg/carousel/admin.go:339 pkg/campsite/types/carousel.go:297 +#: pkg/carousel/admin.go:337 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:340 pkg/campsite/types/carousel.go:298 +#: pkg/carousel/admin.go:338 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." @@ -1299,7 +1330,7 @@ msgstr "El idioma escogido no es válido." msgid "File must be a valid PNG or JPEG image." msgstr "El archivo tiene que ser una imagen PNG o JPEG válida." -#: pkg/app/admin.go:62 +#: pkg/app/admin.go:64 msgid "Access forbidden" msgstr "Acceso prohibido" @@ -1327,61 +1358,61 @@ msgstr "El valor del máximo tiene que ser un número entero." msgid "Maximum must be equal or greater than minimum." msgstr "El valor del máximo tiene que ser igual o mayor al del mínimo." -#: pkg/campsite/types/option.go:361 pkg/campsite/types/admin.go:478 +#: pkg/campsite/types/option.go:361 pkg/campsite/types/admin.go:477 msgid "Price per night can not be empty." msgstr "No podéis dejar el precio por noche en blanco." -#: pkg/campsite/types/option.go:362 pkg/campsite/types/admin.go:479 +#: pkg/campsite/types/option.go:362 pkg/campsite/types/admin.go:478 msgid "Price per night must be a decimal number." msgstr "El precio por noche tiene que ser un número decimal." -#: pkg/campsite/types/option.go:363 pkg/campsite/types/admin.go:480 +#: pkg/campsite/types/option.go:363 pkg/campsite/types/admin.go:479 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:318 +#: pkg/campsite/types/feature.go:258 pkg/services/admin.go:313 msgid "Selected icon is not valid." msgstr "El icono escogido no es válido." -#: pkg/campsite/types/admin.go:306 +#: pkg/campsite/types/admin.go:305 msgctxt "input" msgid "Cover image" msgstr "Imagen de portada" -#: pkg/campsite/types/admin.go:307 +#: pkg/campsite/types/admin.go:306 msgctxt "action" msgid "Set campsite type cover" msgstr "Establecer la portada del tipo de alojamiento" -#: pkg/campsite/types/admin.go:467 +#: pkg/campsite/types/admin.go:466 msgid "Cover image can not be empty." msgstr "No podéis dejar la imagen de portada en blanco." -#: pkg/campsite/types/admin.go:468 +#: pkg/campsite/types/admin.go:467 msgid "Cover image must be an image media type." msgstr "La imagen de portada tiene que ser un medio de tipo imagen." -#: pkg/campsite/types/admin.go:472 +#: pkg/campsite/types/admin.go:471 msgid "Maximum number of campers can not be empty." msgstr "No podéis dejar el número máximo de personas en blanco." -#: pkg/campsite/types/admin.go:473 +#: pkg/campsite/types/admin.go:472 msgid "Maximum number of campers must be an integer number." msgstr "El número máximo de personas tiene que ser entero." -#: pkg/campsite/types/admin.go:474 +#: pkg/campsite/types/admin.go:473 msgid "Maximum number of campers must be one or greater." msgstr "El número máximo de personas no puede ser cero." -#: pkg/campsite/types/admin.go:483 +#: pkg/campsite/types/admin.go:482 msgid "Minimum number of nights can not be empty." msgstr "No podéis dejar el número mínimo de noches en blanco." -#: pkg/campsite/types/admin.go:484 +#: pkg/campsite/types/admin.go:483 msgid "Minimum number of nights must be an integer." msgstr "El número mínimo de noches tiene que ser entero." -#: pkg/campsite/types/admin.go:485 +#: pkg/campsite/types/admin.go:484 msgid "Minimum number of nights must be one or greater." msgstr "El número mínimo de noches no puede ser cero." @@ -1393,95 +1424,105 @@ msgstr "El tipo de alojamiento escogido no es válido." msgid "Label can not be empty." msgstr "No podéis dejar la etiqueta en blanco." -#: pkg/season/admin.go:186 +#: pkg/season/admin.go:183 msgctxt "month" msgid "January" msgstr "enero" -#: pkg/season/admin.go:187 +#: pkg/season/admin.go:184 msgctxt "month" msgid "February" msgstr "febrero" -#: pkg/season/admin.go:188 +#: pkg/season/admin.go:185 msgctxt "month" msgid "March" msgstr "marzo" -#: pkg/season/admin.go:189 +#: pkg/season/admin.go:186 msgctxt "month" msgid "April" msgstr "abril" -#: pkg/season/admin.go:190 +#: pkg/season/admin.go:187 msgctxt "month" msgid "May" msgstr "mayo" -#: pkg/season/admin.go:191 +#: pkg/season/admin.go:188 msgctxt "month" msgid "June" msgstr "junio" -#: pkg/season/admin.go:192 +#: pkg/season/admin.go:189 msgctxt "month" msgid "July" msgstr "julio" -#: pkg/season/admin.go:193 +#: pkg/season/admin.go:190 msgctxt "month" msgid "August" msgstr "agosto" -#: pkg/season/admin.go:194 +#: pkg/season/admin.go:191 msgctxt "month" msgid "September" msgstr "septiembre" -#: pkg/season/admin.go:195 +#: pkg/season/admin.go:192 msgctxt "month" msgid "October" msgstr "octubre" -#: pkg/season/admin.go:196 +#: pkg/season/admin.go:193 msgctxt "month" msgid "November" msgstr "noviembre" -#: pkg/season/admin.go:197 +#: pkg/season/admin.go:194 msgctxt "month" msgid "December" msgstr "diciembre" -#: pkg/season/admin.go:416 +#: pkg/season/admin.go:413 msgid "Color can not be empty." msgstr "No podéis dejar el color en blanco." -#: pkg/season/admin.go:417 +#: pkg/season/admin.go:414 msgid "This color is not valid. It must be like #123abc." msgstr "Este color no es válido. Tiene que ser parecido a #123abc." -#: pkg/season/admin.go:517 +#: pkg/season/admin.go:514 msgctxt "action" msgid "Unset" msgstr "Desasignar" -#: pkg/season/admin.go:548 +#: pkg/season/admin.go:545 msgid "Start date can not be empty." msgstr "No podéis dejar la fecha de inicio en blanco." -#: pkg/season/admin.go:549 +#: pkg/season/admin.go:546 msgid "Start date must be a valid date." msgstr "La fecha de inicio tiene que ser una fecha válida." -#: pkg/season/admin.go:551 +#: pkg/season/admin.go:548 msgid "End date can not be empty." msgstr "No podéis dejar la fecha final en blanco." -#: pkg/season/admin.go:552 +#: pkg/season/admin.go:549 msgid "End date must be a valid date." msgstr "La fecha final tiene que ser una fecha válida." +#: pkg/surroundings/admin.go:267 +msgctxt "input" +msgid "Highlight image" +msgstr "Imagen del punto de interés" + +#: pkg/surroundings/admin.go:268 +msgctxt "action" +msgid "Set highlight image" +msgstr "Establecer la imagen del punto de interés" + #: pkg/company/admin.go:200 pkg/booking/public.go:256 msgid "Selected country is not valid." msgstr "El país escogido no es válido." @@ -1562,11 +1603,11 @@ msgstr "No podéis dejar el formato de número de factura en blanco." msgid "Cross-site request forgery detected." msgstr "Se ha detectado un intento de falsificación de petición en sitios cruzados." -#: pkg/media/admin.go:265 +#: pkg/media/admin.go:312 msgid "Uploaded file can not be empty." msgstr "No podéis dejar el archivo del medio en blanco." -#: pkg/media/admin.go:324 +#: pkg/media/admin.go:371 msgid "Filename can not be empty." msgstr "No podéis dejar el nombre del archivo en blanco." @@ -1674,6 +1715,18 @@ msgstr "%s tiene que ser como mínimo %d." msgid "%s must be at most %d." msgstr "%s tiene que ser como máximo %d" +#~ msgid "Campsite Montagut is an ideal starting point for quiet outings, climbing, swimming in the river and gorges, volcanoes, the Fageda d’en Jordà, cycle tours for all ages…." +#~ msgstr "El Camping Montagut es ideal como punto de salida de excursiones tranquilas, escalada, bañarse en el río y piletones, volcanes, la Fageda d’en Jordà, salidas en bicicleta para todos los niveles…." + +#~ msgid "Get to the Costa Brava and enjoy the beaches, the gastronomy or go kayaking…." +#~ msgstr "Llegar hasta la Costa Brava y disfrutar de las playas, la gastronomía o ir en kayak…." + +#~ msgid "You will also find museums in Olot, Figures, Girona." +#~ msgstr "También encontraréis museos en Olot, Figueres, Girona." + +#~ msgid "As well as music festivals, dance, theater…." +#~ msgstr "Como festivales de música, danza, teatro…." + #~ msgctxt "header" #~ msgid "Translations" #~ msgstr "Traducciones" diff --git a/po/fr.po b/po/fr.po index 935b43f..4996ee1 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-15 02:00+0100\n" +"POT-Creation-Date: 2024-01-16 00:48+0100\n" "PO-Revision-Date: 2023-12-20 10:13+0100\n" "Last-Translator: Oriol Carbonell \n" "Language-Team: French \n" @@ -57,7 +57,7 @@ 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/admin/layout.gohtml:60 +#: web/templates/admin/layout.gohtml:61 msgctxt "title" msgid "Location" msgstr "Comment nous rejoindre" @@ -87,8 +87,9 @@ msgstr "Venez et profitez-en !" #: web/templates/public/home.gohtml:35 #: web/templates/public/surroundings.gohtml:6 -#: web/templates/public/surroundings.gohtml:10 +#: web/templates/public/surroundings.gohtml:11 #: web/templates/public/layout.gohtml:67 web/templates/public/layout.gohtml:95 +#: web/templates/admin/layout.gohtml:64 msgctxt "title" msgid "Surroundings" msgstr "Entourage" @@ -252,61 +253,45 @@ msgctxt "day" msgid "Sun" msgstr "Dim." -#: web/templates/public/surroundings.gohtml:28 +#: web/templates/public/surroundings.gohtml:31 msgctxt "title" msgid "What to Do Outside the Campsite?" msgstr "Que faire à l’extérieur du camping ?" -#: web/templates/public/surroundings.gohtml:31 -msgid "Campsite Montagut is an ideal starting point for quiet outings, climbing, swimming in the river and gorges, volcanoes, the Fageda d’en Jordà, cycle tours for all ages…." -msgstr "Le camping Montagut est un point de départ idéal pour des sorties tranquilles, de l’escalade, des baignades dans la rivière et les gorges, les volcans, la Fageda dâen Jordã, des randonnées à vélo pour tous les âges…." - -#: web/templates/public/surroundings.gohtml:38 -msgid "Get to the Costa Brava and enjoy the beaches, the gastronomy or go kayaking…." -msgstr "Rendez-vous sur la Costa Brava et profitez des plages, de la gastronomie ou faites du kayak…." - -#: web/templates/public/surroundings.gohtml:47 -msgid "You will also find museums in Olot, Figures, Girona." -msgstr "Vous trouverez également des musées à Olot, Figures, Gérone." - -#: web/templates/public/surroundings.gohtml:48 -msgid "As well as music festivals, dance, theater…." -msgstr "Ainsi que des festivals de musique, de danse, de théâtre…." - -#: web/templates/public/surroundings.gohtml:54 +#: web/templates/public/surroundings.gohtml:51 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:57 +#: web/templates/public/surroundings.gohtml:54 msgid "Cycle routes" msgstr "Pistes cyclables" -#: web/templates/public/surroundings.gohtml:58 +#: web/templates/public/surroundings.gohtml:55 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:62 +#: web/templates/public/surroundings.gohtml:59 msgid "Routes" msgstr "Itinéraires" -#: web/templates/public/surroundings.gohtml:63 +#: web/templates/public/surroundings.gohtml:60 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:67 +#: web/templates/public/surroundings.gohtml:64 msgid "Family outing" msgstr "Sortie en famille" -#: web/templates/public/surroundings.gohtml:68 +#: web/templates/public/surroundings.gohtml:65 msgid "Many outing possibilities, for all ages." msgstr "Nombreuses possibilités de sorties, pour tous les âges." -#: web/templates/public/surroundings.gohtml:72 +#: web/templates/public/surroundings.gohtml:69 msgid "Kayak" msgstr "Kayak" -#: web/templates/public/surroundings.gohtml:73 +#: web/templates/public/surroundings.gohtml:70 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…." @@ -411,7 +396,7 @@ msgstr "J’ai lu et j’accepte les conditions msgid "Campsite Montagut" msgstr "Camping Montagut" -#: web/templates/public/layout.gohtml:23 web/templates/admin/layout.gohtml:20 +#: web/templates/public/layout.gohtml:23 web/templates/admin/layout.gohtml:21 msgid "Skip to main content" msgstr "Passer au contenu principal" @@ -422,7 +407,7 @@ msgstr "Menu" #: web/templates/public/layout.gohtml:57 web/templates/public/layout.gohtml:103 #: web/templates/admin/campsite/index.gohtml:6 #: web/templates/admin/campsite/index.gohtml:12 -#: web/templates/admin/layout.gohtml:45 web/templates/admin/layout.gohtml:82 +#: web/templates/admin/layout.gohtml:46 web/templates/admin/layout.gohtml:86 msgctxt "title" msgid "Campsites" msgstr "Locatifs" @@ -465,6 +450,7 @@ msgstr "Slug" #: web/templates/admin/season/form.gohtml:46 #: web/templates/admin/services/form.gohtml:52 #: web/templates/admin/profile.gohtml:26 +#: web/templates/admin/surroundings/form.gohtml:37 msgctxt "input" msgid "Name" msgstr "Nom" @@ -483,6 +469,7 @@ msgstr "Contenu" #: web/templates/admin/campsite/type/form.gohtml:171 #: web/templates/admin/season/form.gohtml:69 #: web/templates/admin/services/form.gohtml:80 +#: web/templates/admin/surroundings/form.gohtml:65 #: web/templates/admin/media/form.gohtml:35 msgctxt "action" msgid "Update" @@ -497,13 +484,14 @@ msgstr "Mettre à jour" #: web/templates/admin/campsite/type/form.gohtml:173 #: web/templates/admin/season/form.gohtml:71 #: web/templates/admin/services/form.gohtml:82 +#: web/templates/admin/surroundings/form.gohtml:67 msgctxt "action" msgid "Add" msgstr "Ajouter" #: web/templates/admin/legal/index.gohtml:6 #: web/templates/admin/legal/index.gohtml:12 -#: web/templates/admin/layout.gohtml:63 +#: web/templates/admin/layout.gohtml:67 msgctxt "title" msgid "Legal Texts" msgstr "Textes juridiques" @@ -518,6 +506,7 @@ msgstr "Ajouter un texte juridique" #: web/templates/admin/campsite/option/index.gohtml:25 #: web/templates/admin/campsite/type/index.gohtml:25 #: web/templates/admin/season/index.gohtml:26 +#: web/templates/admin/surroundings/index.gohtml:26 msgctxt "header" msgid "Name" msgstr "Nom" @@ -631,6 +620,7 @@ msgstr "Ajouter la diapositive" #: web/templates/admin/campsite/carousel/index.gohtml:25 #: web/templates/admin/services/index.gohtml:25 +#: web/templates/admin/surroundings/index.gohtml:25 #: web/templates/admin/home/index.gohtml:25 msgctxt "header" msgid "Image" @@ -646,6 +636,7 @@ msgstr "Légende" #: web/templates/admin/campsite/carousel/index.gohtml:27 #: web/templates/admin/services/index.gohtml:27 #: web/templates/admin/services/index.gohtml:72 +#: web/templates/admin/surroundings/index.gohtml:27 #: web/templates/admin/home/index.gohtml:27 msgctxt "header" msgid "Actions" @@ -660,6 +651,7 @@ msgstr "Êtes-vous sûr de vouloir supprimer cette diapositive ?" #: web/templates/admin/campsite/carousel/index.gohtml:45 #: web/templates/admin/services/index.gohtml:44 #: web/templates/admin/services/index.gohtml:88 +#: web/templates/admin/surroundings/index.gohtml:44 #: web/templates/admin/home/index.gohtml:44 msgctxt "action" msgid "Delete" @@ -827,6 +819,7 @@ msgstr "Installations" #: web/templates/admin/campsite/type/form.gohtml:143 #: web/templates/admin/services/form.gohtml:65 +#: web/templates/admin/surroundings/form.gohtml:50 msgctxt "input" msgid "Description" msgstr "Description" @@ -838,7 +831,7 @@ msgstr "Informations Complémentaires" #: web/templates/admin/campsite/type/index.gohtml:6 #: web/templates/admin/campsite/type/index.gohtml:12 -#: web/templates/admin/layout.gohtml:42 +#: web/templates/admin/layout.gohtml:43 msgctxt "title" msgid "Campsite Types" msgstr "Types d’emplacements de camping" @@ -907,7 +900,7 @@ msgstr "Couleur" #: web/templates/admin/season/index.gohtml:6 #: web/templates/admin/season/index.gohtml:12 -#: web/templates/admin/layout.gohtml:48 +#: web/templates/admin/layout.gohtml:49 msgctxt "title" msgid "Seasons" msgstr "Saisons" @@ -933,7 +926,7 @@ msgid "Cancel" msgstr "Annuler" #: web/templates/admin/payment.gohtml:6 web/templates/admin/payment.gohtml:12 -#: web/templates/admin/layout.gohtml:39 +#: web/templates/admin/layout.gohtml:40 msgctxt "title" msgid "Payment Settings" msgstr "Paramètres de paiement" @@ -969,7 +962,7 @@ msgid "Integration" msgstr "Intégration" #: web/templates/admin/dashboard.gohtml:6 -#: web/templates/admin/dashboard.gohtml:10 web/templates/admin/layout.gohtml:79 +#: web/templates/admin/dashboard.gohtml:10 web/templates/admin/layout.gohtml:83 msgctxt "title" msgid "Dashboard" msgstr "Tableau de bord" @@ -1002,7 +995,7 @@ msgid "New Service" msgstr "Nouveau service" #: web/templates/admin/services/index.gohtml:6 -#: web/templates/admin/layout.gohtml:57 +#: web/templates/admin/layout.gohtml:58 msgctxt "title" msgid "Services Page" msgstr "La page des services" @@ -1037,7 +1030,7 @@ msgid "No services added yet." msgstr "Aucun service n’a encore été ajouté." #: web/templates/admin/profile.gohtml:6 web/templates/admin/profile.gohtml:12 -#: web/templates/admin/layout.gohtml:32 +#: web/templates/admin/layout.gohtml:33 msgctxt "title" msgid "Profile" msgstr "Profil" @@ -1144,29 +1137,64 @@ msgctxt "input" msgid "Legal Disclaimer" msgstr "Avertissement juridique" -#: web/templates/admin/layout.gohtml:28 +#: web/templates/admin/surroundings/form.gohtml:8 +#: web/templates/admin/surroundings/form.gohtml:25 +msgctxt "title" +msgid "Edit Highlight" +msgstr "Modifier un point d’intérêt" + +#: web/templates/admin/surroundings/form.gohtml:10 +#: web/templates/admin/surroundings/form.gohtml:27 +msgctxt "title" +msgid "New Highlight" +msgstr "Nouveau point d’intérêt" + +#: web/templates/admin/surroundings/index.gohtml:6 +msgctxt "title" +msgid "Surroundings Page" +msgstr "Page de l’entourage" + +#: web/templates/admin/surroundings/index.gohtml:11 +msgctxt "title" +msgid "Highlights" +msgstr "Points d’intérêt" + +#: web/templates/admin/surroundings/index.gohtml:12 +msgctxt "action" +msgid "Add highlight" +msgstr "Ajouter un point d’intérêt" + +#: web/templates/admin/surroundings/index.gohtml:31 +msgid "Are you sure you wish to delete this highlight?" +msgstr "Êtes-vous sûr de vouloir supprimer cette point d’intérêt ?" + +#: web/templates/admin/surroundings/index.gohtml:53 +msgid "No highlights added yet." +msgstr "Aucun point d’intérêt n’a encore été ajoutée." + +#: web/templates/admin/layout.gohtml:29 msgctxt "title" msgid "User Menu" msgstr "Menu utilisateur" -#: web/templates/admin/layout.gohtml:36 +#: web/templates/admin/layout.gohtml:37 msgctxt "title" msgid "Company Settings" msgstr "Paramètres de l'entreprise" -#: web/templates/admin/layout.gohtml:51 +#: web/templates/admin/layout.gohtml:52 #: web/templates/admin/media/index.gohtml:6 #: web/templates/admin/media/index.gohtml:11 msgctxt "title" msgid "Media" msgstr "Média" -#: web/templates/admin/layout.gohtml:54 web/templates/admin/home/index.gohtml:6 +#: web/templates/admin/layout.gohtml:55 web/templates/admin/home/index.gohtml:6 msgctxt "title" msgid "Home Page" msgstr "Page d'accueil" -#: web/templates/admin/layout.gohtml:68 +#: web/templates/admin/layout.gohtml:72 msgctxt "action" msgid "Logout" msgstr "Déconnexion" @@ -1237,31 +1265,34 @@ msgid "Upload Media" 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:464 -#: pkg/season/admin.go:415 pkg/services/admin.go:319 +#: pkg/campsite/types/feature.go:259 pkg/campsite/types/admin.go:463 +#: pkg/season/admin.go:412 pkg/services/admin.go:314 +#: pkg/surroundings/admin.go:321 msgid "Name can not be empty." msgstr "Le nom ne peut pas être laissé vide." #: pkg/legal/admin.go:259 pkg/campsite/types/option.go:345 -#: pkg/campsite/types/feature.go:260 pkg/campsite/types/admin.go:465 +#: pkg/campsite/types/feature.go:260 pkg/campsite/types/admin.go:464 msgid "Name must have at least one letter." msgstr "Le nom doit comporter au moins une lettre." -#: pkg/carousel/admin.go:269 pkg/campsite/types/carousel.go:223 +#: pkg/carousel/admin.go:267 pkg/campsite/types/carousel.go:223 msgctxt "input" msgid "Slide image" msgstr "Image du diaporama" -#: pkg/carousel/admin.go:270 pkg/campsite/types/carousel.go:224 +#: pkg/carousel/admin.go:268 pkg/campsite/types/carousel.go:224 msgctxt "action" msgid "Set slide image" msgstr "Définir l’image de la diapositive" -#: pkg/carousel/admin.go:339 pkg/campsite/types/carousel.go:297 +#: pkg/carousel/admin.go:337 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:340 pkg/campsite/types/carousel.go:298 +#: pkg/carousel/admin.go:338 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." @@ -1300,7 +1331,7 @@ msgstr "La langue sélectionnée n’est pas valide." msgid "File must be a valid PNG or JPEG image." msgstr "Le fichier doit être une image PNG ou JPEG valide." -#: pkg/app/admin.go:62 +#: pkg/app/admin.go:64 msgid "Access forbidden" msgstr "Accès interdit" @@ -1328,61 +1359,61 @@ msgstr "Le maximum doit être un nombre entier." msgid "Maximum must be equal or greater than minimum." msgstr "Le maximum doit être égal ou supérieur au minimum." -#: pkg/campsite/types/option.go:361 pkg/campsite/types/admin.go:478 +#: pkg/campsite/types/option.go:361 pkg/campsite/types/admin.go:477 msgid "Price per night can not be empty." msgstr "Le prix par nuit ne peut pas être vide." -#: pkg/campsite/types/option.go:362 pkg/campsite/types/admin.go:479 +#: pkg/campsite/types/option.go:362 pkg/campsite/types/admin.go:478 msgid "Price per night must be a decimal number." msgstr "Le prix par nuit doit être un nombre décimal." -#: pkg/campsite/types/option.go:363 pkg/campsite/types/admin.go:480 +#: pkg/campsite/types/option.go:363 pkg/campsite/types/admin.go:479 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:318 +#: pkg/campsite/types/feature.go:258 pkg/services/admin.go:313 msgid "Selected icon is not valid." msgstr "L’icône sélectionnée n’est pas valide." -#: pkg/campsite/types/admin.go:306 +#: pkg/campsite/types/admin.go:305 msgctxt "input" msgid "Cover image" msgstr "Image de couverture" -#: pkg/campsite/types/admin.go:307 +#: pkg/campsite/types/admin.go:306 msgctxt "action" msgid "Set campsite type cover" msgstr "Définir une couverture type camping" -#: pkg/campsite/types/admin.go:467 +#: pkg/campsite/types/admin.go:466 msgid "Cover image can not be empty." msgstr "L’image de couverture ne peut pas être vide." -#: pkg/campsite/types/admin.go:468 +#: pkg/campsite/types/admin.go:467 msgid "Cover image must be an image media type." msgstr "L’image de couverture doit être de type média d’image." -#: pkg/campsite/types/admin.go:472 +#: pkg/campsite/types/admin.go:471 msgid "Maximum number of campers can not be empty." msgstr "Le nombre maximum de campeurs ne peut pas être vide." -#: pkg/campsite/types/admin.go:473 +#: pkg/campsite/types/admin.go:472 msgid "Maximum number of campers must be an integer number." msgstr "Le nombre maximum de campeurs doit être un nombre entier." -#: pkg/campsite/types/admin.go:474 +#: pkg/campsite/types/admin.go:473 msgid "Maximum number of campers must be one or greater." msgstr "Le nombre maximum de campeurs doit être égal ou supérieur à un campeur." -#: pkg/campsite/types/admin.go:483 +#: pkg/campsite/types/admin.go:482 msgid "Minimum number of nights can not be empty." msgstr "Le nombre minimum de nuits ne peut pas être vide." -#: pkg/campsite/types/admin.go:484 +#: pkg/campsite/types/admin.go:483 msgid "Minimum number of nights must be an integer." msgstr "Le nombre minimum de nuits doit être un entier." -#: pkg/campsite/types/admin.go:485 +#: pkg/campsite/types/admin.go:484 msgid "Minimum number of nights must be one or greater." msgstr "Le nombre minimum de nuits doit être supérieur ou égal à une nuit." @@ -1394,95 +1425,105 @@ msgstr "Le type d’emplacement sélectionné n’est pas valide." msgid "Label can not be empty." msgstr "L'étiquette ne peut pas être vide." -#: pkg/season/admin.go:186 +#: pkg/season/admin.go:183 msgctxt "month" msgid "January" msgstr "Janvier" -#: pkg/season/admin.go:187 +#: pkg/season/admin.go:184 msgctxt "month" msgid "February" msgstr "Février" -#: pkg/season/admin.go:188 +#: pkg/season/admin.go:185 msgctxt "month" msgid "March" msgstr "Mars" -#: pkg/season/admin.go:189 +#: pkg/season/admin.go:186 msgctxt "month" msgid "April" msgstr "Avril" -#: pkg/season/admin.go:190 +#: pkg/season/admin.go:187 msgctxt "month" msgid "May" msgstr "Mai" -#: pkg/season/admin.go:191 +#: pkg/season/admin.go:188 msgctxt "month" msgid "June" msgstr "Juin" -#: pkg/season/admin.go:192 +#: pkg/season/admin.go:189 msgctxt "month" msgid "July" msgstr "Juillet" -#: pkg/season/admin.go:193 +#: pkg/season/admin.go:190 msgctxt "month" msgid "August" msgstr "Août" -#: pkg/season/admin.go:194 +#: pkg/season/admin.go:191 msgctxt "month" msgid "September" msgstr "Septembre" -#: pkg/season/admin.go:195 +#: pkg/season/admin.go:192 msgctxt "month" msgid "October" msgstr "Octobre" -#: pkg/season/admin.go:196 +#: pkg/season/admin.go:193 msgctxt "month" msgid "November" msgstr "Novembre" -#: pkg/season/admin.go:197 +#: pkg/season/admin.go:194 msgctxt "month" msgid "December" msgstr "Décembre" -#: pkg/season/admin.go:416 +#: pkg/season/admin.go:413 msgid "Color can not be empty." msgstr "La couleur ne peut pas être vide." -#: pkg/season/admin.go:417 +#: pkg/season/admin.go:414 msgid "This color is not valid. It must be like #123abc." msgstr "Cette couleur n’est pas valide. Il doit être comme #123abc." -#: pkg/season/admin.go:517 +#: pkg/season/admin.go:514 msgctxt "action" msgid "Unset" msgstr "Unset" -#: pkg/season/admin.go:548 +#: pkg/season/admin.go:545 msgid "Start date can not be empty." msgstr "La date de début ne peut pas être vide." -#: pkg/season/admin.go:549 +#: pkg/season/admin.go:546 msgid "Start date must be a valid date." msgstr "La date de début doit être une date valide." -#: pkg/season/admin.go:551 +#: pkg/season/admin.go:548 msgid "End date can not be empty." msgstr "La date de fin ne peut pas être vide." -#: pkg/season/admin.go:552 +#: pkg/season/admin.go:549 msgid "End date must be a valid date." msgstr "La date de fin doit être une date valide." +#: pkg/surroundings/admin.go:267 +msgctxt "input" +msgid "Highlight image" +msgstr "Image du point d’intérêt" + +#: pkg/surroundings/admin.go:268 +msgctxt "action" +msgid "Set highlight image" +msgstr "Définir l’image du point d’intérêt" + #: pkg/company/admin.go:200 pkg/booking/public.go:256 msgid "Selected country is not valid." msgstr "Le pays sélectionné n’est pas valide." @@ -1563,11 +1604,11 @@ msgstr "Le format du numéro de facture ne peut pas être vide." msgid "Cross-site request forgery detected." msgstr "Détection d’une falsification de requête intersites." -#: pkg/media/admin.go:265 +#: pkg/media/admin.go:312 msgid "Uploaded file can not be empty." msgstr "Le fichier téléchargé ne peut pas être vide." -#: pkg/media/admin.go:324 +#: pkg/media/admin.go:371 msgid "Filename can not be empty." msgstr "Le nom de fichier ne peut pas être vide." @@ -1675,6 +1716,18 @@ msgstr "%s doit être %d ou plus." msgid "%s must be at most %d." msgstr "%s doit être tout au plus %d." +#~ msgid "Campsite Montagut is an ideal starting point for quiet outings, climbing, swimming in the river and gorges, volcanoes, the Fageda d’en Jordà, cycle tours for all ages…." +#~ msgstr "Le camping Montagut est un point de départ idéal pour des sorties tranquilles, de l’escalade, des baignades dans la rivière et les gorges, les volcans, la Fageda dâen Jordã, des randonnées à vélo pour tous les âges…." + +#~ msgid "Get to the Costa Brava and enjoy the beaches, the gastronomy or go kayaking…." +#~ msgstr "Rendez-vous sur la Costa Brava et profitez des plages, de la gastronomie ou faites du kayak…." + +#~ msgid "You will also find museums in Olot, Figures, Girona." +#~ msgstr "Vous trouverez également des musées à Olot, Figures, Gérone." + +#~ msgid "As well as music festivals, dance, theater…." +#~ msgstr "Ainsi que des festivals de musique, de danse, de théâtre…." + #~ msgctxt "header" #~ msgid "Translations" #~ msgstr "Traductions" diff --git a/revert/add_surroundings_highlight.sql b/revert/add_surroundings_highlight.sql new file mode 100644 index 0000000..a7a210e --- /dev/null +++ b/revert/add_surroundings_highlight.sql @@ -0,0 +1,7 @@ +-- Revert camper:add_surroundings_highlight from pg + +begin; + +drop function if exists camper.add_surroundings_highlight(integer, integer, text, text); + +commit; diff --git a/revert/edit_surroundings_highlight.sql b/revert/edit_surroundings_highlight.sql new file mode 100644 index 0000000..2ce3f9d --- /dev/null +++ b/revert/edit_surroundings_highlight.sql @@ -0,0 +1,7 @@ +-- Revert camper:edit_surroundings_highlight from pg + +begin; + +drop function if exists camper.edit_surroundings_highlight(integer, integer, text, text); + +commit; diff --git a/revert/order_surroundings_highlights.sql b/revert/order_surroundings_highlights.sql new file mode 100644 index 0000000..0366a93 --- /dev/null +++ b/revert/order_surroundings_highlights.sql @@ -0,0 +1,7 @@ +-- Revert camper:order_surroundings_highlights from pg + +begin; + +drop function if exists camper.order_surroundings_highlights(integer[]); + +commit; diff --git a/revert/remove_surroundings_highlight.sql b/revert/remove_surroundings_highlight.sql new file mode 100644 index 0000000..9a9e1fe --- /dev/null +++ b/revert/remove_surroundings_highlight.sql @@ -0,0 +1,7 @@ +-- Revert camper:remove_surroundings_highlight from pg + +begin; + +drop function if exists camper.remove_surroundings_highlight(integer); + +commit; diff --git a/revert/surroundings_highlight.sql b/revert/surroundings_highlight.sql new file mode 100644 index 0000000..5b7abe2 --- /dev/null +++ b/revert/surroundings_highlight.sql @@ -0,0 +1,7 @@ +-- Revert camper:surroundings_highlight from pg + +begin; + +drop table if exists camper.surroundings_highlight; + +commit; diff --git a/revert/surroundings_highlight_i18n.sql b/revert/surroundings_highlight_i18n.sql new file mode 100644 index 0000000..a60f3c6 --- /dev/null +++ b/revert/surroundings_highlight_i18n.sql @@ -0,0 +1,7 @@ +-- Revert camper:surroundings_highlight_i18n from pg + +begin; + +drop table if exists camper.surroundings_highlight_i18n; + +commit; diff --git a/revert/translate_surroundings_highlight.sql b/revert/translate_surroundings_highlight.sql new file mode 100644 index 0000000..06b8ee9 --- /dev/null +++ b/revert/translate_surroundings_highlight.sql @@ -0,0 +1,7 @@ +-- Revert camper:translate_surroundings_highlight from pg + +begin; + +drop function if exists camper.translate_surroundings_highlight(integer, text, text, text); + +commit; diff --git a/sqitch.plan b/sqitch.plan index 177adee..088e1f5 100644 --- a/sqitch.plan +++ b/sqitch.plan @@ -141,3 +141,10 @@ campsite_type_i18n__additional_info [campsite_type_i18n] 2024-01-14T22:03:03Z jo add_campsite_type [add_campsite_type@v0 campsite_type__additional_info] 2024-01-14T22:06:19Z jordi fita mas # Add additional_info parameter to add_campsite_type edit_campsite_type [edit_campsite_type@v0 campsite_type__additional_info] 2024-01-14T22:09:40Z jordi fita mas # Add additional_info parameter to edit_campsite_type translate_campsite_type [translate_campsite_type@v0 campsite_type_i18n__additional_info] 2024-01-14T22:12:08Z jordi fita mas # Add additional_info parameter to translate_campsite_type +surroundings_highlight [roles schema_camper company media user_profile] 2024-01-15T19:22:57Z jordi fita mas # Add relation for surroundings highlights +add_surroundings_highlight [roles schema_camper surroundings_highlight] 2024-01-15T19:40:37Z jordi fita mas # Add function to add new surroundings highlighs +edit_surroundings_highlight [roles schema_camper surroundings_highlight] 2024-01-15T19:48:04Z jordi fita mas # Add function to update surrounding higlights +surroundings_highlight_i18n [roles schema_camper surroundings_highlight language] 2024-01-15T20:00:45Z jordi fita mas # Add relation for surrounding highlights translations +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 diff --git a/test/add_surroundings_highlight.sql b/test/add_surroundings_highlight.sql new file mode 100644 index 0000000..76995af --- /dev/null +++ b/test/add_surroundings_highlight.sql @@ -0,0 +1,66 @@ +-- Test add_surroundings_highlight +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', 'add_surroundings_highlight', array['integer', 'integer', 'text', 'text']); +select function_lang_is('camper', 'add_surroundings_highlight', array['integer', 'integer', 'text', 'text'], 'sql'); +select function_returns('camper', 'add_surroundings_highlight', array['integer', 'integer', 'text', 'text'], 'integer'); +select isnt_definer('camper', 'add_surroundings_highlight', array['integer', 'integer', 'text', 'text']); +select volatility_is('camper', 'add_surroundings_highlight', array['integer', 'integer', 'text', 'text'], 'volatile'); +select function_privs_are('camper', 'add_surroundings_highlight', array ['integer', 'integer', 'text', 'text'], 'guest', array[]::text[]); +select function_privs_are('camper', 'add_surroundings_highlight', array ['integer', 'integer', 'text', 'text'], 'employee', array[]::text[]); +select function_privs_are('camper', 'add_surroundings_highlight', array ['integer', 'integer', 'text', 'text'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'add_surroundings_highlight', array ['integer', 'integer', 'text', 'text'], 'authenticator', array[]::text[]); + +set client_min_messages to warning; +truncate surroundings_highlight 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') + , (2, 'Company 4', 'XX234', '', '666-666-666', 'b@b', '', '', '', '', '', '', 60, 'FR', 'USD', 'ca') +; + +insert into media_content (media_type, bytes) +values ('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 (3, 1, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) + , (4, 2, 'cover4.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) +; + +select lives_ok( + $$ select add_surroundings_highlight(1, 3, 'Highlight A', '

What

') $$, + 'Should be able to add a surroundings highlight to the first company' +); + +select lives_ok( + $$ select add_surroundings_highlight(2, 4, 'Highlight B', '') $$, + 'Should be able to add a surroundings highlight to the second company' +); + +select bag_eq( + $$ select company_id, media_id, name, description::text from surroundings_highlight $$, + $$ values (1, 3, 'Highlight A', '

What

') + , (2, 4, 'Highlight B', '') + $$, + 'Should have added all two surroundings highlight' +); + + +select * +from finish(); + +rollback; diff --git a/test/edit_surroundings_highlight.sql b/test/edit_surroundings_highlight.sql new file mode 100644 index 0000000..e9d7292 --- /dev/null +++ b/test/edit_surroundings_highlight.sql @@ -0,0 +1,74 @@ +-- Test edit_surroundings_highlight +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', 'edit_surroundings_highlight', array['integer', 'integer', 'text', 'text']); +select function_lang_is('camper', 'edit_surroundings_highlight', array['integer', 'integer', 'text', 'text'], 'sql'); +select function_returns('camper', 'edit_surroundings_highlight', array['integer', 'integer', 'text', 'text'], 'integer'); +select isnt_definer('camper', 'edit_surroundings_highlight', array['integer', 'integer', 'text', 'text']); +select volatility_is('camper', 'edit_surroundings_highlight', array['integer', 'integer', 'text', 'text'], 'volatile'); +select function_privs_are('camper', 'edit_surroundings_highlight', array ['integer', 'integer', 'text', 'text'], 'guest', array[]::text[]); +select function_privs_are('camper', 'edit_surroundings_highlight', array ['integer', 'integer', 'text', 'text'], 'employee', array[]::text[]); +select function_privs_are('camper', 'edit_surroundings_highlight', array ['integer', 'integer', 'text', 'text'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'edit_surroundings_highlight', array ['integer', 'integer', 'text', 'text'], 'authenticator', array[]::text[]); + + +set client_min_messages to warning; +truncate surroundings_highlight 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"};') +; + +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"};')) +; + +insert into surroundings_highlight (surroundings_highlight_id, company_id, media_id, name, description) +values (8, 1, 2, 'Highlight A', '

1

') + , (9, 1, 3, 'Highlight B', '

2

') +; + +select lives_ok( + $$ select edit_surroundings_highlight(8, 4, 'Highlight 1', '

A

') $$, + 'Should be able to edit the first highlight' +); + +select lives_ok( + $$ select edit_surroundings_highlight(9, null, 'Highlight 2', '

B

') $$, + 'Should be able to edit the second highlight' +); + +select bag_eq( + $$ select surroundings_highlight_id, media_id, name, description::text from surroundings_highlight $$, + $$ values (8, 4, 'Highlight 1', '

A

') + , (9, 3, 'Highlight 2', '

B

') + $$, + 'Should have updated all surroundings highlights.' +); + + +select * +from finish(); + +rollback; diff --git a/test/order_surroundings_highlights.sql b/test/order_surroundings_highlights.sql new file mode 100644 index 0000000..3932469 --- /dev/null +++ b/test/order_surroundings_highlights.sql @@ -0,0 +1,71 @@ +-- Test order_surroundings_highlights +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_surroundings_highlights', array['integer[]']); +select function_lang_is('camper', 'order_surroundings_highlights', array['integer[]'], 'sql'); +select function_returns('camper', 'order_surroundings_highlights', array['integer[]'], 'void'); +select isnt_definer('camper', 'order_surroundings_highlights', array['integer[]']); +select volatility_is('camper', 'order_surroundings_highlights', array['integer[]'], 'volatile'); +select function_privs_are('camper', 'order_surroundings_highlights', array ['integer[]'], 'guest', array[]::text[]); +select function_privs_are('camper', 'order_surroundings_highlights', array ['integer[]'], 'employee', array[]::text[]); +select function_privs_are('camper', 'order_surroundings_highlights', array ['integer[]'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'order_surroundings_highlights', array ['integer[]'], 'authenticator', array[]::text[]); + + +set client_min_messages to warning; +truncate surroundings_highlight 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"};') +; + +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"};')) +; + +insert into surroundings_highlight (surroundings_highlight_id, company_id, media_id, name, description) +values (3, 1, 2, 'A', '') + , (4, 1, 2, 'B', '') + , (5, 1, 2, 'C', '') + , (6, 1, 2, 'D', '') + , (7, 1, 2, 'E', '') +; + +select lives_ok( + $$ select order_surroundings_highlights('{5,7,6,3,4}') $$, + 'Should be able to sort surroundings highlights using their ids' +); + +select bag_eq( + $$ select surroundings_highlight_id, position from surroundings_highlight $$, + $$ values (5, 1) + , (7, 2) + , (6, 3) + , (3, 4) + , (4, 5) + $$, + 'Should have sorted all surroundings highlights.' +); + + +select * +from finish(); + +rollback; diff --git a/test/remove_surroundings_highlight.sql b/test/remove_surroundings_highlight.sql new file mode 100644 index 0000000..52fe578 --- /dev/null +++ b/test/remove_surroundings_highlight.sql @@ -0,0 +1,87 @@ +-- Test remove_surroundings_highlight +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_surroundings_highlight', array['integer']); +select function_lang_is('camper', 'remove_surroundings_highlight', array['integer'], 'sql'); +select function_returns('camper', 'remove_surroundings_highlight', array['integer'], 'void'); +select isnt_definer('camper', 'remove_surroundings_highlight', array['integer']); +select volatility_is('camper', 'remove_surroundings_highlight', array['integer'], 'volatile'); +select function_privs_are('camper', 'remove_surroundings_highlight', array['integer'], 'guest', array[]::text[]); +select function_privs_are('camper', 'remove_surroundings_highlight', array['integer'], 'employee', array[]::text[]); +select function_privs_are('camper', 'remove_surroundings_highlight', array['integer'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'remove_surroundings_highlight', array['integer'], 'authenticator', array[]::text[]); + + +set client_min_messages to warning; +truncate surroundings_highlight 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"};') +; + +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"};')) +; + +insert into surroundings_highlight (surroundings_highlight_id, company_id, media_id, name, description) +values (7, 1, 2, 'Highlight A', '

One

') + , (8, 1, 3, 'Highlight B', '

Two

') + , (9, 1, 3, 'Highlight C', '

Three

') +; + +insert into surroundings_highlight_i18n (surroundings_highlight_id, lang_tag, name, description) +values (7, 'ca', 'Destacat A', '') + , (7, 'es', 'Destacado A', '') + , (8, 'ca', 'Destacat B', '') + , (8, 'es', 'Destacado B', '') + , (9, 'ca', 'Destacat C', '') + , (9, 'es', 'Destacado C', '') +; + +select lives_ok( + $$ select remove_surroundings_highlight(8) $$, + 'Should be able to delete a service' +); + +select bag_eq( + $$ select surroundings_highlight_id, name from surroundings_highlight $$, + $$ values (7, 'Highlight A') + , (9, 'Highlight C') + $$, + 'Should have removed the highlight' +); + +select bag_eq( + $$ select surroundings_highlight_id, lang_tag, name from surroundings_highlight_i18n $$, + $$ values (7, 'ca', 'Destacat A') + , (7, 'es', 'Destacado A') + , (9, 'ca', 'Destacat C') + , (9, 'es', 'Destacado C') + $$, + 'Should have removed the highlight’s translations' +); + +select * +from finish(); + +rollback; diff --git a/test/surroundings_highlight.sql b/test/surroundings_highlight.sql new file mode 100644 index 0000000..f122e72 --- /dev/null +++ b/test/surroundings_highlight.sql @@ -0,0 +1,210 @@ +-- Test surroundings_highlight +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(50); + +set search_path to camper, public; + +select has_table('surroundings_highlight'); +select has_pk('surroundings_highlight'); +select table_privs_are('surroundings_highlight', 'guest', array['SELECT']); +select table_privs_are('surroundings_highlight', 'employee', array['SELECT']); +select table_privs_are('surroundings_highlight', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']); +select table_privs_are('surroundings_highlight', 'authenticator', array[]::text[]); + +select has_column('surroundings_highlight', 'surroundings_highlight_id'); +select col_is_pk('surroundings_highlight', 'surroundings_highlight_id'); +select col_type_is('surroundings_highlight', 'surroundings_highlight_id', 'integer'); +select col_not_null('surroundings_highlight', 'surroundings_highlight_id'); +select col_hasnt_default('surroundings_highlight', 'surroundings_highlight_id'); + +select has_column('surroundings_highlight', 'company_id'); +select col_is_fk('surroundings_highlight', 'company_id'); +select fk_ok('surroundings_highlight', 'company_id', 'company', 'company_id'); +select col_type_is('surroundings_highlight', 'company_id', 'integer'); +select col_not_null('surroundings_highlight', 'company_id'); +select col_hasnt_default('surroundings_highlight', 'company_id'); + +select has_column('surroundings_highlight', 'media_id'); +select col_type_is('surroundings_highlight', 'media_id', 'integer'); +select col_not_null('surroundings_highlight', 'media_id'); +select col_hasnt_default('surroundings_highlight', 'media_id'); + +select has_column('surroundings_highlight', 'name'); +select col_is_fk('surroundings_highlight', 'media_id'); +select fk_ok('surroundings_highlight', 'media_id', 'media', 'media_id'); +select col_type_is('surroundings_highlight', 'name', 'text'); +select col_not_null('surroundings_highlight', 'name'); +select col_hasnt_default('surroundings_highlight', 'name'); + +select has_column('surroundings_highlight', 'description'); +select col_type_is('surroundings_highlight', 'description', 'xml'); +select col_not_null('surroundings_highlight', 'description'); +select col_hasnt_default('surroundings_highlight', 'description'); + +select has_column('surroundings_highlight', 'position'); +select col_type_is('surroundings_highlight', 'position', 'integer'); +select col_not_null('surroundings_highlight', 'position'); +select col_has_default('surroundings_highlight', 'position'); +select col_default_is('surroundings_highlight', 'position', '2147483647'); + + +set client_min_messages to warning; +truncate surroundings_highlight 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 ('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 (6, 2, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) + , (8, 4, 'cover4.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) +; + +insert into surroundings_highlight (company_id, media_id, name, description) +values (2, 6, 'Girona', '

Beautiful

') + , (4, 8, 'Barcelona', '

Shit

') +; + +prepare surroundings_highlight_data as +select company_id, name +from surroundings_highlight +order by company_id, name; + +set role guest; +select bag_eq( + 'surroundings_highlight_data', + $$ values (2, 'Girona') + , (4, 'Barcelona') + $$, + 'Everyone should be able to list all surroundings highlights across all companies' +); +reset role; + +select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'co2'); + +select lives_ok( + $$ insert into surroundings_highlight(company_id, media_id, name, description) values (2, 6, 'Another highlight', '
') $$, + 'Admin from company 2 should be able to insert a new surroundings highlights to that company.' +); + +select bag_eq( + 'surroundings_highlight_data', + $$ values (2, 'Girona') + , (2, 'Another highlight') + , (4, 'Barcelona') + $$, + 'The new row should have been added' +); + +select lives_ok( + $$ update surroundings_highlight set name = 'Another' where company_id = 2 and name = 'Another highlight' $$, + 'Admin from company 2 should be able to update surroundings highlights of that company.' +); + +select bag_eq( + 'surroundings_highlight_data', + $$ values (2, 'Girona') + , (2, 'Another') + , (4, 'Barcelona') + $$, + 'The row should have been updated.' +); + +select lives_ok( + $$ delete from surroundings_highlight where company_id = 2 and name = 'Another' $$, + 'Admin from company 2 should be able to delete surroundings highlights from that company.' +); + +select bag_eq( + 'surroundings_highlight_data', + $$ values (2, 'Girona') + , (4, 'Barcelona') + $$, + 'The row should have been deleted.' +); + +select throws_ok( + $$ insert into surroundings_highlight (company_id, media_id, name, description) values (4, 8, 'Another highlight', '
') $$, + '42501', 'new row violates row-level security policy for table "surroundings_highlight"', + 'Admin from company 2 should NOT be able to insert new surroundings highlights to company 4.' +); + +select lives_ok( + $$ update surroundings_highlight set name = 'Nope' where company_id = 4 $$, + 'Admin from company 2 should not be able to update new surroundings highlights of company 4, but no error if company_id is not changed.' +); + +select bag_eq( + 'surroundings_highlight_data', + $$ values (2, 'Girona') + , (4, 'Barcelona') + $$, + 'No row should have been changed.' +); + +select throws_ok( + $$ update surroundings_highlight set company_id = 4 where company_id = 2 $$, + '42501', 'new row violates row-level security policy for table "surroundings_highlight"', + 'Admin from company 2 should NOT be able to move surroundings highlights to company 4' +); + +select lives_ok( + $$ delete from surroundings_highlight where company_id = 4 $$, + 'Admin from company 2 should NOT be able to delete surroundings highlights from company 4, but not error is thrown' +); + +select bag_eq( + 'surroundings_highlight_data', + $$ values (2, 'Girona') + , (4, 'Barcelona') + $$, + 'No row should have been changed' +); + +select throws_ok( + $$ insert into surroundings_highlight (company_id, media_id, name, description) values (2, 6, ' ', '') $$, + '23514', 'new row for relation "surroundings_highlight" violates check constraint "name_not_empty"', + 'Should not be able to insert surroundings highlights with a blank name.' +); + + +reset role; + + +select * +from finish(); + +rollback; + diff --git a/test/surroundings_highlight_i18n.sql b/test/surroundings_highlight_i18n.sql new file mode 100644 index 0000000..2d2f318 --- /dev/null +++ b/test/surroundings_highlight_i18n.sql @@ -0,0 +1,49 @@ +-- Test surroundings_highlight_i18n +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(27); + +set search_path to camper, public; + +select has_table('surroundings_highlight_i18n'); +select has_pk('surroundings_highlight_i18n'); +select col_is_pk('surroundings_highlight_i18n', array['surroundings_highlight_id', 'lang_tag']); +select table_privs_are('surroundings_highlight_i18n', 'guest', array['SELECT']); +select table_privs_are('surroundings_highlight_i18n', 'employee', array['SELECT']); +select table_privs_are('surroundings_highlight_i18n', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']); +select table_privs_are('surroundings_highlight_i18n', 'authenticator', array[]::text[]); + +select has_column('surroundings_highlight_i18n', 'surroundings_highlight_id'); +select col_is_fk('surroundings_highlight_i18n', 'surroundings_highlight_id'); +select fk_ok('surroundings_highlight_i18n', 'surroundings_highlight_id', 'surroundings_highlight', 'surroundings_highlight_id'); +select col_type_is('surroundings_highlight_i18n', 'surroundings_highlight_id', 'integer'); +select col_not_null('surroundings_highlight_i18n', 'surroundings_highlight_id'); +select col_hasnt_default('surroundings_highlight_i18n', 'surroundings_highlight_id'); + +select has_column('surroundings_highlight_i18n', 'lang_tag'); +select col_is_fk('surroundings_highlight_i18n', 'lang_tag'); +select fk_ok('surroundings_highlight_i18n', 'lang_tag', 'language', 'lang_tag'); +select col_type_is('surroundings_highlight_i18n', 'lang_tag', 'text'); +select col_not_null('surroundings_highlight_i18n', 'lang_tag'); +select col_hasnt_default('surroundings_highlight_i18n', 'lang_tag'); + +select has_column('surroundings_highlight_i18n', 'name'); +select col_type_is('surroundings_highlight_i18n', 'name', 'text'); +select col_not_null('surroundings_highlight_i18n', 'name'); +select col_hasnt_default('surroundings_highlight_i18n', 'name'); + +select has_column('surroundings_highlight_i18n', 'description'); +select col_type_is('surroundings_highlight_i18n', 'description', 'xml'); +select col_not_null('surroundings_highlight_i18n', 'description'); +select col_hasnt_default('surroundings_highlight_i18n', 'description'); + + +select * +from finish(); + +rollback; + diff --git a/test/translate_surroundings_highlight.sql b/test/translate_surroundings_highlight.sql new file mode 100644 index 0000000..a3f80b7 --- /dev/null +++ b/test/translate_surroundings_highlight.sql @@ -0,0 +1,83 @@ +-- Test translate_surroundings_highlight +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_surroundings_highlight', array['integer', 'text', 'text', 'text']); +select function_lang_is('camper', 'translate_surroundings_highlight', array['integer', 'text', 'text', 'text'], 'sql'); +select function_returns('camper', 'translate_surroundings_highlight', array['integer', 'text', 'text', 'text'], 'void'); +select isnt_definer('camper', 'translate_surroundings_highlight', array['integer', 'text', 'text', 'text']); +select volatility_is('camper', 'translate_surroundings_highlight', array['integer', 'text', 'text', 'text'], 'volatile'); +select function_privs_are('camper', 'translate_surroundings_highlight', array['integer', 'text', 'text', 'text'], 'guest', array[]::text[]); +select function_privs_are('camper', 'translate_surroundings_highlight', array['integer', 'text', 'text', 'text'], 'employee', array[]::text[]); +select function_privs_are('camper', 'translate_surroundings_highlight', array['integer', 'text', 'text', 'text'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'translate_surroundings_highlight', array['integer', 'text', 'text', 'text'], 'authenticator', array[]::text[]); + + +set client_min_messages to warning; +truncate surroundings_highlight 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"};') +; + +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"};')) +; + +insert into surroundings_highlight (surroundings_highlight_id, company_id, media_id, name, description) +values (8, 1, 2, 'Highlight A', '

One

') + , (9, 1, 3, 'Highlight B', '

Two

') +; + +insert into surroundings_highlight_i18n (surroundings_highlight_id, lang_tag, name, description) +values (9, 'ca', 'destacatb', '

dos

') +; + +select lives_ok( + $$ select translate_surroundings_highlight(8, 'ca', 'Destacat A', null) $$, + 'Should be able to translate the first highlight' +); + +select lives_ok( + $$ select translate_surroundings_highlight(9, 'es', 'Destacado B', '

Dos

') $$, + 'Should be able to translate the second highlight' +); + +select lives_ok( + $$ select translate_surroundings_highlight(9, 'ca', 'Destacat B', '

I dos

') $$, + 'Should be able to overwrite the catalan translation of the second highlight' +); + +select bag_eq( + $$ select surroundings_highlight_id, lang_tag, i18n.name, i18n.description::text from surroundings_highlight_i18n as i18n join surroundings_highlight using (surroundings_highlight_id) $$, + $$ values (8, 'ca', 'Destacat A', '') + , (9, 'ca', 'Destacat B', '

I dos

') + , (9, 'es', 'Destacado B', '

Dos

') + $$, + 'Should have added and updated all translations.' +); + + +select * +from finish(); + +rollback; diff --git a/verify/add_surroundings_highlight.sql b/verify/add_surroundings_highlight.sql new file mode 100644 index 0000000..c74bd82 --- /dev/null +++ b/verify/add_surroundings_highlight.sql @@ -0,0 +1,7 @@ +-- Verify camper:add_surroundings_highlight on pg + +begin; + +select has_function_privilege('camper.add_surroundings_highlight(integer, integer, text, text)', 'execute'); + +rollback; diff --git a/verify/edit_surroundings_highlight.sql b/verify/edit_surroundings_highlight.sql new file mode 100644 index 0000000..ad4d1fd --- /dev/null +++ b/verify/edit_surroundings_highlight.sql @@ -0,0 +1,7 @@ +-- Verify camper:edit_surroundings_highlight on pg + +begin; + +select has_function_privilege('camper.edit_surroundings_highlight(integer, integer, text, text)', 'execute'); + +rollback; diff --git a/verify/order_surroundings_highlights.sql b/verify/order_surroundings_highlights.sql new file mode 100644 index 0000000..4632815 --- /dev/null +++ b/verify/order_surroundings_highlights.sql @@ -0,0 +1,7 @@ +-- Verify camper:order_surroundings_highlights on pg + +begin; + +select has_function_privilege('camper.order_surroundings_highlights(integer[])', 'execute'); + +rollback; diff --git a/verify/remove_surroundings_highlight.sql b/verify/remove_surroundings_highlight.sql new file mode 100644 index 0000000..403875a --- /dev/null +++ b/verify/remove_surroundings_highlight.sql @@ -0,0 +1,7 @@ +-- Verify camper:remove_surroundings_highlight on pg + +begin; + +select has_function_privilege('camper.remove_surroundings_highlight(integer)', 'execute'); + +rollback; diff --git a/verify/surroundings_highlight.sql b/verify/surroundings_highlight.sql new file mode 100644 index 0000000..fa098db --- /dev/null +++ b/verify/surroundings_highlight.sql @@ -0,0 +1,21 @@ +-- Verify camper:surroundings_highlight on pg + +begin; + +select surroundings_highlight_id + , company_id + , media_id + , name + , description + , position +from camper.surroundings_highlight +where false; + +select 1 / count(*) from pg_class where oid = 'camper.surroundings_highlight'::regclass and relrowsecurity; +select 1 / count(*) from pg_policy where polname = 'guest_ok' and polrelid = 'camper.surroundings_highlight'::regclass; +select 1 / count(*) from pg_policy where polname = 'insert_to_company' and polrelid = 'camper.surroundings_highlight'::regclass; +select 1 / count(*) from pg_policy where polname = 'update_company' and polrelid = 'camper.surroundings_highlight'::regclass; +select 1 / count(*) from pg_policy where polname = 'delete_from_company' and polrelid = 'camper.surroundings_highlight'::regclass; + + +rollback; diff --git a/verify/surroundings_highlight_i18n.sql b/verify/surroundings_highlight_i18n.sql new file mode 100644 index 0000000..17aa501 --- /dev/null +++ b/verify/surroundings_highlight_i18n.sql @@ -0,0 +1,12 @@ +-- Verify camper:surroundings_highlight_i18n on pg + +begin; + +select surroundings_highlight_id + , lang_tag + , name + , description +from camper.surroundings_highlight_i18n +where false; + +rollback; diff --git a/verify/translate_surroundings_highlight.sql b/verify/translate_surroundings_highlight.sql new file mode 100644 index 0000000..fb01b7d --- /dev/null +++ b/verify/translate_surroundings_highlight.sql @@ -0,0 +1,7 @@ +-- Verify camper:translate_surroundings_highlight on pg + +begin; + +select has_function_privilege('camper.translate_surroundings_highlight(integer, text, text, text)', 'execute'); + +rollback; diff --git a/web/static/images/caiac_mar.webp b/web/static/images/caiac_mar.webp deleted file mode 100644 index 865f362..0000000 Binary files a/web/static/images/caiac_mar.webp and /dev/null differ diff --git a/web/static/images/calella_de_palafrugell.webp b/web/static/images/calella_de_palafrugell.webp deleted file mode 100644 index bcec100..0000000 Binary files a/web/static/images/calella_de_palafrugell.webp and /dev/null differ diff --git a/web/static/images/escalada_sadernes.webp b/web/static/images/escalada_sadernes.webp deleted file mode 100644 index 75237e0..0000000 Binary files a/web/static/images/escalada_sadernes.webp and /dev/null differ diff --git a/web/static/images/excusions.webp b/web/static/images/excusions.webp deleted file mode 100644 index 585a7d1..0000000 Binary files a/web/static/images/excusions.webp and /dev/null differ diff --git a/web/static/images/gastronomia.webp b/web/static/images/gastronomia.webp deleted file mode 100644 index 0194f1f..0000000 Binary files a/web/static/images/gastronomia.webp and /dev/null differ diff --git a/web/static/images/museu_dali_figueres.webp b/web/static/images/museu_dali_figueres.webp deleted file mode 100644 index bb44cbc..0000000 Binary files a/web/static/images/museu_dali_figueres.webp and /dev/null differ diff --git a/web/static/images/rutes_amb_bicicleta.webp b/web/static/images/rutes_amb_bicicleta.webp deleted file mode 100644 index 9fe9bc2..0000000 Binary files a/web/static/images/rutes_amb_bicicleta.webp and /dev/null differ diff --git a/web/static/public.css b/web/static/public.css index 9abed80..c124d74 100644 --- a/web/static/public.css +++ b/web/static/public.css @@ -282,7 +282,7 @@ h1 a .name { left: -9999em; } -nav ul, .campsite_type_features ul { +nav ul, .campsite_type_features ul, .outside_activities > ul { list-style: none; padding-left: 0; display: flex; @@ -666,27 +666,6 @@ dt { } } -/* autside-activities tablet & mobile */ -@media (max-width: 64rem) { - - dl, .nature div + div, .outside_activities > div { - flex-direction: column; - } - - .outside_activities > div:first-of-type p { - width: 100% !important; - margin-top: 0 !important; - } - - .outside_activities > div:first-of-type img:last-child { - width: 100% !important; - margin-top: 0 !important; - } - -} - -/* end autside-activities tablet & mobile */ - .outside_activities { margin-top: 2rem; } @@ -701,64 +680,52 @@ dt { margin-bottom: 10rem; } -.outside_activities img { - border-radius: 5px; +.outside_activities > ul { + max-width: 108rem; + margin: 0 auto; + flex-direction: column; + gap: 2.7rem; } -.outside_activities > div { - align-items: start; +.outside_activities article { + display: flex; + gap: 5.5%; + justify-content: space-between; } -.outside_activities > div:first-of-type { - margin-bottom: 5rem; +.outside_activities > ul > li:nth-child(2n) article { + flex-direction: row-reverse; } -.outside_activities > div:first-of-type p { - width: 25%; - margin-top: 12rem; +.outside_activities article h4 { + font-size: 2.3rem; } -.outside_activities > div:first-of-type img { - width: 40%; +.outside_activities article > div { + width: 29.5%; } -.outside_activities > div:first-of-type img:last-child { - width: 35%; - margin-top: 22rem; +.outside_activities article > img { + width: 64%; + aspect-ratio: 16/9; + object-fit: cover; } -.outside_activities > div:nth-of-type(2) > img { - width: 35%; +@media (max-width: 64rem) { + .outside_activities > ul { + gap: 5rem; + } + + .outside_activities article, .outside_activities > ul > li:nth-child(2n) article { + flex-direction: column; + gap: 1rem; + } + + .outside_activities article > div, .outside_activities article > img { + width: 100%; + } } -.outside_activities > div:nth-of-type(2) > div { - width: 30%; - margin-top: 10rem; -} - -.outside_activities > div:nth-of-type(2) > div img { - margin-top: 20rem; -} - -.outside_activities > div:nth-of-type(2) > img:last-child { - margin-top: 22rem; -} - -.outside_activities > div:last-child img { - width: 40%; -} - -.outside_activities > div:last-child img:first-child { - margin-top: 10rem; -} - -.outside_activities > div:last-child img:nth-child(2) { - margin-top: 22rem; -} - -.outside_activities > div:last-child div { - width: 20%; -} .campsite_activities { margin-top: 10rem; @@ -1283,7 +1250,7 @@ input[type="checkbox"]:focus { grid-template-columns: repeat(2, 1fr); } -#booking a { +#booking a, .outside_activities a { color: var(--accent); text-decoration: var(--accent) wavy underline; } diff --git a/web/templates/admin/layout.gohtml b/web/templates/admin/layout.gohtml index 1fd623a..f30f580 100644 --- a/web/templates/admin/layout.gohtml +++ b/web/templates/admin/layout.gohtml @@ -60,6 +60,9 @@
  • {{( pgettext "Location" "title" )}}
  • +
  • + {{( pgettext "Surroundings" "title" )}} +
  • {{( pgettext "Legal Texts" "title" )}}
  • diff --git a/web/templates/admin/surroundings/form.gohtml b/web/templates/admin/surroundings/form.gohtml new file mode 100644 index 0000000..4b93cda --- /dev/null +++ b/web/templates/admin/surroundings/form.gohtml @@ -0,0 +1,72 @@ + +{{ define "title" -}} + {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/carousel.slideForm*/ -}} + {{ if .ID}} + {{( pgettext "Edit Highlight" "title" )}} + {{ else }} + {{( pgettext "New Highlight" "title" )}} + {{ end }} +{{- end }} + +{{ define "content" -}} + {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/surroundings.highlightForm*/ -}} +
    +

    + {{ if .ID }} + {{( pgettext "Edit Highlight" "title" )}} + {{ else }} + {{( pgettext "New Highlight" "title" )}} + {{ end }} +

    + {{ CSRFInput }} +
    + {{ with .Media -}} + {{ template "media-picker" . }} + {{- end }} + {{ with .Name -}} +
    + {{( pgettext "Name" "input")}} + {{ template "lang-selector" . }} + {{ range $lang, $input := . -}} + + {{- end }} + {{ template "error-message" . }} +
    + {{- end }} + {{ with .Description -}} +
    + {{( pgettext "Description" "input")}} + {{ template "lang-selector" . }} + {{ range $lang, $input := . -}} + + {{- end }} + {{ template "error-message" . }} +
    + {{- end }} +
    +
    + +
    +
    +{{- end }} diff --git a/web/templates/admin/surroundings/index.gohtml b/web/templates/admin/surroundings/index.gohtml new file mode 100644 index 0000000..eca20cc --- /dev/null +++ b/web/templates/admin/surroundings/index.gohtml @@ -0,0 +1,55 @@ + +{{ define "title" -}} + {{( pgettext "Surroundings Page" "title" )}} +{{- end }} + +{{ define "content" -}} + {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/surroundings.highlightIndex*/ -}} +

    {{( pgettext "Highlights" "title" )}}

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

    {{( gettext "No highlights added yet." )}}

    + {{- end }} +{{- end }} diff --git a/web/templates/public/surroundings.gohtml b/web/templates/public/surroundings.gohtml index 3d432fe..7f1acef 100644 --- a/web/templates/public/surroundings.gohtml +++ b/web/templates/public/surroundings.gohtml @@ -7,47 +7,44 @@ {{- end }} {{ define "content" -}} + {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/surroundings.surroundingsPage*/ -}}

    {{( pgettext "Surroundings" "title" )}}

    -
    - -
    - -
    - -
    -

    Vine a fer barranquisme per Sadernes!

    - Reserva el teu dia - -
    -
    - -
    +
    +
    +
    +
    +

    Vine a fer barranquisme per Sadernes!

    + Reserva el teu dia + + + + + +
    +
    +

    {{( pgettext "What to Do Outside the Campsite?" "title" )}}

    -
    -

    {{( gettext "Campsite Montagut is an ideal starting point for quiet outings, climbing, swimming in the river and gorges, volcanoes, the Fageda d’en Jordà, cycle tours for all ages…." )}}

    - - -
    -
    - -
    -

    {{( gettext "Get to the Costa Brava and enjoy the beaches, the gastronomy or go kayaking….")}}

    - -
    - -
    -
    - - -
    -

    {{( gettext "You will also find museums in Olot, Figures, Girona.")}}

    -

    {{( gettext "As well as music festivals, dance, theater…." )}}

    -
    -
    + {{ with .Highlights -}} +
      + {{ range . -}} +
    • +
      +
      +

      {{ .Name }}

      + {{ .Description }} +
      + +
      +
    • + {{- end }} +
    + {{- end }}