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.
BIN
demo/bungalows_carousel2.avif
Normal file
After Width: | Height: | Size: 68 KiB |
BIN
demo/bungalows_carousel3.avif
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
demo/bungalows_carousel4.avif
Normal file
After Width: | Height: | Size: 45 KiB |
BIN
demo/bungalows_carousel5.avif
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
demo/bungalows_carousel6.avif
Normal file
After Width: | Height: | Size: 28 KiB |
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;
|
||||
|
BIN
demo/safari_tents_carousel1.avif
Normal file
After Width: | Height: | Size: 141 KiB |
BIN
demo/safari_tents_carousel2.avif
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
demo/safari_tents_carousel3.avif
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
demo/safari_tents_carousel4.avif
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
demo/safari_tents_carousel5.avif
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
demo/safari_tents_carousel6.avif
Normal file
After Width: | Height: | Size: 117 KiB |
BIN
demo/wooden_lodges_carousel0.avif
Normal file
After Width: | Height: | Size: 120 KiB |
BIN
demo/wooden_lodges_carousel1.avif
Normal file
After Width: | Height: | Size: 71 KiB |
BIN
demo/wooden_lodges_carousel2.avif
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
demo/wooden_lodges_carousel3.avif
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
demo/wooden_lodges_carousel4.avif
Normal file
After Width: | Height: | Size: 6.5 KiB |
BIN
demo/wooden_lodges_carousel5.avif
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
demo/wooden_lodges_carousel6.avif
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
demo/wooden_lodges_carousel7.avif
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
demo/wooden_lodges_carousel8.avif
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
demo/wooden_lodges_carousel9.avif
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
demo/wooden_lodges_carouselA.avif
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
demo/wooden_lodges_carouselB.avif
Normal file
After Width: | Height: | Size: 9.6 KiB |
BIN
demo/wooden_lodges_carouselC.avif
Normal file
After Width: | Height: | Size: 8.5 KiB |
28
deploy/add_campsite_type_carousel_slide.sql
Normal file
@ -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;
|
55
deploy/campsite_type_carousel.sql
Normal file
@ -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;
|
24
deploy/campsite_type_carousel_i18n.sql
Normal file
@ -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;
|
37
deploy/remove_campsite_type_carousel_slide.sql
Normal file
@ -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;
|
27
deploy/translate_campsite_type_carousel_slide.sql
Normal file
@ -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 {
|
||||
|
297
pkg/campsite/types/carousel.go
Normal file
@ -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
@ -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
@ -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."
|
||||
|
||||
|
7
revert/add_campsite_type_carousel_slide.sql
Normal file
@ -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;
|
7
revert/campsite_type_carousel.sql
Normal file
@ -0,0 +1,7 @@
|
||||
-- Revert camper:campsite_type_carousel from pg
|
||||
|
||||
begin;
|
||||
|
||||
drop table if exists camper.campsite_type_carousel;
|
||||
|
||||
commit;
|
7
revert/campsite_type_carousel_i18n.sql
Normal file
@ -0,0 +1,7 @@
|
||||
-- Revert camper:campsite_type_carousel_i18n from pg
|
||||
|
||||
begin;
|
||||
|
||||
drop table if exists camper.campsite_type_carousel_i18n;
|
||||
|
||||
commit;
|
7
revert/remove_campsite_type_carousel_slide.sql
Normal file
@ -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;
|
7
revert/translate_campsite_type_carousel_slide.sql
Normal file
@ -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
|
||||
|
94
test/add_campsite_type_carousel_slide.sql
Normal file
@ -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;
|
223
test/campsite_type_carousel.sql
Normal file
@ -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;
|
||||
|
49
test/campsite_type_carousel_i18n.sql
Normal file
@ -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;
|
||||
|
106
test/remove_campsite_type_carousel_slide.sql
Normal file
@ -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;
|
94
test/translate_campsite_type_carousel_slide.sql
Normal file
@ -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;
|
7
verify/add_campsite_type_carousel_slide.sql
Normal file
@ -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;
|
17
verify/campsite_type_carousel.sql
Normal file
@ -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;
|
12
verify/campsite_type_carousel_i18n.sql
Normal file
@ -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;
|
7
verify/remove_campsite_type_carousel_slide.sql
Normal file
@ -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;
|
7
verify/translate_campsite_type_carousel_slide.sql
Normal file
@ -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;
|
||||
}
|
||||
|
||||
|
54
web/templates/admin/campsite/carousel/form.gohtml
Normal file
@ -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 }}
|
52
web/templates/admin/campsite/carousel/index.gohtml
Normal file
@ -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 }}
|
35
web/templates/admin/campsite/carousel/l10n.gohtml
Normal file
@ -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 }}
|
||||
|