Add the carousel for campsite types
I can not reuse the carousel package because these carousels need the campsite site’s slug as a first parameters: i can not have a relation per campsite type, as i do in home and services pages, because the campsite types are added by administration types; even if i had a single relation for slides of home and services pages, these would go in a different relation due to the foreign key to campsite type. What i could reuse, however, is the Slide and SlideEntry types from that package, although i had to export carousel.Translation to be usable from the types package. I should change that to use locale.Translation, but this was the easier option, or i would need to change the queries and templates for carousel package too. Besides that, they work exactly like the slides in home and services pages.
This commit is contained in:
parent
ad7126cc92
commit
471ed9e870
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
135
demo/demo.sql
135
demo/demo.sql
|
@ -46,6 +46,30 @@ select add_media(52, 'services_carousel0.avif', 'image/avif', decode('m4_esyscmd
|
|||
select add_media(52, 'services_carousel1.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/services_carousel1.avif]])', 'base64'));
|
||||
select add_media(52, 'services_carousel2.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/services_carousel2.avif]])', 'base64'));
|
||||
select add_media(52, 'services_carousel3.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/services_carousel3.avif]])', 'base64'));
|
||||
select add_media(52, 'safari_tents_carousel1.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/safari_tents_carousel1.avif]])', 'base64'));
|
||||
select add_media(52, 'safari_tents_carousel2.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/safari_tents_carousel2.avif]])', 'base64'));
|
||||
select add_media(52, 'safari_tents_carousel3.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/safari_tents_carousel3.avif]])', 'base64'));
|
||||
select add_media(52, 'safari_tents_carousel4.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/safari_tents_carousel4.avif]])', 'base64'));
|
||||
select add_media(52, 'safari_tents_carousel5.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/safari_tents_carousel5.avif]])', 'base64'));
|
||||
select add_media(52, 'safari_tents_carousel6.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/safari_tents_carousel6.avif]])', 'base64'));
|
||||
select add_media(52, 'bungalows_carousel2.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/bungalows_carousel2.avif]])', 'base64'));
|
||||
select add_media(52, 'bungalows_carousel3.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/bungalows_carousel3.avif]])', 'base64'));
|
||||
select add_media(52, 'bungalows_carousel4.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/bungalows_carousel4.avif]])', 'base64'));
|
||||
select add_media(52, 'bungalows_carousel5.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/bungalows_carousel5.avif]])', 'base64'));
|
||||
select add_media(52, 'bungalows_carousel6.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/bungalows_carousel6.avif]])', 'base64'));
|
||||
select add_media(52, 'wooden_lodges_carousel0.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/wooden_lodges_carousel0.avif]])', 'base64'));
|
||||
select add_media(52, 'wooden_lodges_carousel1.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/wooden_lodges_carousel1.avif]])', 'base64'));
|
||||
select add_media(52, 'wooden_lodges_carousel2.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/wooden_lodges_carousel2.avif]])', 'base64'));
|
||||
select add_media(52, 'wooden_lodges_carousel3.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/wooden_lodges_carousel3.avif]])', 'base64'));
|
||||
select add_media(52, 'wooden_lodges_carousel4.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/wooden_lodges_carousel4.avif]])', 'base64'));
|
||||
select add_media(52, 'wooden_lodges_carousel5.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/wooden_lodges_carousel5.avif]])', 'base64'));
|
||||
select add_media(52, 'wooden_lodges_carousel6.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/wooden_lodges_carousel6.avif]])', 'base64'));
|
||||
select add_media(52, 'wooden_lodges_carousel7.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/wooden_lodges_carousel7.avif]])', 'base64'));
|
||||
select add_media(52, 'wooden_lodges_carousel8.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/wooden_lodges_carousel8.avif]])', 'base64'));
|
||||
select add_media(52, 'wooden_lodges_carousel9.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/wooden_lodges_carousel9.avif]])', 'base64'));
|
||||
select add_media(52, 'wooden_lodges_carouselA.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/wooden_lodges_carouselA.avif]])', 'base64'));
|
||||
select add_media(52, 'wooden_lodges_carouselB.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/wooden_lodges_carouselB.avif]])', 'base64'));
|
||||
select add_media(52, 'wooden_lodges_carouselC.avif', 'image/avif', decode('m4_esyscmd([[base64 -w0 demo/wooden_lodges_carouselC.avif]])', 'base64'));
|
||||
;
|
||||
|
||||
insert into home_carousel (media_id, caption)
|
||||
|
@ -370,4 +394,115 @@ values (102, 92, 795)
|
|||
, (111, 94, 590)
|
||||
;
|
||||
|
||||
insert into campsite_type_carousel (campsite_type_id, media_id, caption)
|
||||
values (72, 77, 'Llegenda')
|
||||
, (72, 78, 'Llegenda')
|
||||
, (72, 79, 'Llegenda')
|
||||
, (73, 63, 'Llegenda')
|
||||
, (73, 80, 'Llegenda')
|
||||
, (73, 81, 'Llegenda')
|
||||
, (73, 82, 'Llegenda')
|
||||
, (73, 83, 'Llegenda')
|
||||
, (73, 84, 'Llegenda')
|
||||
, (73, 85, 'Llegenda')
|
||||
, (74, 64, 'Llegenda')
|
||||
, (74, 65, 'Llegenda')
|
||||
, (74, 86, 'Llegenda')
|
||||
, (74, 87, 'Llegenda')
|
||||
, (74, 88, 'Llegenda')
|
||||
, (74, 89, 'Llegenda')
|
||||
, (74, 90, 'Llegenda')
|
||||
, (75, 65, 'Llegenda')
|
||||
, (75, 64, 'Llegenda')
|
||||
, (75, 88, 'Llegenda')
|
||||
, (75, 86, 'Llegenda')
|
||||
, (75, 87, 'Llegenda')
|
||||
, (76, 91, 'Llegenda')
|
||||
, (76, 92, 'Llegenda')
|
||||
, (76, 93, 'Llegenda')
|
||||
, (76, 94, 'Llegenda')
|
||||
, (76, 95, 'Llegenda')
|
||||
, (76, 96, 'Llegenda')
|
||||
, (76, 97, 'Llegenda')
|
||||
, (76, 98, 'Llegenda')
|
||||
, (76, 99, 'Llegenda')
|
||||
, (76, 100, 'Llegenda')
|
||||
, (76, 101, 'Llegenda')
|
||||
, (76, 102, 'Llegenda')
|
||||
, (76, 103, 'Llegenda')
|
||||
;
|
||||
|
||||
insert into campsite_type_carousel_i18n (campsite_type_id, media_id, lang_tag, caption)
|
||||
values (72, 77, 'en', 'Legend')
|
||||
, (72, 77, 'es', 'Leyenda')
|
||||
, (72, 78, 'en', 'Legend')
|
||||
, (72, 78, 'es', 'Leyenda')
|
||||
, (72, 79, 'en', 'Legend')
|
||||
, (72, 79, 'es', 'Leyenda')
|
||||
, (73, 63, 'en', 'Legend')
|
||||
, (73, 63, 'es', 'Leyenda')
|
||||
, (73, 80, 'en', 'Legend')
|
||||
, (73, 80, 'es', 'Leyenda')
|
||||
, (73, 81, 'en', 'Legend')
|
||||
, (73, 81, 'es', 'Leyenda')
|
||||
, (73, 82, 'en', 'Legend')
|
||||
, (73, 82, 'es', 'Leyenda')
|
||||
, (73, 83, 'en', 'Legend')
|
||||
, (73, 83, 'es', 'Leyenda')
|
||||
, (73, 84, 'en', 'Legend')
|
||||
, (73, 84, 'es', 'Leyenda')
|
||||
, (73, 85, 'en', 'Legend')
|
||||
, (73, 85, 'es', 'Leyenda')
|
||||
, (74, 64, 'en', 'Legend')
|
||||
, (74, 64, 'es', 'Leyenda')
|
||||
, (74, 65, 'en', 'Legend')
|
||||
, (74, 65, 'es', 'Leyenda')
|
||||
, (74, 86, 'en', 'Legend')
|
||||
, (74, 86, 'es', 'Leyenda')
|
||||
, (74, 87, 'en', 'Legend')
|
||||
, (74, 87, 'es', 'Leyenda')
|
||||
, (74, 88, 'en', 'Legend')
|
||||
, (74, 88, 'es', 'Leyenda')
|
||||
, (74, 89, 'en', 'Legend')
|
||||
, (74, 89, 'es', 'Leyenda')
|
||||
, (74, 90, 'en', 'Legend')
|
||||
, (74, 90, 'es', 'Leyenda')
|
||||
, (75, 65, 'en', 'Legend')
|
||||
, (75, 65, 'es', 'Leyenda')
|
||||
, (75, 64, 'en', 'Legend')
|
||||
, (75, 64, 'es', 'Leyenda')
|
||||
, (75, 88, 'en', 'Legend')
|
||||
, (75, 88, 'es', 'Leyenda')
|
||||
, (75, 86, 'en', 'Legend')
|
||||
, (75, 86, 'es', 'Leyenda')
|
||||
, (75, 87, 'en', 'Legend')
|
||||
, (75, 87, 'es', 'Leyenda')
|
||||
, (76, 91, 'en', 'Legend')
|
||||
, (76, 91, 'es', 'Leyenda')
|
||||
, (76, 92, 'en', 'Legend')
|
||||
, (76, 92, 'es', 'Leyenda')
|
||||
, (76, 93, 'en', 'Legend')
|
||||
, (76, 93, 'es', 'Leyenda')
|
||||
, (76, 94, 'en', 'Legend')
|
||||
, (76, 94, 'es', 'Leyenda')
|
||||
, (76, 95, 'en', 'Legend')
|
||||
, (76, 95, 'es', 'Leyenda')
|
||||
, (76, 96, 'en', 'Legend')
|
||||
, (76, 96, 'es', 'Leyenda')
|
||||
, (76, 97, 'en', 'Legend')
|
||||
, (76, 97, 'es', 'Leyenda')
|
||||
, (76, 98, 'en', 'Legend')
|
||||
, (76, 98, 'es', 'Leyenda')
|
||||
, (76, 99, 'en', 'Legend')
|
||||
, (76, 99, 'es', 'Leyenda')
|
||||
, (76, 100, 'en', 'Legend')
|
||||
, (76, 100, 'es', 'Leyenda')
|
||||
, (76, 101, 'en', 'Legend')
|
||||
, (76, 101, 'es', 'Leyenda')
|
||||
, (76, 102, 'en', 'Legend')
|
||||
, (76, 102, 'es', 'Leyenda')
|
||||
, (76, 103, 'en', 'Legend')
|
||||
, (76, 103, 'es', 'Leyenda')
|
||||
;
|
||||
|
||||
commit;
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,28 @@
|
|||
-- Deploy camper:add_campsite_type_carousel_slide to pg
|
||||
-- requires: roles
|
||||
-- requires: schema_camper
|
||||
-- requires: campsite_type_carousel
|
||||
-- requires: campsite_type
|
||||
|
||||
begin;
|
||||
|
||||
set search_path to camper, public;
|
||||
|
||||
create or replace function add_campsite_type_carousel_slide(slug uuid, media_id integer, caption text) returns integer as
|
||||
$$
|
||||
insert into campsite_type_carousel (campsite_type_id, media_id, caption)
|
||||
select campsite_type_id, add_campsite_type_carousel_slide.media_id, coalesce(caption, '')
|
||||
from campsite_type
|
||||
where slug = add_campsite_type_carousel_slide.slug
|
||||
on conflict (campsite_type_id, media_id) do update
|
||||
set caption = excluded.caption
|
||||
returning campsite_type_id
|
||||
;
|
||||
$$
|
||||
language sql
|
||||
;
|
||||
|
||||
revoke execute on function add_campsite_type_carousel_slide(uuid, integer, text) from public;
|
||||
grant execute on function add_campsite_type_carousel_slide(uuid, integer, text) to admin;
|
||||
|
||||
commit;
|
|
@ -0,0 +1,55 @@
|
|||
-- Deploy camper:campsite_type_carousel to pg
|
||||
-- requires: roles
|
||||
-- requires: schema_camper
|
||||
-- requires: campsite_type
|
||||
-- requires: media
|
||||
-- requires: user_profile
|
||||
|
||||
begin;
|
||||
|
||||
set search_path to camper, public;
|
||||
|
||||
create table campsite_type_carousel (
|
||||
campsite_type_id integer not null references campsite_type,
|
||||
media_id integer not null references media,
|
||||
caption text not null,
|
||||
primary key (campsite_type_id, media_id)
|
||||
);
|
||||
|
||||
grant select on table campsite_type_carousel to guest;
|
||||
grant select on table campsite_type_carousel to employee;
|
||||
grant select, insert, update, delete on table campsite_type_carousel to admin;
|
||||
|
||||
alter table campsite_type_carousel enable row level security;
|
||||
|
||||
create policy guest_ok
|
||||
on campsite_type_carousel
|
||||
for select
|
||||
using (true)
|
||||
;
|
||||
|
||||
create policy insert_to_company
|
||||
on campsite_type_carousel
|
||||
for insert
|
||||
with check (
|
||||
exists (select 1 from campsite_type join media using (company_id) join user_profile using (company_id) where campsite_type.campsite_type_id = campsite_type_carousel.campsite_type_id and media.media_id = campsite_type_carousel.media_id)
|
||||
)
|
||||
;
|
||||
|
||||
create policy update_company
|
||||
on campsite_type_carousel
|
||||
for update
|
||||
using (
|
||||
exists (select 1 from campsite_type join media using (company_id) join user_profile using (company_id) where campsite_type.campsite_type_id = campsite_type_carousel.campsite_type_id and media.media_id = campsite_type_carousel.media_id)
|
||||
)
|
||||
;
|
||||
|
||||
create policy delete_from_company
|
||||
on campsite_type_carousel
|
||||
for delete
|
||||
using (
|
||||
exists (select 1 from campsite_type join media using (company_id) join user_profile using (company_id) where campsite_type.campsite_type_id = campsite_type_carousel.campsite_type_id and media.media_id = campsite_type_carousel.media_id)
|
||||
)
|
||||
;
|
||||
|
||||
commit;
|
|
@ -0,0 +1,24 @@
|
|||
-- Deploy camper:campsite_type_carousel_i18n to pg
|
||||
-- requires: roles
|
||||
-- requires: schema_camper
|
||||
-- requires: campsite_type_carousel
|
||||
-- requires: language
|
||||
|
||||
begin;
|
||||
|
||||
set search_path to camper, public;
|
||||
|
||||
create table campsite_type_carousel_i18n (
|
||||
campsite_type_id integer not null,
|
||||
media_id integer not null,
|
||||
lang_tag text not null references language,
|
||||
caption text not null,
|
||||
primary key (campsite_type_id, media_id, lang_tag),
|
||||
foreign key (campsite_type_id, media_id) references campsite_type_carousel
|
||||
);
|
||||
|
||||
grant select on table campsite_type_carousel_i18n to guest;
|
||||
grant select on table campsite_type_carousel_i18n to employee;
|
||||
grant select, insert, update, delete on table campsite_type_carousel_i18n to admin;
|
||||
|
||||
commit;
|
|
@ -0,0 +1,37 @@
|
|||
-- Deploy camper:remove_campsite_type_carousel_slide to pg
|
||||
-- requires: roles
|
||||
-- requires: schema_camper
|
||||
-- requires: campsite_type_carousel
|
||||
-- requires: campsite_type_carousel_i18n
|
||||
|
||||
begin;
|
||||
|
||||
set search_path to camper, public;
|
||||
|
||||
create or replace function remove_campsite_type_carousel_slide(slug uuid, media_id integer) returns void as
|
||||
$$
|
||||
declare
|
||||
csid integer;
|
||||
begin
|
||||
select campsite_type_id
|
||||
into csid
|
||||
from campsite_type
|
||||
where campsite_type.slug = $1
|
||||
;
|
||||
delete from campsite_type_carousel_i18n
|
||||
where campsite_type_id = csid
|
||||
and campsite_type_carousel_i18n.media_id = $2
|
||||
;
|
||||
delete from campsite_type_carousel
|
||||
where campsite_type_id = csid
|
||||
and campsite_type_carousel.media_id = $2
|
||||
;
|
||||
end
|
||||
$$
|
||||
language plpgsql
|
||||
;
|
||||
|
||||
revoke execute on function remove_campsite_type_carousel_slide(uuid, integer) from public;
|
||||
grant execute on function remove_campsite_type_carousel_slide(uuid, integer) to admin;
|
||||
|
||||
commit;
|
|
@ -0,0 +1,27 @@
|
|||
-- Deploy camper:translate_campsite_type_carousel_slide to pg
|
||||
-- requires: roles
|
||||
-- requires: schema_camper
|
||||
-- requires: campsite_type
|
||||
-- requires: campsite_type_carousel_i18n
|
||||
|
||||
begin;
|
||||
|
||||
set search_path to camper, public;
|
||||
|
||||
create or replace function translate_campsite_type_carousel_slide(slug uuid, media_id integer, lang_tag text, caption text) returns void as
|
||||
$$
|
||||
insert into campsite_type_carousel_i18n (campsite_type_id, media_id, lang_tag, caption)
|
||||
select campsite_type_id, translate_campsite_type_carousel_slide.media_id, lang_tag, coalesce(caption, '')
|
||||
from campsite_type
|
||||
where slug = translate_campsite_type_carousel_slide.slug
|
||||
on conflict (campsite_type_id, media_id, lang_tag) do update
|
||||
set caption = excluded.caption
|
||||
;
|
||||
$$
|
||||
language sql
|
||||
;
|
||||
|
||||
revoke execute on function translate_campsite_type_carousel_slide(uuid, integer, text, text) from public;
|
||||
grant execute on function translate_campsite_type_carousel_slide(uuid, integer, text, text) to admin;
|
||||
|
||||
commit;
|
|
@ -93,6 +93,8 @@ func (h *AdminHandler) typeHandler(user *auth.User, company *auth.Company, conn
|
|||
}
|
||||
case "options":
|
||||
h.optionsHandler(user, company, conn, f.Slug).ServeHTTP(w, r)
|
||||
case "slides":
|
||||
h.carouselHandler(user, company, conn, f.Slug).ServeHTTP(w, r)
|
||||
default:
|
||||
loc, ok := h.locales.Get(head)
|
||||
if !ok {
|
||||
|
|
|
@ -0,0 +1,297 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 jordi fita mas <jfita@peritasoft.com>
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/jackc/pgx/v4"
|
||||
|
||||
"dev.tandem.ws/tandem/camper/pkg/auth"
|
||||
"dev.tandem.ws/tandem/camper/pkg/carousel"
|
||||
"dev.tandem.ws/tandem/camper/pkg/database"
|
||||
"dev.tandem.ws/tandem/camper/pkg/form"
|
||||
httplib "dev.tandem.ws/tandem/camper/pkg/http"
|
||||
"dev.tandem.ws/tandem/camper/pkg/locale"
|
||||
"dev.tandem.ws/tandem/camper/pkg/template"
|
||||
)
|
||||
|
||||
func (h *AdminHandler) carouselHandler(user *auth.User, company *auth.Company, conn *database.Conn, typeSlug string) 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:
|
||||
serveCarouselIndex(w, r, user, company, conn, typeSlug)
|
||||
case http.MethodPost:
|
||||
addSlide(w, r, user, company, conn, typeSlug)
|
||||
default:
|
||||
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodGet)
|
||||
}
|
||||
case "new":
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
f := newSlideForm(typeSlug)
|
||||
f.MustRender(w, r, user, company)
|
||||
default:
|
||||
httplib.MethodNotAllowed(w, r, http.MethodGet)
|
||||
}
|
||||
default:
|
||||
mediaID, err := strconv.Atoi(head)
|
||||
if err != nil {
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
f := newSlideForm(typeSlug)
|
||||
if err := f.FillFromDatabase(r.Context(), conn, mediaID); err != nil {
|
||||
if database.ErrorIsNotFound(err) {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var langTag string
|
||||
langTag, r.URL.Path = httplib.ShiftPath(r.URL.Path)
|
||||
|
||||
switch langTag {
|
||||
case "":
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
f.MustRender(w, r, user, company)
|
||||
case http.MethodPut:
|
||||
editSlide(w, r, user, company, conn, f)
|
||||
case http.MethodDelete:
|
||||
h.deleteSlide(w, r, user, conn, typeSlug, mediaID)
|
||||
default:
|
||||
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut, http.MethodDelete)
|
||||
}
|
||||
default:
|
||||
loc, ok := h.locales.Get(langTag)
|
||||
if !ok {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
l10n := newSlideL10nForm(f, loc)
|
||||
if err := l10n.FillFromDatabase(r.Context(), conn); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
l10n.MustRender(w, r, user, company)
|
||||
case http.MethodPut:
|
||||
editSlideL10n(w, r, user, company, conn, l10n)
|
||||
default:
|
||||
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func serveCarouselIndex(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, typeSlug string) {
|
||||
slides, err := collectSlideEntries(r.Context(), conn, typeSlug)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
page := &carouselIndex{
|
||||
TypeSlug: typeSlug,
|
||||
Slides: slides,
|
||||
}
|
||||
page.MustRender(w, r, user, company)
|
||||
}
|
||||
|
||||
type carouselIndex struct {
|
||||
TypeSlug string
|
||||
Slides []*carousel.SlideEntry
|
||||
}
|
||||
|
||||
func (page *carouselIndex) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
|
||||
template.MustRenderAdmin(w, r, user, company, "campsite/carousel/index.gohtml", page)
|
||||
}
|
||||
|
||||
func mustCollectSlides(ctx context.Context, conn *database.Conn, loc *locale.Locale, typeSlug string) []*carousel.Slide {
|
||||
rows, err := conn.Query(ctx, `
|
||||
select coalesce(i18n.caption, slide.caption) as l10_caption
|
||||
, media.path
|
||||
from campsite_type_carousel as slide
|
||||
join campsite_type using (campsite_type_id)
|
||||
join media on media.media_id = slide.media_id
|
||||
left join campsite_type_carousel_i18n as i18n
|
||||
on i18n.campsite_type_id = slide.campsite_type_id
|
||||
and i18n.media_id = slide.media_id
|
||||
and lang_tag = $1
|
||||
where campsite_type.slug = $2
|
||||
`, loc.Language, typeSlug)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var slides []*carousel.Slide
|
||||
for rows.Next() {
|
||||
slide := &carousel.Slide{}
|
||||
err = rows.Scan(&slide.Caption, &slide.Media)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
slides = append(slides, slide)
|
||||
}
|
||||
if rows.Err() != nil {
|
||||
panic(rows.Err())
|
||||
}
|
||||
|
||||
return slides
|
||||
}
|
||||
|
||||
func collectSlideEntries(ctx context.Context, conn *database.Conn, typeSlug string) ([]*carousel.SlideEntry, error) {
|
||||
rows, err := conn.Query(ctx, `
|
||||
select carousel.media_id
|
||||
, media.path
|
||||
, caption
|
||||
, array_agg((lang_tag, endonym, not exists (select 1 from campsite_type_carousel_i18n as i18n where i18n.media_id = carousel.media_id and i18n.lang_tag = language.lang_tag)) order by endonym)
|
||||
from campsite_type_carousel as carousel
|
||||
join campsite_type using (campsite_type_id)
|
||||
join media on media.media_id = carousel.media_id
|
||||
join company on company.company_id = campsite_type.company_id
|
||||
, language
|
||||
where lang_tag <> default_lang_tag
|
||||
and language.selectable
|
||||
and campsite_type.slug = $1
|
||||
group by carousel.media_id
|
||||
, media.path
|
||||
, caption
|
||||
order by caption
|
||||
`, pgx.QueryResultFormats{pgx.BinaryFormatCode}, typeSlug)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var slides []*carousel.SlideEntry
|
||||
for rows.Next() {
|
||||
slide := &carousel.SlideEntry{}
|
||||
var translations database.RecordArray
|
||||
if err = rows.Scan(&slide.ID, &slide.Media, &slide.Caption, &translations); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, el := range translations.Elements {
|
||||
slide.Translations = append(slide.Translations, &carousel.Translation{
|
||||
Language: el.Fields[0].Get().(string),
|
||||
Endonym: el.Fields[1].Get().(string),
|
||||
Missing: el.Fields[2].Get().(bool),
|
||||
})
|
||||
}
|
||||
slides = append(slides, slide)
|
||||
}
|
||||
|
||||
return slides, nil
|
||||
}
|
||||
|
||||
func addSlide(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, typeSlug string) {
|
||||
f := newSlideForm(typeSlug)
|
||||
editSlide(w, r, user, company, conn, f)
|
||||
}
|
||||
|
||||
func editSlide(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, f *slideForm) {
|
||||
f.process(w, r, user, company, conn, func(ctx context.Context) {
|
||||
conn.MustExec(ctx, "select add_campsite_type_carousel_slide($1, $2, $3)", f.TypeSlug, f.Media, f.Caption)
|
||||
})
|
||||
}
|
||||
|
||||
func (h *AdminHandler) deleteSlide(w http.ResponseWriter, r *http.Request, user *auth.User, conn *database.Conn, typeSlug string, mediaId int) {
|
||||
if err := user.VerifyCSRFToken(r); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
conn.MustExec(r.Context(), "select remove_campsite_type_carousel_slide($1, $2)", typeSlug, mediaId)
|
||||
httplib.Redirect(w, r, "/admin/campsites/types/"+typeSlug+"/slides", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
type slideForm struct {
|
||||
TypeSlug string
|
||||
MediaID int
|
||||
Media *form.Media
|
||||
Caption *form.Input
|
||||
}
|
||||
|
||||
func newSlideForm(typeSlug string) *slideForm {
|
||||
return &slideForm{
|
||||
TypeSlug: typeSlug,
|
||||
Media: &form.Media{
|
||||
Input: &form.Input{
|
||||
Name: "media",
|
||||
},
|
||||
Label: locale.PgettextNoop("Slide image", "input"),
|
||||
Prompt: locale.PgettextNoop("Set slide image", "action"),
|
||||
},
|
||||
Caption: &form.Input{
|
||||
Name: "caption",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (f *slideForm) FillFromDatabase(ctx context.Context, conn *database.Conn, mediaID int) error {
|
||||
f.MediaID = mediaID
|
||||
row := conn.QueryRow(ctx, `
|
||||
select caption
|
||||
, carousel.media_id::text
|
||||
from campsite_type_carousel as carousel
|
||||
join campsite_type using (campsite_type_id)
|
||||
where campsite_type.slug = $1
|
||||
and carousel.media_id = $2
|
||||
`, f.TypeSlug, mediaID)
|
||||
return row.Scan(&f.Caption.Val, &f.Media.Val)
|
||||
}
|
||||
|
||||
func (f *slideForm) process(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, act func(ctx context.Context)) {
|
||||
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
|
||||
}
|
||||
act(r.Context())
|
||||
httplib.Redirect(w, r, "/admin/campsites/types/"+f.TypeSlug+"/slides", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (f *slideForm) Parse(r *http.Request) error {
|
||||
if err := r.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
f.Caption.FillValue(r)
|
||||
f.Media.FillValue(r)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *slideForm) 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
|
||||
}
|
||||
}
|
||||
return v.AllOK, nil
|
||||
}
|
||||
|
||||
func (f *slideForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
|
||||
template.MustRenderAdmin(w, r, user, company, "campsite/carousel/form.gohtml", f)
|
||||
}
|
|
@ -128,3 +128,70 @@ func (l10n *optionL10nForm) Valid(l *locale.Locale) bool {
|
|||
v.CheckRequired(&l10n.Name.Input, l.GettextNoop("Name can not be empty."))
|
||||
return v.AllOK
|
||||
}
|
||||
|
||||
type slideL10nForm struct {
|
||||
Locale *locale.Locale
|
||||
TypeSlug string
|
||||
MediaID int
|
||||
Caption *form.L10nInput
|
||||
}
|
||||
|
||||
func newSlideL10nForm(f *slideForm, loc *locale.Locale) *slideL10nForm {
|
||||
return &slideL10nForm{
|
||||
Locale: loc,
|
||||
TypeSlug: f.TypeSlug,
|
||||
MediaID: f.MediaID,
|
||||
Caption: f.Caption.L10nInput(),
|
||||
}
|
||||
}
|
||||
|
||||
func (l10n *slideL10nForm) FillFromDatabase(ctx context.Context, conn *database.Conn) error {
|
||||
row := conn.QueryRow(ctx, `
|
||||
select coalesce(i18n.caption, '') as l10n_caption
|
||||
from campsite_type_carousel as carousel
|
||||
join campsite_type using (campsite_type_id)
|
||||
left join campsite_type_carousel_i18n as i18n
|
||||
on carousel.campsite_type_id = i18n.campsite_type_id
|
||||
and carousel.media_id = i18n.media_id
|
||||
and i18n.lang_tag = $1
|
||||
where campsite_type.slug = $2 and carousel.media_id = $3
|
||||
`, l10n.Locale.Language, l10n.TypeSlug, l10n.MediaID)
|
||||
return row.Scan(&l10n.Caption.Val)
|
||||
}
|
||||
|
||||
func (l10n *slideL10nForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
|
||||
template.MustRenderAdmin(w, r, user, company, "campsite/carousel/l10n.gohtml", l10n)
|
||||
}
|
||||
|
||||
func editSlideL10n(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, l10n *slideL10nForm) {
|
||||
if err := l10n.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 !l10n.Valid(user.Locale) {
|
||||
if !httplib.IsHTMxRequest(r) {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
}
|
||||
l10n.MustRender(w, r, user, company)
|
||||
return
|
||||
}
|
||||
conn.MustExec(r.Context(), "select translate_campsite_type_carousel_slide($1, $2, $3, $4)", l10n.TypeSlug, l10n.MediaID, l10n.Locale.Language, l10n.Caption)
|
||||
httplib.Redirect(w, r, "/admin/campsites/types/"+l10n.TypeSlug+"/slides", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (l10n *slideL10nForm) Parse(r *http.Request) error {
|
||||
if err := r.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
l10n.Caption.FillValue(r)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l10n *slideL10nForm) Valid(l *locale.Locale) bool {
|
||||
v := form.NewValidator(l)
|
||||
return v.AllOK
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/jackc/pgx/v4"
|
||||
|
||||
"dev.tandem.ws/tandem/camper/pkg/auth"
|
||||
"dev.tandem.ws/tandem/camper/pkg/carousel"
|
||||
"dev.tandem.ws/tandem/camper/pkg/database"
|
||||
httplib "dev.tandem.ws/tandem/camper/pkg/http"
|
||||
"dev.tandem.ws/tandem/camper/pkg/locale"
|
||||
|
@ -51,6 +52,7 @@ func (h *PublicHandler) Handler(user *auth.User, company *auth.Company, conn *da
|
|||
type publicPage struct {
|
||||
*template.PublicPage
|
||||
Name string
|
||||
Carousel []*carousel.Slide
|
||||
Prices []*typePrice
|
||||
Description gotemplate.HTML
|
||||
}
|
||||
|
@ -71,6 +73,7 @@ type optionPrice struct {
|
|||
func newPublicPage(ctx context.Context, conn *database.Conn, loc *locale.Locale, slug string) (*publicPage, error) {
|
||||
page := &publicPage{
|
||||
PublicPage: template.NewPublicPage(),
|
||||
Carousel: mustCollectSlides(ctx, conn, loc, slug),
|
||||
}
|
||||
row := conn.QueryRow(ctx, `
|
||||
select coalesce(i18n.name, campsite_type.name) as l10n_name
|
||||
|
|
|
@ -144,10 +144,10 @@ func MustCollectSlides(ctx context.Context, company *auth.Company, conn *databas
|
|||
type SlideEntry struct {
|
||||
Slide
|
||||
ID int
|
||||
Translations []*translation
|
||||
Translations []*Translation
|
||||
}
|
||||
|
||||
type translation struct {
|
||||
type Translation struct {
|
||||
Language string
|
||||
Endonym string
|
||||
Missing bool
|
||||
|
@ -184,7 +184,7 @@ func CollectSlideEntries(ctx context.Context, company *auth.Company, conn *datab
|
|||
return nil, err
|
||||
}
|
||||
for _, el := range translations.Elements {
|
||||
slide.Translations = append(slide.Translations, &translation{
|
||||
slide.Translations = append(slide.Translations, &Translation{
|
||||
el.Fields[0].Get().(string),
|
||||
el.Fields[1].Get().(string),
|
||||
el.Fields[2].Get().(bool),
|
||||
|
|
211
po/ca.po
211
po/ca.po
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: camper\n"
|
||||
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
||||
"POT-Creation-Date: 2023-10-06 22:10+0200\n"
|
||||
"POT-Creation-Date: 2023-10-12 16:26+0200\n"
|
||||
"PO-Revision-Date: 2023-07-22 23:45+0200\n"
|
||||
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
||||
"Language-Team: Catalan <ca@dodds.net>\n"
|
||||
|
@ -77,22 +77,22 @@ msgstr "Descobreix l’entorn"
|
|||
msgid "Come and enjoy!"
|
||||
msgstr "Vine a gaudir!"
|
||||
|
||||
#: web/templates/public/campsite/type.gohtml:17
|
||||
#: web/templates/public/campsite/type.gohtml:40
|
||||
#: web/templates/admin/campsite/option/form.gohtml:58
|
||||
#: web/templates/admin/campsite/type/form.gohtml:73
|
||||
msgctxt "title"
|
||||
msgid "Prices"
|
||||
msgstr "Preus"
|
||||
|
||||
#: web/templates/public/campsite/type.gohtml:26
|
||||
#: web/templates/public/campsite/type.gohtml:50
|
||||
msgid "%s €/night"
|
||||
msgstr "%s €/nit"
|
||||
|
||||
#: web/templates/public/campsite/type.gohtml:28
|
||||
#: web/templates/public/campsite/type.gohtml:52
|
||||
msgid "%s: %s €/night"
|
||||
msgstr "%s: %s €/nit"
|
||||
|
||||
#: web/templates/public/campsite/type.gohtml:31
|
||||
#: web/templates/public/campsite/type.gohtml:55
|
||||
msgid "*Minimum %d nights per stay"
|
||||
msgstr "*Mínim %d nits per estada"
|
||||
|
||||
|
@ -203,11 +203,14 @@ msgstr "Nova diapositiva del carrusel"
|
|||
|
||||
#: web/templates/admin/carousel/form.gohtml:37
|
||||
#: web/templates/admin/carousel/l10n.gohtml:20
|
||||
#: web/templates/admin/campsite/carousel/form.gohtml:37
|
||||
#: web/templates/admin/campsite/carousel/l10n.gohtml:20
|
||||
msgctxt "input"
|
||||
msgid "Caption"
|
||||
msgstr "Llegenda"
|
||||
|
||||
#: web/templates/admin/carousel/form.gohtml:47
|
||||
#: web/templates/admin/campsite/carousel/form.gohtml:47
|
||||
#: web/templates/admin/campsite/form.gohtml:70
|
||||
#: web/templates/admin/campsite/option/form.gohtml:78
|
||||
#: web/templates/admin/campsite/type/form.gohtml:108
|
||||
|
@ -219,6 +222,7 @@ msgid "Update"
|
|||
msgstr "Actualitza"
|
||||
|
||||
#: web/templates/admin/carousel/form.gohtml:49
|
||||
#: web/templates/admin/campsite/carousel/form.gohtml:49
|
||||
#: web/templates/admin/campsite/form.gohtml:72
|
||||
#: web/templates/admin/campsite/option/form.gohtml:80
|
||||
#: web/templates/admin/campsite/type/form.gohtml:110
|
||||
|
@ -235,6 +239,7 @@ msgid "Translate Carousel Slide to %s"
|
|||
msgstr "Traducció de la diapositiva del carrusel a %s"
|
||||
|
||||
#: web/templates/admin/carousel/l10n.gohtml:21
|
||||
#: web/templates/admin/campsite/carousel/l10n.gohtml:21
|
||||
#: web/templates/admin/campsite/option/l10n.gohtml:21
|
||||
#: web/templates/admin/campsite/type/l10n.gohtml:21
|
||||
#: web/templates/admin/campsite/type/l10n.gohtml:33
|
||||
|
@ -245,6 +250,7 @@ msgid "Source:"
|
|||
msgstr "Origen:"
|
||||
|
||||
#: web/templates/admin/carousel/l10n.gohtml:23
|
||||
#: web/templates/admin/campsite/carousel/l10n.gohtml:23
|
||||
#: web/templates/admin/campsite/option/l10n.gohtml:23
|
||||
#: web/templates/admin/campsite/type/l10n.gohtml:23
|
||||
#: web/templates/admin/campsite/type/l10n.gohtml:36
|
||||
|
@ -256,6 +262,7 @@ msgid "Translation:"
|
|||
msgstr "Traducció:"
|
||||
|
||||
#: web/templates/admin/carousel/l10n.gohtml:32
|
||||
#: web/templates/admin/campsite/carousel/l10n.gohtml:32
|
||||
#: web/templates/admin/campsite/option/l10n.gohtml:32
|
||||
#: web/templates/admin/campsite/type/l10n.gohtml:45
|
||||
#: web/templates/admin/season/l10n.gohtml:32
|
||||
|
@ -264,6 +271,90 @@ msgctxt "action"
|
|||
msgid "Translate"
|
||||
msgstr "Tradueix"
|
||||
|
||||
#: web/templates/admin/campsite/carousel/form.gohtml:8
|
||||
#: web/templates/admin/campsite/carousel/form.gohtml:25
|
||||
msgctxt "title"
|
||||
msgid "Edit Campsite Type Carousel Slide"
|
||||
msgstr "Edició de la diapositiva del carrusel del tipus d’allotjament"
|
||||
|
||||
#: web/templates/admin/campsite/carousel/form.gohtml:10
|
||||
#: web/templates/admin/campsite/carousel/form.gohtml:27
|
||||
msgctxt "title"
|
||||
msgid "New Campsite Type Carousel Slide"
|
||||
msgstr "Nova diapositiva del carrusel del tipus d’allotjament"
|
||||
|
||||
#: web/templates/admin/campsite/carousel/index.gohtml:6
|
||||
#: web/templates/admin/campsite/carousel/index.gohtml:11
|
||||
msgctxt "title"
|
||||
msgid "Campsite Type Carousel"
|
||||
msgstr "Carrusel del tipus d’allotjament"
|
||||
|
||||
#: web/templates/admin/campsite/carousel/index.gohtml:12
|
||||
#: web/templates/admin/services/index.gohtml:12
|
||||
#: web/templates/admin/home/index.gohtml:12
|
||||
msgctxt "action"
|
||||
msgid "Add slide"
|
||||
msgstr "Afegeix diapositiva"
|
||||
|
||||
#: web/templates/admin/campsite/carousel/index.gohtml:17
|
||||
#: web/templates/admin/services/index.gohtml:17
|
||||
#: web/templates/admin/home/index.gohtml:17
|
||||
msgctxt "header"
|
||||
msgid "Image"
|
||||
msgstr "Imatge"
|
||||
|
||||
#: web/templates/admin/campsite/carousel/index.gohtml:18
|
||||
#: web/templates/admin/services/index.gohtml:18
|
||||
#: web/templates/admin/home/index.gohtml:18
|
||||
msgctxt "header"
|
||||
msgid "Caption"
|
||||
msgstr "Llegenda"
|
||||
|
||||
#: web/templates/admin/campsite/carousel/index.gohtml:19
|
||||
#: web/templates/admin/campsite/option/index.gohtml:18
|
||||
#: web/templates/admin/campsite/type/index.gohtml:18
|
||||
#: web/templates/admin/season/index.gohtml:19
|
||||
#: web/templates/admin/services/index.gohtml:19
|
||||
#: web/templates/admin/services/index.gohtml:60
|
||||
#: web/templates/admin/home/index.gohtml:19
|
||||
msgctxt "header"
|
||||
msgid "Translations"
|
||||
msgstr "Traduccions"
|
||||
|
||||
#: web/templates/admin/campsite/carousel/index.gohtml:20
|
||||
#: web/templates/admin/services/index.gohtml:20
|
||||
#: web/templates/admin/services/index.gohtml:61
|
||||
#: web/templates/admin/home/index.gohtml:20
|
||||
msgctxt "header"
|
||||
msgid "Actions"
|
||||
msgstr "Accions"
|
||||
|
||||
#: web/templates/admin/campsite/carousel/index.gohtml:24
|
||||
#: web/templates/admin/services/index.gohtml:24
|
||||
#: web/templates/admin/home/index.gohtml:24
|
||||
msgid "Are you sure you wish to delete this slide?"
|
||||
msgstr "Esteu segur de voler esborrar aquesta diapositiva?"
|
||||
|
||||
#: web/templates/admin/campsite/carousel/index.gohtml:42
|
||||
#: web/templates/admin/services/index.gohtml:42
|
||||
#: web/templates/admin/services/index.gohtml:80
|
||||
#: web/templates/admin/home/index.gohtml:42
|
||||
msgctxt "action"
|
||||
msgid "Delete"
|
||||
msgstr "Esborra"
|
||||
|
||||
#: web/templates/admin/campsite/carousel/index.gohtml:50
|
||||
#: web/templates/admin/services/index.gohtml:50
|
||||
#: web/templates/admin/home/index.gohtml:50
|
||||
msgid "No slides added yet."
|
||||
msgstr "No s’ha afegit cap diapositiva encara."
|
||||
|
||||
#: web/templates/admin/campsite/carousel/l10n.gohtml:7
|
||||
#: web/templates/admin/campsite/carousel/l10n.gohtml:14
|
||||
msgctxt "title"
|
||||
msgid "Translate Campsite Type Carousel Slide to %s"
|
||||
msgstr "Traducció de la diapositiva del carrusel del tipus d’allotjament a %s"
|
||||
|
||||
#: web/templates/admin/campsite/form.gohtml:8
|
||||
#: web/templates/admin/campsite/form.gohtml:25
|
||||
msgctxt "title"
|
||||
|
@ -355,16 +446,6 @@ msgctxt "header"
|
|||
msgid "Name"
|
||||
msgstr "Nom"
|
||||
|
||||
#: web/templates/admin/campsite/option/index.gohtml:18
|
||||
#: web/templates/admin/campsite/type/index.gohtml:18
|
||||
#: web/templates/admin/season/index.gohtml:19
|
||||
#: web/templates/admin/services/index.gohtml:19
|
||||
#: web/templates/admin/services/index.gohtml:60
|
||||
#: web/templates/admin/home/index.gohtml:19
|
||||
msgctxt "header"
|
||||
msgid "Translations"
|
||||
msgstr "Traduccions"
|
||||
|
||||
#: web/templates/admin/campsite/option/index.gohtml:39
|
||||
msgid "No campsite type options added yet."
|
||||
msgstr "No s’ha afegit cap opció al tipus d’allotjament encara."
|
||||
|
@ -391,13 +472,13 @@ msgid "Type"
|
|||
msgstr "Tipus"
|
||||
|
||||
#: web/templates/admin/campsite/index.gohtml:28
|
||||
#: web/templates/admin/campsite/type/index.gohtml:37
|
||||
#: web/templates/admin/campsite/type/index.gohtml:39
|
||||
#: web/templates/admin/season/index.gohtml:39
|
||||
msgid "Yes"
|
||||
msgstr "Sí"
|
||||
|
||||
#: web/templates/admin/campsite/index.gohtml:28
|
||||
#: web/templates/admin/campsite/type/index.gohtml:37
|
||||
#: web/templates/admin/campsite/type/index.gohtml:39
|
||||
#: web/templates/admin/season/index.gohtml:39
|
||||
msgid "No"
|
||||
msgstr "No"
|
||||
|
@ -419,7 +500,7 @@ msgid "New Campsite Type"
|
|||
msgstr "Nou tipus d’allotjament"
|
||||
|
||||
#: web/templates/admin/campsite/type/form.gohtml:37
|
||||
#: web/templates/admin/campsite/type/index.gohtml:20
|
||||
#: web/templates/admin/campsite/type/index.gohtml:21
|
||||
msgctxt "campsite type"
|
||||
msgid "Active"
|
||||
msgstr "Actiu"
|
||||
|
@ -464,12 +545,22 @@ msgctxt "header"
|
|||
msgid "Options"
|
||||
msgstr "Opcions"
|
||||
|
||||
#: web/templates/admin/campsite/type/index.gohtml:36
|
||||
#: web/templates/admin/campsite/type/index.gohtml:20
|
||||
msgctxt "header"
|
||||
msgid "Carousel"
|
||||
msgstr "Carrusel"
|
||||
|
||||
#: web/templates/admin/campsite/type/index.gohtml:37
|
||||
msgctxt "action"
|
||||
msgid "Edit Options"
|
||||
msgstr "Edita les opcions"
|
||||
|
||||
#: web/templates/admin/campsite/type/index.gohtml:43
|
||||
#: web/templates/admin/campsite/type/index.gohtml:38
|
||||
msgctxt "action"
|
||||
msgid "Edit Carousel"
|
||||
msgstr "Edita el carrusel"
|
||||
|
||||
#: web/templates/admin/campsite/type/index.gohtml:45
|
||||
msgid "No campsite types added yet."
|
||||
msgstr "No s’ha afegit cap tipus d’allotjament encara."
|
||||
|
||||
|
@ -631,48 +722,6 @@ msgctxt "title"
|
|||
msgid "Carousel"
|
||||
msgstr "Carrusel"
|
||||
|
||||
#: web/templates/admin/services/index.gohtml:12
|
||||
#: web/templates/admin/home/index.gohtml:12
|
||||
msgctxt "action"
|
||||
msgid "Add slide"
|
||||
msgstr "Afegeix diapositiva"
|
||||
|
||||
#: web/templates/admin/services/index.gohtml:17
|
||||
#: web/templates/admin/home/index.gohtml:17
|
||||
msgctxt "header"
|
||||
msgid "Image"
|
||||
msgstr "Imatge"
|
||||
|
||||
#: web/templates/admin/services/index.gohtml:18
|
||||
#: web/templates/admin/home/index.gohtml:18
|
||||
msgctxt "header"
|
||||
msgid "Caption"
|
||||
msgstr "Llegenda"
|
||||
|
||||
#: web/templates/admin/services/index.gohtml:20
|
||||
#: web/templates/admin/services/index.gohtml:61
|
||||
#: web/templates/admin/home/index.gohtml:20
|
||||
msgctxt "header"
|
||||
msgid "Actions"
|
||||
msgstr "Accions"
|
||||
|
||||
#: web/templates/admin/services/index.gohtml:24
|
||||
#: web/templates/admin/home/index.gohtml:24
|
||||
msgid "Are you sure you wish to delete this slide?"
|
||||
msgstr "Esteu segur de voler esborrar aquesta diapositiva?"
|
||||
|
||||
#: web/templates/admin/services/index.gohtml:42
|
||||
#: web/templates/admin/services/index.gohtml:80
|
||||
#: web/templates/admin/home/index.gohtml:42
|
||||
msgctxt "action"
|
||||
msgid "Delete"
|
||||
msgstr "Esborra"
|
||||
|
||||
#: web/templates/admin/services/index.gohtml:50
|
||||
#: web/templates/admin/home/index.gohtml:50
|
||||
msgid "No slides added yet."
|
||||
msgstr "No s’ha afegit cap diapositiva encara."
|
||||
|
||||
#: web/templates/admin/services/index.gohtml:54
|
||||
msgctxt "action"
|
||||
msgid "Add service"
|
||||
|
@ -893,21 +942,21 @@ msgctxt "title"
|
|||
msgid "Upload Media"
|
||||
msgstr "Pujada de mèdia"
|
||||
|
||||
#: pkg/carousel/admin.go:233
|
||||
#: pkg/carousel/admin.go:233 pkg/campsite/types/carousel.go:232
|
||||
msgctxt "input"
|
||||
msgid "Slide image"
|
||||
msgstr "Imatge de la diapositiva"
|
||||
|
||||
#: pkg/carousel/admin.go:234
|
||||
#: pkg/carousel/admin.go:234 pkg/campsite/types/carousel.go:233
|
||||
msgctxt "action"
|
||||
msgid "Set slide image"
|
||||
msgstr "Estableix la imatge de la diapositiva"
|
||||
|
||||
#: pkg/carousel/admin.go:286
|
||||
#: pkg/carousel/admin.go:286 pkg/campsite/types/carousel.go:287
|
||||
msgid "Slide image can not be empty."
|
||||
msgstr "No podeu deixar la imatge de la diapositiva en blanc."
|
||||
|
||||
#: pkg/carousel/admin.go:287
|
||||
#: pkg/carousel/admin.go:287 pkg/campsite/types/carousel.go:288
|
||||
msgid "Slide image must be an image media type."
|
||||
msgstr "La imatge de la diapositiva ha de ser un mèdia de tipus imatge."
|
||||
|
||||
|
@ -934,7 +983,7 @@ msgstr "Automàtic"
|
|||
|
||||
#: pkg/app/user.go:249 pkg/campsite/types/l10n.go:73
|
||||
#: pkg/campsite/types/l10n.go:128 pkg/campsite/types/option.go:336
|
||||
#: pkg/campsite/types/admin.go:389 pkg/season/l10n.go:69
|
||||
#: pkg/campsite/types/admin.go:391 pkg/season/l10n.go:69
|
||||
#: pkg/season/admin.go:382 pkg/services/l10n.go:73 pkg/services/admin.go:266
|
||||
msgid "Name can not be empty."
|
||||
msgstr "No podeu deixar el nom en blanc."
|
||||
|
@ -955,7 +1004,7 @@ msgstr "El fitxer has de ser una imatge PNG o JPEG vàlida."
|
|||
msgid "Access forbidden"
|
||||
msgstr "Accés prohibit"
|
||||
|
||||
#: pkg/campsite/types/option.go:337 pkg/campsite/types/admin.go:390
|
||||
#: pkg/campsite/types/option.go:337 pkg/campsite/types/admin.go:392
|
||||
msgid "Name must have at least one letter."
|
||||
msgstr "El nom ha de tenir com a mínim una lletra."
|
||||
|
||||
|
@ -983,57 +1032,57 @@ 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:353 pkg/campsite/types/admin.go:403
|
||||
#: pkg/campsite/types/option.go:353 pkg/campsite/types/admin.go:405
|
||||
msgid "Price per night can not be empty."
|
||||
msgstr "No podeu deixar el preu per nit en blanc."
|
||||
|
||||
#: pkg/campsite/types/option.go:354 pkg/campsite/types/admin.go:404
|
||||
#: pkg/campsite/types/option.go:354 pkg/campsite/types/admin.go:406
|
||||
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:355 pkg/campsite/types/admin.go:405
|
||||
#: pkg/campsite/types/option.go:355 pkg/campsite/types/admin.go:407
|
||||
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/admin.go:280
|
||||
#: pkg/campsite/types/admin.go:282
|
||||
msgctxt "input"
|
||||
msgid "Cover image"
|
||||
msgstr "Imatge de portada"
|
||||
|
||||
#: pkg/campsite/types/admin.go:281
|
||||
#: pkg/campsite/types/admin.go:283
|
||||
msgctxt "action"
|
||||
msgid "Set campsite type cover"
|
||||
msgstr "Estableix la portada del tipus d’allotjament"
|
||||
|
||||
#: pkg/campsite/types/admin.go:392
|
||||
#: pkg/campsite/types/admin.go:394
|
||||
msgid "Cover image can not be empty."
|
||||
msgstr "No podeu deixar la imatge de portada en blanc."
|
||||
|
||||
#: pkg/campsite/types/admin.go:393
|
||||
#: pkg/campsite/types/admin.go:395
|
||||
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:397
|
||||
#: pkg/campsite/types/admin.go:399
|
||||
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:398
|
||||
#: pkg/campsite/types/admin.go:400
|
||||
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:399
|
||||
#: pkg/campsite/types/admin.go:401
|
||||
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:408
|
||||
#: pkg/campsite/types/admin.go:410
|
||||
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:409
|
||||
#: pkg/campsite/types/admin.go:411
|
||||
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:410
|
||||
#: pkg/campsite/types/admin.go:412
|
||||
msgid "Minimum number of nights must be one or greater."
|
||||
msgstr "El número mínim de nits no pot ser zero."
|
||||
|
||||
|
|
211
po/es.po
211
po/es.po
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: camper\n"
|
||||
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
||||
"POT-Creation-Date: 2023-10-06 22:10+0200\n"
|
||||
"POT-Creation-Date: 2023-10-12 16:26+0200\n"
|
||||
"PO-Revision-Date: 2023-07-22 23:46+0200\n"
|
||||
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
||||
"Language-Team: Spanish <es@tp.org.es>\n"
|
||||
|
@ -77,22 +77,22 @@ msgstr "Descubre el entorno"
|
|||
msgid "Come and enjoy!"
|
||||
msgstr "¡Ven a disfrutar!"
|
||||
|
||||
#: web/templates/public/campsite/type.gohtml:17
|
||||
#: web/templates/public/campsite/type.gohtml:40
|
||||
#: web/templates/admin/campsite/option/form.gohtml:58
|
||||
#: web/templates/admin/campsite/type/form.gohtml:73
|
||||
msgctxt "title"
|
||||
msgid "Prices"
|
||||
msgstr "Precios"
|
||||
|
||||
#: web/templates/public/campsite/type.gohtml:26
|
||||
#: web/templates/public/campsite/type.gohtml:50
|
||||
msgid "%s €/night"
|
||||
msgstr "%s €/noche"
|
||||
|
||||
#: web/templates/public/campsite/type.gohtml:28
|
||||
#: web/templates/public/campsite/type.gohtml:52
|
||||
msgid "%s: %s €/night"
|
||||
msgstr ":%s: %s €/noche"
|
||||
|
||||
#: web/templates/public/campsite/type.gohtml:31
|
||||
#: web/templates/public/campsite/type.gohtml:55
|
||||
msgid "*Minimum %d nights per stay"
|
||||
msgstr "*Mínimo %d noches por estancia"
|
||||
|
||||
|
@ -203,11 +203,14 @@ msgstr "Nueva diapositiva del carrusel"
|
|||
|
||||
#: web/templates/admin/carousel/form.gohtml:37
|
||||
#: web/templates/admin/carousel/l10n.gohtml:20
|
||||
#: web/templates/admin/campsite/carousel/form.gohtml:37
|
||||
#: web/templates/admin/campsite/carousel/l10n.gohtml:20
|
||||
msgctxt "input"
|
||||
msgid "Caption"
|
||||
msgstr "Leyenda"
|
||||
|
||||
#: web/templates/admin/carousel/form.gohtml:47
|
||||
#: web/templates/admin/campsite/carousel/form.gohtml:47
|
||||
#: web/templates/admin/campsite/form.gohtml:70
|
||||
#: web/templates/admin/campsite/option/form.gohtml:78
|
||||
#: web/templates/admin/campsite/type/form.gohtml:108
|
||||
|
@ -219,6 +222,7 @@ msgid "Update"
|
|||
msgstr "Actualizar"
|
||||
|
||||
#: web/templates/admin/carousel/form.gohtml:49
|
||||
#: web/templates/admin/campsite/carousel/form.gohtml:49
|
||||
#: web/templates/admin/campsite/form.gohtml:72
|
||||
#: web/templates/admin/campsite/option/form.gohtml:80
|
||||
#: web/templates/admin/campsite/type/form.gohtml:110
|
||||
|
@ -235,6 +239,7 @@ msgid "Translate Carousel Slide to %s"
|
|||
msgstr "Traducción de la diapositiva de carrusel a %s"
|
||||
|
||||
#: web/templates/admin/carousel/l10n.gohtml:21
|
||||
#: web/templates/admin/campsite/carousel/l10n.gohtml:21
|
||||
#: web/templates/admin/campsite/option/l10n.gohtml:21
|
||||
#: web/templates/admin/campsite/type/l10n.gohtml:21
|
||||
#: web/templates/admin/campsite/type/l10n.gohtml:33
|
||||
|
@ -245,6 +250,7 @@ msgid "Source:"
|
|||
msgstr "Origen:"
|
||||
|
||||
#: web/templates/admin/carousel/l10n.gohtml:23
|
||||
#: web/templates/admin/campsite/carousel/l10n.gohtml:23
|
||||
#: web/templates/admin/campsite/option/l10n.gohtml:23
|
||||
#: web/templates/admin/campsite/type/l10n.gohtml:23
|
||||
#: web/templates/admin/campsite/type/l10n.gohtml:36
|
||||
|
@ -256,6 +262,7 @@ msgid "Translation:"
|
|||
msgstr "Traducción"
|
||||
|
||||
#: web/templates/admin/carousel/l10n.gohtml:32
|
||||
#: web/templates/admin/campsite/carousel/l10n.gohtml:32
|
||||
#: web/templates/admin/campsite/option/l10n.gohtml:32
|
||||
#: web/templates/admin/campsite/type/l10n.gohtml:45
|
||||
#: web/templates/admin/season/l10n.gohtml:32
|
||||
|
@ -264,6 +271,90 @@ msgctxt "action"
|
|||
msgid "Translate"
|
||||
msgstr "Traducir"
|
||||
|
||||
#: web/templates/admin/campsite/carousel/form.gohtml:8
|
||||
#: web/templates/admin/campsite/carousel/form.gohtml:25
|
||||
msgctxt "title"
|
||||
msgid "Edit Campsite Type Carousel Slide"
|
||||
msgstr "Edición de la diapositiva del carrusel del tipo de alojamiento"
|
||||
|
||||
#: web/templates/admin/campsite/carousel/form.gohtml:10
|
||||
#: web/templates/admin/campsite/carousel/form.gohtml:27
|
||||
msgctxt "title"
|
||||
msgid "New Campsite Type Carousel Slide"
|
||||
msgstr "Nueva diapositiva del carrusel del tipo de alojamiento"
|
||||
|
||||
#: web/templates/admin/campsite/carousel/index.gohtml:6
|
||||
#: web/templates/admin/campsite/carousel/index.gohtml:11
|
||||
msgctxt "title"
|
||||
msgid "Campsite Type Carousel"
|
||||
msgstr "Carrusel del tipo de alojamiento"
|
||||
|
||||
#: web/templates/admin/campsite/carousel/index.gohtml:12
|
||||
#: web/templates/admin/services/index.gohtml:12
|
||||
#: web/templates/admin/home/index.gohtml:12
|
||||
msgctxt "action"
|
||||
msgid "Add slide"
|
||||
msgstr "Añadir diapositiva"
|
||||
|
||||
#: web/templates/admin/campsite/carousel/index.gohtml:17
|
||||
#: web/templates/admin/services/index.gohtml:17
|
||||
#: web/templates/admin/home/index.gohtml:17
|
||||
msgctxt "header"
|
||||
msgid "Image"
|
||||
msgstr "Imagen"
|
||||
|
||||
#: web/templates/admin/campsite/carousel/index.gohtml:18
|
||||
#: web/templates/admin/services/index.gohtml:18
|
||||
#: web/templates/admin/home/index.gohtml:18
|
||||
msgctxt "header"
|
||||
msgid "Caption"
|
||||
msgstr "Leyenda"
|
||||
|
||||
#: web/templates/admin/campsite/carousel/index.gohtml:19
|
||||
#: web/templates/admin/campsite/option/index.gohtml:18
|
||||
#: web/templates/admin/campsite/type/index.gohtml:18
|
||||
#: web/templates/admin/season/index.gohtml:19
|
||||
#: web/templates/admin/services/index.gohtml:19
|
||||
#: web/templates/admin/services/index.gohtml:60
|
||||
#: web/templates/admin/home/index.gohtml:19
|
||||
msgctxt "header"
|
||||
msgid "Translations"
|
||||
msgstr "Traducciones"
|
||||
|
||||
#: web/templates/admin/campsite/carousel/index.gohtml:20
|
||||
#: web/templates/admin/services/index.gohtml:20
|
||||
#: web/templates/admin/services/index.gohtml:61
|
||||
#: web/templates/admin/home/index.gohtml:20
|
||||
msgctxt "header"
|
||||
msgid "Actions"
|
||||
msgstr "Acciones"
|
||||
|
||||
#: web/templates/admin/campsite/carousel/index.gohtml:24
|
||||
#: web/templates/admin/services/index.gohtml:24
|
||||
#: web/templates/admin/home/index.gohtml:24
|
||||
msgid "Are you sure you wish to delete this slide?"
|
||||
msgstr "¿Estáis seguro de querer borrar esta diapositiva?"
|
||||
|
||||
#: web/templates/admin/campsite/carousel/index.gohtml:42
|
||||
#: web/templates/admin/services/index.gohtml:42
|
||||
#: web/templates/admin/services/index.gohtml:80
|
||||
#: web/templates/admin/home/index.gohtml:42
|
||||
msgctxt "action"
|
||||
msgid "Delete"
|
||||
msgstr "Borrar"
|
||||
|
||||
#: web/templates/admin/campsite/carousel/index.gohtml:50
|
||||
#: web/templates/admin/services/index.gohtml:50
|
||||
#: web/templates/admin/home/index.gohtml:50
|
||||
msgid "No slides added yet."
|
||||
msgstr "No se ha añadido ninguna diapositiva todavía."
|
||||
|
||||
#: web/templates/admin/campsite/carousel/l10n.gohtml:7
|
||||
#: web/templates/admin/campsite/carousel/l10n.gohtml:14
|
||||
msgctxt "title"
|
||||
msgid "Translate Campsite Type Carousel Slide to %s"
|
||||
msgstr "Traducción de la diapositiva de carrusel del tipo de alojamiento a %s"
|
||||
|
||||
#: web/templates/admin/campsite/form.gohtml:8
|
||||
#: web/templates/admin/campsite/form.gohtml:25
|
||||
msgctxt "title"
|
||||
|
@ -355,16 +446,6 @@ msgctxt "header"
|
|||
msgid "Name"
|
||||
msgstr "Nombre"
|
||||
|
||||
#: web/templates/admin/campsite/option/index.gohtml:18
|
||||
#: web/templates/admin/campsite/type/index.gohtml:18
|
||||
#: web/templates/admin/season/index.gohtml:19
|
||||
#: web/templates/admin/services/index.gohtml:19
|
||||
#: web/templates/admin/services/index.gohtml:60
|
||||
#: web/templates/admin/home/index.gohtml:19
|
||||
msgctxt "header"
|
||||
msgid "Translations"
|
||||
msgstr "Traducciones"
|
||||
|
||||
#: web/templates/admin/campsite/option/index.gohtml:39
|
||||
msgid "No campsite type options added yet."
|
||||
msgstr "No se ha añadido ninguna opció al tipo de alojamiento todavía."
|
||||
|
@ -391,13 +472,13 @@ msgid "Type"
|
|||
msgstr "Tipo"
|
||||
|
||||
#: web/templates/admin/campsite/index.gohtml:28
|
||||
#: web/templates/admin/campsite/type/index.gohtml:37
|
||||
#: web/templates/admin/campsite/type/index.gohtml:39
|
||||
#: web/templates/admin/season/index.gohtml:39
|
||||
msgid "Yes"
|
||||
msgstr "Sí"
|
||||
|
||||
#: web/templates/admin/campsite/index.gohtml:28
|
||||
#: web/templates/admin/campsite/type/index.gohtml:37
|
||||
#: web/templates/admin/campsite/type/index.gohtml:39
|
||||
#: web/templates/admin/season/index.gohtml:39
|
||||
msgid "No"
|
||||
msgstr "No"
|
||||
|
@ -419,7 +500,7 @@ msgid "New Campsite Type"
|
|||
msgstr "Nuevo tipo de alojamiento"
|
||||
|
||||
#: web/templates/admin/campsite/type/form.gohtml:37
|
||||
#: web/templates/admin/campsite/type/index.gohtml:20
|
||||
#: web/templates/admin/campsite/type/index.gohtml:21
|
||||
msgctxt "campsite type"
|
||||
msgid "Active"
|
||||
msgstr "Activo"
|
||||
|
@ -464,12 +545,22 @@ msgctxt "header"
|
|||
msgid "Options"
|
||||
msgstr "Opciones"
|
||||
|
||||
#: web/templates/admin/campsite/type/index.gohtml:36
|
||||
#: web/templates/admin/campsite/type/index.gohtml:20
|
||||
msgctxt "header"
|
||||
msgid "Carousel"
|
||||
msgstr "Carrusel"
|
||||
|
||||
#: web/templates/admin/campsite/type/index.gohtml:37
|
||||
msgctxt "action"
|
||||
msgid "Edit Options"
|
||||
msgstr "Editar opciones"
|
||||
|
||||
#: web/templates/admin/campsite/type/index.gohtml:43
|
||||
#: web/templates/admin/campsite/type/index.gohtml:38
|
||||
msgctxt "action"
|
||||
msgid "Edit Carousel"
|
||||
msgstr "Editar el carrusel"
|
||||
|
||||
#: web/templates/admin/campsite/type/index.gohtml:45
|
||||
msgid "No campsite types added yet."
|
||||
msgstr "No se ha añadido ningún tipo de alojamiento todavía."
|
||||
|
||||
|
@ -631,48 +722,6 @@ msgctxt "title"
|
|||
msgid "Carousel"
|
||||
msgstr "Carrusel"
|
||||
|
||||
#: web/templates/admin/services/index.gohtml:12
|
||||
#: web/templates/admin/home/index.gohtml:12
|
||||
msgctxt "action"
|
||||
msgid "Add slide"
|
||||
msgstr "Añadir diapositiva"
|
||||
|
||||
#: web/templates/admin/services/index.gohtml:17
|
||||
#: web/templates/admin/home/index.gohtml:17
|
||||
msgctxt "header"
|
||||
msgid "Image"
|
||||
msgstr "Imagen"
|
||||
|
||||
#: web/templates/admin/services/index.gohtml:18
|
||||
#: web/templates/admin/home/index.gohtml:18
|
||||
msgctxt "header"
|
||||
msgid "Caption"
|
||||
msgstr "Leyenda"
|
||||
|
||||
#: web/templates/admin/services/index.gohtml:20
|
||||
#: web/templates/admin/services/index.gohtml:61
|
||||
#: web/templates/admin/home/index.gohtml:20
|
||||
msgctxt "header"
|
||||
msgid "Actions"
|
||||
msgstr "Acciones"
|
||||
|
||||
#: web/templates/admin/services/index.gohtml:24
|
||||
#: web/templates/admin/home/index.gohtml:24
|
||||
msgid "Are you sure you wish to delete this slide?"
|
||||
msgstr "¿Estáis seguro de querer borrar esta diapositiva?"
|
||||
|
||||
#: web/templates/admin/services/index.gohtml:42
|
||||
#: web/templates/admin/services/index.gohtml:80
|
||||
#: web/templates/admin/home/index.gohtml:42
|
||||
msgctxt "action"
|
||||
msgid "Delete"
|
||||
msgstr "Borrar"
|
||||
|
||||
#: web/templates/admin/services/index.gohtml:50
|
||||
#: web/templates/admin/home/index.gohtml:50
|
||||
msgid "No slides added yet."
|
||||
msgstr "No se ha añadido ninguna diapositiva todavía."
|
||||
|
||||
#: web/templates/admin/services/index.gohtml:54
|
||||
msgctxt "action"
|
||||
msgid "Add service"
|
||||
|
@ -893,21 +942,21 @@ msgctxt "title"
|
|||
msgid "Upload Media"
|
||||
msgstr "Subida de medio"
|
||||
|
||||
#: pkg/carousel/admin.go:233
|
||||
#: pkg/carousel/admin.go:233 pkg/campsite/types/carousel.go:232
|
||||
msgctxt "input"
|
||||
msgid "Slide image"
|
||||
msgstr "Imagen de la diapositiva"
|
||||
|
||||
#: pkg/carousel/admin.go:234
|
||||
#: pkg/carousel/admin.go:234 pkg/campsite/types/carousel.go:233
|
||||
msgctxt "action"
|
||||
msgid "Set slide image"
|
||||
msgstr "Establecer la imagen de la diapositiva"
|
||||
|
||||
#: pkg/carousel/admin.go:286
|
||||
#: pkg/carousel/admin.go:286 pkg/campsite/types/carousel.go:287
|
||||
msgid "Slide image can not be empty."
|
||||
msgstr "No podéis dejar la imagen de la diapositiva en blanco."
|
||||
|
||||
#: pkg/carousel/admin.go:287
|
||||
#: pkg/carousel/admin.go:287 pkg/campsite/types/carousel.go:288
|
||||
msgid "Slide image must be an image media type."
|
||||
msgstr "La imagen de la diapositiva tiene que ser un medio de tipo imagen."
|
||||
|
||||
|
@ -934,7 +983,7 @@ msgstr "Automático"
|
|||
|
||||
#: pkg/app/user.go:249 pkg/campsite/types/l10n.go:73
|
||||
#: pkg/campsite/types/l10n.go:128 pkg/campsite/types/option.go:336
|
||||
#: pkg/campsite/types/admin.go:389 pkg/season/l10n.go:69
|
||||
#: pkg/campsite/types/admin.go:391 pkg/season/l10n.go:69
|
||||
#: pkg/season/admin.go:382 pkg/services/l10n.go:73 pkg/services/admin.go:266
|
||||
msgid "Name can not be empty."
|
||||
msgstr "No podéis dejar el nombre en blanco."
|
||||
|
@ -955,7 +1004,7 @@ msgstr "El archivo tiene que ser una imagen PNG o JPEG válida."
|
|||
msgid "Access forbidden"
|
||||
msgstr "Acceso prohibido"
|
||||
|
||||
#: pkg/campsite/types/option.go:337 pkg/campsite/types/admin.go:390
|
||||
#: pkg/campsite/types/option.go:337 pkg/campsite/types/admin.go:392
|
||||
msgid "Name must have at least one letter."
|
||||
msgstr "El nombre tiene que tener como mínimo una letra."
|
||||
|
||||
|
@ -983,57 +1032,57 @@ 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:353 pkg/campsite/types/admin.go:403
|
||||
#: pkg/campsite/types/option.go:353 pkg/campsite/types/admin.go:405
|
||||
msgid "Price per night can not be empty."
|
||||
msgstr "No podéis dejar el precio por noche en blanco."
|
||||
|
||||
#: pkg/campsite/types/option.go:354 pkg/campsite/types/admin.go:404
|
||||
#: pkg/campsite/types/option.go:354 pkg/campsite/types/admin.go:406
|
||||
msgid "Price per night must be a decimal number."
|
||||
msgstr "El precio por noche tien que ser un número decimal."
|
||||
|
||||
#: pkg/campsite/types/option.go:355 pkg/campsite/types/admin.go:405
|
||||
#: pkg/campsite/types/option.go:355 pkg/campsite/types/admin.go:407
|
||||
msgid "Price per night must be zero or greater."
|
||||
msgstr "El precio por noche tiene que ser como mínimo cero."
|
||||
|
||||
#: pkg/campsite/types/admin.go:280
|
||||
#: pkg/campsite/types/admin.go:282
|
||||
msgctxt "input"
|
||||
msgid "Cover image"
|
||||
msgstr "Imagen de portada"
|
||||
|
||||
#: pkg/campsite/types/admin.go:281
|
||||
#: pkg/campsite/types/admin.go:283
|
||||
msgctxt "action"
|
||||
msgid "Set campsite type cover"
|
||||
msgstr "Establecer la portada del tipo de alojamiento"
|
||||
|
||||
#: pkg/campsite/types/admin.go:392
|
||||
#: pkg/campsite/types/admin.go:394
|
||||
msgid "Cover image can not be empty."
|
||||
msgstr "No podéis dejar la imagen de portada en blanco."
|
||||
|
||||
#: pkg/campsite/types/admin.go:393
|
||||
#: pkg/campsite/types/admin.go:395
|
||||
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:397
|
||||
#: pkg/campsite/types/admin.go:399
|
||||
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:398
|
||||
#: pkg/campsite/types/admin.go:400
|
||||
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:399
|
||||
#: pkg/campsite/types/admin.go:401
|
||||
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:408
|
||||
#: pkg/campsite/types/admin.go:410
|
||||
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:409
|
||||
#: pkg/campsite/types/admin.go:411
|
||||
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:410
|
||||
#: pkg/campsite/types/admin.go:412
|
||||
msgid "Minimum number of nights must be one or greater."
|
||||
msgstr "El número mínimo de noches no puede ser cero."
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
-- Revert camper:add_campsite_type_carousel_slide from pg
|
||||
|
||||
begin;
|
||||
|
||||
drop function if exists camper.add_campsite_type_carousel_slide(uuid, integer, text);
|
||||
|
||||
commit;
|
|
@ -0,0 +1,7 @@
|
|||
-- Revert camper:campsite_type_carousel from pg
|
||||
|
||||
begin;
|
||||
|
||||
drop table if exists camper.campsite_type_carousel;
|
||||
|
||||
commit;
|
|
@ -0,0 +1,7 @@
|
|||
-- Revert camper:campsite_type_carousel_i18n from pg
|
||||
|
||||
begin;
|
||||
|
||||
drop table if exists camper.campsite_type_carousel_i18n;
|
||||
|
||||
commit;
|
|
@ -0,0 +1,7 @@
|
|||
-- Revert camper:remove_campsite_type_carousel_slide from pg
|
||||
|
||||
begin;
|
||||
|
||||
drop function if exists camper.remove_campsite_type_carousel_slide(uuid, integer);
|
||||
|
||||
commit;
|
|
@ -0,0 +1,7 @@
|
|||
-- Revert camper:translate_campsite_type_carousel_slide from pg
|
||||
|
||||
begin;
|
||||
|
||||
drop function if exists camper.translate_campsite_type_carousel_slide(uuid, integer, text, text);
|
||||
|
||||
commit;
|
|
@ -99,3 +99,8 @@ add_campsite_type_option [roles schema_camper campsite_type_option campsite_type
|
|||
edit_campsite_type_option [roles schema_camper campsite_type_option] 2023-10-06T09:51:02Z jordi fita mas <jordi@tandem.blog> # Add function to edit campsite type options
|
||||
extension_postgis [schema_public] 2023-10-06T17:18:52Z jordi fita mas <jordi@tandem.blog> # Add PostGIS extension
|
||||
company_geography [roles schema_camper company user_profile extension_postgis] 2023-10-06T17:53:34Z jordi fita mas <jordi@tandem.blog> # Add the relation for the GPS coordinates of companies
|
||||
campsite_type_carousel [roles schema_camper campsite_type media user_profile] 2023-10-09T17:18:38Z jordi fita mas <jordi@tandem.blog> # Add the carousel for campsite types
|
||||
campsite_type_carousel_i18n [roles schema_camper campsite_type_carousel language] 2023-10-09T17:45:09Z jordi fita mas <jordi@tandem.blog> # Add relation for campsite type carousel translations
|
||||
add_campsite_type_carousel_slide [roles schema_camper campsite_type_carousel campsite_type] 2023-10-09T17:59:49Z jordi fita mas <jordi@tandem.blog> # Add function to create slides for the campsite type carousel
|
||||
translate_campsite_type_carousel_slide [roles schema_camper campsite_type campsite_type_carousel_i18n] 2023-10-09T18:17:13Z jordi fita mas <jordi@tandem.blog> # Add function to translate a campsite type slide
|
||||
remove_campsite_type_carousel_slide [roles schema_camper campsite_type_carousel campsite_type_carousel_i18n] 2023-10-09T18:26:49Z jordi fita mas <jordi@tandem.blog> # Add function to remove campsite type slides
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
-- Test add_campsite_type_carousel_slide
|
||||
set client_min_messages to warning;
|
||||
create extension if not exists pgtap;
|
||||
reset client_min_messages;
|
||||
|
||||
begin;
|
||||
|
||||
select plan(14);
|
||||
|
||||
set search_path to camper, public;
|
||||
|
||||
select has_function('camper', 'add_campsite_type_carousel_slide', array['uuid', 'integer', 'text']);
|
||||
select function_lang_is('camper', 'add_campsite_type_carousel_slide', array['uuid', 'integer', 'text'], 'sql');
|
||||
select function_returns('camper', 'add_campsite_type_carousel_slide', array['uuid', 'integer', 'text'], 'integer');
|
||||
select isnt_definer('camper', 'add_campsite_type_carousel_slide', array['uuid', 'integer', 'text']);
|
||||
select volatility_is('camper', 'add_campsite_type_carousel_slide', array['uuid', 'integer', 'text'], 'volatile');
|
||||
select function_privs_are('camper', 'add_campsite_type_carousel_slide', array['uuid', 'integer', 'text'], 'guest', array[]::text[]);
|
||||
select function_privs_are('camper', 'add_campsite_type_carousel_slide', array['uuid', 'integer', 'text'], 'employee', array[]::text[]);
|
||||
select function_privs_are('camper', 'add_campsite_type_carousel_slide', array['uuid', 'integer', 'text'], 'admin', array['EXECUTE']);
|
||||
select function_privs_are('camper', 'add_campsite_type_carousel_slide', array['uuid', 'integer', 'text'], 'authenticator', array[]::text[]);
|
||||
|
||||
|
||||
set client_min_messages to warning;
|
||||
truncate campsite_type_carousel_i18n cascade;
|
||||
truncate campsite_type_carousel cascade;
|
||||
truncate campsite_type 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, country_code, currency_code, default_lang_tag)
|
||||
values (1, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', 'ES', 'EUR', 'ca')
|
||||
;
|
||||
|
||||
insert into media_content (media_type, bytes)
|
||||
values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};')
|
||||
, ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ff00ff","a"};')
|
||||
, ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffff00","a"};')
|
||||
, ('text/plain', 'hello, world!')
|
||||
, ('image/svg+xml', '<svg xmlns="http://www.w3.org/2000/svg" width="1" height="1"/>')
|
||||
;
|
||||
|
||||
insert into media (media_id, company_id, original_filename, content_hash)
|
||||
values (2, 1, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};'))
|
||||
, (3, 1, 'cover3.xpm', sha256('static char *s[]={"1 1 1 1","a c #ff00ff","a"};'))
|
||||
, (4, 1, 'cover4.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffff00","a"};'))
|
||||
, (5, 1, 'text.txt', sha256('hello, world!'))
|
||||
, (6, 1, 'image.svg', sha256('<svg xmlns="http://www.w3.org/2000/svg" width="1" height="1"/>'))
|
||||
;
|
||||
|
||||
insert into campsite_type (campsite_type_id, company_id, slug, media_id, name, description, max_campers, dogs_allowed, active)
|
||||
values (10, 1, '87452b88-b48f-48d3-bb6c-0296de64164e', 2, 'Type A', '<p>A</p>', 5, false, true)
|
||||
, (11, 1, '9b6370f7-f941-46f2-bc6e-de455675bd0a', 3, 'Type B', '<p>B</p>', 4, true, false)
|
||||
;
|
||||
|
||||
insert into campsite_type_carousel (campsite_type_id, media_id, caption)
|
||||
values (10, 4, 'A caption')
|
||||
;
|
||||
|
||||
select lives_ok(
|
||||
$$ select add_campsite_type_carousel_slide('87452b88-b48f-48d3-bb6c-0296de64164e', 5, 'A caption') $$,
|
||||
'Should be able to add a carousel slide with a caption'
|
||||
);
|
||||
|
||||
select lives_ok(
|
||||
$$ select add_campsite_type_carousel_slide('9b6370f7-f941-46f2-bc6e-de455675bd0a', 6, null) $$,
|
||||
'Should be able to add a carousel slide without caption'
|
||||
);
|
||||
|
||||
select lives_ok(
|
||||
$$ select add_campsite_type_carousel_slide('87452b88-b48f-48d3-bb6c-0296de64164e', 4, 'New caption') $$,
|
||||
'Should be able to overwrite a slide with a new caption'
|
||||
);
|
||||
|
||||
select bag_eq(
|
||||
$$ select campsite_type_id, media_id, caption from campsite_type_carousel $$,
|
||||
$$ values (10, 4, 'New caption')
|
||||
, (10, 5, 'A caption')
|
||||
, (11, 6, '')
|
||||
$$,
|
||||
'Should have all three slides'
|
||||
);
|
||||
|
||||
select is_empty(
|
||||
$$ select * from campsite_type_carousel_i18n $$,
|
||||
'Should not have added any translation'
|
||||
);
|
||||
|
||||
select *
|
||||
from finish();
|
||||
|
||||
rollback;
|
|
@ -0,0 +1,223 @@
|
|||
-- Test campsite_type_carousel
|
||||
set client_min_messages to warning;
|
||||
create extension if not exists pgtap;
|
||||
reset client_min_messages;
|
||||
|
||||
begin;
|
||||
|
||||
select plan(40);
|
||||
|
||||
set search_path to camper, public;
|
||||
|
||||
select has_table('campsite_type_carousel');
|
||||
select has_pk('campsite_type_carousel');
|
||||
select col_is_pk('campsite_type_carousel', array['campsite_type_id', 'media_id']);
|
||||
select table_privs_are('campsite_type_carousel', 'guest', array['SELECT']);
|
||||
select table_privs_are('campsite_type_carousel', 'employee', array['SELECT']);
|
||||
select table_privs_are('campsite_type_carousel', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']);
|
||||
select table_privs_are('campsite_type_carousel', 'authenticator', array[]::text[]);
|
||||
|
||||
select has_column('campsite_type_carousel', 'campsite_type_id');
|
||||
select col_is_fk('campsite_type_carousel', 'campsite_type_id');
|
||||
select fk_ok('campsite_type_carousel', 'campsite_type_id', 'campsite_type', 'campsite_type_id');
|
||||
select col_type_is('campsite_type_carousel', 'campsite_type_id', 'integer');
|
||||
select col_not_null('campsite_type_carousel', 'campsite_type_id');
|
||||
select col_hasnt_default('campsite_type_carousel', 'campsite_type_id');
|
||||
|
||||
select has_column('campsite_type_carousel', 'media_id');
|
||||
select col_is_fk('campsite_type_carousel', 'media_id');
|
||||
select fk_ok('campsite_type_carousel', 'media_id', 'media', 'media_id');
|
||||
select col_type_is('campsite_type_carousel', 'media_id', 'integer');
|
||||
select col_not_null('campsite_type_carousel', 'media_id');
|
||||
select col_hasnt_default('campsite_type_carousel', 'media_id');
|
||||
|
||||
select has_column('campsite_type_carousel', 'caption');
|
||||
select col_type_is('campsite_type_carousel', 'caption', 'text');
|
||||
select col_not_null('campsite_type_carousel', 'caption');
|
||||
select col_hasnt_default('campsite_type_carousel', 'caption');
|
||||
|
||||
|
||||
set client_min_messages to warning;
|
||||
truncate campsite_type_carousel cascade;
|
||||
truncate campsite_type 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, country_code, currency_code, default_lang_tag)
|
||||
values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', 'ES', 'EUR', 'ca')
|
||||
, (4, 'Company 4', 'XX234', '', '666-666-666', 'b@b', '', '', '', '', '', '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"};')
|
||||
, ('text/plain', 'content2')
|
||||
, ('text/plain', 'content3')
|
||||
, ('text/plain', 'content4')
|
||||
, ('text/plain', 'content5')
|
||||
;
|
||||
|
||||
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"};'))
|
||||
, ( 7, 2, 'text2.txt', sha256('content2'))
|
||||
, ( 8, 2, 'text3.txt', sha256('content3'))
|
||||
, ( 9, 4, 'cover4.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};'))
|
||||
, (10, 4, 'text4.txt', sha256('content4'))
|
||||
, (11, 4, 'text5.txt', sha256('content5'))
|
||||
;
|
||||
|
||||
insert into campsite_type (campsite_type_id, company_id, name, media_id, dogs_allowed, max_campers)
|
||||
values (21, 2, 'Wooden lodge', 6, false, 7)
|
||||
, (22, 4, 'Bungalow', 9, false, 6)
|
||||
;
|
||||
|
||||
insert into campsite_type_carousel (campsite_type_id, media_id, caption)
|
||||
values (21, 7, 'Caption 7')
|
||||
, (22, 10, 'Caption 10')
|
||||
;
|
||||
|
||||
prepare carousel_data as
|
||||
select campsite_type_id, media_id, caption
|
||||
from campsite_type_carousel
|
||||
;
|
||||
|
||||
set role guest;
|
||||
select bag_eq(
|
||||
'carousel_data',
|
||||
$$ values (21, 7, 'Caption 7')
|
||||
, (22, 10, 'Caption 10')
|
||||
$$,
|
||||
'Everyone should be able to list all campsite slides across all companies'
|
||||
);
|
||||
reset role;
|
||||
|
||||
select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'co2');
|
||||
|
||||
select lives_ok(
|
||||
$$ insert into campsite_type_carousel(campsite_type_id, media_id, caption) values (21, 8, 'Caption 8') $$,
|
||||
'Admin from company 2 should be able to insert a new slide to campsite types of that company.'
|
||||
);
|
||||
|
||||
select bag_eq(
|
||||
'carousel_data',
|
||||
$$ values (21, 7, 'Caption 7')
|
||||
, (21, 8, 'Caption 8')
|
||||
, (22, 10, 'Caption 10')
|
||||
$$,
|
||||
'The new row should have been added'
|
||||
);
|
||||
|
||||
select lives_ok(
|
||||
$$ update campsite_type_carousel set caption = 'Caption 8.8' where media_id = 8 $$,
|
||||
'Admin from company 2 should be able to update campsite type slides of that company.'
|
||||
);
|
||||
|
||||
select bag_eq(
|
||||
'carousel_data',
|
||||
$$ values (21, 7, 'Caption 7')
|
||||
, (21, 8, 'Caption 8.8')
|
||||
, (22, 10, 'Caption 10')
|
||||
$$,
|
||||
'The row should have been updated.'
|
||||
);
|
||||
|
||||
select lives_ok(
|
||||
$$ delete from campsite_type_carousel where media_id = 8 $$,
|
||||
'Admin from company 2 should be able to delete campsite type slides from that company.'
|
||||
);
|
||||
|
||||
select bag_eq(
|
||||
'carousel_data',
|
||||
$$ values (21, 7, 'Caption 7')
|
||||
, (22, 10, 'Caption 10')
|
||||
$$,
|
||||
'The row should have been deleted.'
|
||||
);
|
||||
|
||||
select throws_ok(
|
||||
$$ insert into campsite_type_carousel (campsite_type_id, media_id, caption) values (21, 10, 'Nope') $$,
|
||||
'42501', 'new row violates row-level security policy for table "campsite_type_carousel"',
|
||||
'Admin from company 2 should NOT be able to insert a new campsite types slide from a media of company 4.'
|
||||
);
|
||||
|
||||
select throws_ok(
|
||||
$$ insert into campsite_type_carousel (campsite_type_id, media_id, caption) values (22, 8, 'Nope') $$,
|
||||
'42501', 'new row violates row-level security policy for table "campsite_type_carousel"',
|
||||
'Admin from company 2 should NOT be able to insert a slide to a campsite type of company 4.'
|
||||
);
|
||||
|
||||
select lives_ok(
|
||||
$$ update campsite_type_carousel set caption = 'Nope' where campsite_type_id = 22 $$,
|
||||
'Admin from company 2 should not be able to update slides of campsite types from company 4, but no error if campsite_type_id or media_id is not changed.'
|
||||
);
|
||||
|
||||
select lives_ok(
|
||||
$$ update campsite_type_carousel set caption = 'Nope' where media_id = 10 $$,
|
||||
'Admin from company 2 should not be able to update slides of campsite types from company 4, but no error if campsite_type_id or media_id is not changed.'
|
||||
);
|
||||
|
||||
select bag_eq(
|
||||
'carousel_data',
|
||||
$$ values (21, 7, 'Caption 7')
|
||||
, (22, 10, 'Caption 10')
|
||||
$$,
|
||||
'No row should have been changed.'
|
||||
);
|
||||
|
||||
select throws_ok(
|
||||
$$ update campsite_type_carousel set campsite_type_id = 22 where campsite_type_id = 21 $$,
|
||||
'42501', 'new row violates row-level security policy for table "campsite_type_carousel"',
|
||||
'Admin from company 2 should NOT be able to move slides to campsite types of company 4'
|
||||
);
|
||||
|
||||
select throws_ok(
|
||||
$$ update campsite_type_carousel set media_id = 11 where media_id = 7 $$,
|
||||
'42501', 'new row violates row-level security policy for table "campsite_type_carousel"',
|
||||
'Admin from company 2 should NOT be able to use media from company 4'
|
||||
);
|
||||
|
||||
select lives_ok(
|
||||
$$ delete from campsite_type_carousel where campsite_type_id = 22 $$,
|
||||
'Admin from company 2 should NOT be able to delete slides of campsite types from company 4, but not error is thrown'
|
||||
);
|
||||
|
||||
select lives_ok(
|
||||
$$ delete from campsite_type_carousel where media_id = 10 $$,
|
||||
'Admin from company 2 should NOT be able to delete slides with media from company 4, but not error is thrown'
|
||||
);
|
||||
|
||||
select bag_eq(
|
||||
'carousel_data',
|
||||
$$ values (21, 7, 'Caption 7')
|
||||
, (22, 10, 'Caption 10')
|
||||
$$,
|
||||
'No row should have been changed'
|
||||
);
|
||||
|
||||
reset role;
|
||||
|
||||
select *
|
||||
from finish();
|
||||
|
||||
rollback;
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
-- Test campsite_type_carousel_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('campsite_type_carousel_i18n');
|
||||
select has_pk('campsite_type_carousel_i18n');
|
||||
select col_is_pk('campsite_type_carousel_i18n', array['campsite_type_id', 'media_id', 'lang_tag']);
|
||||
select col_is_fk('campsite_type_carousel_i18n', array['campsite_type_id', 'media_id']);
|
||||
select fk_ok('campsite_type_carousel_i18n', array['campsite_type_id', 'media_id'], 'campsite_type_carousel', array['campsite_type_id', 'media_id']);
|
||||
select table_privs_are('campsite_type_carousel_i18n', 'guest', array['SELECT']);
|
||||
select table_privs_are('campsite_type_carousel_i18n', 'employee', array['SELECT']);
|
||||
select table_privs_are('campsite_type_carousel_i18n', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']);
|
||||
select table_privs_are('campsite_type_carousel_i18n', 'authenticator', array[]::text[]);
|
||||
|
||||
select has_column('campsite_type_carousel_i18n', 'campsite_type_id');
|
||||
select col_type_is('campsite_type_carousel_i18n', 'campsite_type_id', 'integer');
|
||||
select col_not_null('campsite_type_carousel_i18n', 'campsite_type_id');
|
||||
select col_hasnt_default('campsite_type_carousel_i18n', 'campsite_type_id');
|
||||
|
||||
select has_column('campsite_type_carousel_i18n', 'media_id');
|
||||
select col_type_is('campsite_type_carousel_i18n', 'media_id', 'integer');
|
||||
select col_not_null('campsite_type_carousel_i18n', 'media_id');
|
||||
select col_hasnt_default('campsite_type_carousel_i18n', 'media_id');
|
||||
|
||||
select has_column('campsite_type_carousel_i18n', 'lang_tag');
|
||||
select col_is_fk('campsite_type_carousel_i18n', 'lang_tag');
|
||||
select fk_ok('campsite_type_carousel_i18n', 'lang_tag', 'language', 'lang_tag');
|
||||
select col_type_is('campsite_type_carousel_i18n', 'lang_tag', 'text');
|
||||
select col_not_null('campsite_type_carousel_i18n', 'lang_tag');
|
||||
select col_hasnt_default('campsite_type_carousel_i18n', 'lang_tag');
|
||||
|
||||
select has_column('campsite_type_carousel_i18n', 'caption');
|
||||
select col_type_is('campsite_type_carousel_i18n', 'caption', 'text');
|
||||
select col_not_null('campsite_type_carousel_i18n', 'caption');
|
||||
select col_hasnt_default('campsite_type_carousel_i18n', 'caption');
|
||||
|
||||
|
||||
select *
|
||||
from finish();
|
||||
|
||||
rollback;
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
-- Test remove_campsite_type_carousel_slide
|
||||
set client_min_messages to warning;
|
||||
create extension if not exists pgtap;
|
||||
reset client_min_messages;
|
||||
|
||||
begin;
|
||||
|
||||
select plan(13);
|
||||
|
||||
set search_path to camper, public;
|
||||
|
||||
select has_function('camper', 'remove_campsite_type_carousel_slide', array['uuid', 'integer']);
|
||||
select function_lang_is('camper', 'remove_campsite_type_carousel_slide', array['uuid', 'integer'], 'plpgsql');
|
||||
select function_returns('camper', 'remove_campsite_type_carousel_slide', array['uuid', 'integer'], 'void');
|
||||
select isnt_definer('camper', 'remove_campsite_type_carousel_slide', array['uuid', 'integer']);
|
||||
select volatility_is('camper', 'remove_campsite_type_carousel_slide', array['uuid', 'integer'], 'volatile');
|
||||
select function_privs_are('camper', 'remove_campsite_type_carousel_slide', array['uuid', 'integer'], 'guest', array[]::text[]);
|
||||
select function_privs_are('camper', 'remove_campsite_type_carousel_slide', array['uuid', 'integer'], 'employee', array[]::text[]);
|
||||
select function_privs_are('camper', 'remove_campsite_type_carousel_slide', array['uuid', 'integer'], 'admin', array['EXECUTE']);
|
||||
select function_privs_are('camper', 'remove_campsite_type_carousel_slide', array['uuid', 'integer'], 'authenticator', array[]::text[]);
|
||||
|
||||
|
||||
set client_min_messages to warning;
|
||||
truncate campsite_type_carousel_i18n cascade;
|
||||
truncate campsite_type_carousel cascade;
|
||||
truncate media cascade;
|
||||
truncate media_content cascade;
|
||||
truncate company cascade;
|
||||
reset client_min_messages;
|
||||
|
||||
insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, country_code, currency_code, default_lang_tag)
|
||||
values (1, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', 'ES', 'EUR', 'ca')
|
||||
;
|
||||
|
||||
insert into media_content (media_type, bytes)
|
||||
values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};')
|
||||
, ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ff00ff","a"};')
|
||||
, ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffff00","a"};')
|
||||
, ('text/plain', 'hello, world!')
|
||||
, ('image/svg+xml', '<svg xmlns="http://www.w3.org/2000/svg" width="1" height="1"/>')
|
||||
;
|
||||
|
||||
insert into media (media_id, company_id, original_filename, content_hash)
|
||||
values (2, 1, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};'))
|
||||
, (3, 1, 'cover3.xpm', sha256('static char *s[]={"1 1 1 1","a c #ff00ff","a"};'))
|
||||
, (4, 1, 'cover4.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffff00","a"};'))
|
||||
, (5, 1, 'text.txt', sha256('hello, world!'))
|
||||
, (6, 1, 'image.svg', sha256('<svg xmlns="http://www.w3.org/2000/svg" width="1" height="1"/>'))
|
||||
;
|
||||
|
||||
insert into campsite_type (campsite_type_id, company_id, slug, media_id, name, description, max_campers, dogs_allowed, active)
|
||||
values (10, 1, '87452b88-b48f-48d3-bb6c-0296de64164e', 2, 'Type A', '<p>A</p>', 5, false, true)
|
||||
, (11, 1, '9b6370f7-f941-46f2-bc6e-de455675bd0a', 3, 'Type B', '<p>B</p>', 4, true, false)
|
||||
;
|
||||
|
||||
insert into campsite_type_carousel (campsite_type_id, media_id, caption)
|
||||
values (10, 3, 'Source caption')
|
||||
, (10, 4, 'Source caption')
|
||||
, (11, 5, 'Another caption')
|
||||
, (11, 6, 'N/A')
|
||||
;
|
||||
|
||||
insert into campsite_type_carousel_i18n (campsite_type_id, media_id, lang_tag, caption)
|
||||
values (10, 3, 'en', 'Target caption')
|
||||
, (10, 3, 'es', 'Target caption (spanish)')
|
||||
, (10, 4, 'en', 'Target caption')
|
||||
, (10, 4, 'es', 'Target caption (spanish)')
|
||||
, (11, 5, 'en', 'Target caption')
|
||||
, (11, 5, 'es', 'Target caption (spanish)')
|
||||
, (11, 6, 'en', 'Target caption')
|
||||
, (11, 6, 'es', 'Target caption (spanish)')
|
||||
;
|
||||
|
||||
select lives_ok(
|
||||
$$ select remove_campsite_type_carousel_slide('87452b88-b48f-48d3-bb6c-0296de64164e', 3) $$,
|
||||
'Should be able to delete a slide from the first campsite_type'
|
||||
);
|
||||
|
||||
select lives_ok(
|
||||
$$ select remove_campsite_type_carousel_slide('9b6370f7-f941-46f2-bc6e-de455675bd0a', 6) $$,
|
||||
'Should be able to delete a slide from the first campsite_type'
|
||||
);
|
||||
|
||||
select bag_eq(
|
||||
$$ select campsite_type_id, media_id, caption from campsite_type_carousel $$,
|
||||
$$ values (10, 4, 'Source caption')
|
||||
, (11, 5, 'Another caption')
|
||||
$$,
|
||||
'Should have removed the slides'
|
||||
);
|
||||
|
||||
select bag_eq(
|
||||
$$ select campsite_type_id, media_id, lang_tag, caption from campsite_type_carousel_i18n $$,
|
||||
$$ values (10, 4, 'en', 'Target caption')
|
||||
, (10, 4, 'es', 'Target caption (spanish)')
|
||||
, (11, 5, 'en', 'Target caption')
|
||||
, (11, 5, 'es', 'Target caption (spanish)')
|
||||
$$,
|
||||
'Should have removed the slides’ translations'
|
||||
);
|
||||
|
||||
|
||||
select *
|
||||
from finish();
|
||||
|
||||
rollback;
|
|
@ -0,0 +1,94 @@
|
|||
-- Test translate_campsite_type_carousel_slide
|
||||
set client_min_messages to warning;
|
||||
create extension if not exists pgtap;
|
||||
reset client_min_messages;
|
||||
|
||||
begin;
|
||||
|
||||
select plan(13);
|
||||
|
||||
set search_path to camper, public;
|
||||
|
||||
select has_function('camper', 'translate_campsite_type_carousel_slide', array['uuid', 'integer', 'text', 'text']);
|
||||
select function_lang_is('camper', 'translate_campsite_type_carousel_slide', array['uuid', 'integer', 'text', 'text'], 'sql');
|
||||
select function_returns('camper', 'translate_campsite_type_carousel_slide', array['uuid', 'integer', 'text', 'text'], 'void');
|
||||
select isnt_definer('camper', 'translate_campsite_type_carousel_slide', array['uuid', 'integer', 'text', 'text']);
|
||||
select volatility_is('camper', 'translate_campsite_type_carousel_slide', array['uuid', 'integer', 'text', 'text'], 'volatile');
|
||||
select function_privs_are('camper', 'translate_campsite_type_carousel_slide', array['uuid', 'integer', 'text', 'text'], 'guest', array[]::text[]);
|
||||
select function_privs_are('camper', 'translate_campsite_type_carousel_slide', array['uuid', 'integer', 'text', 'text'], 'employee', array[]::text[]);
|
||||
select function_privs_are('camper', 'translate_campsite_type_carousel_slide', array['uuid', 'integer', 'text', 'text'], 'admin', array['EXECUTE']);
|
||||
select function_privs_are('camper', 'translate_campsite_type_carousel_slide', array['uuid', 'integer', 'text', 'text'], 'authenticator', array[]::text[]);
|
||||
|
||||
|
||||
set client_min_messages to warning;
|
||||
truncate campsite_type_carousel_i18n cascade;
|
||||
truncate campsite_type_carousel cascade;
|
||||
truncate media cascade;
|
||||
truncate media_content cascade;
|
||||
truncate company cascade;
|
||||
reset client_min_messages;
|
||||
|
||||
insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, country_code, currency_code, default_lang_tag)
|
||||
values (1, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', 'ES', 'EUR', 'ca')
|
||||
;
|
||||
|
||||
insert into media_content (media_type, bytes)
|
||||
values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};')
|
||||
, ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ff00ff","a"};')
|
||||
, ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffff00","a"};')
|
||||
, ('text/plain', 'hello, world!')
|
||||
, ('image/svg+xml', '<svg xmlns="http://www.w3.org/2000/svg" width="1" height="1"/>')
|
||||
;
|
||||
|
||||
insert into media (media_id, company_id, original_filename, content_hash)
|
||||
values (2, 1, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};'))
|
||||
, (3, 1, 'cover3.xpm', sha256('static char *s[]={"1 1 1 1","a c #ff00ff","a"};'))
|
||||
, (4, 1, 'cover4.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffff00","a"};'))
|
||||
, (5, 1, 'text.txt', sha256('hello, world!'))
|
||||
, (6, 1, 'image.svg', sha256('<svg xmlns="http://www.w3.org/2000/svg" width="1" height="1"/>'))
|
||||
;
|
||||
|
||||
insert into campsite_type (campsite_type_id, company_id, slug, media_id, name, description, max_campers, dogs_allowed, active)
|
||||
values (10, 1, '87452b88-b48f-48d3-bb6c-0296de64164e', 2, 'Type A', '<p>A</p>', 5, false, true)
|
||||
, (11, 1, '9b6370f7-f941-46f2-bc6e-de455675bd0a', 3, 'Type B', '<p>B</p>', 4, true, false)
|
||||
;
|
||||
|
||||
insert into campsite_type_carousel (campsite_type_id, media_id, caption)
|
||||
values (10, 4, 'Source caption')
|
||||
, (11, 5, 'Another caption')
|
||||
, (11, 6, 'N/A')
|
||||
;
|
||||
|
||||
insert into campsite_type_carousel_i18n (campsite_type_id, media_id, lang_tag, caption)
|
||||
values (10, 4, 'en', 'Target caption')
|
||||
;
|
||||
|
||||
select lives_ok(
|
||||
$$ select translate_campsite_type_carousel_slide('87452b88-b48f-48d3-bb6c-0296de64164e', 4, 'ca', 'Traducció') $$,
|
||||
'Should be able to translate a carousel slide'
|
||||
);
|
||||
|
||||
select lives_ok(
|
||||
$$ select translate_campsite_type_carousel_slide('9b6370f7-f941-46f2-bc6e-de455675bd0a', 5, 'es', null) $$,
|
||||
'Should be able to “translate” a carousel slide to the empty string'
|
||||
);
|
||||
|
||||
select lives_ok(
|
||||
$$ select translate_campsite_type_carousel_slide('87452b88-b48f-48d3-bb6c-0296de64164e', 4, 'en', 'Not anymore') $$,
|
||||
'Should be able to overwrite a slide’s translation'
|
||||
);
|
||||
|
||||
select bag_eq(
|
||||
$$ select campsite_type_id, media_id, lang_tag, caption from campsite_type_carousel_i18n $$,
|
||||
$$ values (10, 4, 'ca', 'Traducció')
|
||||
, (10, 4, 'en', 'Not anymore')
|
||||
, (11, 5, 'es', '')
|
||||
$$,
|
||||
'Should have all three slides'
|
||||
);
|
||||
|
||||
|
||||
select *
|
||||
from finish();
|
||||
|
||||
rollback;
|
|
@ -0,0 +1,7 @@
|
|||
-- Verify camper:add_campsite_type_carousel_slide on pg
|
||||
|
||||
begin;
|
||||
|
||||
select has_function_privilege('camper.add_campsite_type_carousel_slide(uuid, integer, text)', 'execute');
|
||||
|
||||
rollback;
|
|
@ -0,0 +1,17 @@
|
|||
-- Verify camper:campsite_type_carousel on pg
|
||||
|
||||
begin;
|
||||
|
||||
select campsite_type_id
|
||||
, media_id
|
||||
, caption
|
||||
from camper.campsite_type_carousel
|
||||
where false;
|
||||
|
||||
select 1 / count(*) from pg_class where oid = 'camper.campsite_type_carousel'::regclass and relrowsecurity;
|
||||
select 1 / count(*) from pg_policy where polname = 'guest_ok' and polrelid = 'camper.campsite_type_carousel'::regclass;
|
||||
select 1 / count(*) from pg_policy where polname = 'insert_to_company' and polrelid = 'camper.campsite_type_carousel'::regclass;
|
||||
select 1 / count(*) from pg_policy where polname = 'update_company' and polrelid = 'camper.campsite_type_carousel'::regclass;
|
||||
select 1 / count(*) from pg_policy where polname = 'delete_from_company' and polrelid = 'camper.campsite_type_carousel'::regclass;
|
||||
|
||||
rollback;
|
|
@ -0,0 +1,12 @@
|
|||
-- Verify camper:campsite_type_carousel_i18n on pg
|
||||
|
||||
begin;
|
||||
|
||||
select campsite_type_id
|
||||
, media_id
|
||||
, lang_tag
|
||||
, caption
|
||||
from camper.campsite_type_carousel_i18n
|
||||
where false;
|
||||
|
||||
rollback;
|
|
@ -0,0 +1,7 @@
|
|||
-- Verify camper:remove_campsite_type_carousel_slide on pg
|
||||
|
||||
begin;
|
||||
|
||||
select has_function_privilege('camper.remove_campsite_type_carousel_slide(uuid, integer)', 'execute');
|
||||
|
||||
rollback;
|
|
@ -0,0 +1,7 @@
|
|||
-- Verify camper:translate_campsite_type_carousel_slide on pg
|
||||
|
||||
begin;
|
||||
|
||||
select has_function_privilege('camper.translate_campsite_type_carousel_slide(uuid, integer, text, text)', 'execute');
|
||||
|
||||
rollback;
|
|
@ -584,7 +584,7 @@ dt {
|
|||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.outside_activities h3, .campsite_services .spiel {
|
||||
.outside_activities h3, .campsite_services .spiel, .campsite_type .spiel {
|
||||
font-size: calc(2.2rem + 4vw);
|
||||
font-weight: 600;
|
||||
line-height: .9em;
|
||||
|
@ -662,7 +662,7 @@ dt {
|
|||
margin-bottom: 5rem;
|
||||
}
|
||||
|
||||
.campsite_services.carousel .slick-track {
|
||||
.campsite_services.carousel .slick-track, .campsite_type.carousel .slick-track {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
<!--
|
||||
SPDX-FileCopyrightText: 2023 jordi fita mas <jordi@tandem.blog>
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
{{ define "title" -}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.slideForm*/ -}}
|
||||
{{ if .MediaID }}
|
||||
{{( pgettext "Edit Campsite Type Carousel Slide" "title" )}}
|
||||
{{ else }}
|
||||
{{( pgettext "New Campsite Type Carousel Slide" "title" )}}
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
|
||||
{{ define "content" -}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.slideForm*/ -}}
|
||||
<form
|
||||
{{ if .MediaID }}
|
||||
data-hx-put="/admin/campsites/types/{{ .TypeSlug }}/slides/{{ .MediaID }}"
|
||||
{{ else }}
|
||||
action="/admin/campsites/types/{{ .TypeSlug }}/slides" method="post"
|
||||
{{ end }}
|
||||
>
|
||||
<h2>
|
||||
{{ if .MediaID }}
|
||||
{{( pgettext "Edit Campsite Type Carousel Slide" "title" )}}
|
||||
{{ else }}
|
||||
{{( pgettext "New Campsite Type Carousel Slide" "title" )}}
|
||||
{{ end }}
|
||||
</h2>
|
||||
{{ CSRFInput }}
|
||||
<fieldset>
|
||||
{{ with .Media -}}
|
||||
{{ template "media-picker" . }}
|
||||
{{- end }}
|
||||
{{ with .Caption -}}
|
||||
<label>
|
||||
{{( pgettext "Caption" "input")}}<br>
|
||||
<input type="text" name="{{ .Name }}" value="{{ .Val }}"
|
||||
{{ template "error-attrs" . }}><br>
|
||||
</label>
|
||||
{{ template "error-message" . }}
|
||||
{{- end }}
|
||||
</fieldset>
|
||||
<footer>
|
||||
<button type="submit">
|
||||
{{ if .MediaID }}
|
||||
{{( pgettext "Update" "action" )}}
|
||||
{{ else }}
|
||||
{{( pgettext "Add" "action" )}}
|
||||
{{ end }}
|
||||
</button>
|
||||
</footer>
|
||||
</form>
|
||||
{{- end }}
|
|
@ -0,0 +1,52 @@
|
|||
<!--
|
||||
SPDX-FileCopyrightText: 2023 jordi fita mas <jordi@tandem.blog>
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
{{ define "title" -}}
|
||||
{{( pgettext "Campsite Type Carousel" "title" )}}
|
||||
{{- end }}
|
||||
|
||||
{{ define "content" -}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.carouselIndex*/ -}}
|
||||
<h2>{{( pgettext "Campsite Type Carousel" "title" )}}</h2>
|
||||
<a href="/admin/campsites/types/{{ .TypeSlug }}/slides/new">{{( pgettext "Add slide" "action" )}}</a>
|
||||
{{ if .Slides -}}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">{{( pgettext "Image" "header" )}}</th>
|
||||
<th scope="col">{{( pgettext "Caption" "header" )}}</th>
|
||||
<th scope="col">{{( pgettext "Translations" "header" )}}</th>
|
||||
<th scope="col">{{( pgettext "Actions" "header" )}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{ $confirm := (gettext "Are you sure you wish to delete this slide?")}}
|
||||
{{ range $slide := .Slides -}}
|
||||
<tr>
|
||||
<td><a href="/admin/campsites/types/{{ $.TypeSlug }}/slides/{{ .ID }}"><img src="{{ .Media }}" alt=""></a></td>
|
||||
<td><a href="/admin/campsites/types/{{ $.TypeSlug }}/slides/{{ .ID }}">{{ .Caption }}</a></td>
|
||||
<td>
|
||||
{{ range .Translations }}
|
||||
<a
|
||||
{{ if .Missing }}
|
||||
class="missing-translation"
|
||||
{{ end }}
|
||||
href="/admin/campsites/types/{{ $.TypeSlug }}/slides/{{ $slide.ID }}/{{ .Language }}">{{ .Endonym }}</a>
|
||||
{{ end }}
|
||||
</td>
|
||||
<td>
|
||||
<form data-hx-delete="/admin/campsites/types/{{ $.TypeSlug }}/slides/{{ .ID }}"
|
||||
data-hx-confirm="{{ $confirm }}"
|
||||
data-hx-headers='{ {{ CSRFHeader }} }'>
|
||||
<button type="submit">{{( pgettext "Delete" "action" )}}</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{{- end }}
|
||||
</tbody>
|
||||
</table>
|
||||
{{ else -}}
|
||||
<p>{{( gettext "No slides added yet." )}}</p>
|
||||
{{- end }}
|
||||
{{- end }}
|
|
@ -0,0 +1,35 @@
|
|||
<!--
|
||||
SPDX-FileCopyrightText: 2023 jordi fita mas <jordi@tandem.blog>
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
{{ define "title" -}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.slideL10nForm*/ -}}
|
||||
{{printf (pgettext "Translate Campsite Type Carousel Slide to %s" "title") .Locale.Endonym }}
|
||||
{{- end }}
|
||||
|
||||
{{ define "content" -}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.slideL10nForm*/ -}}
|
||||
<form data-hx-put="/admin/campsites/types/{{ .TypeSlug }}/slides/{{ .MediaID }}/{{ .Locale.Language }}">
|
||||
<h2>
|
||||
{{printf (pgettext "Translate Campsite Type Carousel Slide to %s" "title") .Locale.Endonym }}
|
||||
</h2>
|
||||
{{ CSRFInput }}
|
||||
<fieldset>
|
||||
{{ with .Caption -}}
|
||||
<fieldset>
|
||||
<legend>{{( pgettext "Caption" "input")}}</legend>
|
||||
{{( gettext "Source:" )}} {{ .Source }}<br>
|
||||
<label>
|
||||
{{( pgettext "Translation:" "input" )}}
|
||||
<input type="text" name="{{ .Name }}" value="{{ .Val }}"
|
||||
{{ template "error-attrs" . }}><br>
|
||||
</label>
|
||||
{{ template "error-message" . }}
|
||||
</fieldset>
|
||||
{{- end }}
|
||||
</fieldset>
|
||||
<footer>
|
||||
<button type="submit">{{( pgettext "Translate" "action" )}}</button>
|
||||
</footer>
|
||||
</form>
|
||||
{{- end }}
|
|
@ -17,6 +17,7 @@
|
|||
<th scope="col">{{( pgettext "Name" "header" )}}</th>
|
||||
<th scope="col">{{( pgettext "Translations" "header" )}}</th>
|
||||
<th scope="col">{{( pgettext "Options" "header" )}}</th>
|
||||
<th scope="col">{{( pgettext "Carousel" "header" )}}</th>
|
||||
<th scope="col">{{( pgettext "Active" "campsite type" )}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -34,6 +35,7 @@
|
|||
{{ end }}
|
||||
</td>
|
||||
<td><a href="/admin/campsites/types/{{ .Slug }}/options">{{( pgettext "Edit Options" "action" )}}</a></td>
|
||||
<td><a href="/admin/campsites/types/{{ .Slug }}/slides">{{( pgettext "Edit Carousel" "action" )}}</a></td>
|
||||
<td>{{ if .Active }}{{( gettext "Yes" )}}{{ else }}{{( gettext "No" )}}{{ end }}</td>
|
||||
</tr>
|
||||
{{- end }}
|
||||
|
|
|
@ -7,9 +7,32 @@
|
|||
{{ .Name }}
|
||||
{{- end }}
|
||||
|
||||
{{ define "head" -}}
|
||||
{{ template "carouselStyle" }}
|
||||
{{- end }}
|
||||
|
||||
{{ define "content" -}}
|
||||
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.publicPage*/ -}}
|
||||
<h2>{{ .Name }}</h2>
|
||||
|
||||
{{ with .Carousel -}}
|
||||
<div class="campsite_type carousel">
|
||||
<div class="spiel">
|
||||
<p>TODO</p>
|
||||
</div>
|
||||
{{ range . -}}
|
||||
{{ if .Caption -}}
|
||||
<figure>
|
||||
<img src="{{ .Media }}" alt=""/>
|
||||
<figcaption>{{ .Caption }}</figcaption>
|
||||
</figure>
|
||||
{{- else -}}
|
||||
<img src="{{ .Media }}" alt=""/>
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
</div>
|
||||
{{- end }}
|
||||
|
||||
{{ .Description }}
|
||||
|
||||
{{ with .Prices -}}
|
||||
|
@ -34,4 +57,7 @@
|
|||
</dl>
|
||||
</article>
|
||||
{{- end }}
|
||||
|
||||
{{ template "carouselInit" }}
|
||||
|
||||
{{- end }}
|
||||
|
|
Loading…
Reference in New Issue