diff --git a/demo/demo.sql b/demo/demo.sql index c01cc5a..53766f1 100644 --- a/demo/demo.sql +++ b/demo/demo.sql @@ -234,88 +234,910 @@ values (82, 'en', 'Max. 5 pax') ; alter table campsite alter column campsite_id restart with 82; -select add_campsite(72, '2'); -select add_campsite(72, '3'); -select add_campsite(72, '4'); -select add_campsite(72, '5'); -select add_campsite(72, '6'); -select add_campsite(72, '7'); -select add_campsite(72, '8'); -select add_campsite(72, '9'); -select add_campsite(72, '10'); -select add_campsite(72, '11'); -select add_campsite(72, '12'); -select add_campsite(72, '14'); -select add_campsite(72, '15'); -select add_campsite(72, '16'); -select add_campsite(72, '17'); -select add_campsite(72, '18'); -select add_campsite(72, '19'); -select add_campsite(72, '20'); -select add_campsite(72, '21'); -select add_campsite(72, '22'); -select add_campsite(72, '23'); -select add_campsite(72, '24'); -select add_campsite(72, '25'); -select add_campsite(72, '26'); -select add_campsite(72, '27'); -select add_campsite(72, '28'); -select add_campsite(72, '29'); -select add_campsite(72, '42'); -select add_campsite(72, '43'); -select add_campsite(72, '44'); -select add_campsite(72, '45'); -select add_campsite(72, '46'); -select add_campsite(72, '47'); -select add_campsite(72, '48'); -select add_campsite(72, '50'); -select add_campsite(72, '51'); -select add_campsite(72, '52'); -select add_campsite(72, '53'); -select add_campsite(72, '54'); -select add_campsite(72, '55'); -select add_campsite(72, '56'); -select add_campsite(72, '57'); -select add_campsite(72, '58'); -select add_campsite(72, '59'); -select add_campsite(72, '60'); -select add_campsite(72, '61'); -select add_campsite(72, '62'); -select add_campsite(72, '63'); -select add_campsite(72, '64'); -select add_campsite(72, '65'); -select add_campsite(72, '69'); -select add_campsite(72, '70'); -select add_campsite(72, '71'); -select add_campsite(72, '72'); -select add_campsite(72, '73'); -select add_campsite(72, '74'); -select add_campsite(72, '75'); -select add_campsite(72, '76'); -select add_campsite(72, '77'); -select add_campsite(73, '78'); -select add_campsite(72, '79'); -select add_campsite(72, '80'); -select add_campsite(72, '81'); -select add_campsite(72, '82'); -select add_campsite(72, '83'); -select add_campsite(76, '84'); -select add_campsite(76, '85'); -select add_campsite(72, '89'); -select add_campsite(72, '90'); -select add_campsite(72, '91'); -select add_campsite(72, '92'); -select add_campsite(72, '93'); -select add_campsite(72, '94'); -select add_campsite(72, '95'); -select add_campsite(72, '96'); -select add_campsite(72, '97'); -select add_campsite(72, '98'); -select add_campsite(72, 'B1'); -select add_campsite(72, 'D1'); -select add_campsite(72, 'D2'); -select add_campsite(72, 'D3'); -select add_campsite(72, 'D4'); +select add_campsite(72, '2', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '3', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '4', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '5', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '6', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '7', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '8', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '9', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '10', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '11', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '12', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '14', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '15', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '16', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '17', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '18', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '19', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '20', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '21', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '22', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '23', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '24', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '25', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '26', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '27', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '28', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '29', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '42', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '43', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '44', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '45', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '46', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '47', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '48', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '50', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '51', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '52', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '53', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '54', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '55', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '56', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '57', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '58', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '59', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '60', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '61', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '62', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '63', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '64', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '65', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '69', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '70', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '71', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '72', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '73', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '74', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '75', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '76', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '77', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(73, '78', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '79', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '80', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '81', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '82', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '83', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(76, '84', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(76, '85', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '89', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '90', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '91', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '92', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '93', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '94', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '95', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '96', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '97', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, '98', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, 'B1', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, 'D1', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, 'D2', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, 'D3', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); +select add_campsite(72, 'D4', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

', '

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.

'); + +select add_campsite_carousel_slide(72, '2', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '2', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '2', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '2', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '2', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '2', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '3', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '3', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '3', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '3', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '3', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '3', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '4', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '4', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '4', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '4', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '4', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '4', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '5', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '5', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '5', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '5', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '5', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '5', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '6', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '6', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '6', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '6', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '6', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '6', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '7', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '7', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '7', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '7', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '7', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '7', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '8', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '8', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '8', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '8', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '8', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '8', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '9', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '9', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '9', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '9', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '9', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '9', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '10', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '10', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '10', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '10', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '10', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '10', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '11', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '11', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '11', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '11', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '11', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '11', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '12', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '12', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '12', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '12', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '12', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '12', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '14', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '14', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '14', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '14', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '14', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '14', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '15', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '15', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '15', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '15', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '15', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '15', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '16', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '16', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '16', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '16', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '16', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '16', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '17', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '17', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '17', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '17', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '17', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '17', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '18', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '18', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '18', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '18', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '18', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '18', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '19', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '19', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '19', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '19', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '19', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '19', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '20', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '20', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '20', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '20', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '20', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '20', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '21', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '21', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '21', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '21', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '21', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '21', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '22', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '22', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '22', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '22', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '22', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '22', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '23', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '23', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '23', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '23', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '23', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '23', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '24', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '24', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '24', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '24', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '24', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '24', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '25', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '25', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '25', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '25', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '25', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '25', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '26', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '26', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '26', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '26', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '26', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '26', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '27', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '27', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '27', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '27', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '27', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '27', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '28', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '28', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '28', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '28', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '28', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '28', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '29', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '29', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '29', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '29', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '29', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '29', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '42', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '42', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '42', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '42', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '42', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '42', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '43', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '43', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '43', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '43', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '43', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '43', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '44', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '44', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '44', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '44', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '44', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '44', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '45', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '45', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '45', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '45', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '45', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '45', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '46', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '46', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '46', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '46', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '46', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '46', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '47', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '47', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '47', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '47', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '47', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '47', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '48', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '48', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '48', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '48', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '48', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '48', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '50', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '50', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '50', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '50', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '50', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '50', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '51', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '51', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '51', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '51', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '51', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '51', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '52', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '52', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '52', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '52', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '52', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '52', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '53', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '53', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '53', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '53', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '53', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '53', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '54', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '54', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '54', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '54', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '54', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '54', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '55', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '55', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '55', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '55', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '55', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '55', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '56', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '56', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '56', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '56', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '56', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '56', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '57', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '57', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '57', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '57', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '57', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '57', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '58', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '58', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '58', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '58', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '58', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '58', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '59', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '59', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '59', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '59', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '59', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '59', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '60', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '60', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '60', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '60', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '60', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '60', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '61', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '61', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '61', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '61', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '61', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '61', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '62', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '62', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '62', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '62', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '62', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '62', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '63', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '63', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '63', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '63', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '63', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '63', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '64', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '64', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '64', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '64', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '64', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '64', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '65', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '65', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '65', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '65', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '65', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '65', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '69', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '69', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '69', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '69', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '69', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '69', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '70', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '70', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '70', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '70', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '70', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '70', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '71', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '71', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '71', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '71', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '71', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '71', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '72', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '72', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '72', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '72', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '72', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '72', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '73', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '73', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '73', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '73', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '73', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '73', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '74', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '74', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '74', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '74', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '74', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '74', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '75', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '75', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '75', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '75', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '75', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '75', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '76', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '76', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '76', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '76', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '76', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '76', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '77', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '77', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '77', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '77', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '77', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '77', 85, 'Llegenda'); +select add_campsite_carousel_slide(73, '78', 80, 'Llegenda'); +select add_campsite_carousel_slide(73, '78', 81, 'Llegenda'); +select add_campsite_carousel_slide(73, '78', 82, 'Llegenda'); +select add_campsite_carousel_slide(73, '78', 83, 'Llegenda'); +select add_campsite_carousel_slide(73, '78', 84, 'Llegenda'); +select add_campsite_carousel_slide(73, '78', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '79', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '79', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '79', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '79', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '79', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '79', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '80', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '80', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '80', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '80', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '80', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '80', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '81', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '81', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '81', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '81', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '81', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '81', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '82', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '82', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '82', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '82', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '82', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '82', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '83', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '83', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '83', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '83', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '83', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '83', 85, 'Llegenda'); +select add_campsite_carousel_slide(76, '84', 80, 'Llegenda'); +select add_campsite_carousel_slide(76, '84', 81, 'Llegenda'); +select add_campsite_carousel_slide(76, '84', 82, 'Llegenda'); +select add_campsite_carousel_slide(76, '84', 83, 'Llegenda'); +select add_campsite_carousel_slide(76, '84', 84, 'Llegenda'); +select add_campsite_carousel_slide(76, '84', 85, 'Llegenda'); +select add_campsite_carousel_slide(76, '85', 80, 'Llegenda'); +select add_campsite_carousel_slide(76, '85', 81, 'Llegenda'); +select add_campsite_carousel_slide(76, '85', 82, 'Llegenda'); +select add_campsite_carousel_slide(76, '85', 83, 'Llegenda'); +select add_campsite_carousel_slide(76, '85', 84, 'Llegenda'); +select add_campsite_carousel_slide(76, '85', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '89', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '89', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '89', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '89', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '89', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '89', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '90', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '90', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '90', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '90', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '90', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '90', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '91', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '91', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '91', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '91', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '91', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '91', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '92', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '92', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '92', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '92', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '92', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '92', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '93', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '93', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '93', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '93', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '93', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '93', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '94', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '94', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '94', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '94', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '94', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '94', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '95', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '95', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '95', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '95', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '95', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '95', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '96', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '96', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '96', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '96', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '96', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '96', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '97', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '97', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '97', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '97', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '97', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '97', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, '98', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, '98', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, '98', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, '98', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, '98', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, '98', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, 'B1', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, 'B1', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, 'B1', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, 'B1', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, 'B1', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, 'B1', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D1', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D1', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D1', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D1', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D1', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D1', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D2', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D2', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D2', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D2', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D2', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D2', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D3', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D3', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D3', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D3', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D3', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D3', 85, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D4', 80, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D4', 81, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D4', 82, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D4', 83, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D4', 84, 'Llegenda'); +select add_campsite_carousel_slide(72, 'D4', 85, 'Llegenda'); + +select add_campsite_feature(72, '2', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '2', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '2', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '2', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '3', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '3', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '3', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '3', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '4', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '4', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '4', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '4', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '5', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '5', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '5', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '5', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '6', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '6', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '6', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '6', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '7', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '7', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '7', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '7', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '8', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '8', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '8', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '8', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '9', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '9', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '9', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '9', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '10', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '10', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '10', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '10', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '11', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '11', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '11', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '11', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '12', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '12', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '12', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '12', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '14', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '14', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '14', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '14', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '15', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '15', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '15', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '15', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '16', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '16', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '16', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '16', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '17', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '17', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '17', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '17', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '18', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '18', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '18', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '18', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '19', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '19', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '19', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '19', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '20', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '20', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '20', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '20', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '21', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '21', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '21', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '21', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '22', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '22', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '22', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '22', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '23', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '23', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '23', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '23', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '24', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '24', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '24', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '24', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '25', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '25', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '25', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '25', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '26', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '26', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '26', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '26', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '27', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '27', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '27', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '27', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '28', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '28', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '28', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '28', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '29', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '29', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '29', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '29', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '42', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '42', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '42', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '42', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '43', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '43', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '43', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '43', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '44', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '44', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '44', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '44', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '45', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '45', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '45', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '45', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '46', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '46', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '46', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '46', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '47', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '47', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '47', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '47', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '48', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '48', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '48', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '48', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '50', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '50', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '50', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '50', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '51', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '51', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '51', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '51', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '52', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '52', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '52', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '52', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '53', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '53', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '53', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '53', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '54', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '54', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '54', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '54', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '55', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '55', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '55', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '55', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '56', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '56', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '56', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '56', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '57', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '57', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '57', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '57', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '58', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '58', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '58', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '58', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '59', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '59', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '59', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '59', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '60', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '60', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '60', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '60', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '61', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '61', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '61', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '61', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '62', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '62', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '62', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '62', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '63', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '63', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '63', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '63', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '64', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '64', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '64', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '64', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '65', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '65', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '65', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '65', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '69', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '69', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '69', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '69', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '70', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '70', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '70', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '70', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '71', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '71', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '71', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '71', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '72', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '72', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '72', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '72', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '73', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '73', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '73', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '73', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '74', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '74', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '74', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '74', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '75', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '75', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '75', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '75', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '76', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '76', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '76', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '76', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '77', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '77', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '77', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '77', 'shower', 'Accés als serveis'); +select add_campsite_feature(73, '78', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(73, '78', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(73, '78', 'electricity', 'Electricitat'); +select add_campsite_feature(73, '78', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '79', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '79', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '79', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '79', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '80', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '80', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '80', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '80', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '81', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '81', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '81', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '81', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '82', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '82', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '82', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '82', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '83', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '83', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '83', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '83', 'shower', 'Accés als serveis'); +select add_campsite_feature(76, '84', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(76, '84', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(76, '84', 'electricity', 'Electricitat'); +select add_campsite_feature(76, '84', 'shower', 'Accés als serveis'); +select add_campsite_feature(76, '85', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(76, '85', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(76, '85', 'electricity', 'Electricitat'); +select add_campsite_feature(76, '85', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '89', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '89', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '89', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '89', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '90', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '90', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '90', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '90', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '91', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '91', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '91', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '91', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '92', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '92', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '92', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '92', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '93', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '93', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '93', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '93', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '94', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '94', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '94', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '94', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '95', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '95', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '95', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '95', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '96', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '96', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '96', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '96', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '97', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '97', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '97', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '97', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, '98', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, '98', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, '98', 'electricity', 'Electricitat'); +select add_campsite_feature(72, '98', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, 'B1', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, 'B1', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, 'B1', 'electricity', 'Electricitat'); +select add_campsite_feature(72, 'B1', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, 'D1', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, 'D1', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, 'D1', 'electricity', 'Electricitat'); +select add_campsite_feature(72, 'D1', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, 'D2', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, 'D2', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, 'D2', 'electricity', 'Electricitat'); +select add_campsite_feature(72, 'D2', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, 'D3', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, 'D3', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, 'D3', 'electricity', 'Electricitat'); +select add_campsite_feature(72, 'D3', 'shower', 'Accés als serveis'); +select add_campsite_feature(72, 'D4', 'person', 'Máx. 6 pers.'); +select add_campsite_feature(72, 'D4', 'area', 'de 55 a 65 m²'); +select add_campsite_feature(72, 'D4', 'electricity', 'Electricitat'); +select add_campsite_feature(72, 'D4', 'shower', 'Accés als serveis'); alter table service alter column service_id restart with 82; insert into service (company_id, icon_name, name, description) diff --git a/deploy/add_campsite.sql b/deploy/add_campsite.sql index 046bfbe..c1fdf34 100644 --- a/deploy/add_campsite.sql +++ b/deploy/add_campsite.sql @@ -8,13 +8,15 @@ begin; set search_path to camper, public; -create or replace function add_campsite(campsite_type integer, label text) returns integer as +drop function if exists add_campsite(integer, text); + +create or replace function add_campsite(campsite_type integer, label text, info1 text, info2 text) returns integer as $$ declare cid integer; begin - insert into campsite (company_id, campsite_type_id, label) - select company_id, campsite_type_id, label + insert into campsite (company_id, campsite_type_id, label, info1, info2) + select company_id, campsite_type_id, label, xmlparse(content info1), xmlparse(content info2) from campsite_type where campsite_type_id = add_campsite.campsite_type returning campsite_id into cid @@ -28,7 +30,7 @@ $$ language plpgsql ; -revoke execute on function add_campsite(integer, text) from public; -grant execute on function add_campsite(integer, text) to admin; +revoke execute on function add_campsite(integer, text, text, text) from public; +grant execute on function add_campsite(integer, text, text, text) to admin; commit; diff --git a/deploy/add_campsite@v1.sql b/deploy/add_campsite@v1.sql new file mode 100644 index 0000000..046bfbe --- /dev/null +++ b/deploy/add_campsite@v1.sql @@ -0,0 +1,34 @@ +-- Deploy camper:add_campsite to pg +-- requires: roles +-- requires: schema_camper +-- requires: campsite +-- requires: campsite_type + +begin; + +set search_path to camper, public; + +create or replace function add_campsite(campsite_type integer, label text) returns integer as +$$ +declare + cid integer; +begin + insert into campsite (company_id, campsite_type_id, label) + select company_id, campsite_type_id, label + from campsite_type + where campsite_type_id = add_campsite.campsite_type + returning campsite_id into cid + ; + if cid is null then + raise foreign_key_violation using message = 'insert or update on table "campsite" violates foreign key constraint "campsite_campsite_type_id_fkey"'; + end if; + return cid; +end +$$ + language plpgsql +; + +revoke execute on function add_campsite(integer, text) from public; +grant execute on function add_campsite(integer, text) to admin; + +commit; diff --git a/deploy/add_campsite_carousel_slide.sql b/deploy/add_campsite_carousel_slide.sql new file mode 100644 index 0000000..96c3434 --- /dev/null +++ b/deploy/add_campsite_carousel_slide.sql @@ -0,0 +1,29 @@ +-- Deploy camper:add_campsite_carousel_slide to pg +-- requires: roles +-- requires: schema_camper +-- requires: campsite +-- requires: campsite_carousel + +begin; + +set search_path to camper, public; + +create or replace function add_campsite_carousel_slide(company_id integer, label text, media_id integer, caption text) returns integer as +$$ + insert into campsite_carousel (campsite_id, media_id, caption) + select campsite_id, media_id, coalesce(caption, '') + from campsite + where label = add_campsite_carousel_slide.label + and company_id = add_campsite_carousel_slide.company_id + on conflict (campsite_id, media_id) do update + set caption = excluded.caption + returning campsite_id + ; +$$ + language sql +; + +revoke execute on function add_campsite_carousel_slide(integer, text, integer, text) from public; +grant execute on function add_campsite_carousel_slide(integer, text, integer, text) to admin; + +commit; diff --git a/deploy/add_campsite_feature.sql b/deploy/add_campsite_feature.sql new file mode 100644 index 0000000..f7a50e4 --- /dev/null +++ b/deploy/add_campsite_feature.sql @@ -0,0 +1,27 @@ +-- Deploy camper:add_campsite_feature to pg +-- requires: roles +-- requires: schema_camper +-- requires: campsite_feature +-- requires: campsite + +begin; + +set search_path to camper, public; + +create or replace function add_campsite_feature(company_id integer, campsite_label text, icon_name text, name text) returns integer as +$$ + insert into campsite_feature (campsite_id, icon_name, name) + select campsite_id, icon_name, add_campsite_feature.name + from campsite + where label = campsite_label + and company_id = add_campsite_feature.company_id + returning campsite_feature_id + ; +$$ + language sql +; + +revoke execute on function add_campsite_feature(integer, text, text, text) from public; +grant execute on function add_campsite_feature(integer, text, text, text) to admin; + +commit; diff --git a/deploy/campsite__info.sql b/deploy/campsite__info.sql new file mode 100644 index 0000000..cd9525a --- /dev/null +++ b/deploy/campsite__info.sql @@ -0,0 +1,11 @@ +-- Deploy camper:campsite__info to pg +-- requires: campsite + +begin; + +alter table camper.campsite + add column info1 xml not null default ''::xml +, add column info2 xml not null default ''::xml +; + +commit; diff --git a/deploy/campsite_carousel.sql b/deploy/campsite_carousel.sql new file mode 100644 index 0000000..bda2422 --- /dev/null +++ b/deploy/campsite_carousel.sql @@ -0,0 +1,56 @@ +-- Deploy camper:campsite_carousel to pg +-- requires: roles +-- requires: schema_camper +-- requires: campsite +-- requires: media +-- requires: user_profile + +begin; + +set search_path to camper, public; + +create table campsite_carousel ( + campsite_id integer not null references campsite, + media_id integer not null references media, + caption text not null, + position integer not null default 2147483647, + primary key (campsite_id, media_id) +); + +grant select on table campsite_carousel to guest; +grant select on table campsite_carousel to employee; +grant select, insert, update, delete on table campsite_carousel to admin; + +alter table campsite_carousel enable row level security; + +create policy guest_ok +on campsite_carousel +for select +using (true) +; + +create policy insert_to_company +on campsite_carousel +for insert +with check ( + exists (select 1 from campsite join media using (company_id) join user_profile using (company_id) where campsite.campsite_id = campsite_carousel.campsite_id and media.media_id = campsite_carousel.media_id) +) +; + +create policy update_company +on campsite_carousel +for update +using ( + exists (select 1 from campsite join media using (company_id) join user_profile using (company_id) where campsite.campsite_id = campsite_carousel.campsite_id and media.media_id = campsite_carousel.media_id) +) +; + +create policy delete_from_company +on campsite_carousel +for delete +using ( + exists (select 1 from campsite join media using (company_id) join user_profile using (company_id) where campsite.campsite_id = campsite_carousel.campsite_id and media.media_id = campsite_carousel.media_id) +) +; + +commit; diff --git a/deploy/campsite_carousel_i18n.sql b/deploy/campsite_carousel_i18n.sql new file mode 100644 index 0000000..ccbc676 --- /dev/null +++ b/deploy/campsite_carousel_i18n.sql @@ -0,0 +1,24 @@ +-- Deploy camper:campsite_carousel_i18n to pg +-- requires: roles +-- requires: schema_camper +-- requires: campsite_carousel +-- requires: language + +begin; + +set search_path to camper, public; + +create table campsite_carousel_i18n ( + campsite_id integer not null, + media_id integer not null, + lang_tag text not null references language, + caption text, + primary key (campsite_id, media_id, lang_tag), + foreign key (campsite_id, media_id) references campsite_carousel +); + +grant select on table campsite_carousel_i18n to guest; +grant select on table campsite_carousel_i18n to employee; +grant select, insert, update, delete on table campsite_carousel_i18n to admin; + +commit; diff --git a/deploy/campsite_feature.sql b/deploy/campsite_feature.sql new file mode 100644 index 0000000..2bfc262 --- /dev/null +++ b/deploy/campsite_feature.sql @@ -0,0 +1,56 @@ +-- Deploy camper:campsite_feature to pg +-- requires: roles +-- requires: schema_camper +-- requires: campsite +-- requires: icon +-- requires: user_profile + +begin; + +set search_path to camper, public; + +create table campsite_feature ( + campsite_feature_id integer generated by default as identity primary key, + campsite_id integer not null references campsite, + icon_name text not null references icon, + name text not null constraint name_not_empty check(length(trim(name)) > 0), + position integer not null default 2147483647 +); + +grant select on table campsite_feature to guest; +grant select on table campsite_feature to employee; +grant select, insert, update, delete on table campsite_feature to admin; + +alter table campsite_feature enable row level security; + +create policy guest_ok +on campsite_feature +for select +using (true) +; + +create policy insert_to_company +on campsite_feature +for insert +with check ( + exists (select 1 from campsite join user_profile using (company_id) where campsite.campsite_id = campsite_feature.campsite_id) +) +; + +create policy update_company +on campsite_feature +for update +using ( + exists (select 1 from campsite join user_profile using (company_id) where campsite.campsite_id = campsite_feature.campsite_id) +) +; + +create policy delete_from_company +on campsite_feature +for delete +using ( + exists (select 1 from campsite join user_profile using (company_id) where campsite.campsite_id = campsite_feature.campsite_id) +) +; + +commit; diff --git a/deploy/campsite_feature_i18n.sql b/deploy/campsite_feature_i18n.sql new file mode 100644 index 0000000..c787a72 --- /dev/null +++ b/deploy/campsite_feature_i18n.sql @@ -0,0 +1,22 @@ +-- Deploy camper:campsite_feature_i18n to pg +-- requires: roles +-- requires: schema_camper +-- requires: campsite_feature +-- requires: language + +begin; + +set search_path to camper, public; + +create table campsite_feature_i18n ( + campsite_feature_id integer not null references campsite_feature, + lang_tag text not null references language, + name text, + primary key (campsite_feature_id, lang_tag) +); + +grant select on table campsite_feature_i18n to guest; +grant select on table campsite_feature_i18n to employee; +grant select, insert, update, delete on table campsite_feature_i18n to admin; + +commit; diff --git a/deploy/campsite_i18n.sql b/deploy/campsite_i18n.sql new file mode 100644 index 0000000..cae02ee --- /dev/null +++ b/deploy/campsite_i18n.sql @@ -0,0 +1,23 @@ +-- Deploy camper:campsite_i18n to pg +-- requires: roles +-- requires: schema_camper +-- requires: campsite +-- requires: language + +begin; + +set search_path to camper, public; + +create table campsite_i18n ( + campsite_id integer not null references campsite, + lang_tag text not null references language, + info1 xml, + info2 xml, + primary key (campsite_id, lang_tag) +); + +grant select on campsite_i18n to guest; +grant select on campsite_i18n to employee; +grant select, insert, update, delete on campsite_i18n to admin; + +commit; diff --git a/deploy/edit_campsite.sql b/deploy/edit_campsite.sql index bcaf2d8..35278f9 100644 --- a/deploy/edit_campsite.sql +++ b/deploy/edit_campsite.sql @@ -7,11 +7,15 @@ begin; set search_path to camper, public; -create or replace function edit_campsite(campsite_id integer, campsite_type integer, new_label text, active boolean) returns integer as +drop function edit_campsite(integer, integer, text, boolean); + +create or replace function edit_campsite(campsite_id integer, campsite_type integer, new_label text, new_info1 text, new_info2 text, active boolean) returns integer as $$ update campsite set label = edit_campsite.new_label , campsite_type_id = edit_campsite.campsite_type + , info1 = xmlparse(content new_info1) + , info2 = xmlparse(content new_info2) , active = edit_campsite.active where campsite_id = edit_campsite.campsite_id returning campsite_id; @@ -19,7 +23,7 @@ $$ language sql ; -revoke execute on function edit_campsite(integer, integer, text, boolean) from public; -grant execute on function edit_campsite(integer, integer, text, boolean) to admin; +revoke execute on function edit_campsite(integer, integer, text, text, text, boolean) from public; +grant execute on function edit_campsite(integer, integer, text, text, text, boolean) to admin; commit; diff --git a/deploy/edit_campsite@v1.sql b/deploy/edit_campsite@v1.sql new file mode 100644 index 0000000..bcaf2d8 --- /dev/null +++ b/deploy/edit_campsite@v1.sql @@ -0,0 +1,25 @@ +-- Deploy camper:edit_campsite to pg +-- requires: roles +-- requires: schema_camper +-- requires: campsite + +begin; + +set search_path to camper, public; + +create or replace function edit_campsite(campsite_id integer, campsite_type integer, new_label text, active boolean) returns integer as +$$ + update campsite + set label = edit_campsite.new_label + , campsite_type_id = edit_campsite.campsite_type + , active = edit_campsite.active + where campsite_id = edit_campsite.campsite_id + returning campsite_id; +$$ + language sql +; + +revoke execute on function edit_campsite(integer, integer, text, boolean) from public; +grant execute on function edit_campsite(integer, integer, text, boolean) to admin; + +commit; diff --git a/deploy/edit_campsite_feature.sql b/deploy/edit_campsite_feature.sql new file mode 100644 index 0000000..7c02f5a --- /dev/null +++ b/deploy/edit_campsite_feature.sql @@ -0,0 +1,25 @@ +-- Deploy camper:edit_campsite_feature to pg +-- requires: roles +-- requires: schema_camper +-- requires: campsite_feature + +begin; + +set search_path to camper, public; + +create or replace function edit_campsite_feature(feature_id integer, icon_name text, name text) returns integer as +$$ + update campsite_feature + set icon_name = edit_campsite_feature.icon_name + , name = edit_campsite_feature.name + where campsite_feature_id = feature_id + returning campsite_feature_id + ; +$$ + language sql +; + +revoke execute on function edit_campsite_feature(integer, text, text) from public; +grant execute on function edit_campsite_feature(integer, text, text) to admin; + +commit; diff --git a/deploy/order_campsite_carousel.sql b/deploy/order_campsite_carousel.sql new file mode 100644 index 0000000..1f6e851 --- /dev/null +++ b/deploy/order_campsite_carousel.sql @@ -0,0 +1,27 @@ +-- Deploy camper:order_campsite_carousel to pg +-- requires: roles +-- requires: campsite_carousel +-- requires: campsite + +begin; + +set search_path to camper, public; + +create or replace function order_campsite_carousel(label text, company_id integer, positions integer[]) returns void as +$$ + update campsite_carousel + set position = cast(temp.position as integer) + from unnest(positions) with ordinality as temp(media_id, position) + join campsite on campsite.label = order_campsite_carousel.label + and campsite.company_id = order_campsite_carousel.company_id + where campsite_carousel.campsite_id = campsite.campsite_id + and campsite_carousel.media_id = temp.media_id + ; +$$ + language sql +; + +revoke execute on function order_campsite_carousel(text, integer, integer[]) from public; +grant execute on function order_campsite_carousel(text, integer, integer[]) to admin; + +commit; diff --git a/deploy/order_campsite_features.sql b/deploy/order_campsite_features.sql new file mode 100644 index 0000000..ce8c123 --- /dev/null +++ b/deploy/order_campsite_features.sql @@ -0,0 +1,24 @@ +-- Deploy camper:order_campsite_features to pg +-- requires: roles +-- requires: schema_camper +-- requires: campsite_feature + +begin; + +set search_path to camper, public; + +create or replace function order_campsite_features(positions integer[]) returns void as +$$ + update campsite_feature + set position = cast(temp.position as integer) + from unnest(positions) with ordinality as temp(feature_id, position) + where campsite_feature_id = temp.feature_id + ; +$$ + language sql +; + +revoke execute on function order_campsite_features(integer[]) from public; +grant execute on function order_campsite_features(integer[]) to admin; + +commit; diff --git a/deploy/remove_campsite_carousel_slide.sql b/deploy/remove_campsite_carousel_slide.sql new file mode 100644 index 0000000..02c0491 --- /dev/null +++ b/deploy/remove_campsite_carousel_slide.sql @@ -0,0 +1,40 @@ +-- Deploy camper:remove_campsite_carousel_slide to pg +-- requires: roles +-- requires: schema_camper +-- requires: campsite_carousel +-- requires: campsite_carousel_i18n + +begin; + +set search_path to camper, public; + +create or replace function remove_campsite_carousel_slide(company_id integer, label text, media_id integer) returns void as +$$ +declare + csid integer; +begin + select campsite_id + into csid + from campsite + where campsite.label = remove_campsite_carousel_slide.label + and campsite.company_id = remove_campsite_carousel_slide.company_id + ; + + delete from campsite_carousel_i18n + where campsite_id = csid + and campsite_carousel_i18n.media_id = remove_campsite_carousel_slide.media_id + ; + + delete from campsite_carousel + where campsite_id = csid + and campsite_carousel.media_id = remove_campsite_carousel_slide.media_id + ; +end +$$ + language plpgsql +; + +revoke execute on function remove_campsite_carousel_slide(integer, text, integer) from public; +grant execute on function remove_campsite_carousel_slide(integer, text, integer) to admin; + +commit; diff --git a/deploy/remove_campsite_feature.sql b/deploy/remove_campsite_feature.sql new file mode 100644 index 0000000..a6768c8 --- /dev/null +++ b/deploy/remove_campsite_feature.sql @@ -0,0 +1,22 @@ +-- Deploy camper:remove_campsite_feature to pg +-- requires: roles +-- requires: schema_camper +-- requires: campsite_feature +-- requires: campsite_feature_i18n + +begin; + +set search_path to camper, public; + +create or replace function remove_campsite_feature(feature_id integer) returns void as +$$ + delete from campsite_feature_i18n where campsite_feature_id = feature_id; + delete from campsite_feature where campsite_feature_id = feature_id; +$$ + language sql +; + +revoke execute on function remove_campsite_feature(integer) from public; +grant execute on function remove_campsite_feature(integer) to admin; + +commit; diff --git a/deploy/translate_campsite.sql b/deploy/translate_campsite.sql new file mode 100644 index 0000000..e9d3453 --- /dev/null +++ b/deploy/translate_campsite.sql @@ -0,0 +1,26 @@ +-- Deploy camper:translate_campsite to pg +-- requires: roles +-- requires: schema_camper +-- requires: campsite_i18n + +begin; + +set search_path to camper, public; + +create or replace function translate_campsite(campsite_id integer, lang_tag text, info1 text, info2 text) returns void as +$$ + insert into campsite_i18n (campsite_id, lang_tag, info1, info2) + values (campsite_id, lang_tag, case trim(info1) when '' then null else xmlparse(content info1) end, case trim(info2) when '' then null else xmlparse(content info2) end) + on conflict (campsite_id, lang_tag) + do update + set info1 = excluded.info1 + , info2 = excluded.info2 + ; +$$ + language sql +; + +revoke execute on function translate_campsite(integer, text, text, text) from public; +grant execute on function translate_campsite(integer, text, text, text) to admin; + +commit; diff --git a/deploy/translate_campsite_carousel_slide.sql b/deploy/translate_campsite_carousel_slide.sql new file mode 100644 index 0000000..8960251 --- /dev/null +++ b/deploy/translate_campsite_carousel_slide.sql @@ -0,0 +1,28 @@ +-- Deploy camper:translate_campsite_carousel_slide to pg +-- requires: roles +-- requires: schema_camper +-- requires: campsite +-- requires: campsite_carousel_i18n + +begin; + +set search_path to camper, public; + +create or replace function translate_campsite_carousel_slide(company_id integer, label text, media_id integer, lang_tag text, caption text) returns void as +$$ + insert into campsite_carousel_i18n (campsite_id, media_id, lang_tag, caption) + select campsite_id, translate_campsite_carousel_slide.media_id, lang_tag, case trim(caption) when '' then null else caption end + from campsite + where label = translate_campsite_carousel_slide.label + and company_id = translate_campsite_carousel_slide.company_id + on conflict (campsite_id, media_id, lang_tag) do update + set caption = excluded.caption + ; +$$ + language sql +; + +revoke execute on function translate_campsite_carousel_slide(integer, text, integer, text, text) from public; +grant execute on function translate_campsite_carousel_slide(integer, text, integer, text, text) to admin; + +commit; diff --git a/deploy/translate_campsite_feature.sql b/deploy/translate_campsite_feature.sql new file mode 100644 index 0000000..0e0d51a --- /dev/null +++ b/deploy/translate_campsite_feature.sql @@ -0,0 +1,24 @@ +-- Deploy camper:translate_campsite_feature to pg +-- requires: roles +-- requires: schema_camper +-- requires: campsite_feature_i18n + +begin; + +set search_path to camper, public; + +create or replace function translate_campsite_feature(feature_id integer, lang_tag text, name text) returns void as +$$ + insert into campsite_feature_i18n (campsite_feature_id, lang_tag, name) + values (feature_id, lang_tag, case trim(name) when '' then null else name end) + on conflict (campsite_feature_id, lang_tag) do update + set name = excluded.name + ; +$$ + language sql +; + +revoke execute on function translate_campsite_feature(integer, text, text) from public; +grant execute on function translate_campsite_feature(integer, text, text) to admin; + +commit; diff --git a/pkg/campsite/admin.go b/pkg/campsite/admin.go index 5d57398..667cbde 100644 --- a/pkg/campsite/admin.go +++ b/pkg/campsite/admin.go @@ -9,6 +9,8 @@ import ( "context" "net/http" + "github.com/jackc/pgx/v4" + "dev.tandem.ws/tandem/camper/pkg/auth" "dev.tandem.ws/tandem/camper/pkg/campsite/types" "dev.tandem.ws/tandem/camper/pkg/database" @@ -37,7 +39,7 @@ func (h *AdminHandler) Handler(user *auth.User, company *auth.Company, conn *dat case "new": switch r.Method { case http.MethodGet: - f := newCampsiteForm(r.Context(), conn) + f := newCampsiteForm(r.Context(), conn, company) f.MustRender(w, r, user, company) default: httplib.MethodNotAllowed(w, r, http.MethodGet) @@ -54,7 +56,7 @@ func (h *AdminHandler) Handler(user *auth.User, company *auth.Company, conn *dat httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPost) } default: - f := newCampsiteForm(r.Context(), conn) + f := newCampsiteForm(r.Context(), conn, company) if err := f.FillFromDatabase(r.Context(), conn, company, head); err != nil { if database.ErrorIsNotFound(err) { http.NotFound(w, r) @@ -74,6 +76,10 @@ func (h *AdminHandler) Handler(user *auth.User, company *auth.Company, conn *dat default: httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut) } + case "slides": + h.carouselHandler(user, company, conn, f.Label.Val).ServeHTTP(w, r) + case "features": + h.featuresHandler(user, company, conn, f.Label.Val).ServeHTTP(w, r) default: http.NotFound(w, r) } @@ -133,17 +139,37 @@ func (page *campsiteIndex) MustRender(w http.ResponseWriter, r *http.Request, us } func addCampsite(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) { - f := newCampsiteForm(r.Context(), conn) + f := newCampsiteForm(r.Context(), conn, company) processCampsiteForm(w, r, user, company, conn, f, func(ctx context.Context, tx *database.Tx) error { - _, err := tx.AddCampsite(r.Context(), f.CampsiteType.String(), f.Label.Val) - return err + var err error + f.ID, err = tx.AddCampsite(ctx, f.CampsiteType.Int(), f.Label.Val, f.Info1[f.DefaultLang].Val, f.Info2[f.DefaultLang].Val) + if err != nil { + return err + } + return translateCampsite(ctx, tx, company, f) }) httplib.Redirect(w, r, "/admin/campsites", http.StatusSeeOther) } +func translateCampsite(ctx context.Context, tx *database.Tx, company *auth.Company, f *campsiteForm) error { + for lang := range company.Locales { + l := lang.String() + if l == f.DefaultLang { + continue + } + if err := tx.TranslateCampsite(ctx, f.ID, lang, f.Info1[l].Val, f.Info2[l].Val); err != nil { + return err + } + } + return nil +} + func editCampsite(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, f *campsiteForm) { processCampsiteForm(w, r, user, company, conn, f, func(ctx context.Context, tx *database.Tx) error { - return tx.EditCampsite(r.Context(), f.ID, f.CampsiteType.String(), f.Label.Val, f.Active.Checked) + if err := tx.EditCampsite(ctx, f.ID, f.CampsiteType.Int(), f.Label.Val, f.Info1[f.DefaultLang].Val, f.Info2[f.DefaultLang].Val, f.Active.Checked); err != nil { + return err + } + return translateCampsite(ctx, tx, company, f) }) httplib.Redirect(w, r, "/admin/campsites", http.StatusSeeOther) } @@ -166,16 +192,20 @@ func processCampsiteForm(w http.ResponseWriter, r *http.Request, user *auth.User } type campsiteForm struct { + DefaultLang string ID int CurrentLabel string Active *form.Checkbox CampsiteType *form.Select Label *form.Input + Info1 form.I18nInput + Info2 form.I18nInput } -func newCampsiteForm(ctx context.Context, conn *database.Conn) *campsiteForm { +func newCampsiteForm(ctx context.Context, conn *database.Conn, company *auth.Company) *campsiteForm { campsiteTypes := form.MustGetOptions(ctx, conn, "select campsite_type_id::text, name from campsite_type where active") return &campsiteForm{ + DefaultLang: company.DefaultLanguage.String(), Active: &form.Checkbox{ Name: "active", Checked: true, @@ -187,20 +217,45 @@ func newCampsiteForm(ctx context.Context, conn *database.Conn) *campsiteForm { Label: &form.Input{ Name: "label", }, + Info1: form.NewI18nInput(company.Locales, "info1"), + Info2: form.NewI18nInput(company.Locales, "info2"), } } func (f *campsiteForm) FillFromDatabase(ctx context.Context, conn *database.Conn, company *auth.Company, label string) error { f.CurrentLabel = label + var info1 database.RecordArray + var info2 database.RecordArray row := conn.QueryRow(ctx, ` select campsite_id , array[campsite_type_id::text] , label + , campsite.info1::text + , campsite.info2::text , active + , array_agg((lang_tag, i18n.info1::text)) + , array_agg((lang_tag, i18n.info2::text)) from campsite + left join campsite_i18n as i18n using (campsite_id) where company_id = $1 - and label = $2`, company.ID, label) - return row.Scan(&f.ID, &f.CampsiteType.Selected, &f.Label.Val, &f.Active.Checked) + and label = $2 + group by campsite_id + , campsite_type_id + , label + , campsite.info1::text + , campsite.info2::text + , active + `, pgx.QueryResultFormats{pgx.BinaryFormatCode}, company.ID, label) + if err := row.Scan(&f.ID, &f.CampsiteType.Selected, &f.Label.Val, &f.Info1[f.DefaultLang].Val, &f.Info2[f.DefaultLang].Val, &f.Active.Checked, &info1, &info2); err != nil { + return err + } + if err := f.Info1.FillArray(info1); err != nil { + return err + } + if err := f.Info2.FillArray(info2); err != nil { + return err + } + return nil } func (f *campsiteForm) Parse(r *http.Request) error { @@ -210,6 +265,8 @@ func (f *campsiteForm) Parse(r *http.Request) error { f.Active.FillValue(r) f.CampsiteType.FillValue(r) f.Label.FillValue(r) + f.Info1.FillValue(r) + f.Info2.FillValue(r) return nil } diff --git a/pkg/campsite/carousel.go b/pkg/campsite/carousel.go new file mode 100644 index 0000000..f961623 --- /dev/null +++ b/pkg/campsite/carousel.go @@ -0,0 +1,339 @@ +/* + * SPDX-FileCopyrightText: 2023 jordi fita mas + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package campsite + +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, label 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, label) + case http.MethodPost: + addSlide(w, r, user, company, conn, label) + default: + httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodGet) + } + case "new": + switch r.Method { + case http.MethodGet: + f := newSlideForm(company, label) + f.MustRender(w, r, user, company) + default: + httplib.MethodNotAllowed(w, r, http.MethodGet) + } + case "order": + switch r.Method { + case http.MethodPost: + orderCarousel(w, r, user, company, conn, label) + default: + httplib.MethodNotAllowed(w, r, http.MethodGet) + } + default: + mediaID, err := strconv.Atoi(head) + if err != nil { + http.NotFound(w, r) + return + } + f := newSlideForm(company, label) + if err := f.FillFromDatabase(r.Context(), conn, company, 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: + deleteSlide(w, r, user, company, conn, label, mediaID) + default: + httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut, http.MethodDelete) + } + default: + http.NotFound(w, r) + } + } + }) +} + +func serveCarouselIndex(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, label string) { + slides, err := collectSlideEntries(r.Context(), conn, company, label) + if err != nil { + panic(err) + } + page := &carouselIndex{ + Label: label, + Slides: slides, + } + page.MustRender(w, r, user, company) +} + +type carouselIndex struct { + Label 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, company *auth.Company, loc *locale.Locale, label string) []*carousel.Slide { + rows, err := conn.Query(ctx, ` + select coalesce(i18n.caption, slide.caption) as l10_caption + , media.path + from campsite_carousel as slide + join campsite using (campsite_id) + join media on media.media_id = slide.media_id + left join campsite_carousel_i18n as i18n + on i18n.campsite_id = slide.campsite_id + and i18n.media_id = slide.media_id + and lang_tag = $1 + where campsite.label = $2 + and campsite.company_id = $3 + order by slide.position, l10_caption + `, loc.Language, label, company.ID) + 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, company *auth.Company, label string) ([]*carousel.SlideEntry, error) { + rows, err := conn.Query(ctx, ` + select carousel.media_id + , media.path + , caption + from campsite_carousel as carousel + join campsite using (campsite_id) + join media on media.media_id = carousel.media_id + where campsite.label = $1 + and campsite.company_id = $2 + order by carousel.position, caption + `, label, company.ID) + if err != nil { + return nil, err + } + defer rows.Close() + + var slides []*carousel.SlideEntry + for rows.Next() { + slide := &carousel.SlideEntry{} + if err = rows.Scan(&slide.ID, &slide.Media, &slide.Caption); err != nil { + return nil, err + } + slides = append(slides, slide) + } + + return slides, nil +} + +func addSlide(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, label string) { + f := newSlideForm(company, label) + 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, tx *database.Tx) error { + if err := tx.AddCampsiteCarouselSlide(ctx, f.Label, company.ID, f.Media.Int(), f.Caption[f.DefaultLang].Val); err != nil { + return nil + } + for lang := range company.Locales { + l := lang.String() + if l == f.DefaultLang { + continue + } + if err := tx.TranslateCampsiteCarouselSlide(ctx, f.Label, company.ID, f.Media.Int(), lang, f.Caption[l].Val); err != nil { + return err + } + } + return nil + }) +} + +func deleteSlide(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, label string, mediaID int) { + if err := user.VerifyCSRFToken(r); err != nil { + http.Error(w, err.Error(), http.StatusForbidden) + return + } + if err := conn.RemoveCampsiteCarouselSlide(r.Context(), label, company.ID, mediaID); err != nil { + panic(err) + } + httplib.Redirect(w, r, "/admin/campsites/"+label+"/slides", http.StatusSeeOther) +} + +type slideForm struct { + DefaultLang string + Label string + MediaID int + Media *form.Media + Caption form.I18nInput +} + +func newSlideForm(company *auth.Company, label string) *slideForm { + return &slideForm{ + DefaultLang: company.DefaultLanguage.String(), + Label: label, + Media: &form.Media{ + Input: &form.Input{ + Name: "media", + }, + Label: locale.PgettextNoop("Slide image", "input"), + Prompt: locale.PgettextNoop("Set slide image", "action"), + }, + Caption: form.NewI18nInput(company.Locales, "caption"), + } +} + +func (f *slideForm) FillFromDatabase(ctx context.Context, conn *database.Conn, company *auth.Company, mediaID int) error { + f.MediaID = mediaID + var caption database.RecordArray + row := conn.QueryRow(ctx, ` + select carousel.caption + , carousel.media_id::text + , array_agg((lang_tag, i18n.caption)) + from campsite_carousel as carousel + left join campsite_carousel_i18n as i18n using (campsite_id, media_id) + join campsite using (campsite_id) + where campsite.label = $1 + and campsite.company_id = $2 + and carousel.media_id = $3 + group by carousel.caption + , carousel.media_id::text + `, pgx.QueryResultFormats{pgx.BinaryFormatCode}, f.Label, company.ID, mediaID) + if err := row.Scan(&f.Caption[f.DefaultLang].Val, &f.Media.Val, &caption); err != nil { + return err + } + if err := f.Caption.FillArray(caption); err != nil { + return err + } + return nil +} + +func (f *slideForm) process(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, act func(ctx context.Context, tx *database.Tx) error) { + if err := f.Parse(r); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + if err := user.VerifyCSRFToken(r); err != nil { + http.Error(w, err.Error(), http.StatusForbidden) + return + } + if ok, err := f.Valid(r.Context(), conn, user.Locale); err != nil { + panic(err) + } else if !ok { + if !httplib.IsHTMxRequest(r) { + w.WriteHeader(http.StatusUnprocessableEntity) + } + f.MustRender(w, r, user, company) + return + } + tx := conn.MustBegin(r.Context()) + if err := act(r.Context(), tx); err == nil { + if err := tx.Commit(r.Context()); err != nil { + panic(err) + } + } else { + if err := tx.Rollback(r.Context()); err != nil { + panic(err) + } + panic(err) + } + httplib.Redirect(w, r, "/admin/campsites/"+f.Label+"/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) +} + +func orderCarousel(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, label string) { + if err := r.ParseForm(); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + if err := user.VerifyCSRFToken(r); err != nil { + http.Error(w, err.Error(), http.StatusForbidden) + return + } + input := r.PostForm["media_id"] + if len(input) > 0 { + var ids []int + for _, s := range input { + if id, err := strconv.Atoi(s); err == nil { + ids = append(ids, id) + } else { + http.Error(w, err.Error(), http.StatusUnprocessableEntity) + return + } + } + if err := conn.OrderCampsiteCarousel(r.Context(), label, company.ID, ids); err != nil { + panic(err) + } + } + serveCarouselIndex(w, r, user, company, conn, label) +} diff --git a/pkg/campsite/feature.go b/pkg/campsite/feature.go new file mode 100644 index 0000000..995680b --- /dev/null +++ b/pkg/campsite/feature.go @@ -0,0 +1,304 @@ +/* + * SPDX-FileCopyrightText: 2023 jordi fita mas + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package campsite + +import ( + "context" + "net/http" + "strconv" + + "github.com/jackc/pgx/v4" + + "dev.tandem.ws/tandem/camper/pkg/auth" + "dev.tandem.ws/tandem/camper/pkg/database" + "dev.tandem.ws/tandem/camper/pkg/form" + httplib "dev.tandem.ws/tandem/camper/pkg/http" + "dev.tandem.ws/tandem/camper/pkg/locale" + "dev.tandem.ws/tandem/camper/pkg/template" +) + +func (h *AdminHandler) featuresHandler(user *auth.User, company *auth.Company, conn *database.Conn, label 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: + serveFeatureIndex(w, r, user, company, conn, label) + case http.MethodPost: + addFeature(w, r, user, company, conn, label) + default: + httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPost) + } + case "new": + switch r.Method { + case http.MethodGet: + f := newFeatureForm(r.Context(), company, conn, label) + f.MustRender(w, r, user, company) + default: + httplib.MethodNotAllowed(w, r, http.MethodGet) + } + case "order": + switch r.Method { + case http.MethodPost: + orderFeatures(w, r, user, company, conn, label) + default: + httplib.MethodNotAllowed(w, r, http.MethodPost) + } + default: + id, err := strconv.Atoi(head) + if err != nil { + http.NotFound(w, r) + return + } + f := newFeatureForm(r.Context(), company, conn, label) + if err := f.FillFromDatabase(r.Context(), conn, id); err != nil { + if database.ErrorIsNotFound(err) { + http.NotFound(w, r) + return + } + panic(err) + } + h.featureHandler(user, company, conn, f).ServeHTTP(w, r) + } + }) +} + +func (h *AdminHandler) featureHandler(user *auth.User, company *auth.Company, conn *database.Conn, f *featureForm) 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: + f.MustRender(w, r, user, company) + case http.MethodPut: + editFeature(w, r, user, company, conn, f) + case http.MethodDelete: + deleteFeature(w, r, user, conn, f.Label, f.ID) + default: + httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut, http.MethodDelete) + } + default: + http.NotFound(w, r) + } + }) +} + +func serveFeatureIndex(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, label string) { + features, err := collectFeatureEntries(r.Context(), conn, company, label) + if err != nil { + panic(err) + } + page := &featureIndex{ + Label: label, + Features: features, + } + page.MustRender(w, r, user, company) +} + +func collectFeatureEntries(ctx context.Context, conn *database.Conn, company *auth.Company, label string) ([]*featureEntry, error) { + rows, err := conn.Query(ctx, ` + select campsite_feature_id + , '/admin/campsites/' || campsite.label || '/features/' || campsite_feature_id + , feature.icon_name + , feature.name + from campsite_feature as feature + join campsite using (campsite_id) + where campsite.label = $1 + and campsite.company_id = $2 + order by feature.position, feature.name + `, label, company.ID) + if err != nil { + return nil, err + } + defer rows.Close() + + var features []*featureEntry + for rows.Next() { + feature := &featureEntry{} + if err = rows.Scan(&feature.ID, &feature.URL, &feature.Icon, &feature.Name); err != nil { + return nil, err + } + features = append(features, feature) + } + + return features, nil +} + +type featureEntry struct { + ID int + URL string + Icon string + Name string +} + +type featureIndex struct { + Label string + Features []*featureEntry +} + +func (page *featureIndex) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) { + template.MustRenderAdmin(w, r, user, company, "campsite/feature/index.gohtml", page) +} + +func addFeature(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, label string) { + f := newFeatureForm(r.Context(), company, conn, label) + processFeatureForm(w, r, user, company, conn, f, func(ctx context.Context, tx *database.Tx) error { + var err error + f.ID, err = tx.AddCampsiteFeature(ctx, label, company.ID, f.Icon.String(), f.Name[f.DefaultLang].Val) + if err != nil { + return err + } + return translateFeatures(ctx, tx, company, f) + }) +} + +func translateFeatures(ctx context.Context, tx *database.Tx, company *auth.Company, f *featureForm) error { + for lang := range company.Locales { + l := lang.String() + if l == f.DefaultLang { + continue + } + if err := tx.TranslateCampsiteFeature(ctx, f.ID, lang, f.Name[l].Val); err != nil { + return err + } + } + return nil +} + +func editFeature(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, f *featureForm) { + processFeatureForm(w, r, user, company, conn, f, func(ctx context.Context, tx *database.Tx) error { + if _, err := tx.EditCampsiteFeature(ctx, f.ID, f.Icon.String(), f.Name[f.DefaultLang].Val); err != nil { + return err + } + return translateFeatures(ctx, tx, company, f) + }) +} + +func processFeatureForm(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, f *featureForm, act func(ctx context.Context, tx *database.Tx) error) { + if ok, err := form.Handle(f, w, r, user); err != nil { + return + } else if !ok { + f.MustRender(w, r, user, company) + return + } + + tx := conn.MustBegin(r.Context()) + defer tx.Rollback(r.Context()) + if err := act(r.Context(), tx); err == nil { + tx.MustCommit(r.Context()) + } else { + panic(err) + } + httplib.Redirect(w, r, "/admin/campsites/"+f.Label+"/features", http.StatusSeeOther) +} + +func deleteFeature(w http.ResponseWriter, r *http.Request, user *auth.User, conn *database.Conn, label string, id int) { + if err := user.VerifyCSRFToken(r); err != nil { + http.Error(w, err.Error(), http.StatusForbidden) + return + } + if err := conn.RemoveCampsiteFeature(r.Context(), id); err != nil { + panic(err) + } + httplib.Redirect(w, r, "/admin/campsites/"+label+"/features", http.StatusSeeOther) +} + +type featureForm struct { + DefaultLang string + ID int + Label string + Icon *form.Select + Name form.I18nInput +} + +func newFeatureForm(ctx context.Context, company *auth.Company, conn *database.Conn, label string) *featureForm { + return &featureForm{ + DefaultLang: company.DefaultLanguage.String(), + Label: label, + Icon: &form.Select{ + Name: "icon", + Options: form.MustGetOptions(ctx, conn, "select icon_name, icon_name from icon order by 1"), + }, + Name: form.NewI18nInput(company.Locales, "name"), + } +} + +func (f *featureForm) FillFromDatabase(ctx context.Context, conn *database.Conn, id int) error { + f.ID = id + var name database.RecordArray + row := conn.QueryRow(ctx, ` + select array[icon_name] + , feature.name + , array_agg((lang_tag, i18n.name)) + from campsite_feature as feature + left join campsite_feature_i18n as i18n using (campsite_feature_id) + where campsite_feature_id = $1 + group by icon_name + , feature.name + `, pgx.QueryResultFormats{pgx.BinaryFormatCode}, id) + if err := row.Scan(&f.Icon.Selected, &f.Name[f.DefaultLang].Val, &name); err != nil { + return err + } + if err := f.Name.FillArray(name); err != nil { + return err + } + return nil +} + +func (f *featureForm) Parse(r *http.Request) error { + if err := r.ParseForm(); err != nil { + return err + } + f.Icon.FillValue(r) + f.Name.FillValue(r) + return nil +} + +func (f *featureForm) Valid(l *locale.Locale) bool { + v := form.NewValidator(l) + v.CheckSelectedOptions(f.Icon, l.GettextNoop("Selected icon is not valid.")) + if v.CheckRequired(f.Name[f.DefaultLang], l.GettextNoop("Name can not be empty.")) { + v.CheckMinLength(f.Name[f.DefaultLang], 1, l.GettextNoop("Name must have at least one letter.")) + } + return v.AllOK +} + +func (f *featureForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) { + template.MustRenderAdmin(w, r, user, company, "campsite/feature/form.gohtml", f) +} + +func orderFeatures(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, label string) { + if err := r.ParseForm(); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + if err := user.VerifyCSRFToken(r); err != nil { + http.Error(w, err.Error(), http.StatusForbidden) + return + } + input := r.PostForm["feature_id"] + if len(input) > 0 { + var ids []int + for _, s := range input { + if id, err := strconv.Atoi(s); err == nil { + ids = append(ids, id) + } else { + http.Error(w, err.Error(), http.StatusUnprocessableEntity) + return + } + } + if err := conn.OrderCampsiteFeatures(r.Context(), ids); err != nil { + panic(err) + } + } + serveFeatureIndex(w, r, user, company, conn, label) +} diff --git a/pkg/campsite/public.go b/pkg/campsite/public.go index 2b469d1..6b04068 100644 --- a/pkg/campsite/public.go +++ b/pkg/campsite/public.go @@ -6,13 +6,18 @@ package campsite import ( + "context" "net/http" "time" + "golang.org/x/text/language" + "dev.tandem.ws/tandem/camper/pkg/auth" "dev.tandem.ws/tandem/camper/pkg/campsite/types" + "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" "dev.tandem.ws/tandem/camper/pkg/season" "dev.tandem.ws/tandem/camper/pkg/template" ) @@ -38,7 +43,26 @@ func (h *PublicHandler) Handler(user *auth.User, company *auth.Company, conn *da case "calendar": h.calendarHandler(user, company, conn).ServeHTTP(w, r) default: - http.NotFound(w, r) + page, err := newPublicPage(r.Context(), company, conn, user.Locale, head) + if database.ErrorIsNotFound(err) { + http.NotFound(w, r) + return + } else if err != nil { + panic(err) + } + + head, r.URL.Path = httplib.ShiftPath(r.URL.Path) + switch head { + case "": + switch r.Method { + case http.MethodGet: + page.MustRender(w, r, user, company, conn) + default: + httplib.MethodNotAllowed(w, r, http.MethodGet) + } + default: + http.NotFound(w, r) + } } }) } @@ -67,3 +91,77 @@ func (h *PublicHandler) calendarHandler(user *auth.User, company *auth.Company, } }) } + +type publicPage struct { + *template.PublicPage + TypeName string + Label string + Carousel []*carousel.Slide + Features []*feature + Info []string +} + +func newPublicPage(ctx context.Context, company *auth.Company, conn *database.Conn, loc *locale.Locale, label string) (*publicPage, error) { + page := &publicPage{ + PublicPage: template.NewPublicPage(), + Label: label, + Carousel: mustCollectSlides(ctx, conn, company, loc, label), + } + row := conn.QueryRow(ctx, ` + select coalesce(type_i18n.name, campsite_type.name) as l10n_type_name + , array[coalesce(campsite_i18n.info1, campsite.info1)::text, coalesce(campsite_i18n.info2, campsite.info2)::text] as info + from campsite + join campsite_type using (campsite_type_id) + left join campsite_type_i18n as type_i18n on campsite_type.campsite_type_id = type_i18n.campsite_type_id and type_i18n.lang_tag = $1 + left join campsite_i18n on campsite.campsite_id = campsite_i18n.campsite_id and campsite_i18n.lang_tag = $1 + where campsite_type.company_id = $2 + and label = $3 + and campsite.active + `, loc.Language, company.ID, label) + if err := row.Scan(&page.TypeName, &page.Info); err != nil { + return nil, err + } + var err error + page.Features, err = collectFeatures(ctx, conn, company, loc.Language, label) + if err != nil { + return nil, err + } + + return page, nil +} + +func (p *publicPage) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) { + p.Setup(r, user, company, conn) + template.MustRenderPublic(w, r, user, company, "campsite/page.gohtml", p) +} + +type feature struct { + Icon string + Name string +} + +func collectFeatures(ctx context.Context, conn *database.Conn, company *auth.Company, language language.Tag, label string) ([]*feature, error) { + rows, err := conn.Query(ctx, ` + select feature.icon_name + , coalesce(i18n.name, feature.name) as l10n_name + from campsite_feature as feature + join campsite using (campsite_id) + left join campsite_feature_i18n as i18n on feature.campsite_feature_id = i18n.campsite_feature_id and i18n.lang_tag = $1 + where campsite.label = $2 + and campsite.company_id = $3 + order by feature.position + `, language, label, company.ID) + if err != nil { + return nil, err + } + + var features []*feature + for rows.Next() { + f := &feature{} + if err = rows.Scan(&f.Icon, &f.Name); err != nil { + return nil, err + } + features = append(features, f) + } + return features, nil +} diff --git a/pkg/campsite/types/carousel.go b/pkg/campsite/types/carousel.go index 04c1aa1..94d70df 100644 --- a/pkg/campsite/types/carousel.go +++ b/pkg/campsite/types/carousel.go @@ -106,7 +106,7 @@ type carouselIndex struct { } 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) + template.MustRenderAdmin(w, r, user, company, "campsite/type/carousel/index.gohtml", page) } func mustCollectSlides(ctx context.Context, conn *database.Conn, loc *locale.Locale, typeSlug string) []*carousel.Slide { @@ -305,7 +305,7 @@ func (f *slideForm) Valid(ctx context.Context, conn *database.Conn, l *locale.Lo } 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) + template.MustRenderAdmin(w, r, user, company, "campsite/type/carousel/form.gohtml", f) } func orderCarousel(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, typeSlug string) { diff --git a/pkg/campsite/types/feature.go b/pkg/campsite/types/feature.go index a0fff7c..5743408 100644 --- a/pkg/campsite/types/feature.go +++ b/pkg/campsite/types/feature.go @@ -143,7 +143,7 @@ type featureIndex struct { } func (page *featureIndex) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) { - template.MustRenderAdmin(w, r, user, company, "campsite/feature/index.gohtml", page) + template.MustRenderAdmin(w, r, user, company, "campsite/type/feature/index.gohtml", page) } func addFeature(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, typeSlug string) { @@ -263,7 +263,7 @@ func (f *featureForm) Valid(l *locale.Locale) bool { } func (f *featureForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) { - template.MustRenderAdmin(w, r, user, company, "campsite/feature/form.gohtml", f) + template.MustRenderAdmin(w, r, user, company, "campsite/type/feature/form.gohtml", f) } func orderFeatures(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, typeSlug string) { diff --git a/pkg/campsite/types/option.go b/pkg/campsite/types/option.go index 68744a9..19679c6 100644 --- a/pkg/campsite/types/option.go +++ b/pkg/campsite/types/option.go @@ -150,7 +150,7 @@ type optionIndex struct { } func (page *optionIndex) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) { - template.MustRenderAdmin(w, r, user, company, "campsite/option/index.gohtml", page) + template.MustRenderAdmin(w, r, user, company, "campsite/type/option/index.gohtml", page) } func addOption(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, typeSlug string) { @@ -381,7 +381,7 @@ func (f *optionForm) Valid(l *locale.Locale) bool { } func (f *optionForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) { - template.MustRenderAdmin(w, r, user, company, "campsite/option/form.gohtml", f) + template.MustRenderAdmin(w, r, user, company, "campsite/type/option/form.gohtml", f) } func orderOptions(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, typeSlug string) { diff --git a/pkg/database/funcs.go b/pkg/database/funcs.go index e2f8f71..ff56e58 100644 --- a/pkg/database/funcs.go +++ b/pkg/database/funcs.go @@ -11,12 +11,60 @@ import ( "golang.org/x/text/language" ) -func (tx *Tx) AddCampsite(ctx context.Context, typeSlug string, label string) (int, error) { - return tx.GetInt(ctx, "select add_campsite($1, $2)", typeSlug, label) +func (tx *Tx) AddCampsite(ctx context.Context, typeID int, label string, info1 string, info2 string) (int, error) { + return tx.GetInt(ctx, "select add_campsite($1, $2, $3, $4)", typeID, label, info1, info2) } -func (tx *Tx) EditCampsite(ctx context.Context, id int, typeSlug string, label string, active bool) error { - _, err := tx.Exec(ctx, "select edit_campsite($1, $2, $3, $4)", id, typeSlug, label, active) +func (tx *Tx) EditCampsite(ctx context.Context, id int, typeID int, label string, info1 string, info2 string, active bool) error { + _, err := tx.Exec(ctx, "select edit_campsite($1, $2, $3, $4, $5, $6)", id, typeID, label, info1, info2, active) + return err +} + +func (tx *Tx) TranslateCampsite(ctx context.Context, id int, langTag language.Tag, info1 string, info2 string) error { + _, err := tx.Exec(ctx, "select translate_campsite($1, $2, $3, $4)", id, langTag, info1, info2) + return err +} + +func (tx *Tx) AddCampsiteCarouselSlide(ctx context.Context, label string, companyID int, mediaID int, caption string) error { + _, err := tx.Exec(ctx, "select add_campsite_carousel_slide($1, $2, $3, $4)", companyID, label, mediaID, caption) + return err +} + +func (tx *Tx) TranslateCampsiteCarouselSlide(ctx context.Context, label string, companyID int, mediaID int, langTag language.Tag, caption string) error { + _, err := tx.Exec(ctx, "select translate_campsite_carousel_slide($1, $2, $3, $4, $5)", companyID, label, mediaID, langTag, caption) + return err +} + +func (c *Conn) RemoveCampsiteCarouselSlide(ctx context.Context, label string, companyID int, mediaID int) error { + _, err := c.Exec(ctx, "select remove_campsite_carousel_slide($1, $2, $3)", companyID, label, mediaID) + return err +} + +func (c *Conn) OrderCampsiteCarousel(ctx context.Context, label string, companyID int, mediaIDs []int) error { + _, err := c.Exec(ctx, "select order_campsite_carousel($1, $2, $3)", companyID, label, mediaIDs) + return err +} + +func (tx *Tx) AddCampsiteFeature(ctx context.Context, label string, companyID int, iconName string, name string) (int, error) { + return tx.GetInt(ctx, "select add_campsite_feature($1, $2, $3, $4)", companyID, label, iconName, name) +} + +func (tx *Tx) EditCampsiteFeature(ctx context.Context, id int, iconName string, name string) (int, error) { + return tx.GetInt(ctx, "select edit_campsite_feature($1, $2, $3)", id, iconName, name) +} + +func (tx *Tx) TranslateCampsiteFeature(ctx context.Context, id int, langTag language.Tag, name string) error { + _, err := tx.Exec(ctx, "select translate_campsite_feature($1, $2, $3)", id, langTag, name) + return err +} + +func (c *Conn) OrderCampsiteFeatures(ctx context.Context, ids []int) error { + _, err := c.Exec(ctx, "select order_campsite_features($1)", ids) + return err +} + +func (c *Conn) RemoveCampsiteFeature(ctx context.Context, id int) error { + _, err := c.Exec(ctx, "select remove_campsite_feature($1)", id) return err } diff --git a/pkg/form/select.go b/pkg/form/select.go index 03e0492..03ff0c4 100644 --- a/pkg/form/select.go +++ b/pkg/form/select.go @@ -9,6 +9,7 @@ import ( "context" "database/sql/driver" "net/http" + "strconv" "dev.tandem.ws/tandem/camper/pkg/database" ) @@ -35,6 +36,14 @@ func (s *Select) String() string { return s.Selected[0] } +func (s *Select) Int() int { + i, err := strconv.Atoi(s.String()) + if err != nil { + panic(err) + } + return i +} + func (s *Select) FillValue(r *http.Request) { s.Selected = r.Form[s.Name] } diff --git a/po/ca.po b/po/ca.po index b15eaad..0f0c298 100644 --- a/po/ca.po +++ b/po/ca.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: camper\n" "Report-Msgid-Bugs-To: jordi@tandem.blog\n" -"POT-Creation-Date: 2024-01-24 11:14+0100\n" +"POT-Creation-Date: 2024-01-26 21:20+0100\n" "PO-Revision-Date: 2023-07-22 23:45+0200\n" "Last-Translator: jordi fita mas \n" "Language-Team: Catalan \n" @@ -129,8 +129,8 @@ msgid "Calendar" msgstr "Calendari" #: web/templates/public/campsite/type.gohtml:73 -#: web/templates/admin/campsite/option/form.gohtml:70 #: web/templates/admin/campsite/type/form.gohtml:109 +#: web/templates/admin/campsite/type/option/form.gohtml:70 msgctxt "title" msgid "Prices" msgstr "Preus" @@ -165,6 +165,7 @@ msgid "No dogs allowed." msgstr "No es permeten gossos." #: web/templates/public/campsite/type.gohtml:112 +#: web/templates/public/campsite/page.gohtml:39 msgctxt "title" msgid "Features" msgstr "Característiques" @@ -398,11 +399,15 @@ msgstr "Menú" #: web/templates/admin/campsite/carousel/form.gohtml:16 #: web/templates/admin/campsite/carousel/index.gohtml:10 #: web/templates/admin/campsite/form.gohtml:15 -#: web/templates/admin/campsite/option/form.gohtml:16 -#: web/templates/admin/campsite/option/index.gohtml:10 #: web/templates/admin/campsite/index.gohtml:6 #: web/templates/admin/campsite/index.gohtml:15 +#: web/templates/admin/campsite/type/feature/form.gohtml:16 +#: web/templates/admin/campsite/type/feature/index.gohtml:10 +#: web/templates/admin/campsite/type/carousel/form.gohtml:16 +#: web/templates/admin/campsite/type/carousel/index.gohtml:10 #: web/templates/admin/campsite/type/form.gohtml:15 +#: web/templates/admin/campsite/type/option/form.gohtml:16 +#: web/templates/admin/campsite/type/option/index.gohtml:10 #: web/templates/admin/campsite/type/index.gohtml:10 #: web/templates/admin/layout.gohtml:46 web/templates/admin/layout.gohtml:92 msgctxt "title" @@ -449,9 +454,10 @@ msgid "Slug" msgstr "Àlies" #: web/templates/admin/legal/form.gohtml:50 -#: web/templates/admin/campsite/feature/form.gohtml:59 -#: web/templates/admin/campsite/option/form.gohtml:41 +#: web/templates/admin/campsite/feature/form.gohtml:50 +#: web/templates/admin/campsite/type/feature/form.gohtml:59 #: web/templates/admin/campsite/type/form.gohtml:51 +#: web/templates/admin/campsite/type/option/form.gohtml:41 #: web/templates/admin/season/form.gohtml:50 #: web/templates/admin/services/form.gohtml:53 #: web/templates/admin/profile.gohtml:29 @@ -467,11 +473,13 @@ msgstr "Contingut" #: web/templates/admin/legal/form.gohtml:88 #: web/templates/admin/carousel/form.gohtml:55 -#: web/templates/admin/campsite/feature/form.gohtml:74 -#: web/templates/admin/campsite/carousel/form.gohtml:59 -#: web/templates/admin/campsite/form.gohtml:74 -#: web/templates/admin/campsite/option/form.gohtml:90 +#: web/templates/admin/campsite/feature/form.gohtml:65 +#: web/templates/admin/campsite/carousel/form.gohtml:50 +#: web/templates/admin/campsite/form.gohtml:92 +#: web/templates/admin/campsite/type/feature/form.gohtml:74 +#: web/templates/admin/campsite/type/carousel/form.gohtml:59 #: web/templates/admin/campsite/type/form.gohtml:202 +#: web/templates/admin/campsite/type/option/form.gohtml:90 #: web/templates/admin/season/form.gohtml:73 #: web/templates/admin/services/form.gohtml:81 #: web/templates/admin/surroundings/form.gohtml:69 @@ -484,11 +492,13 @@ msgstr "Actualitza" #: web/templates/admin/legal/form.gohtml:90 #: web/templates/admin/carousel/form.gohtml:57 -#: web/templates/admin/campsite/feature/form.gohtml:76 -#: web/templates/admin/campsite/carousel/form.gohtml:61 -#: web/templates/admin/campsite/form.gohtml:76 -#: web/templates/admin/campsite/option/form.gohtml:92 +#: web/templates/admin/campsite/feature/form.gohtml:67 +#: web/templates/admin/campsite/carousel/form.gohtml:52 +#: web/templates/admin/campsite/form.gohtml:94 +#: web/templates/admin/campsite/type/feature/form.gohtml:76 +#: web/templates/admin/campsite/type/carousel/form.gohtml:61 #: web/templates/admin/campsite/type/form.gohtml:204 +#: web/templates/admin/campsite/type/option/form.gohtml:92 #: web/templates/admin/season/form.gohtml:75 #: web/templates/admin/services/form.gohtml:83 #: web/templates/admin/surroundings/form.gohtml:71 @@ -502,8 +512,9 @@ msgid "Add Legal Text" msgstr "Afegeix text legal" #: web/templates/admin/legal/index.gohtml:20 -#: web/templates/admin/campsite/feature/index.gohtml:31 -#: web/templates/admin/campsite/option/index.gohtml:30 +#: web/templates/admin/campsite/feature/index.gohtml:30 +#: web/templates/admin/campsite/type/feature/index.gohtml:31 +#: web/templates/admin/campsite/type/option/index.gohtml:30 #: web/templates/admin/campsite/type/index.gohtml:29 #: web/templates/admin/season/index.gohtml:29 #: web/templates/admin/user/index.gohtml:20 @@ -529,7 +540,8 @@ msgid "New Carousel Slide" msgstr "Nova diapositiva del carrusel" #: web/templates/admin/carousel/form.gohtml:40 -#: web/templates/admin/campsite/carousel/form.gohtml:44 +#: web/templates/admin/campsite/carousel/form.gohtml:35 +#: web/templates/admin/campsite/type/carousel/form.gohtml:44 msgctxt "input" msgid "Caption" msgstr "Llegenda" @@ -562,98 +574,38 @@ msgid "Save changes" msgstr "Desa els canvis" #: web/templates/admin/campsite/feature/form.gohtml:8 -#: web/templates/admin/campsite/feature/form.gohtml:32 msgctxt "title" -msgid "Edit Campsite Type Feature" -msgstr "Edició de les característiques del tipus d’allotjament" +msgid "Edit Campsite Feature" +msgstr "Edició de les característiques de l’allotjament" #: web/templates/admin/campsite/feature/form.gohtml:10 -#: web/templates/admin/campsite/feature/form.gohtml:34 msgctxt "title" -msgid "New Campsite Type Feature" -msgstr "Nova característica de tipus d’allotjament" +msgid "New Campsite Feature" +msgstr "Nova característica de l’allotjament" #: web/templates/admin/campsite/feature/form.gohtml:17 -#: web/templates/admin/campsite/feature/index.gohtml:11 -#: web/templates/admin/campsite/carousel/form.gohtml:17 -#: web/templates/admin/campsite/carousel/index.gohtml:11 -#: web/templates/admin/campsite/option/form.gohtml:17 -#: web/templates/admin/campsite/option/index.gohtml:11 -#: web/templates/admin/campsite/type/form.gohtml:16 -#: web/templates/admin/campsite/type/index.gohtml:6 -#: web/templates/admin/campsite/type/index.gohtml:16 -#: web/templates/admin/layout.gohtml:43 -msgctxt "title" -msgid "Campsite Types" -msgstr "Tipus d’allotjaments" - -#: web/templates/admin/campsite/feature/form.gohtml:18 #: web/templates/admin/campsite/feature/index.gohtml:6 -#: web/templates/admin/campsite/feature/index.gohtml:17 msgctxt "title" -msgid "Campsite Type Features" -msgstr "Característiques del tipus d’allotjaments" +msgid "Campsite Features" +msgstr "Característiques de l’allotjament" -#: web/templates/admin/campsite/feature/form.gohtml:41 +#: web/templates/admin/campsite/feature/form.gohtml:32 +#: web/templates/admin/campsite/type/feature/form.gohtml:41 #: web/templates/admin/services/form.gohtml:35 msgctxt "input" msgid "Icon" msgstr "Icona" -#: web/templates/admin/campsite/feature/index.gohtml:16 +#: web/templates/admin/campsite/feature/index.gohtml:15 +#: web/templates/admin/campsite/type/feature/index.gohtml:16 msgctxt "action" msgid "Add Feature" msgstr "Afegeix característica" -#: web/templates/admin/campsite/feature/index.gohtml:48 -msgid "No campsite type features added yet." -msgstr "No s’ha afegit cap característica al tipus d’allotjament encara." - -#: web/templates/admin/campsite/carousel/form.gohtml:8 -#: web/templates/admin/campsite/carousel/form.gohtml:32 -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:34 -msgctxt "title" -msgid "New Campsite Type Carousel Slide" -msgstr "Nova diapositiva del carrusel del tipus d’allotjament" - -#: web/templates/admin/campsite/carousel/form.gohtml:18 -#: web/templates/admin/campsite/carousel/index.gohtml:6 -#: web/templates/admin/campsite/carousel/index.gohtml:16 -msgctxt "title" -msgid "Campsite Type Carousel" -msgstr "Carrusel del tipus d’allotjament" - -#: web/templates/admin/campsite/carousel/index.gohtml:17 -#: web/templates/admin/services/index.gohtml:15 -#: web/templates/admin/home/index.gohtml:84 -msgctxt "action" -msgid "Add slide" -msgstr "Afegeix diapositiva" - -#: web/templates/admin/campsite/carousel/index.gohtml:30 -#: web/templates/admin/services/index.gohtml:28 -#: web/templates/admin/surroundings/index.gohtml:82 -#: web/templates/admin/home/index.gohtml:52 -#: web/templates/admin/home/index.gohtml:97 -msgctxt "header" -msgid "Image" -msgstr "Imatge" - +#: web/templates/admin/campsite/feature/index.gohtml:31 #: web/templates/admin/campsite/carousel/index.gohtml:31 -#: web/templates/admin/services/index.gohtml:29 -#: web/templates/admin/home/index.gohtml:53 -#: web/templates/admin/home/index.gohtml:98 -msgctxt "header" -msgid "Caption" -msgstr "Llegenda" - -#: web/templates/admin/campsite/carousel/index.gohtml:32 -#: web/templates/admin/campsite/option/index.gohtml:31 +#: web/templates/admin/campsite/type/carousel/index.gohtml:32 +#: web/templates/admin/campsite/type/option/index.gohtml:31 #: web/templates/admin/services/index.gohtml:30 #: web/templates/admin/services/index.gohtml:75 #: web/templates/admin/user/index.gohtml:23 @@ -664,14 +616,15 @@ msgctxt "header" msgid "Actions" msgstr "Accions" -#: web/templates/admin/campsite/carousel/index.gohtml:36 -#: web/templates/admin/services/index.gohtml:34 -#: web/templates/admin/home/index.gohtml:103 -msgid "Are you sure you wish to delete this slide?" -msgstr "Esteu segur de voler esborrar aquesta diapositiva?" +#: web/templates/admin/campsite/feature/index.gohtml:35 +#: web/templates/admin/campsite/type/option/index.gohtml:35 +msgid "Are you sure you wish to delete this option?" +msgstr "Esteu segur de voler esborrar aquesta opció?" -#: web/templates/admin/campsite/carousel/index.gohtml:50 -#: web/templates/admin/campsite/option/index.gohtml:47 +#: web/templates/admin/campsite/feature/index.gohtml:47 +#: web/templates/admin/campsite/carousel/index.gohtml:49 +#: web/templates/admin/campsite/type/carousel/index.gohtml:50 +#: web/templates/admin/campsite/type/option/index.gohtml:47 #: web/templates/admin/services/index.gohtml:47 #: web/templates/admin/services/index.gohtml:91 #: web/templates/admin/user/index.gohtml:37 @@ -683,125 +636,220 @@ msgctxt "action" msgid "Delete" msgstr "Esborra" -#: web/templates/admin/campsite/carousel/index.gohtml:59 +#: web/templates/admin/campsite/feature/index.gohtml:56 +msgid "No campsite features added yet." +msgstr "No s’ha afegit cap característica a l’allotjament encara." + +#: web/templates/admin/campsite/carousel/form.gohtml:8 +msgctxt "title" +msgid "Edit Campsite Carousel Slide" +msgstr "Edició de la diapositiva del carrusel de l’allotjament" + +#: web/templates/admin/campsite/carousel/form.gohtml:10 +msgctxt "title" +msgid "New Campsite Carousel Slide" +msgstr "Nova diapositiva del carrusel de l’allotjament" + +#: web/templates/admin/campsite/carousel/form.gohtml:17 +#: web/templates/admin/campsite/carousel/index.gohtml:6 +msgctxt "title" +msgid "Campsite Carousel" +msgstr "Carrusel de l’allotjament" + +#: web/templates/admin/campsite/carousel/index.gohtml:16 +#: web/templates/admin/campsite/type/carousel/index.gohtml:17 +#: web/templates/admin/services/index.gohtml:15 +#: web/templates/admin/home/index.gohtml:84 +msgctxt "action" +msgid "Add slide" +msgstr "Afegeix diapositiva" + +#: web/templates/admin/campsite/carousel/index.gohtml:29 +#: web/templates/admin/campsite/type/carousel/index.gohtml:30 +#: web/templates/admin/services/index.gohtml:28 +#: web/templates/admin/surroundings/index.gohtml:82 +#: web/templates/admin/home/index.gohtml:52 +#: web/templates/admin/home/index.gohtml:97 +msgctxt "header" +msgid "Image" +msgstr "Imatge" + +#: web/templates/admin/campsite/carousel/index.gohtml:30 +#: web/templates/admin/campsite/type/carousel/index.gohtml:31 +#: web/templates/admin/services/index.gohtml:29 +#: web/templates/admin/home/index.gohtml:53 +#: web/templates/admin/home/index.gohtml:98 +msgctxt "header" +msgid "Caption" +msgstr "Llegenda" + +#: web/templates/admin/campsite/carousel/index.gohtml:35 +#: web/templates/admin/campsite/type/carousel/index.gohtml:36 +#: web/templates/admin/services/index.gohtml:34 +#: web/templates/admin/home/index.gohtml:103 +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:58 +#: web/templates/admin/campsite/type/carousel/index.gohtml:59 #: web/templates/admin/services/index.gohtml:56 #: web/templates/admin/home/index.gohtml:125 msgid "No slides added yet." msgstr "No s’ha afegit cap diapositiva encara." #: web/templates/admin/campsite/form.gohtml:8 -#: web/templates/admin/campsite/form.gohtml:29 msgctxt "title" msgid "Edit Campsite" msgstr "Edició de l’allotjament" #: web/templates/admin/campsite/form.gohtml:10 -#: web/templates/admin/campsite/form.gohtml:31 msgctxt "title" msgid "New Campsite" msgstr "Nou allotjament" -#: web/templates/admin/campsite/form.gohtml:41 -#: web/templates/admin/campsite/index.gohtml:23 +#: web/templates/admin/campsite/form.gohtml:33 +#: web/templates/admin/campsite/index.gohtml:27 msgctxt "campsite" msgid "Active" msgstr "Actiu" -#: web/templates/admin/campsite/form.gohtml:50 +#: web/templates/admin/campsite/form.gohtml:42 msgctxt "input" msgid "Campsite Type" msgstr "Tipus d’allotjament" -#: web/templates/admin/campsite/form.gohtml:55 +#: web/templates/admin/campsite/form.gohtml:47 msgid "Select campsite type" msgstr "Escolliu un tipus d’allotjament" -#: web/templates/admin/campsite/form.gohtml:64 +#: web/templates/admin/campsite/form.gohtml:56 msgctxt "input" msgid "Label" msgstr "Etiqueta" -#: web/templates/admin/campsite/option/form.gohtml:8 -#: web/templates/admin/campsite/option/form.gohtml:32 -msgctxt "title" -msgid "Edit Campsite Type Option" -msgstr "Edició de l’opció del tipus d’allotjament" - -#: web/templates/admin/campsite/option/form.gohtml:10 -#: web/templates/admin/campsite/option/form.gohtml:34 -msgctxt "title" -msgid "New Campsite Type Option" -msgstr "Nova opció del tipus d’allotjament" - -#: web/templates/admin/campsite/option/form.gohtml:18 -#: web/templates/admin/campsite/option/index.gohtml:6 -#: web/templates/admin/campsite/option/index.gohtml:17 -msgctxt "title" -msgid "Campsite Type Options" -msgstr "Opcions del tipus d’allotjament" - -#: web/templates/admin/campsite/option/form.gohtml:54 +#: web/templates/admin/campsite/form.gohtml:64 msgctxt "input" -msgid "Minimum" -msgstr "Mínim" +msgid "Info (First Column)" +msgstr "Informació (primera columna)" -#: web/templates/admin/campsite/option/form.gohtml:62 +#: web/templates/admin/campsite/form.gohtml:77 msgctxt "input" -msgid "Maximum" -msgstr "Màxim" - -#: web/templates/admin/campsite/option/form.gohtml:76 -#: web/templates/admin/campsite/type/form.gohtml:115 -msgctxt "input" -msgid "Price per night" -msgstr "Preu per nit" - -#: web/templates/admin/campsite/option/index.gohtml:16 -msgctxt "action" -msgid "Add Option" -msgstr "Afegeix opció" - -#: web/templates/admin/campsite/option/index.gohtml:35 -msgid "Are you sure you wish to delete this option?" -msgstr "Esteu segur de voler esborrar aquesta opció?" - -#: web/templates/admin/campsite/option/index.gohtml:56 -msgid "No campsite type options added yet." -msgstr "No s’ha afegit cap opció al tipus d’allotjament encara." +msgid "Info (Second Column)" +msgstr "Informació (segona columna)" #: web/templates/admin/campsite/index.gohtml:14 msgctxt "action" msgid "Add Campsite" msgstr "Afegeix allotjament" -#: web/templates/admin/campsite/index.gohtml:21 +#: web/templates/admin/campsite/index.gohtml:23 msgctxt "header" msgid "Label" msgstr "Etiqueta" -#: web/templates/admin/campsite/index.gohtml:22 +#: web/templates/admin/campsite/index.gohtml:24 msgctxt "header" msgid "Type" msgstr "Tipus" -#: web/templates/admin/campsite/index.gohtml:31 +#: web/templates/admin/campsite/index.gohtml:25 +#: web/templates/admin/campsite/type/index.gohtml:30 +msgctxt "header" +msgid "Features" +msgstr "Característiques" + +#: web/templates/admin/campsite/index.gohtml:26 +#: web/templates/admin/campsite/type/index.gohtml:32 +msgctxt "header" +msgid "Carousel" +msgstr "Carrusel" + +#: web/templates/admin/campsite/index.gohtml:36 +#: web/templates/admin/campsite/type/index.gohtml:45 +msgctxt "action" +msgid "Edit Features" +msgstr "Edita les característiques" + +#: web/templates/admin/campsite/index.gohtml:39 +#: web/templates/admin/campsite/type/index.gohtml:51 +msgctxt "action" +msgid "Edit Carousel" +msgstr "Edita el carrusel" + +#: web/templates/admin/campsite/index.gohtml:41 #: web/templates/admin/campsite/type/index.gohtml:53 #: web/templates/admin/season/index.gohtml:44 #: web/templates/admin/user/login-attempts.gohtml:31 msgid "Yes" msgstr "Sí" -#: web/templates/admin/campsite/index.gohtml:31 +#: web/templates/admin/campsite/index.gohtml:41 #: web/templates/admin/campsite/type/index.gohtml:53 #: web/templates/admin/season/index.gohtml:44 #: web/templates/admin/user/login-attempts.gohtml:31 msgid "No" msgstr "No" -#: web/templates/admin/campsite/index.gohtml:37 +#: web/templates/admin/campsite/index.gohtml:47 msgid "No campsites added yet." msgstr "No s’ha afegit cap allotjament encara." +#: web/templates/admin/campsite/type/feature/form.gohtml:8 +#: web/templates/admin/campsite/type/feature/form.gohtml:32 +msgctxt "title" +msgid "Edit Campsite Type Feature" +msgstr "Edició de les característiques del tipus d’allotjament" + +#: web/templates/admin/campsite/type/feature/form.gohtml:10 +#: web/templates/admin/campsite/type/feature/form.gohtml:34 +msgctxt "title" +msgid "New Campsite Type Feature" +msgstr "Nova característica de tipus d’allotjament" + +#: web/templates/admin/campsite/type/feature/form.gohtml:17 +#: web/templates/admin/campsite/type/feature/index.gohtml:11 +#: web/templates/admin/campsite/type/carousel/form.gohtml:17 +#: web/templates/admin/campsite/type/carousel/index.gohtml:11 +#: web/templates/admin/campsite/type/form.gohtml:16 +#: web/templates/admin/campsite/type/option/form.gohtml:17 +#: web/templates/admin/campsite/type/option/index.gohtml:11 +#: web/templates/admin/campsite/type/index.gohtml:6 +#: web/templates/admin/campsite/type/index.gohtml:16 +#: web/templates/admin/layout.gohtml:43 +msgctxt "title" +msgid "Campsite Types" +msgstr "Tipus d’allotjaments" + +#: web/templates/admin/campsite/type/feature/form.gohtml:18 +#: web/templates/admin/campsite/type/feature/index.gohtml:6 +#: web/templates/admin/campsite/type/feature/index.gohtml:17 +msgctxt "title" +msgid "Campsite Type Features" +msgstr "Característiques del tipus d’allotjaments" + +#: web/templates/admin/campsite/type/feature/index.gohtml:48 +msgid "No campsite type features added yet." +msgstr "No s’ha afegit cap característica al tipus d’allotjament encara." + +#: web/templates/admin/campsite/type/carousel/form.gohtml:8 +#: web/templates/admin/campsite/type/carousel/form.gohtml:32 +msgctxt "title" +msgid "Edit Campsite Type Carousel Slide" +msgstr "Edició de la diapositiva del carrusel del tipus d’allotjament" + +#: web/templates/admin/campsite/type/carousel/form.gohtml:10 +#: web/templates/admin/campsite/type/carousel/form.gohtml:34 +msgctxt "title" +msgid "New Campsite Type Carousel Slide" +msgstr "Nova diapositiva del carrusel del tipus d’allotjament" + +#: web/templates/admin/campsite/type/carousel/form.gohtml:18 +#: web/templates/admin/campsite/type/carousel/index.gohtml:6 +#: web/templates/admin/campsite/type/carousel/index.gohtml:16 +msgctxt "title" +msgid "Campsite Type Carousel" +msgstr "Carrusel del tipus d’allotjament" + #: web/templates/admin/campsite/type/form.gohtml:8 #: web/templates/admin/campsite/type/form.gohtml:30 msgctxt "title" @@ -840,6 +888,12 @@ msgctxt "input" msgid "Dogs allowed" msgstr "Es permeten gossos" +#: web/templates/admin/campsite/type/form.gohtml:115 +#: web/templates/admin/campsite/type/option/form.gohtml:76 +msgctxt "input" +msgid "Price per night" +msgstr "Preu per nit" + #: web/templates/admin/campsite/type/form.gohtml:123 msgctxt "input" msgid "Minimum number of nights" @@ -872,41 +926,59 @@ msgctxt "input" msgid "Additional Information" msgstr "Informació addicional" +#: web/templates/admin/campsite/type/option/form.gohtml:8 +#: web/templates/admin/campsite/type/option/form.gohtml:32 +msgctxt "title" +msgid "Edit Campsite Type Option" +msgstr "Edició de l’opció del tipus d’allotjament" + +#: web/templates/admin/campsite/type/option/form.gohtml:10 +#: web/templates/admin/campsite/type/option/form.gohtml:34 +msgctxt "title" +msgid "New Campsite Type Option" +msgstr "Nova opció del tipus d’allotjament" + +#: web/templates/admin/campsite/type/option/form.gohtml:18 +#: web/templates/admin/campsite/type/option/index.gohtml:6 +#: web/templates/admin/campsite/type/option/index.gohtml:17 +msgctxt "title" +msgid "Campsite Type Options" +msgstr "Opcions del tipus d’allotjament" + +#: web/templates/admin/campsite/type/option/form.gohtml:54 +msgctxt "input" +msgid "Minimum" +msgstr "Mínim" + +#: web/templates/admin/campsite/type/option/form.gohtml:62 +msgctxt "input" +msgid "Maximum" +msgstr "Màxim" + +#: web/templates/admin/campsite/type/option/index.gohtml:16 +msgctxt "action" +msgid "Add Option" +msgstr "Afegeix opció" + +#: web/templates/admin/campsite/type/option/index.gohtml:56 +msgid "No campsite type options added yet." +msgstr "No s’ha afegit cap opció al tipus d’allotjament encara." + #: web/templates/admin/campsite/type/index.gohtml:15 msgctxt "action" msgid "Add Type" msgstr "Afegeix tipus" -#: web/templates/admin/campsite/type/index.gohtml:30 -msgctxt "header" -msgid "Features" -msgstr "Característiques" - #: web/templates/admin/campsite/type/index.gohtml:31 msgctxt "header" msgid "Options" msgstr "Opcions" -#: web/templates/admin/campsite/type/index.gohtml:32 -msgctxt "header" -msgid "Carousel" -msgstr "Carrusel" - -#: web/templates/admin/campsite/type/index.gohtml:45 -msgctxt "action" -msgid "Edit Features" -msgstr "Edita les característiques" - #: web/templates/admin/campsite/type/index.gohtml:48 msgctxt "action" msgid "Edit Options" msgstr "Edita les opcions" -#: web/templates/admin/campsite/type/index.gohtml:51 -msgctxt "action" -msgid "Edit Carousel" -msgstr "Edita el carrusel" - #: web/templates/admin/campsite/type/index.gohtml:60 msgid "No campsite types added yet." msgstr "No s’ha afegit cap tipus d’allotjament encara." @@ -1467,33 +1539,36 @@ msgstr "No s’ha trobat cap reserva." #: pkg/legal/admin.go:258 pkg/app/user.go:249 pkg/campsite/types/option.go:357 #: pkg/campsite/types/feature.go:259 pkg/campsite/types/admin.go:483 -#: pkg/season/admin.go:412 pkg/services/admin.go:316 -#: pkg/surroundings/admin.go:340 +#: pkg/campsite/feature.go:269 pkg/season/admin.go:412 +#: pkg/services/admin.go:316 pkg/surroundings/admin.go:340 msgid "Name can not be empty." msgstr "No podeu deixar el nom en blanc." #: pkg/legal/admin.go:259 pkg/campsite/types/option.go:358 #: pkg/campsite/types/feature.go:260 pkg/campsite/types/admin.go:484 +#: pkg/campsite/feature.go:270 msgid "Name must have at least one letter." msgstr "El nom ha de tenir com a mínim una lletra." #: pkg/carousel/admin.go:276 pkg/campsite/types/carousel.go:225 +#: pkg/campsite/carousel.go:227 msgctxt "input" msgid "Slide image" msgstr "Imatge de la diapositiva" #: pkg/carousel/admin.go:277 pkg/campsite/types/carousel.go:226 +#: pkg/campsite/carousel.go:228 msgctxt "action" msgid "Set slide image" msgstr "Estableix la imatge de la diapositiva" #: pkg/carousel/admin.go:346 pkg/campsite/types/carousel.go:299 -#: pkg/surroundings/admin.go:335 +#: pkg/campsite/carousel.go:302 pkg/surroundings/admin.go:335 msgid "Slide image can not be empty." msgstr "No podeu deixar la imatge de la diapositiva en blanc." #: pkg/carousel/admin.go:347 pkg/campsite/types/carousel.go:300 -#: pkg/surroundings/admin.go:336 +#: pkg/campsite/carousel.go:303 pkg/surroundings/admin.go:336 msgid "Slide image must be an image media type." msgstr "La imatge de la diapositiva ha de ser un mèdia de tipus imatge." @@ -1572,7 +1647,8 @@ msgstr "El preu per nit ha de ser un número decimal." msgid "Price per night must be zero or greater." msgstr "El preu per nit ha de ser com a mínim zero." -#: pkg/campsite/types/feature.go:258 pkg/services/admin.go:315 +#: pkg/campsite/types/feature.go:258 pkg/campsite/feature.go:268 +#: pkg/services/admin.go:315 msgid "Selected icon is not valid." msgstr "La icona escollida no és vàlida." @@ -1626,11 +1702,11 @@ msgstr "El número mínim de nits ha de ser enter." msgid "Minimum number of nights must be one or greater." msgstr "El número mínim de nits no pot ser zero." -#: pkg/campsite/admin.go:226 pkg/booking/public.go:278 +#: pkg/campsite/admin.go:274 pkg/booking/public.go:278 msgid "Selected campsite type is not valid." msgstr "El tipus d’allotjament escollit no és vàlid." -#: pkg/campsite/admin.go:227 +#: pkg/campsite/admin.go:275 msgid "Label can not be empty." msgstr "No podeu deixar l’etiqueta en blanc." diff --git a/po/es.po b/po/es.po index 19f29d8..adaf48a 100644 --- a/po/es.po +++ b/po/es.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: camper\n" "Report-Msgid-Bugs-To: jordi@tandem.blog\n" -"POT-Creation-Date: 2024-01-24 11:14+0100\n" +"POT-Creation-Date: 2024-01-26 21:20+0100\n" "PO-Revision-Date: 2023-07-22 23:46+0200\n" "Last-Translator: jordi fita mas \n" "Language-Team: Spanish \n" @@ -129,8 +129,8 @@ msgid "Calendar" msgstr "Calendario" #: web/templates/public/campsite/type.gohtml:73 -#: web/templates/admin/campsite/option/form.gohtml:70 #: web/templates/admin/campsite/type/form.gohtml:109 +#: web/templates/admin/campsite/type/option/form.gohtml:70 msgctxt "title" msgid "Prices" msgstr "Precios" @@ -165,6 +165,7 @@ msgid "No dogs allowed." msgstr "No se permiten perros" #: web/templates/public/campsite/type.gohtml:112 +#: web/templates/public/campsite/page.gohtml:39 msgctxt "title" msgid "Features" msgstr "Características" @@ -398,11 +399,15 @@ msgstr "Menú" #: web/templates/admin/campsite/carousel/form.gohtml:16 #: web/templates/admin/campsite/carousel/index.gohtml:10 #: web/templates/admin/campsite/form.gohtml:15 -#: web/templates/admin/campsite/option/form.gohtml:16 -#: web/templates/admin/campsite/option/index.gohtml:10 #: web/templates/admin/campsite/index.gohtml:6 #: web/templates/admin/campsite/index.gohtml:15 +#: web/templates/admin/campsite/type/feature/form.gohtml:16 +#: web/templates/admin/campsite/type/feature/index.gohtml:10 +#: web/templates/admin/campsite/type/carousel/form.gohtml:16 +#: web/templates/admin/campsite/type/carousel/index.gohtml:10 #: web/templates/admin/campsite/type/form.gohtml:15 +#: web/templates/admin/campsite/type/option/form.gohtml:16 +#: web/templates/admin/campsite/type/option/index.gohtml:10 #: web/templates/admin/campsite/type/index.gohtml:10 #: web/templates/admin/layout.gohtml:46 web/templates/admin/layout.gohtml:92 msgctxt "title" @@ -449,9 +454,10 @@ msgid "Slug" msgstr "Álias" #: web/templates/admin/legal/form.gohtml:50 -#: web/templates/admin/campsite/feature/form.gohtml:59 -#: web/templates/admin/campsite/option/form.gohtml:41 +#: web/templates/admin/campsite/feature/form.gohtml:50 +#: web/templates/admin/campsite/type/feature/form.gohtml:59 #: web/templates/admin/campsite/type/form.gohtml:51 +#: web/templates/admin/campsite/type/option/form.gohtml:41 #: web/templates/admin/season/form.gohtml:50 #: web/templates/admin/services/form.gohtml:53 #: web/templates/admin/profile.gohtml:29 @@ -467,11 +473,13 @@ msgstr "Contenido" #: web/templates/admin/legal/form.gohtml:88 #: web/templates/admin/carousel/form.gohtml:55 -#: web/templates/admin/campsite/feature/form.gohtml:74 -#: web/templates/admin/campsite/carousel/form.gohtml:59 -#: web/templates/admin/campsite/form.gohtml:74 -#: web/templates/admin/campsite/option/form.gohtml:90 +#: web/templates/admin/campsite/feature/form.gohtml:65 +#: web/templates/admin/campsite/carousel/form.gohtml:50 +#: web/templates/admin/campsite/form.gohtml:92 +#: web/templates/admin/campsite/type/feature/form.gohtml:74 +#: web/templates/admin/campsite/type/carousel/form.gohtml:59 #: web/templates/admin/campsite/type/form.gohtml:202 +#: web/templates/admin/campsite/type/option/form.gohtml:90 #: web/templates/admin/season/form.gohtml:73 #: web/templates/admin/services/form.gohtml:81 #: web/templates/admin/surroundings/form.gohtml:69 @@ -484,11 +492,13 @@ msgstr "Actualizar" #: web/templates/admin/legal/form.gohtml:90 #: web/templates/admin/carousel/form.gohtml:57 -#: web/templates/admin/campsite/feature/form.gohtml:76 -#: web/templates/admin/campsite/carousel/form.gohtml:61 -#: web/templates/admin/campsite/form.gohtml:76 -#: web/templates/admin/campsite/option/form.gohtml:92 +#: web/templates/admin/campsite/feature/form.gohtml:67 +#: web/templates/admin/campsite/carousel/form.gohtml:52 +#: web/templates/admin/campsite/form.gohtml:94 +#: web/templates/admin/campsite/type/feature/form.gohtml:76 +#: web/templates/admin/campsite/type/carousel/form.gohtml:61 #: web/templates/admin/campsite/type/form.gohtml:204 +#: web/templates/admin/campsite/type/option/form.gohtml:92 #: web/templates/admin/season/form.gohtml:75 #: web/templates/admin/services/form.gohtml:83 #: web/templates/admin/surroundings/form.gohtml:71 @@ -502,8 +512,9 @@ msgid "Add Legal Text" msgstr "Añadir texto legal" #: web/templates/admin/legal/index.gohtml:20 -#: web/templates/admin/campsite/feature/index.gohtml:31 -#: web/templates/admin/campsite/option/index.gohtml:30 +#: web/templates/admin/campsite/feature/index.gohtml:30 +#: web/templates/admin/campsite/type/feature/index.gohtml:31 +#: web/templates/admin/campsite/type/option/index.gohtml:30 #: web/templates/admin/campsite/type/index.gohtml:29 #: web/templates/admin/season/index.gohtml:29 #: web/templates/admin/user/index.gohtml:20 @@ -529,7 +540,8 @@ msgid "New Carousel Slide" msgstr "Nueva diapositiva del carrusel" #: web/templates/admin/carousel/form.gohtml:40 -#: web/templates/admin/campsite/carousel/form.gohtml:44 +#: web/templates/admin/campsite/carousel/form.gohtml:35 +#: web/templates/admin/campsite/type/carousel/form.gohtml:44 msgctxt "input" msgid "Caption" msgstr "Leyenda" @@ -562,98 +574,38 @@ msgid "Save changes" msgstr "Guardar los cambios" #: web/templates/admin/campsite/feature/form.gohtml:8 -#: web/templates/admin/campsite/feature/form.gohtml:32 msgctxt "title" -msgid "Edit Campsite Type Feature" -msgstr "Edición de las características del tipo de alojamiento" +msgid "Edit Campsite Feature" +msgstr "Edición de las características del alojamiento" #: web/templates/admin/campsite/feature/form.gohtml:10 -#: web/templates/admin/campsite/feature/form.gohtml:34 msgctxt "title" -msgid "New Campsite Type Feature" -msgstr "Nueva característica del tipo de alojamiento" +msgid "New Campsite Feature" +msgstr "Nueva característica del alojamiento" #: web/templates/admin/campsite/feature/form.gohtml:17 -#: web/templates/admin/campsite/feature/index.gohtml:11 -#: web/templates/admin/campsite/carousel/form.gohtml:17 -#: web/templates/admin/campsite/carousel/index.gohtml:11 -#: web/templates/admin/campsite/option/form.gohtml:17 -#: web/templates/admin/campsite/option/index.gohtml:11 -#: web/templates/admin/campsite/type/form.gohtml:16 -#: web/templates/admin/campsite/type/index.gohtml:6 -#: web/templates/admin/campsite/type/index.gohtml:16 -#: web/templates/admin/layout.gohtml:43 -msgctxt "title" -msgid "Campsite Types" -msgstr "Tipos de alojamientos" - -#: web/templates/admin/campsite/feature/form.gohtml:18 #: web/templates/admin/campsite/feature/index.gohtml:6 -#: web/templates/admin/campsite/feature/index.gohtml:17 msgctxt "title" -msgid "Campsite Type Features" -msgstr "Características del tipo de alojamiento" +msgid "Campsite Features" +msgstr "Características del alojamiento" -#: web/templates/admin/campsite/feature/form.gohtml:41 +#: web/templates/admin/campsite/feature/form.gohtml:32 +#: web/templates/admin/campsite/type/feature/form.gohtml:41 #: web/templates/admin/services/form.gohtml:35 msgctxt "input" msgid "Icon" msgstr "Icono" -#: web/templates/admin/campsite/feature/index.gohtml:16 +#: web/templates/admin/campsite/feature/index.gohtml:15 +#: web/templates/admin/campsite/type/feature/index.gohtml:16 msgctxt "action" msgid "Add Feature" msgstr "Añadir características" -#: web/templates/admin/campsite/feature/index.gohtml:48 -msgid "No campsite type features added yet." -msgstr "No se ha añadido ninguna característica al tipo de alojamiento todavía." - -#: web/templates/admin/campsite/carousel/form.gohtml:8 -#: web/templates/admin/campsite/carousel/form.gohtml:32 -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:34 -msgctxt "title" -msgid "New Campsite Type Carousel Slide" -msgstr "Nueva diapositiva del carrusel del tipo de alojamiento" - -#: web/templates/admin/campsite/carousel/form.gohtml:18 -#: web/templates/admin/campsite/carousel/index.gohtml:6 -#: web/templates/admin/campsite/carousel/index.gohtml:16 -msgctxt "title" -msgid "Campsite Type Carousel" -msgstr "Carrusel del tipo de alojamiento" - -#: web/templates/admin/campsite/carousel/index.gohtml:17 -#: web/templates/admin/services/index.gohtml:15 -#: web/templates/admin/home/index.gohtml:84 -msgctxt "action" -msgid "Add slide" -msgstr "Añadir diapositiva" - -#: web/templates/admin/campsite/carousel/index.gohtml:30 -#: web/templates/admin/services/index.gohtml:28 -#: web/templates/admin/surroundings/index.gohtml:82 -#: web/templates/admin/home/index.gohtml:52 -#: web/templates/admin/home/index.gohtml:97 -msgctxt "header" -msgid "Image" -msgstr "Imagen" - +#: web/templates/admin/campsite/feature/index.gohtml:31 #: web/templates/admin/campsite/carousel/index.gohtml:31 -#: web/templates/admin/services/index.gohtml:29 -#: web/templates/admin/home/index.gohtml:53 -#: web/templates/admin/home/index.gohtml:98 -msgctxt "header" -msgid "Caption" -msgstr "Leyenda" - -#: web/templates/admin/campsite/carousel/index.gohtml:32 -#: web/templates/admin/campsite/option/index.gohtml:31 +#: web/templates/admin/campsite/type/carousel/index.gohtml:32 +#: web/templates/admin/campsite/type/option/index.gohtml:31 #: web/templates/admin/services/index.gohtml:30 #: web/templates/admin/services/index.gohtml:75 #: web/templates/admin/user/index.gohtml:23 @@ -664,14 +616,15 @@ msgctxt "header" msgid "Actions" msgstr "Acciones" -#: web/templates/admin/campsite/carousel/index.gohtml:36 -#: web/templates/admin/services/index.gohtml:34 -#: web/templates/admin/home/index.gohtml:103 -msgid "Are you sure you wish to delete this slide?" -msgstr "¿Estáis seguro de querer borrar esta diapositiva?" +#: web/templates/admin/campsite/feature/index.gohtml:35 +#: web/templates/admin/campsite/type/option/index.gohtml:35 +msgid "Are you sure you wish to delete this option?" +msgstr "¿Estáis seguro de querer borrar esta opción?" -#: web/templates/admin/campsite/carousel/index.gohtml:50 -#: web/templates/admin/campsite/option/index.gohtml:47 +#: web/templates/admin/campsite/feature/index.gohtml:47 +#: web/templates/admin/campsite/carousel/index.gohtml:49 +#: web/templates/admin/campsite/type/carousel/index.gohtml:50 +#: web/templates/admin/campsite/type/option/index.gohtml:47 #: web/templates/admin/services/index.gohtml:47 #: web/templates/admin/services/index.gohtml:91 #: web/templates/admin/user/index.gohtml:37 @@ -683,125 +636,220 @@ msgctxt "action" msgid "Delete" msgstr "Borrar" -#: web/templates/admin/campsite/carousel/index.gohtml:59 +#: web/templates/admin/campsite/feature/index.gohtml:56 +msgid "No campsite features added yet." +msgstr "No se ha añadido ninguna característica al alojamiento todavía." + +#: web/templates/admin/campsite/carousel/form.gohtml:8 +msgctxt "title" +msgid "Edit Campsite Carousel Slide" +msgstr "Edición de la diapositiva del carrusel del alojamiento" + +#: web/templates/admin/campsite/carousel/form.gohtml:10 +msgctxt "title" +msgid "New Campsite Carousel Slide" +msgstr "Nueva diapositiva del carrusel del alojamiento" + +#: web/templates/admin/campsite/carousel/form.gohtml:17 +#: web/templates/admin/campsite/carousel/index.gohtml:6 +msgctxt "title" +msgid "Campsite Carousel" +msgstr "Carrusel del alojamiento" + +#: web/templates/admin/campsite/carousel/index.gohtml:16 +#: web/templates/admin/campsite/type/carousel/index.gohtml:17 +#: web/templates/admin/services/index.gohtml:15 +#: web/templates/admin/home/index.gohtml:84 +msgctxt "action" +msgid "Add slide" +msgstr "Añadir diapositiva" + +#: web/templates/admin/campsite/carousel/index.gohtml:29 +#: web/templates/admin/campsite/type/carousel/index.gohtml:30 +#: web/templates/admin/services/index.gohtml:28 +#: web/templates/admin/surroundings/index.gohtml:82 +#: web/templates/admin/home/index.gohtml:52 +#: web/templates/admin/home/index.gohtml:97 +msgctxt "header" +msgid "Image" +msgstr "Imagen" + +#: web/templates/admin/campsite/carousel/index.gohtml:30 +#: web/templates/admin/campsite/type/carousel/index.gohtml:31 +#: web/templates/admin/services/index.gohtml:29 +#: web/templates/admin/home/index.gohtml:53 +#: web/templates/admin/home/index.gohtml:98 +msgctxt "header" +msgid "Caption" +msgstr "Leyenda" + +#: web/templates/admin/campsite/carousel/index.gohtml:35 +#: web/templates/admin/campsite/type/carousel/index.gohtml:36 +#: web/templates/admin/services/index.gohtml:34 +#: web/templates/admin/home/index.gohtml:103 +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:58 +#: web/templates/admin/campsite/type/carousel/index.gohtml:59 #: web/templates/admin/services/index.gohtml:56 #: web/templates/admin/home/index.gohtml:125 msgid "No slides added yet." msgstr "No se ha añadido ninguna diapositiva todavía." #: web/templates/admin/campsite/form.gohtml:8 -#: web/templates/admin/campsite/form.gohtml:29 msgctxt "title" msgid "Edit Campsite" msgstr "Edición del alojamientos" #: web/templates/admin/campsite/form.gohtml:10 -#: web/templates/admin/campsite/form.gohtml:31 msgctxt "title" msgid "New Campsite" msgstr "Nuevo alojamiento" -#: web/templates/admin/campsite/form.gohtml:41 -#: web/templates/admin/campsite/index.gohtml:23 +#: web/templates/admin/campsite/form.gohtml:33 +#: web/templates/admin/campsite/index.gohtml:27 msgctxt "campsite" msgid "Active" msgstr "Activo" -#: web/templates/admin/campsite/form.gohtml:50 +#: web/templates/admin/campsite/form.gohtml:42 msgctxt "input" msgid "Campsite Type" msgstr "Tipo de alojamiento" -#: web/templates/admin/campsite/form.gohtml:55 +#: web/templates/admin/campsite/form.gohtml:47 msgid "Select campsite type" msgstr "Escoged un tipo de alojamiento" -#: web/templates/admin/campsite/form.gohtml:64 +#: web/templates/admin/campsite/form.gohtml:56 msgctxt "input" msgid "Label" msgstr "Etiqueta" -#: web/templates/admin/campsite/option/form.gohtml:8 -#: web/templates/admin/campsite/option/form.gohtml:32 -msgctxt "title" -msgid "Edit Campsite Type Option" -msgstr "Edición de la opción del tipo de alojamiento" - -#: web/templates/admin/campsite/option/form.gohtml:10 -#: web/templates/admin/campsite/option/form.gohtml:34 -msgctxt "title" -msgid "New Campsite Type Option" -msgstr "Nueva opción del tipo de alojamiento" - -#: web/templates/admin/campsite/option/form.gohtml:18 -#: web/templates/admin/campsite/option/index.gohtml:6 -#: web/templates/admin/campsite/option/index.gohtml:17 -msgctxt "title" -msgid "Campsite Type Options" -msgstr "Opciones del tipo de alojamiento" - -#: web/templates/admin/campsite/option/form.gohtml:54 +#: web/templates/admin/campsite/form.gohtml:64 msgctxt "input" -msgid "Minimum" -msgstr "Mínimo" +msgid "Info (First Column)" +msgstr "Información (primera columna)" -#: web/templates/admin/campsite/option/form.gohtml:62 +#: web/templates/admin/campsite/form.gohtml:77 msgctxt "input" -msgid "Maximum" -msgstr "Màximo" - -#: web/templates/admin/campsite/option/form.gohtml:76 -#: web/templates/admin/campsite/type/form.gohtml:115 -msgctxt "input" -msgid "Price per night" -msgstr "Precio por noche" - -#: web/templates/admin/campsite/option/index.gohtml:16 -msgctxt "action" -msgid "Add Option" -msgstr "Añadir opción" - -#: web/templates/admin/campsite/option/index.gohtml:35 -msgid "Are you sure you wish to delete this option?" -msgstr "¿Estáis seguro de querer borrar esta opción?" - -#: web/templates/admin/campsite/option/index.gohtml:56 -msgid "No campsite type options added yet." -msgstr "No se ha añadido ninguna opció al tipo de alojamiento todavía." +msgid "Info (Second Column)" +msgstr "Información (segunda columna)" #: web/templates/admin/campsite/index.gohtml:14 msgctxt "action" msgid "Add Campsite" msgstr "Añadir alojamiento" -#: web/templates/admin/campsite/index.gohtml:21 +#: web/templates/admin/campsite/index.gohtml:23 msgctxt "header" msgid "Label" msgstr "Etiqueta" -#: web/templates/admin/campsite/index.gohtml:22 +#: web/templates/admin/campsite/index.gohtml:24 msgctxt "header" msgid "Type" msgstr "Tipo" -#: web/templates/admin/campsite/index.gohtml:31 +#: web/templates/admin/campsite/index.gohtml:25 +#: web/templates/admin/campsite/type/index.gohtml:30 +msgctxt "header" +msgid "Features" +msgstr "Características" + +#: web/templates/admin/campsite/index.gohtml:26 +#: web/templates/admin/campsite/type/index.gohtml:32 +msgctxt "header" +msgid "Carousel" +msgstr "Carrusel" + +#: web/templates/admin/campsite/index.gohtml:36 +#: web/templates/admin/campsite/type/index.gohtml:45 +msgctxt "action" +msgid "Edit Features" +msgstr "Editar las características" + +#: web/templates/admin/campsite/index.gohtml:39 +#: web/templates/admin/campsite/type/index.gohtml:51 +msgctxt "action" +msgid "Edit Carousel" +msgstr "Editar el carrusel" + +#: web/templates/admin/campsite/index.gohtml:41 #: web/templates/admin/campsite/type/index.gohtml:53 #: web/templates/admin/season/index.gohtml:44 #: web/templates/admin/user/login-attempts.gohtml:31 msgid "Yes" msgstr "Sí" -#: web/templates/admin/campsite/index.gohtml:31 +#: web/templates/admin/campsite/index.gohtml:41 #: web/templates/admin/campsite/type/index.gohtml:53 #: web/templates/admin/season/index.gohtml:44 #: web/templates/admin/user/login-attempts.gohtml:31 msgid "No" msgstr "No" -#: web/templates/admin/campsite/index.gohtml:37 +#: web/templates/admin/campsite/index.gohtml:47 msgid "No campsites added yet." msgstr "No se ha añadido ningún alojamiento todavía." +#: web/templates/admin/campsite/type/feature/form.gohtml:8 +#: web/templates/admin/campsite/type/feature/form.gohtml:32 +msgctxt "title" +msgid "Edit Campsite Type Feature" +msgstr "Edición de las características del tipo de alojamiento" + +#: web/templates/admin/campsite/type/feature/form.gohtml:10 +#: web/templates/admin/campsite/type/feature/form.gohtml:34 +msgctxt "title" +msgid "New Campsite Type Feature" +msgstr "Nueva característica del tipo de alojamiento" + +#: web/templates/admin/campsite/type/feature/form.gohtml:17 +#: web/templates/admin/campsite/type/feature/index.gohtml:11 +#: web/templates/admin/campsite/type/carousel/form.gohtml:17 +#: web/templates/admin/campsite/type/carousel/index.gohtml:11 +#: web/templates/admin/campsite/type/form.gohtml:16 +#: web/templates/admin/campsite/type/option/form.gohtml:17 +#: web/templates/admin/campsite/type/option/index.gohtml:11 +#: web/templates/admin/campsite/type/index.gohtml:6 +#: web/templates/admin/campsite/type/index.gohtml:16 +#: web/templates/admin/layout.gohtml:43 +msgctxt "title" +msgid "Campsite Types" +msgstr "Tipos de alojamientos" + +#: web/templates/admin/campsite/type/feature/form.gohtml:18 +#: web/templates/admin/campsite/type/feature/index.gohtml:6 +#: web/templates/admin/campsite/type/feature/index.gohtml:17 +msgctxt "title" +msgid "Campsite Type Features" +msgstr "Características del tipo de alojamiento" + +#: web/templates/admin/campsite/type/feature/index.gohtml:48 +msgid "No campsite type features added yet." +msgstr "No se ha añadido ninguna característica al tipo de alojamiento todavía." + +#: web/templates/admin/campsite/type/carousel/form.gohtml:8 +#: web/templates/admin/campsite/type/carousel/form.gohtml:32 +msgctxt "title" +msgid "Edit Campsite Type Carousel Slide" +msgstr "Edición de la diapositiva del carrusel del tipo de alojamiento" + +#: web/templates/admin/campsite/type/carousel/form.gohtml:10 +#: web/templates/admin/campsite/type/carousel/form.gohtml:34 +msgctxt "title" +msgid "New Campsite Type Carousel Slide" +msgstr "Nueva diapositiva del carrusel del tipo de alojamiento" + +#: web/templates/admin/campsite/type/carousel/form.gohtml:18 +#: web/templates/admin/campsite/type/carousel/index.gohtml:6 +#: web/templates/admin/campsite/type/carousel/index.gohtml:16 +msgctxt "title" +msgid "Campsite Type Carousel" +msgstr "Carrusel del tipo de alojamiento" + #: web/templates/admin/campsite/type/form.gohtml:8 #: web/templates/admin/campsite/type/form.gohtml:30 msgctxt "title" @@ -840,6 +888,12 @@ msgctxt "input" msgid "Dogs allowed" msgstr "Se permiten perros" +#: web/templates/admin/campsite/type/form.gohtml:115 +#: web/templates/admin/campsite/type/option/form.gohtml:76 +msgctxt "input" +msgid "Price per night" +msgstr "Precio por noche" + #: web/templates/admin/campsite/type/form.gohtml:123 msgctxt "input" msgid "Minimum number of nights" @@ -872,41 +926,59 @@ msgctxt "input" msgid "Additional Information" msgstr "Información adicional" +#: web/templates/admin/campsite/type/option/form.gohtml:8 +#: web/templates/admin/campsite/type/option/form.gohtml:32 +msgctxt "title" +msgid "Edit Campsite Type Option" +msgstr "Edición de la opción del tipo de alojamiento" + +#: web/templates/admin/campsite/type/option/form.gohtml:10 +#: web/templates/admin/campsite/type/option/form.gohtml:34 +msgctxt "title" +msgid "New Campsite Type Option" +msgstr "Nueva opción del tipo de alojamiento" + +#: web/templates/admin/campsite/type/option/form.gohtml:18 +#: web/templates/admin/campsite/type/option/index.gohtml:6 +#: web/templates/admin/campsite/type/option/index.gohtml:17 +msgctxt "title" +msgid "Campsite Type Options" +msgstr "Opciones del tipo de alojamiento" + +#: web/templates/admin/campsite/type/option/form.gohtml:54 +msgctxt "input" +msgid "Minimum" +msgstr "Mínimo" + +#: web/templates/admin/campsite/type/option/form.gohtml:62 +msgctxt "input" +msgid "Maximum" +msgstr "Màximo" + +#: web/templates/admin/campsite/type/option/index.gohtml:16 +msgctxt "action" +msgid "Add Option" +msgstr "Añadir opción" + +#: web/templates/admin/campsite/type/option/index.gohtml:56 +msgid "No campsite type options added yet." +msgstr "No se ha añadido ninguna opció al tipo de alojamiento todavía." + #: web/templates/admin/campsite/type/index.gohtml:15 msgctxt "action" msgid "Add Type" msgstr "Añadir tipo" -#: web/templates/admin/campsite/type/index.gohtml:30 -msgctxt "header" -msgid "Features" -msgstr "Características" - #: web/templates/admin/campsite/type/index.gohtml:31 msgctxt "header" msgid "Options" msgstr "Opciones" -#: web/templates/admin/campsite/type/index.gohtml:32 -msgctxt "header" -msgid "Carousel" -msgstr "Carrusel" - -#: web/templates/admin/campsite/type/index.gohtml:45 -msgctxt "action" -msgid "Edit Features" -msgstr "Editar las características" - #: web/templates/admin/campsite/type/index.gohtml:48 msgctxt "action" msgid "Edit Options" msgstr "Editar opciones" -#: web/templates/admin/campsite/type/index.gohtml:51 -msgctxt "action" -msgid "Edit Carousel" -msgstr "Editar el carrusel" - #: web/templates/admin/campsite/type/index.gohtml:60 msgid "No campsite types added yet." msgstr "No se ha añadido ningún tipo de alojamiento todavía." @@ -1467,33 +1539,36 @@ msgstr "No se ha encontrado ninguna reserva." #: pkg/legal/admin.go:258 pkg/app/user.go:249 pkg/campsite/types/option.go:357 #: pkg/campsite/types/feature.go:259 pkg/campsite/types/admin.go:483 -#: pkg/season/admin.go:412 pkg/services/admin.go:316 -#: pkg/surroundings/admin.go:340 +#: pkg/campsite/feature.go:269 pkg/season/admin.go:412 +#: pkg/services/admin.go:316 pkg/surroundings/admin.go:340 msgid "Name can not be empty." msgstr "No podéis dejar el nombre en blanco." #: pkg/legal/admin.go:259 pkg/campsite/types/option.go:358 #: pkg/campsite/types/feature.go:260 pkg/campsite/types/admin.go:484 +#: pkg/campsite/feature.go:270 msgid "Name must have at least one letter." msgstr "El nombre tiene que tener como mínimo una letra." #: pkg/carousel/admin.go:276 pkg/campsite/types/carousel.go:225 +#: pkg/campsite/carousel.go:227 msgctxt "input" msgid "Slide image" msgstr "Imagen de la diapositiva" #: pkg/carousel/admin.go:277 pkg/campsite/types/carousel.go:226 +#: pkg/campsite/carousel.go:228 msgctxt "action" msgid "Set slide image" msgstr "Establecer la imagen de la diapositiva" #: pkg/carousel/admin.go:346 pkg/campsite/types/carousel.go:299 -#: pkg/surroundings/admin.go:335 +#: pkg/campsite/carousel.go:302 pkg/surroundings/admin.go:335 msgid "Slide image can not be empty." msgstr "No podéis dejar la imagen de la diapositiva en blanco." #: pkg/carousel/admin.go:347 pkg/campsite/types/carousel.go:300 -#: pkg/surroundings/admin.go:336 +#: pkg/campsite/carousel.go:303 pkg/surroundings/admin.go:336 msgid "Slide image must be an image media type." msgstr "La imagen de la diapositiva tiene que ser un medio de tipo imagen." @@ -1572,7 +1647,8 @@ msgstr "El precio por noche tiene que ser un número decimal." msgid "Price per night must be zero or greater." msgstr "El precio por noche tiene que ser como mínimo cero." -#: pkg/campsite/types/feature.go:258 pkg/services/admin.go:315 +#: pkg/campsite/types/feature.go:258 pkg/campsite/feature.go:268 +#: pkg/services/admin.go:315 msgid "Selected icon is not valid." msgstr "El icono escogido no es válido." @@ -1626,11 +1702,11 @@ msgstr "El número mínimo de noches tiene que ser entero." msgid "Minimum number of nights must be one or greater." msgstr "El número mínimo de noches no puede ser cero." -#: pkg/campsite/admin.go:226 pkg/booking/public.go:278 +#: pkg/campsite/admin.go:274 pkg/booking/public.go:278 msgid "Selected campsite type is not valid." msgstr "El tipo de alojamiento escogido no es válido." -#: pkg/campsite/admin.go:227 +#: pkg/campsite/admin.go:275 msgid "Label can not be empty." msgstr "No podéis dejar la etiqueta en blanco." diff --git a/po/fr.po b/po/fr.po index b4d778a..7c0de22 100644 --- a/po/fr.po +++ b/po/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: camper\n" "Report-Msgid-Bugs-To: jordi@tandem.blog\n" -"POT-Creation-Date: 2024-01-24 11:14+0100\n" +"POT-Creation-Date: 2024-01-26 21:20+0100\n" "PO-Revision-Date: 2023-12-20 10:13+0100\n" "Last-Translator: Oriol Carbonell \n" "Language-Team: French \n" @@ -130,8 +130,8 @@ msgid "Calendar" msgstr "Calendrier" #: web/templates/public/campsite/type.gohtml:73 -#: web/templates/admin/campsite/option/form.gohtml:70 #: web/templates/admin/campsite/type/form.gohtml:109 +#: web/templates/admin/campsite/type/option/form.gohtml:70 msgctxt "title" msgid "Prices" msgstr "Prix" @@ -166,6 +166,7 @@ msgid "No dogs allowed." msgstr "Chiens interdits." #: web/templates/public/campsite/type.gohtml:112 +#: web/templates/public/campsite/page.gohtml:39 msgctxt "title" msgid "Features" msgstr "Caractéristiques" @@ -399,11 +400,15 @@ msgstr "Menu" #: web/templates/admin/campsite/carousel/form.gohtml:16 #: web/templates/admin/campsite/carousel/index.gohtml:10 #: web/templates/admin/campsite/form.gohtml:15 -#: web/templates/admin/campsite/option/form.gohtml:16 -#: web/templates/admin/campsite/option/index.gohtml:10 #: web/templates/admin/campsite/index.gohtml:6 #: web/templates/admin/campsite/index.gohtml:15 +#: web/templates/admin/campsite/type/feature/form.gohtml:16 +#: web/templates/admin/campsite/type/feature/index.gohtml:10 +#: web/templates/admin/campsite/type/carousel/form.gohtml:16 +#: web/templates/admin/campsite/type/carousel/index.gohtml:10 #: web/templates/admin/campsite/type/form.gohtml:15 +#: web/templates/admin/campsite/type/option/form.gohtml:16 +#: web/templates/admin/campsite/type/option/index.gohtml:10 #: web/templates/admin/campsite/type/index.gohtml:10 #: web/templates/admin/layout.gohtml:46 web/templates/admin/layout.gohtml:92 msgctxt "title" @@ -450,9 +455,10 @@ msgid "Slug" msgstr "Slug" #: web/templates/admin/legal/form.gohtml:50 -#: web/templates/admin/campsite/feature/form.gohtml:59 -#: web/templates/admin/campsite/option/form.gohtml:41 +#: web/templates/admin/campsite/feature/form.gohtml:50 +#: web/templates/admin/campsite/type/feature/form.gohtml:59 #: web/templates/admin/campsite/type/form.gohtml:51 +#: web/templates/admin/campsite/type/option/form.gohtml:41 #: web/templates/admin/season/form.gohtml:50 #: web/templates/admin/services/form.gohtml:53 #: web/templates/admin/profile.gohtml:29 @@ -468,11 +474,13 @@ msgstr "Contenu" #: web/templates/admin/legal/form.gohtml:88 #: web/templates/admin/carousel/form.gohtml:55 -#: web/templates/admin/campsite/feature/form.gohtml:74 -#: web/templates/admin/campsite/carousel/form.gohtml:59 -#: web/templates/admin/campsite/form.gohtml:74 -#: web/templates/admin/campsite/option/form.gohtml:90 +#: web/templates/admin/campsite/feature/form.gohtml:65 +#: web/templates/admin/campsite/carousel/form.gohtml:50 +#: web/templates/admin/campsite/form.gohtml:92 +#: web/templates/admin/campsite/type/feature/form.gohtml:74 +#: web/templates/admin/campsite/type/carousel/form.gohtml:59 #: web/templates/admin/campsite/type/form.gohtml:202 +#: web/templates/admin/campsite/type/option/form.gohtml:90 #: web/templates/admin/season/form.gohtml:73 #: web/templates/admin/services/form.gohtml:81 #: web/templates/admin/surroundings/form.gohtml:69 @@ -485,11 +493,13 @@ msgstr "Mettre à jour" #: web/templates/admin/legal/form.gohtml:90 #: web/templates/admin/carousel/form.gohtml:57 -#: web/templates/admin/campsite/feature/form.gohtml:76 -#: web/templates/admin/campsite/carousel/form.gohtml:61 -#: web/templates/admin/campsite/form.gohtml:76 -#: web/templates/admin/campsite/option/form.gohtml:92 +#: web/templates/admin/campsite/feature/form.gohtml:67 +#: web/templates/admin/campsite/carousel/form.gohtml:52 +#: web/templates/admin/campsite/form.gohtml:94 +#: web/templates/admin/campsite/type/feature/form.gohtml:76 +#: web/templates/admin/campsite/type/carousel/form.gohtml:61 #: web/templates/admin/campsite/type/form.gohtml:204 +#: web/templates/admin/campsite/type/option/form.gohtml:92 #: web/templates/admin/season/form.gohtml:75 #: web/templates/admin/services/form.gohtml:83 #: web/templates/admin/surroundings/form.gohtml:71 @@ -503,8 +513,9 @@ msgid "Add Legal Text" msgstr "Ajouter un texte juridique" #: web/templates/admin/legal/index.gohtml:20 -#: web/templates/admin/campsite/feature/index.gohtml:31 -#: web/templates/admin/campsite/option/index.gohtml:30 +#: web/templates/admin/campsite/feature/index.gohtml:30 +#: web/templates/admin/campsite/type/feature/index.gohtml:31 +#: web/templates/admin/campsite/type/option/index.gohtml:30 #: web/templates/admin/campsite/type/index.gohtml:29 #: web/templates/admin/season/index.gohtml:29 #: web/templates/admin/user/index.gohtml:20 @@ -530,7 +541,8 @@ msgid "New Carousel Slide" msgstr "Nouveau toboggan carrousel" #: web/templates/admin/carousel/form.gohtml:40 -#: web/templates/admin/campsite/carousel/form.gohtml:44 +#: web/templates/admin/campsite/carousel/form.gohtml:35 +#: web/templates/admin/campsite/type/carousel/form.gohtml:44 msgctxt "input" msgid "Caption" msgstr "Légende" @@ -563,98 +575,38 @@ msgid "Save changes" msgstr "Enregistrer les changements" #: web/templates/admin/campsite/feature/form.gohtml:8 -#: web/templates/admin/campsite/feature/form.gohtml:32 msgctxt "title" -msgid "Edit Campsite Type Feature" -msgstr "Modifier l’entité de type de camping" +msgid "Edit Campsite Feature" +msgstr "Modifier l’entité de camping" #: web/templates/admin/campsite/feature/form.gohtml:10 -#: web/templates/admin/campsite/feature/form.gohtml:34 msgctxt "title" -msgid "New Campsite Type Feature" -msgstr "Nouvelle fonctionnalité de type de camping" +msgid "New Campsite Feature" +msgstr "Nouvelle fonctionnalité de camping" #: web/templates/admin/campsite/feature/form.gohtml:17 -#: web/templates/admin/campsite/feature/index.gohtml:11 -#: web/templates/admin/campsite/carousel/form.gohtml:17 -#: web/templates/admin/campsite/carousel/index.gohtml:11 -#: web/templates/admin/campsite/option/form.gohtml:17 -#: web/templates/admin/campsite/option/index.gohtml:11 -#: web/templates/admin/campsite/type/form.gohtml:16 -#: web/templates/admin/campsite/type/index.gohtml:6 -#: web/templates/admin/campsite/type/index.gohtml:16 -#: web/templates/admin/layout.gohtml:43 -msgctxt "title" -msgid "Campsite Types" -msgstr "Types d’emplacements de camping" - -#: web/templates/admin/campsite/feature/form.gohtml:18 #: web/templates/admin/campsite/feature/index.gohtml:6 -#: web/templates/admin/campsite/feature/index.gohtml:17 msgctxt "title" -msgid "Campsite Type Features" -msgstr "Caractéristiques du type d’emplacement de camping" +msgid "Campsite Features" +msgstr "Caractéristiques de camping" -#: web/templates/admin/campsite/feature/form.gohtml:41 +#: web/templates/admin/campsite/feature/form.gohtml:32 +#: web/templates/admin/campsite/type/feature/form.gohtml:41 #: web/templates/admin/services/form.gohtml:35 msgctxt "input" msgid "Icon" msgstr "Icône" -#: web/templates/admin/campsite/feature/index.gohtml:16 +#: web/templates/admin/campsite/feature/index.gohtml:15 +#: web/templates/admin/campsite/type/feature/index.gohtml:16 msgctxt "action" msgid "Add Feature" msgstr "Ajouter une fonctionnalité" -#: web/templates/admin/campsite/feature/index.gohtml:48 -msgid "No campsite type features added yet." -msgstr "Aucune fonctionnalité de type camping n’a encore été ajoutée." - -#: web/templates/admin/campsite/carousel/form.gohtml:8 -#: web/templates/admin/campsite/carousel/form.gohtml:32 -msgctxt "title" -msgid "Edit Campsite Type Carousel Slide" -msgstr "Modifier la diapositive du carrousel de type camping" - -#: web/templates/admin/campsite/carousel/form.gohtml:10 -#: web/templates/admin/campsite/carousel/form.gohtml:34 -msgctxt "title" -msgid "New Campsite Type Carousel Slide" -msgstr "Nouveau toboggan de carrousel de type camping" - -#: web/templates/admin/campsite/carousel/form.gohtml:18 -#: web/templates/admin/campsite/carousel/index.gohtml:6 -#: web/templates/admin/campsite/carousel/index.gohtml:16 -msgctxt "title" -msgid "Campsite Type Carousel" -msgstr "Type de camping Carrousel" - -#: web/templates/admin/campsite/carousel/index.gohtml:17 -#: web/templates/admin/services/index.gohtml:15 -#: web/templates/admin/home/index.gohtml:84 -msgctxt "action" -msgid "Add slide" -msgstr "Ajouter la diapositive" - -#: web/templates/admin/campsite/carousel/index.gohtml:30 -#: web/templates/admin/services/index.gohtml:28 -#: web/templates/admin/surroundings/index.gohtml:82 -#: web/templates/admin/home/index.gohtml:52 -#: web/templates/admin/home/index.gohtml:97 -msgctxt "header" -msgid "Image" -msgstr "Image" - +#: web/templates/admin/campsite/feature/index.gohtml:31 #: web/templates/admin/campsite/carousel/index.gohtml:31 -#: web/templates/admin/services/index.gohtml:29 -#: web/templates/admin/home/index.gohtml:53 -#: web/templates/admin/home/index.gohtml:98 -msgctxt "header" -msgid "Caption" -msgstr "Légende" - -#: web/templates/admin/campsite/carousel/index.gohtml:32 -#: web/templates/admin/campsite/option/index.gohtml:31 +#: web/templates/admin/campsite/type/carousel/index.gohtml:32 +#: web/templates/admin/campsite/type/option/index.gohtml:31 #: web/templates/admin/services/index.gohtml:30 #: web/templates/admin/services/index.gohtml:75 #: web/templates/admin/user/index.gohtml:23 @@ -665,14 +617,15 @@ msgctxt "header" msgid "Actions" msgstr "Actions" -#: web/templates/admin/campsite/carousel/index.gohtml:36 -#: web/templates/admin/services/index.gohtml:34 -#: web/templates/admin/home/index.gohtml:103 -msgid "Are you sure you wish to delete this slide?" -msgstr "Êtes-vous sûr de vouloir supprimer cette diapositive ?" +#: web/templates/admin/campsite/feature/index.gohtml:35 +#: web/templates/admin/campsite/type/option/index.gohtml:35 +msgid "Are you sure you wish to delete this option?" +msgstr "Êtes-vous sûr de vouloir supprimer cette option ?" -#: web/templates/admin/campsite/carousel/index.gohtml:50 -#: web/templates/admin/campsite/option/index.gohtml:47 +#: web/templates/admin/campsite/feature/index.gohtml:47 +#: web/templates/admin/campsite/carousel/index.gohtml:49 +#: web/templates/admin/campsite/type/carousel/index.gohtml:50 +#: web/templates/admin/campsite/type/option/index.gohtml:47 #: web/templates/admin/services/index.gohtml:47 #: web/templates/admin/services/index.gohtml:91 #: web/templates/admin/user/index.gohtml:37 @@ -684,125 +637,220 @@ msgctxt "action" msgid "Delete" msgstr "Supprimer" -#: web/templates/admin/campsite/carousel/index.gohtml:59 +#: web/templates/admin/campsite/feature/index.gohtml:56 +msgid "No campsite features added yet." +msgstr "Aucune fonctionnalité de camping n’a encore été ajoutée." + +#: web/templates/admin/campsite/carousel/form.gohtml:8 +msgctxt "title" +msgid "Edit Campsite Carousel Slide" +msgstr "Modifier la diapositive du carrousel de camping" + +#: web/templates/admin/campsite/carousel/form.gohtml:10 +msgctxt "title" +msgid "New Campsite Carousel Slide" +msgstr "Nouveau toboggan de carrousel de camping" + +#: web/templates/admin/campsite/carousel/form.gohtml:17 +#: web/templates/admin/campsite/carousel/index.gohtml:6 +msgctxt "title" +msgid "Campsite Carousel" +msgstr "Camping Carrousel" + +#: web/templates/admin/campsite/carousel/index.gohtml:16 +#: web/templates/admin/campsite/type/carousel/index.gohtml:17 +#: web/templates/admin/services/index.gohtml:15 +#: web/templates/admin/home/index.gohtml:84 +msgctxt "action" +msgid "Add slide" +msgstr "Ajouter la diapositive" + +#: web/templates/admin/campsite/carousel/index.gohtml:29 +#: web/templates/admin/campsite/type/carousel/index.gohtml:30 +#: web/templates/admin/services/index.gohtml:28 +#: web/templates/admin/surroundings/index.gohtml:82 +#: web/templates/admin/home/index.gohtml:52 +#: web/templates/admin/home/index.gohtml:97 +msgctxt "header" +msgid "Image" +msgstr "Image" + +#: web/templates/admin/campsite/carousel/index.gohtml:30 +#: web/templates/admin/campsite/type/carousel/index.gohtml:31 +#: web/templates/admin/services/index.gohtml:29 +#: web/templates/admin/home/index.gohtml:53 +#: web/templates/admin/home/index.gohtml:98 +msgctxt "header" +msgid "Caption" +msgstr "Légende" + +#: web/templates/admin/campsite/carousel/index.gohtml:35 +#: web/templates/admin/campsite/type/carousel/index.gohtml:36 +#: web/templates/admin/services/index.gohtml:34 +#: web/templates/admin/home/index.gohtml:103 +msgid "Are you sure you wish to delete this slide?" +msgstr "Êtes-vous sûr de vouloir supprimer cette diapositive ?" + +#: web/templates/admin/campsite/carousel/index.gohtml:58 +#: web/templates/admin/campsite/type/carousel/index.gohtml:59 #: web/templates/admin/services/index.gohtml:56 #: web/templates/admin/home/index.gohtml:125 msgid "No slides added yet." msgstr "Aucune diapositive n’a encore été ajoutée." #: web/templates/admin/campsite/form.gohtml:8 -#: web/templates/admin/campsite/form.gohtml:29 msgctxt "title" msgid "Edit Campsite" msgstr "Modifier le camping" #: web/templates/admin/campsite/form.gohtml:10 -#: web/templates/admin/campsite/form.gohtml:31 msgctxt "title" msgid "New Campsite" msgstr "Nouveau camping" -#: web/templates/admin/campsite/form.gohtml:41 -#: web/templates/admin/campsite/index.gohtml:23 +#: web/templates/admin/campsite/form.gohtml:33 +#: web/templates/admin/campsite/index.gohtml:27 msgctxt "campsite" msgid "Active" msgstr "Actif" -#: web/templates/admin/campsite/form.gohtml:50 +#: web/templates/admin/campsite/form.gohtml:42 msgctxt "input" msgid "Campsite Type" msgstr "Type d’emplacement de camping" -#: web/templates/admin/campsite/form.gohtml:55 +#: web/templates/admin/campsite/form.gohtml:47 msgid "Select campsite type" msgstr "Sélectionnez le type d’emplacement" -#: web/templates/admin/campsite/form.gohtml:64 +#: web/templates/admin/campsite/form.gohtml:56 msgctxt "input" msgid "Label" msgstr "Label" -#: web/templates/admin/campsite/option/form.gohtml:8 -#: web/templates/admin/campsite/option/form.gohtml:32 -msgctxt "title" -msgid "Edit Campsite Type Option" -msgstr "Modifier l’option Type d’emplacement de camping" - -#: web/templates/admin/campsite/option/form.gohtml:10 -#: web/templates/admin/campsite/option/form.gohtml:34 -msgctxt "title" -msgid "New Campsite Type Option" -msgstr "Nouvelle option de type d’emplacement de camping" - -#: web/templates/admin/campsite/option/form.gohtml:18 -#: web/templates/admin/campsite/option/index.gohtml:6 -#: web/templates/admin/campsite/option/index.gohtml:17 -msgctxt "title" -msgid "Campsite Type Options" -msgstr "Options de type d’emplacement de camping" - -#: web/templates/admin/campsite/option/form.gohtml:54 +#: web/templates/admin/campsite/form.gohtml:64 msgctxt "input" -msgid "Minimum" -msgstr "Minimum" +msgid "Info (First Column)" +msgstr "Info (première colonne)" -#: web/templates/admin/campsite/option/form.gohtml:62 +#: web/templates/admin/campsite/form.gohtml:77 msgctxt "input" -msgid "Maximum" -msgstr "Maximum" - -#: web/templates/admin/campsite/option/form.gohtml:76 -#: web/templates/admin/campsite/type/form.gohtml:115 -msgctxt "input" -msgid "Price per night" -msgstr "Prix par nuit" - -#: web/templates/admin/campsite/option/index.gohtml:16 -msgctxt "action" -msgid "Add Option" -msgstr "Ajouter une option" - -#: web/templates/admin/campsite/option/index.gohtml:35 -msgid "Are you sure you wish to delete this option?" -msgstr "Êtes-vous sûr de vouloir supprimer cette option ?" - -#: web/templates/admin/campsite/option/index.gohtml:56 -msgid "No campsite type options added yet." -msgstr "Aucune option de type de camping n’a encore été ajoutée." +msgid "Info (Second Column)" +msgstr "Info (deuxième colonne)" #: web/templates/admin/campsite/index.gohtml:14 msgctxt "action" msgid "Add Campsite" msgstr "Ajouter un camping" -#: web/templates/admin/campsite/index.gohtml:21 +#: web/templates/admin/campsite/index.gohtml:23 msgctxt "header" msgid "Label" msgstr "Label" -#: web/templates/admin/campsite/index.gohtml:22 +#: web/templates/admin/campsite/index.gohtml:24 msgctxt "header" msgid "Type" msgstr "Type" -#: web/templates/admin/campsite/index.gohtml:31 +#: web/templates/admin/campsite/index.gohtml:25 +#: web/templates/admin/campsite/type/index.gohtml:30 +msgctxt "header" +msgid "Features" +msgstr "Caractéristiques" + +#: web/templates/admin/campsite/index.gohtml:26 +#: web/templates/admin/campsite/type/index.gohtml:32 +msgctxt "header" +msgid "Carousel" +msgstr "Carrousel" + +#: web/templates/admin/campsite/index.gohtml:36 +#: web/templates/admin/campsite/type/index.gohtml:45 +msgctxt "action" +msgid "Edit Features" +msgstr "Edit Caractéristiques" + +#: web/templates/admin/campsite/index.gohtml:39 +#: web/templates/admin/campsite/type/index.gohtml:51 +msgctxt "action" +msgid "Edit Carousel" +msgstr "Modifier le carrousel" + +#: web/templates/admin/campsite/index.gohtml:41 #: web/templates/admin/campsite/type/index.gohtml:53 #: web/templates/admin/season/index.gohtml:44 #: web/templates/admin/user/login-attempts.gohtml:31 msgid "Yes" msgstr "Oui" -#: web/templates/admin/campsite/index.gohtml:31 +#: web/templates/admin/campsite/index.gohtml:41 #: web/templates/admin/campsite/type/index.gohtml:53 #: web/templates/admin/season/index.gohtml:44 #: web/templates/admin/user/login-attempts.gohtml:31 msgid "No" msgstr "Non" -#: web/templates/admin/campsite/index.gohtml:37 +#: web/templates/admin/campsite/index.gohtml:47 msgid "No campsites added yet." msgstr "Aucun camping n’a encore été ajouté." +#: web/templates/admin/campsite/type/feature/form.gohtml:8 +#: web/templates/admin/campsite/type/feature/form.gohtml:32 +msgctxt "title" +msgid "Edit Campsite Type Feature" +msgstr "Modifier l’entité de type de camping" + +#: web/templates/admin/campsite/type/feature/form.gohtml:10 +#: web/templates/admin/campsite/type/feature/form.gohtml:34 +msgctxt "title" +msgid "New Campsite Type Feature" +msgstr "Nouvelle fonctionnalité de type de camping" + +#: web/templates/admin/campsite/type/feature/form.gohtml:17 +#: web/templates/admin/campsite/type/feature/index.gohtml:11 +#: web/templates/admin/campsite/type/carousel/form.gohtml:17 +#: web/templates/admin/campsite/type/carousel/index.gohtml:11 +#: web/templates/admin/campsite/type/form.gohtml:16 +#: web/templates/admin/campsite/type/option/form.gohtml:17 +#: web/templates/admin/campsite/type/option/index.gohtml:11 +#: web/templates/admin/campsite/type/index.gohtml:6 +#: web/templates/admin/campsite/type/index.gohtml:16 +#: web/templates/admin/layout.gohtml:43 +msgctxt "title" +msgid "Campsite Types" +msgstr "Types d’emplacements de camping" + +#: web/templates/admin/campsite/type/feature/form.gohtml:18 +#: web/templates/admin/campsite/type/feature/index.gohtml:6 +#: web/templates/admin/campsite/type/feature/index.gohtml:17 +msgctxt "title" +msgid "Campsite Type Features" +msgstr "Caractéristiques du type d’emplacement de camping" + +#: web/templates/admin/campsite/type/feature/index.gohtml:48 +msgid "No campsite type features added yet." +msgstr "Aucune fonctionnalité de type camping n’a encore été ajoutée." + +#: web/templates/admin/campsite/type/carousel/form.gohtml:8 +#: web/templates/admin/campsite/type/carousel/form.gohtml:32 +msgctxt "title" +msgid "Edit Campsite Type Carousel Slide" +msgstr "Modifier la diapositive du carrousel de type camping" + +#: web/templates/admin/campsite/type/carousel/form.gohtml:10 +#: web/templates/admin/campsite/type/carousel/form.gohtml:34 +msgctxt "title" +msgid "New Campsite Type Carousel Slide" +msgstr "Nouveau toboggan de carrousel de type camping" + +#: web/templates/admin/campsite/type/carousel/form.gohtml:18 +#: web/templates/admin/campsite/type/carousel/index.gohtml:6 +#: web/templates/admin/campsite/type/carousel/index.gohtml:16 +msgctxt "title" +msgid "Campsite Type Carousel" +msgstr "Type de camping Carrousel" + #: web/templates/admin/campsite/type/form.gohtml:8 #: web/templates/admin/campsite/type/form.gohtml:30 msgctxt "title" @@ -841,6 +889,12 @@ msgctxt "input" msgid "Dogs allowed" msgstr "Chiens acceptés" +#: web/templates/admin/campsite/type/form.gohtml:115 +#: web/templates/admin/campsite/type/option/form.gohtml:76 +msgctxt "input" +msgid "Price per night" +msgstr "Prix par nuit" + #: web/templates/admin/campsite/type/form.gohtml:123 msgctxt "input" msgid "Minimum number of nights" @@ -873,41 +927,59 @@ msgctxt "input" msgid "Additional Information" msgstr "Informations Complémentaires" +#: web/templates/admin/campsite/type/option/form.gohtml:8 +#: web/templates/admin/campsite/type/option/form.gohtml:32 +msgctxt "title" +msgid "Edit Campsite Type Option" +msgstr "Modifier l’option Type d’emplacement de camping" + +#: web/templates/admin/campsite/type/option/form.gohtml:10 +#: web/templates/admin/campsite/type/option/form.gohtml:34 +msgctxt "title" +msgid "New Campsite Type Option" +msgstr "Nouvelle option de type d’emplacement de camping" + +#: web/templates/admin/campsite/type/option/form.gohtml:18 +#: web/templates/admin/campsite/type/option/index.gohtml:6 +#: web/templates/admin/campsite/type/option/index.gohtml:17 +msgctxt "title" +msgid "Campsite Type Options" +msgstr "Options de type d’emplacement de camping" + +#: web/templates/admin/campsite/type/option/form.gohtml:54 +msgctxt "input" +msgid "Minimum" +msgstr "Minimum" + +#: web/templates/admin/campsite/type/option/form.gohtml:62 +msgctxt "input" +msgid "Maximum" +msgstr "Maximum" + +#: web/templates/admin/campsite/type/option/index.gohtml:16 +msgctxt "action" +msgid "Add Option" +msgstr "Ajouter une option" + +#: web/templates/admin/campsite/type/option/index.gohtml:56 +msgid "No campsite type options added yet." +msgstr "Aucune option de type de camping n’a encore été ajoutée." + #: web/templates/admin/campsite/type/index.gohtml:15 msgctxt "action" msgid "Add Type" msgstr "Ajouter un type" -#: web/templates/admin/campsite/type/index.gohtml:30 -msgctxt "header" -msgid "Features" -msgstr "Caractéristiques" - #: web/templates/admin/campsite/type/index.gohtml:31 msgctxt "header" msgid "Options" msgstr "Options" -#: web/templates/admin/campsite/type/index.gohtml:32 -msgctxt "header" -msgid "Carousel" -msgstr "Carrousel" - -#: web/templates/admin/campsite/type/index.gohtml:45 -msgctxt "action" -msgid "Edit Features" -msgstr "Edit Caractéristiques" - #: web/templates/admin/campsite/type/index.gohtml:48 msgctxt "action" msgid "Edit Options" msgstr "Modifier les options" -#: web/templates/admin/campsite/type/index.gohtml:51 -msgctxt "action" -msgid "Edit Carousel" -msgstr "Modifier le carrousel" - #: web/templates/admin/campsite/type/index.gohtml:60 msgid "No campsite types added yet." msgstr "Aucun type d’emplacement n’a encore été ajouté." @@ -1468,33 +1540,36 @@ msgstr "Aucune réservation trouvée." #: pkg/legal/admin.go:258 pkg/app/user.go:249 pkg/campsite/types/option.go:357 #: pkg/campsite/types/feature.go:259 pkg/campsite/types/admin.go:483 -#: pkg/season/admin.go:412 pkg/services/admin.go:316 -#: pkg/surroundings/admin.go:340 +#: pkg/campsite/feature.go:269 pkg/season/admin.go:412 +#: pkg/services/admin.go:316 pkg/surroundings/admin.go:340 msgid "Name can not be empty." msgstr "Le nom ne peut pas être laissé vide." #: pkg/legal/admin.go:259 pkg/campsite/types/option.go:358 #: pkg/campsite/types/feature.go:260 pkg/campsite/types/admin.go:484 +#: pkg/campsite/feature.go:270 msgid "Name must have at least one letter." msgstr "Le nom doit comporter au moins une lettre." #: pkg/carousel/admin.go:276 pkg/campsite/types/carousel.go:225 +#: pkg/campsite/carousel.go:227 msgctxt "input" msgid "Slide image" msgstr "Image du diaporama" #: pkg/carousel/admin.go:277 pkg/campsite/types/carousel.go:226 +#: pkg/campsite/carousel.go:228 msgctxt "action" msgid "Set slide image" msgstr "Définir l’image de la diapositive" #: pkg/carousel/admin.go:346 pkg/campsite/types/carousel.go:299 -#: pkg/surroundings/admin.go:335 +#: pkg/campsite/carousel.go:302 pkg/surroundings/admin.go:335 msgid "Slide image can not be empty." msgstr "L’image de la diapositive ne peut pas être vide." #: pkg/carousel/admin.go:347 pkg/campsite/types/carousel.go:300 -#: pkg/surroundings/admin.go:336 +#: pkg/campsite/carousel.go:303 pkg/surroundings/admin.go:336 msgid "Slide image must be an image media type." msgstr "L’image de la diapositive doit être de type média d’image." @@ -1573,7 +1648,8 @@ msgstr "Le prix par nuit doit être un nombre décimal." msgid "Price per night must be zero or greater." msgstr "Le prix par nuit doit être égal ou supérieur." -#: pkg/campsite/types/feature.go:258 pkg/services/admin.go:315 +#: pkg/campsite/types/feature.go:258 pkg/campsite/feature.go:268 +#: pkg/services/admin.go:315 msgid "Selected icon is not valid." msgstr "L’icône sélectionnée n’est pas valide." @@ -1627,11 +1703,11 @@ msgstr "Le nombre minimum de nuits doit être un entier." msgid "Minimum number of nights must be one or greater." msgstr "Le nombre minimum de nuits doit être supérieur ou égal à une nuit." -#: pkg/campsite/admin.go:226 pkg/booking/public.go:278 +#: pkg/campsite/admin.go:274 pkg/booking/public.go:278 msgid "Selected campsite type is not valid." msgstr "Le type d’emplacement sélectionné n’est pas valide." -#: pkg/campsite/admin.go:227 +#: pkg/campsite/admin.go:275 msgid "Label can not be empty." msgstr "L'étiquette ne peut pas être vide." diff --git a/revert/add_campsite.sql b/revert/add_campsite.sql index b349d62..2a2b048 100644 --- a/revert/add_campsite.sql +++ b/revert/add_campsite.sql @@ -1,7 +1,36 @@ --- Revert camper:add_campsite from pg +-- Deploy camper:add_campsite to pg +-- requires: roles +-- requires: schema_camper +-- requires: campsite +-- requires: campsite_type begin; -drop function if exists camper.add_campsite(integer, text); +set search_path to camper, public; + +drop function if exists add_campsite(integer, text, text, text); + +create or replace function add_campsite(campsite_type integer, label text) returns integer as +$$ +declare + cid integer; +begin + insert into campsite (company_id, campsite_type_id, label) + select company_id, campsite_type_id, label + from campsite_type + where campsite_type_id = add_campsite.campsite_type + returning campsite_id into cid + ; + if cid is null then + raise foreign_key_violation using message = 'insert or update on table "campsite" violates foreign key constraint "campsite_campsite_type_id_fkey"'; + end if; + return cid; +end +$$ + language plpgsql +; + +revoke execute on function add_campsite(integer, text) from public; +grant execute on function add_campsite(integer, text) to admin; commit; diff --git a/revert/add_campsite@v1.sql b/revert/add_campsite@v1.sql new file mode 100644 index 0000000..b349d62 --- /dev/null +++ b/revert/add_campsite@v1.sql @@ -0,0 +1,7 @@ +-- Revert camper:add_campsite from pg + +begin; + +drop function if exists camper.add_campsite(integer, text); + +commit; diff --git a/revert/add_campsite_carousel_slide.sql b/revert/add_campsite_carousel_slide.sql new file mode 100644 index 0000000..9c71ffc --- /dev/null +++ b/revert/add_campsite_carousel_slide.sql @@ -0,0 +1,7 @@ +-- Revert camper:add_campsite_carousel_slide from pg + +begin; + +drop function if exists camper.add_campsite_carousel_slide(integer, text, integer, text); + +commit; diff --git a/revert/add_campsite_feature.sql b/revert/add_campsite_feature.sql new file mode 100644 index 0000000..bd2859c --- /dev/null +++ b/revert/add_campsite_feature.sql @@ -0,0 +1,7 @@ +-- Revert camper:add_campsite_feature from pg + +begin; + +drop function if exists camper.add_campsite_feature(integer, text, text, text); + +commit; diff --git a/revert/campsite__info.sql b/revert/campsite__info.sql new file mode 100644 index 0000000..20ca098 --- /dev/null +++ b/revert/campsite__info.sql @@ -0,0 +1,10 @@ +-- Revert camper:campsite__info from pg + +begin; + +alter table camper.campsite + drop column if exists info1 +, drop column if exists info2 +; + +commit; diff --git a/revert/campsite_carousel.sql b/revert/campsite_carousel.sql new file mode 100644 index 0000000..5dadf7b --- /dev/null +++ b/revert/campsite_carousel.sql @@ -0,0 +1,7 @@ +-- Revert camper:campsite_carousel from pg + +begin; + +drop table if exists camper.campsite_carousel; + +commit; diff --git a/revert/campsite_carousel_i18n.sql b/revert/campsite_carousel_i18n.sql new file mode 100644 index 0000000..4a560a1 --- /dev/null +++ b/revert/campsite_carousel_i18n.sql @@ -0,0 +1,7 @@ +-- Revert camper:campsite_carousel_i18n from pg + +begin; + +drop table if exists camper.campsite_carousel_i18n; + +commit; diff --git a/revert/campsite_feature.sql b/revert/campsite_feature.sql new file mode 100644 index 0000000..9ac2de6 --- /dev/null +++ b/revert/campsite_feature.sql @@ -0,0 +1,7 @@ +-- Revert camper:campsite_feature from pg + +begin; + +drop table if exists camper.campsite_feature; + +commit; diff --git a/revert/campsite_feature_i18n.sql b/revert/campsite_feature_i18n.sql new file mode 100644 index 0000000..5dd1c5c --- /dev/null +++ b/revert/campsite_feature_i18n.sql @@ -0,0 +1,7 @@ +-- Revert camper:campsite_feature_i18n from pg + +begin; + +drop table if exists camper.campsite_feature_i18n; + +commit; diff --git a/revert/campsite_i18n.sql b/revert/campsite_i18n.sql new file mode 100644 index 0000000..9f2c4b2 --- /dev/null +++ b/revert/campsite_i18n.sql @@ -0,0 +1,7 @@ +-- Revert camper:campsite_i18n from pg + +begin; + +drop table if exists camper.campsite_i18n; + +commit; diff --git a/revert/edit_campsite.sql b/revert/edit_campsite.sql index 464a4e2..bf109da 100644 --- a/revert/edit_campsite.sql +++ b/revert/edit_campsite.sql @@ -1,7 +1,27 @@ --- Revert camper:edit_campsite from pg +-- Deploy camper:edit_campsite to pg +-- requires: roles +-- requires: schema_camper +-- requires: campsite begin; -drop function if exists camper.edit_campsite(integer, integer, text, boolean); +set search_path to camper, public; + +drop function if exists edit_campsite(integer, integer, text, text, text, boolean); + +create or replace function edit_campsite(campsite_id integer, campsite_type integer, new_label text, active boolean) returns integer as +$$ + update campsite + set label = edit_campsite.new_label + , campsite_type_id = edit_campsite.campsite_type + , active = edit_campsite.active + where campsite_id = edit_campsite.campsite_id + returning campsite_id; +$$ + language sql +; + +revoke execute on function edit_campsite(integer, integer, text, boolean) from public; +grant execute on function edit_campsite(integer, integer, text, boolean) to admin; commit; diff --git a/revert/edit_campsite@v1.sql b/revert/edit_campsite@v1.sql new file mode 100644 index 0000000..464a4e2 --- /dev/null +++ b/revert/edit_campsite@v1.sql @@ -0,0 +1,7 @@ +-- Revert camper:edit_campsite from pg + +begin; + +drop function if exists camper.edit_campsite(integer, integer, text, boolean); + +commit; diff --git a/revert/edit_campsite_feature.sql b/revert/edit_campsite_feature.sql new file mode 100644 index 0000000..5bb0f8b --- /dev/null +++ b/revert/edit_campsite_feature.sql @@ -0,0 +1,7 @@ +-- Revert camper:edit_campsite_feature from pg + +begin; + +drop function if exists camper.edit_campsite_feature(integer, text, text); + +commit; diff --git a/revert/order_campsite_carousel.sql b/revert/order_campsite_carousel.sql new file mode 100644 index 0000000..d6d9e09 --- /dev/null +++ b/revert/order_campsite_carousel.sql @@ -0,0 +1,7 @@ +-- Revert camper:order_campsite_carousel from pg + +begin; + +drop function if exists camper.order_campsite_carousel(text, integer, integer[]); + +commit; diff --git a/revert/order_campsite_features.sql b/revert/order_campsite_features.sql new file mode 100644 index 0000000..acc5c81 --- /dev/null +++ b/revert/order_campsite_features.sql @@ -0,0 +1,7 @@ +-- Revert camper:order_campsite_features from pg + +begin; + +drop function if exists camper.order_campsite_features(integer[]); + +commit; diff --git a/revert/remove_campsite_carousel_slide.sql b/revert/remove_campsite_carousel_slide.sql new file mode 100644 index 0000000..48921a7 --- /dev/null +++ b/revert/remove_campsite_carousel_slide.sql @@ -0,0 +1,7 @@ +-- Revert camper:remove_campsite_carousel_slide from pg + +begin; + +drop function if exists camper.remove_campsite_carousel_slide(integer, text, integer); + +commit; diff --git a/revert/remove_campsite_feature.sql b/revert/remove_campsite_feature.sql new file mode 100644 index 0000000..73af3b3 --- /dev/null +++ b/revert/remove_campsite_feature.sql @@ -0,0 +1,7 @@ +-- Revert camper:remove_campsite_feature from pg + +begin; + +drop function if exists camper.remove_campsite_feature(integer); + +commit; diff --git a/revert/translate_campsite.sql b/revert/translate_campsite.sql new file mode 100644 index 0000000..79194d7 --- /dev/null +++ b/revert/translate_campsite.sql @@ -0,0 +1,7 @@ +-- Revert camper:translate_campsite from pg + +begin; + +drop function if exists camper.translate_campsite(integer, text, text, text); + +commit; diff --git a/revert/translate_campsite_carousel_slide.sql b/revert/translate_campsite_carousel_slide.sql new file mode 100644 index 0000000..92b6405 --- /dev/null +++ b/revert/translate_campsite_carousel_slide.sql @@ -0,0 +1,7 @@ +-- Revert camper:translate_campsite_carousel_slide from pg + +begin; + +drop function if exists camper.translate_campsite_carousel_slide(integer, text, integer, text, text); + +commit; diff --git a/revert/translate_campsite_feature.sql b/revert/translate_campsite_feature.sql new file mode 100644 index 0000000..534f0d6 --- /dev/null +++ b/revert/translate_campsite_feature.sql @@ -0,0 +1,7 @@ +-- Revert camper:translate_campsite_feature from pg + +begin; + +drop function if exists camper.translate_campsite_feature(integer, text, text); + +commit; diff --git a/sqitch.plan b/sqitch.plan index 7b536fe..772b38f 100644 --- a/sqitch.plan +++ b/sqitch.plan @@ -178,3 +178,21 @@ surroundings_ad_i18n [roles schema_camper surroundings_ad language] 2024-01-23T1 remove_surroundings_ad [roles schema_camper surroundings_ad surroundings_ad_i18n] 2024-01-23T11:41:47Z jordi fita mas # Add function to remove surroundings ad translate_surroundings_ad [roles schema_camper surroundings_ad_i18n] 2024-01-23T12:06:32Z jordi fita mas # Add function to translate surroundings ad available_icons [available_icons@v1] 2024-01-23T23:56:34Z jordi fita mas # Add pet icon +campsite__info [campsite] 2024-01-25T18:49:56Z jordi fita mas # Add info1 and info2 columns to campsite +add_campsite [add_campsite@v1 campsite__info] 2024-01-25T19:03:30Z jordi fita mas # Add info1 and info2 parameters to add_campsite +edit_campsite [edit_campsite@v1 campsite__info] 2024-01-25T19:06:38Z jordi fita mas # Add info1 and info2 parameters to edit_campsite +campsite_i18n [roles schema_camper campsite language] 2024-01-25T19:15:42Z jordi fita mas # Add relation for campsite translation +translate_campsite [roles schema_camper campsite_i18n] 2024-01-25T19:21:58Z jordi fita mas # Add function to translate campsites +campsite_carousel [roles schema_camper campsite media user_profile] 2024-01-26T01:43:53Z jordi fita mas # Add relation of campsite carousel slides +add_campsite_carousel_slide [roles schema_camper campsite campsite_carousel] 2024-01-26T02:06:17Z jordi fita mas # Add function to add campsite carousel slides +order_campsite_carousel [roles campsite_carousel campsite] 2024-01-26T02:19:24Z jordi fita mas # Add function to order campsite carousel slides +campsite_carousel_i18n [roles schema_camper campsite_carousel language] 2024-01-26T02:32:57Z jordi fita mas # Add relation of campsite carousel translations +translate_campsite_carousel_slide [roles schema_camper campsite campsite_carousel_i18n] 2024-01-26T02:41:27Z jordi fita mas # Add function to translate campsite carousel slides +remove_campsite_carousel_slide [roles schema_camper campsite_carousel campsite_carousel_i18n] 2024-01-26T02:56:26Z jordi fita mas # Add function to remove campsite carousel slide +campsite_feature [roles schema_camper campsite icon user_profile] 2024-01-26T18:36:53Z jordi fita mas # Add relation of campsite features +add_campsite_feature [roles schema_camper campsite_feature campsite] 2024-01-26T18:54:02Z jordi fita mas # Add function to add campsite features +edit_campsite_feature [roles schema_camper campsite_feature] 2024-01-26T19:02:58Z jordi fita mas # Add function to edit campsite features +order_campsite_features [roles schema_camper campsite_feature] 2024-01-26T19:09:46Z jordi fita mas # Add function to order campsite features +campsite_feature_i18n [roles schema_camper campsite_feature language] 2024-01-26T19:17:09Z jordi fita mas # Add relation for campsite features translation +translate_campsite_feature [roles schema_camper campsite_feature_i18n] 2024-01-26T19:26:21Z jordi fita mas # Add function to translate campsite features +remove_campsite_feature [roles schema_camper campsite_feature campsite_feature_i18n] 2024-01-26T19:34:52Z jordi fita mas # Add function to remove campsite features diff --git a/test/add_campsite.sql b/test/add_campsite.sql index e996f1f..a33a831 100644 --- a/test/add_campsite.sql +++ b/test/add_campsite.sql @@ -9,15 +9,15 @@ set search_path to camper, public; select plan(14); -select has_function('camper', 'add_campsite', array ['integer', 'text']); -select function_lang_is('camper', 'add_campsite', array ['integer', 'text'], 'plpgsql'); -select function_returns('camper', 'add_campsite', array ['integer', 'text'], 'integer'); -select isnt_definer('camper', 'add_campsite', array ['integer', 'text']); -select volatility_is('camper', 'add_campsite', array ['integer', 'text'], 'volatile'); -select function_privs_are('camper', 'add_campsite', array ['integer', 'text'], 'guest', array[]::text[]); -select function_privs_are('camper', 'add_campsite', array ['integer', 'text'], 'employee', array[]::text[]); -select function_privs_are('camper', 'add_campsite', array ['integer', 'text'], 'admin', array['EXECUTE']); -select function_privs_are('camper', 'add_campsite', array ['integer', 'text'], 'authenticator', array[]::text[]); +select has_function('camper', 'add_campsite', array ['integer', 'text', 'text', 'text']); +select function_lang_is('camper', 'add_campsite', array ['integer', 'text', 'text', 'text'], 'plpgsql'); +select function_returns('camper', 'add_campsite', array ['integer', 'text', 'text', 'text'], 'integer'); +select isnt_definer('camper', 'add_campsite', array ['integer', 'text', 'text', 'text']); +select volatility_is('camper', 'add_campsite', array ['integer', 'text', 'text', 'text'], 'volatile'); +select function_privs_are('camper', 'add_campsite', array ['integer', 'text', 'text', 'text'], 'guest', array[]::text[]); +select function_privs_are('camper', 'add_campsite', array ['integer', 'text', 'text', 'text'], 'employee', array[]::text[]); +select function_privs_are('camper', 'add_campsite', array ['integer', 'text', 'text', 'text'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'add_campsite', array ['integer', 'text', 'text', 'text'], 'authenticator', array[]::text[]); set client_min_messages to warning; @@ -50,31 +50,31 @@ values (11, 1, 3, 'A', false, 5) ; select lives_ok( - $$ select add_campsite(11, 'A1') $$, + $$ select add_campsite(11, 'A1', '

A1.1

', '

A1.2

') $$, 'Should be able to add a campsite to the first company' ); select lives_ok( - $$ select add_campsite(12, 'B1') $$, + $$ select add_campsite(12, 'B1', '

B1.1

', '

B1.2

') $$, 'Should be able to add a campsite to the same company, but of a different type' ); select lives_ok( - $$ select add_campsite(21, 'C1') $$, + $$ select add_campsite(21, 'C1', '

C1.1

', '

C1.2

') $$, 'Should be able to add a campsite to the second company' ); select throws_ok( - $$ select add_campsite(22, 'C1') $$, + $$ select add_campsite(22, 'C1', '', '') $$, '23503', 'insert or update on table "campsite" violates foreign key constraint "campsite_campsite_type_id_fkey"', 'Should raise an error if the campsite type is not valid.' ); select bag_eq( - $$ select company_id, campsite_type_id, label, active from campsite $$, - $$ values (1, 11, 'A1', true) - , (1, 12, 'B1', true) - , (2, 21, 'C1', true) + $$ select company_id, campsite_type_id, label, info1::text, info2::text, active from campsite $$, + $$ values (1, 11, 'A1', '

A1.1

', '

A1.2

', true) + , (1, 12, 'B1', '

B1.1

', '

B1.2

', true) + , (2, 21, 'C1', '

C1.1

', '

C1.2

', true) $$, 'Should have added all campsites' ); diff --git a/test/add_campsite_carousel_slide.sql b/test/add_campsite_carousel_slide.sql new file mode 100644 index 0000000..8d26156 --- /dev/null +++ b/test/add_campsite_carousel_slide.sql @@ -0,0 +1,96 @@ +-- Test add_campsite_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', 'add_campsite_carousel_slide', array['integer', 'text', 'integer', 'text']); +select function_lang_is('camper', 'add_campsite_carousel_slide', array['integer', 'text', 'integer', 'text'], 'sql'); +select function_returns('camper', 'add_campsite_carousel_slide', array['integer', 'text', 'integer', 'text'], 'integer'); +select isnt_definer('camper', 'add_campsite_carousel_slide', array['integer', 'text', 'integer', 'text']); +select volatility_is('camper', 'add_campsite_carousel_slide', array['integer', 'text', 'integer', 'text'], 'volatile'); +select function_privs_are('camper', 'add_campsite_carousel_slide', array['integer', 'text', 'integer', 'text'], 'guest', array[]::text[]); +select function_privs_are('camper', 'add_campsite_carousel_slide', array['integer', 'text', 'integer', 'text'], 'employee', array[]::text[]); +select function_privs_are('camper', 'add_campsite_carousel_slide', array['integer', 'text', 'integer', 'text'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'add_campsite_carousel_slide', array['integer', 'text', 'integer', 'text'], 'authenticator', array[]::text[]); + + +set client_min_messages to warning; +truncate campsite_carousel cascade; +truncate campsite 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, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag) +values (1, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') + , (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') +; + +insert into media_content (media_type, bytes) +values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};') + , ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ff00ff","a"};') + , ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffff00","a"};') + , ('text/plain', 'hello, world!') + , ('image/svg+xml', '') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values (3, 1, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) + , (4, 2, 'cover3.xpm', sha256('static char *s[]={"1 1 1 1","a c #ff00ff","a"};')) + , (5, 1, 'cover4.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffff00","a"};')) + , (6, 1, 'text.txt', sha256('hello, world!')) + , (7, 1, 'image.svg', sha256('')) +; + +insert into campsite_type (campsite_type_id, company_id, media_id, name, description, max_campers, dogs_allowed, active) +values (10, 1, 3, 'Type A', '

A

', 5, false, true) + , (11, 2, 4, 'Type A', '

A

', 5, false, true) +; + +insert into campsite (campsite_id, company_id, label, campsite_type_id) +values (11, 1, 'A1', 10) + , (12, 1, 'Z9', 10) + , (13, 2, 'A1', 11) +; + +insert into campsite_carousel (campsite_id, media_id, caption) +values (11, 5, 'A caption') +; + +select lives_ok( + $$ select add_campsite_carousel_slide(1, 'A1', 6, 'A caption') $$, + 'Should be able to add a carousel slide with a caption' +); + +select lives_ok( + $$ select add_campsite_carousel_slide(1, 'Z9', 7, null) $$, + 'Should be able to add a carousel slide without caption' +); + +select lives_ok( + $$ select add_campsite_carousel_slide(1, 'A1', 5, 'New caption') $$, + 'Should be able to overwrite a slide with a new caption' +); + +select bag_eq( + $$ select campsite_id, media_id, caption from campsite_carousel $$, + $$ values (11, 5, 'New caption') + , (11, 6, 'A caption') + , (12, 7, '') + $$, + 'Should have all three slides' +); + +select * +from finish(); + +rollback; diff --git a/test/add_campsite_feature.sql b/test/add_campsite_feature.sql new file mode 100644 index 0000000..f057db2 --- /dev/null +++ b/test/add_campsite_feature.sql @@ -0,0 +1,77 @@ +-- Test add_campsite_feature +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(12); + +set search_path to camper, public; + +select has_function('camper', 'add_campsite_feature', array['integer', 'text', 'text', 'text']); +select function_lang_is('camper', 'add_campsite_feature', array['integer', 'text', 'text', 'text'], 'sql'); +select function_returns('camper', 'add_campsite_feature', array['integer', 'text', 'text', 'text'], 'integer'); +select isnt_definer('camper', 'add_campsite_feature', array['integer', 'text', 'text', 'text']); +select volatility_is('camper', 'add_campsite_feature', array['integer', 'text', 'text', 'text'], 'volatile'); +select function_privs_are('camper', 'add_campsite_feature', array ['integer', 'text', 'text', 'text'], 'guest', array[]::text[]); +select function_privs_are('camper', 'add_campsite_feature', array ['integer', 'text', 'text', 'text'], 'employee', array[]::text[]); +select function_privs_are('camper', 'add_campsite_feature', array ['integer', 'text', 'text', 'text'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'add_campsite_feature', array ['integer', 'text', 'text', 'text'], 'authenticator', array[]::text[]); + + +set client_min_messages to warning; +truncate campsite_feature cascade; +truncate campsite 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, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag) +values (1, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') + , (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') +; + +insert into media_content (media_type, bytes) +values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values (3, 1, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) +; + +insert into campsite_type (campsite_type_id, company_id, media_id, name, description, active, dogs_allowed, max_campers) +values (4, 1, 3, 'Type A', '

A

', true, false, 4) + , (5, 1, 3, 'Type B', '

B

', true, false, 5) +; + +insert into campsite (campsite_id, company_id, label, campsite_type_id) +values (6, 1, 'A1', 4) + , (7, 2, 'A1', 5) +; + +select lives_ok( + $$ select add_campsite_feature(1, 'A1', 'wifi', 'Feature 1') $$, + 'Should be able to add an feature to the first campsite' +); + +select lives_ok( + $$ select add_campsite_feature(2, 'A1', 'information', 'Feature 2') $$, + 'Should be able to add an feature to the second campsite' +); + +select bag_eq( + $$ select campsite_id, icon_name, name from campsite_feature $$, + $$ values (6, 'wifi', 'Feature 1') + , (7, 'information', 'Feature 2') + $$, + 'Should have added all two campsite features' +); + +select * +from finish(); + +rollback; diff --git a/test/campsite.sql b/test/campsite.sql index 1507e0a..59b52d2 100644 --- a/test/campsite.sql +++ b/test/campsite.sql @@ -5,7 +5,7 @@ reset client_min_messages; begin; -select plan(47); +select plan(55); set search_path to camper, public; @@ -42,6 +42,18 @@ select col_type_is('campsite', 'label', 'text'); select col_not_null('campsite', 'label'); select col_hasnt_default('campsite', 'label'); +select has_column('campsite', 'info1'); +select col_type_is('campsite', 'info1', 'xml'); +select col_not_null('campsite', 'info1'); +select col_has_default('campsite', 'info1'); +--select col_default_is('campsite', 'info1', ''); + +select has_column('campsite', 'info2'); +select col_type_is('campsite', 'info2', 'xml'); +select col_not_null('campsite', 'info2'); +select col_has_default('campsite', 'info2'); +--select col_default_is('campsite', 'info2', ''); + select has_column('campsite', 'active'); select col_type_is('campsite', 'active', 'boolean'); select col_not_null('campsite', 'active'); diff --git a/test/campsite_carousel.sql b/test/campsite_carousel.sql new file mode 100644 index 0000000..5461461 --- /dev/null +++ b/test/campsite_carousel.sql @@ -0,0 +1,236 @@ +-- Test campsite_carousel +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(45); + +set search_path to camper, public; + +select has_table('campsite_carousel'); +select has_pk('campsite_carousel'); +select col_is_pk('campsite_carousel', array['campsite_id', 'media_id']); +select table_privs_are('campsite_carousel', 'guest', array['SELECT']); +select table_privs_are('campsite_carousel', 'employee', array['SELECT']); +select table_privs_are('campsite_carousel', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']); +select table_privs_are('campsite_carousel', 'authenticator', array[]::text[]); + +select has_column('campsite_carousel', 'campsite_id'); +select col_is_fk('campsite_carousel', 'campsite_id'); +select fk_ok('campsite_carousel', 'campsite_id', 'campsite', 'campsite_id'); +select col_type_is('campsite_carousel', 'campsite_id', 'integer'); +select col_not_null('campsite_carousel', 'campsite_id'); +select col_hasnt_default('campsite_carousel', 'campsite_id'); + +select has_column('campsite_carousel', 'media_id'); +select col_is_fk('campsite_carousel', 'media_id'); +select fk_ok('campsite_carousel', 'media_id', 'media', 'media_id'); +select col_type_is('campsite_carousel', 'media_id', 'integer'); +select col_not_null('campsite_carousel', 'media_id'); +select col_hasnt_default('campsite_carousel', 'media_id'); + +select has_column('campsite_carousel', 'caption'); +select col_type_is('campsite_carousel', 'caption', 'text'); +select col_not_null('campsite_carousel', 'caption'); +select col_hasnt_default('campsite_carousel', 'caption'); + +select has_column('campsite_carousel', 'position'); +select col_type_is('campsite_carousel', 'position', 'integer'); +select col_not_null('campsite_carousel', 'position'); +select col_has_default('campsite_carousel', 'position'); +select col_default_is('campsite_carousel', 'position', '2147483647'); + + +set client_min_messages to warning; +truncate campsite_carousel cascade; +truncate campsite 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, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag) +values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') + , (4, 'Company 4', 'XX234', '', '666-666-666', 'b@b', '', '', '', '', '', '', 60, 'FR', 'USD', 'ca') +; + +insert into company_user (company_id, user_id, role) +values (2, 1, 'admin') + , (4, 5, 'admin') +; + +insert into company_host (company_id, host) +values (2, 'co2') + , (4, 'co4') +; + +insert into media_content (media_type, bytes) +values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};') + , ('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 (campsite_id, company_id, label, campsite_type_id) +values (23, 2, 'W1', 21) + , (24, 4, 'B1', 22) +; + +insert into campsite_carousel (campsite_id, media_id, caption) +values (23, 7, 'Caption 7') + , (24, 10, 'Caption 10') +; + +prepare carousel_data as +select campsite_id, media_id, caption +from campsite_carousel +; + +set role guest; +select bag_eq( + 'carousel_data', + $$ values (23, 7, 'Caption 7') + , (24, 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_carousel(campsite_id, media_id, caption) values (23, 8, 'Caption 8') $$, + 'Admin from company 2 should be able to insert a new slide to campsites of that company.' +); + +select bag_eq( + 'carousel_data', + $$ values (23, 7, 'Caption 7') + , (23, 8, 'Caption 8') + , (24, 10, 'Caption 10') + $$, + 'The new row should have been added' +); + +select lives_ok( + $$ update campsite_carousel set caption = 'Caption 8.8' where media_id = 8 $$, + 'Admin from company 2 should be able to update campsite slides of that company.' +); + +select bag_eq( + 'carousel_data', + $$ values (23, 7, 'Caption 7') + , (23, 8, 'Caption 8.8') + , (24, 10, 'Caption 10') + $$, + 'The row should have been updated.' +); + +select lives_ok( + $$ delete from campsite_carousel where media_id = 8 $$, + 'Admin from company 2 should be able to delete campsite slides from that company.' +); + +select bag_eq( + 'carousel_data', + $$ values (23, 7, 'Caption 7') + , (24, 10, 'Caption 10') + $$, + 'The row should have been deleted.' +); + +select throws_ok( + $$ insert into campsite_carousel (campsite_id, media_id, caption) values (23, 10, 'Nope') $$, + '42501', 'new row violates row-level security policy for table "campsite_carousel"', + 'Admin from company 2 should NOT be able to insert a new campsites slide from a media of company 4.' +); + +select throws_ok( + $$ insert into campsite_carousel (campsite_id, media_id, caption) values (24, 8, 'Nope') $$, + '42501', 'new row violates row-level security policy for table "campsite_carousel"', + 'Admin from company 2 should NOT be able to insert a slide to a campsite of company 4.' +); + +select lives_ok( + $$ update campsite_carousel set caption = 'Nope' where campsite_id = 24 $$, + 'Admin from company 2 should not be able to update slides of campsites from company 4, but no error if campsite_id or media_id is not changed.' +); + +select lives_ok( + $$ update campsite_carousel set caption = 'Nope' where media_id = 10 $$, + 'Admin from company 2 should not be able to update slides of campsites from company 4, but no error if campsite_id or media_id is not changed.' +); + +select bag_eq( + 'carousel_data', + $$ values (23, 7, 'Caption 7') + , (24, 10, 'Caption 10') + $$, + 'No row should have been changed.' +); + +select throws_ok( + $$ update campsite_carousel set campsite_id = 24 where campsite_id = 23 $$, + '42501', 'new row violates row-level security policy for table "campsite_carousel"', + 'Admin from company 2 should NOT be able to move slides to campsites of company 4' +); + +select throws_ok( + $$ update campsite_carousel set media_id = 11 where media_id = 7 $$, + '42501', 'new row violates row-level security policy for table "campsite_carousel"', + 'Admin from company 2 should NOT be able to use media from company 4' +); + +select lives_ok( + $$ delete from campsite_carousel where campsite_id = 24 $$, + 'Admin from company 2 should NOT be able to delete slides of campsites from company 4, but not error is thrown' +); + +select lives_ok( + $$ delete from campsite_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 (23, 7, 'Caption 7') + , (24, 10, 'Caption 10') + $$, + 'No row should have been changed' +); + +reset role; + + +select * +from finish(); + +rollback; + diff --git a/test/campsite_carousel_i18n.sql b/test/campsite_carousel_i18n.sql new file mode 100644 index 0000000..59b90f1 --- /dev/null +++ b/test/campsite_carousel_i18n.sql @@ -0,0 +1,49 @@ +-- Test campsite_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_carousel_i18n'); +select has_pk('campsite_carousel_i18n'); +select col_is_pk('campsite_carousel_i18n', array['campsite_id', 'media_id', 'lang_tag']); +select col_is_fk('campsite_carousel_i18n', array['campsite_id', 'media_id']); +select fk_ok('campsite_carousel_i18n', array['campsite_id', 'media_id'], 'campsite_carousel', array['campsite_id', 'media_id']); +select table_privs_are('campsite_carousel_i18n', 'guest', array['SELECT']); +select table_privs_are('campsite_carousel_i18n', 'employee', array['SELECT']); +select table_privs_are('campsite_carousel_i18n', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']); +select table_privs_are('campsite_carousel_i18n', 'authenticator', array[]::text[]); + +select has_column('campsite_carousel_i18n', 'campsite_id'); +select col_type_is('campsite_carousel_i18n', 'campsite_id', 'integer'); +select col_not_null('campsite_carousel_i18n', 'campsite_id'); +select col_hasnt_default('campsite_carousel_i18n', 'campsite_id'); + +select has_column('campsite_carousel_i18n', 'media_id'); +select col_type_is('campsite_carousel_i18n', 'media_id', 'integer'); +select col_not_null('campsite_carousel_i18n', 'media_id'); +select col_hasnt_default('campsite_carousel_i18n', 'media_id'); + +select has_column('campsite_carousel_i18n', 'lang_tag'); +select col_is_fk('campsite_carousel_i18n', 'lang_tag'); +select fk_ok('campsite_carousel_i18n', 'lang_tag', 'language', 'lang_tag'); +select col_type_is('campsite_carousel_i18n', 'lang_tag', 'text'); +select col_not_null('campsite_carousel_i18n', 'lang_tag'); +select col_hasnt_default('campsite_carousel_i18n', 'lang_tag'); + +select has_column('campsite_carousel_i18n', 'caption'); +select col_type_is('campsite_carousel_i18n', 'caption', 'text'); +select col_is_null('campsite_carousel_i18n', 'caption'); +select col_hasnt_default('campsite_carousel_i18n', 'caption'); + + +select * +from finish(); + +rollback; + diff --git a/test/campsite_feature.sql b/test/campsite_feature.sql new file mode 100644 index 0000000..0395330 --- /dev/null +++ b/test/campsite_feature.sql @@ -0,0 +1,216 @@ +-- Test campsite_feature +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(46); + +set search_path to camper, public; + +select has_table('campsite_feature'); +select has_pk('campsite_feature'); +select table_privs_are('campsite_feature', 'guest', array['SELECT']); +select table_privs_are('campsite_feature', 'employee', array['SELECT']); +select table_privs_are('campsite_feature', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']); +select table_privs_are('campsite_feature', 'authenticator', array[]::text[]); + +select has_column('campsite_feature', 'campsite_feature_id'); +select col_is_pk('campsite_feature', 'campsite_feature_id'); +select col_type_is('campsite_feature', 'campsite_feature_id', 'integer'); +select col_not_null('campsite_feature', 'campsite_feature_id'); +select col_hasnt_default('campsite_feature', 'campsite_feature_id'); + +select has_column('campsite_feature', 'campsite_id'); +select col_is_fk('campsite_feature', 'campsite_id'); +select fk_ok('campsite_feature', 'campsite_id', 'campsite', 'campsite_id'); +select col_type_is('campsite_feature', 'campsite_id', 'integer'); +select col_not_null('campsite_feature', 'campsite_id'); +select col_hasnt_default('campsite_feature', 'campsite_id'); + +select has_column('campsite_feature', 'icon_name'); +select col_is_fk('campsite_feature', 'icon_name'); +select fk_ok('campsite_feature', 'icon_name', 'icon', 'icon_name'); +select col_type_is('campsite_feature', 'icon_name', 'text'); +select col_not_null('campsite_feature', 'icon_name'); +select col_hasnt_default('campsite_feature', 'icon_name'); + +select has_column('campsite_feature', 'name'); +select col_type_is('campsite_feature', 'name', 'text'); +select col_not_null('campsite_feature', 'name'); +select col_hasnt_default('campsite_feature', 'name'); + +select has_column('campsite_feature', 'position'); +select col_type_is('campsite_feature', 'position', 'integer'); +select col_not_null('campsite_feature', 'position'); +select col_has_default('campsite_feature', 'position'); +select col_default_is('campsite_feature', 'position', '2147483647'); + + +set client_min_messages to warning; +truncate campsite_feature cascade; +truncate campsite 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, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag) +values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') + , (4, 'Company 4', 'XX234', '', '666-666-666', 'b@b', '', '', '', '', '', '', 60, 'FR', 'USD', 'ca') +; + +insert into company_user (company_id, user_id, role) +values (2, 1, 'admin') + , (4, 5, 'admin') +; + +insert into company_host (company_id, host) +values (2, 'co2') + , (4, 'co4') +; + +insert into media_content (media_type, bytes) +values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values (6, 2, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) + , (8, 4, 'cover4.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) +; + +insert into campsite_type (campsite_type_id, company_id, name, media_id, dogs_allowed, max_campers) +values (16, 2, 'Wooden lodge', 6, false, 7) + , (18, 4, 'Bungalow', 8, false, 6) +; + +insert into campsite (campsite_id, company_id, label, campsite_type_id) +values (26, 2, 'W1', 16) + , (28, 4, 'B1', 18) +; + +insert into campsite_feature (campsite_id, icon_name, name) +values (26, 'information', 'Feature 26.1') + , (28, 'wifi', 'Feature 28.1') +; + +prepare campsite_feature_data as +select campsite_id, name +from campsite_feature +; + +set role guest; +select bag_eq( + 'campsite_feature_data', + $$ values (26, 'Feature 26.1') + , (28, 'Feature 28.1') + $$, + 'Everyone should be able to list all campsite features across all companies' +); +reset role; + +select set_cookie('44facbb30d8a419dfd4bfbc44a4b5539d4970148dfc84bed0e/demo@tandem.blog', 'co2'); + +select lives_ok( + $$ insert into campsite_feature(campsite_id, icon_name, name) values (26, 'castle', 'Feature 26.2') $$, + 'Admin from company 2 should be able to insert a new campsite feature to that company.' +); + +select bag_eq( + 'campsite_feature_data', + $$ values (26, 'Feature 26.1') + , (26, 'Feature 26.2') + , (28, 'Feature 28.1') + $$, + 'The new row should have been added' +); + +select lives_ok( + $$ update campsite_feature set name = 'Feature 26-2' where campsite_id = 26 and name = 'Feature 26.2' $$, + 'Admin from company 2 should be able to update campsite feature of that company.' +); + +select bag_eq( + 'campsite_feature_data', + $$ values (26, 'Feature 26.1') + , (26, 'Feature 26-2') + , (28, 'Feature 28.1') + $$, + 'The row should have been updated.' +); + +select lives_ok( + $$ delete from campsite_feature where campsite_id = 26 and name = 'Feature 26-2' $$, + 'Admin from company 2 should be able to delete campsite feature from that company.' +); + +select bag_eq( + 'campsite_feature_data', + $$ values (26, 'Feature 26.1') + , (28, 'Feature 28.1') + $$, + 'The row should have been deleted.' +); + +select throws_ok( + $$ insert into campsite_feature (campsite_id, icon_name, name) values (28, 'toilet', 'Feature 28.2') $$, + '42501', 'new row violates row-level security policy for table "campsite_feature"', + 'Admin from company 2 should NOT be able to insert new campsite features to company 4.' +); + +select lives_ok( + $$ update campsite_feature set name = 'Feature 28-1' where campsite_id = 28 $$, + 'Admin from company 2 should not be able to update campsites of company 4, but no error if campsite_id is not changed.' +); + +select bag_eq( + 'campsite_feature_data', + $$ values (26, 'Feature 26.1') + , (28, 'Feature 28.1') + $$, + 'No row should have been changed.' +); + +select throws_ok( + $$ update campsite_feature set campsite_id = 28 where campsite_id = 26 $$, + '42501', 'new row violates row-level security policy for table "campsite_feature"', + 'Admin from company 2 should NOT be able to move campsite feature to one of company 4' +); + +select lives_ok( + $$ delete from campsite_feature where campsite_id = 28 $$, + 'Admin from company 2 should NOT be able to delete campsite from company 4, but not error is thrown' +); + +select bag_eq( + 'campsite_feature_data', + $$ values (26, 'Feature 26.1') + , (28, 'Feature 28.1') + $$, + 'No row should have been changed' +); + +select throws_ok( + $$ insert into campsite_feature (campsite_id, icon_name, name) values (26, 'baby', ' ') $$, + '23514', 'new row for relation "campsite_feature" violates check constraint "name_not_empty"', + 'Should not be able to insert campsite features with a blank name.' +); + +reset role; + + +select * +from finish(); + +rollback; + diff --git a/test/campsite_feature_i18n.sql b/test/campsite_feature_i18n.sql new file mode 100644 index 0000000..53621d2 --- /dev/null +++ b/test/campsite_feature_i18n.sql @@ -0,0 +1,44 @@ +-- Test campsite_feature_i18n +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(23); + +set search_path to camper, public; + +select has_table('campsite_feature_i18n'); +select has_pk('campsite_feature_i18n'); +select col_is_pk('campsite_feature_i18n', array['campsite_feature_id', 'lang_tag']); +select table_privs_are('campsite_feature_i18n', 'guest', array['SELECT']); +select table_privs_are('campsite_feature_i18n', 'employee', array['SELECT']); +select table_privs_are('campsite_feature_i18n', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']); +select table_privs_are('campsite_feature_i18n', 'authenticator', array[]::text[]); + +select has_column('campsite_feature_i18n', 'campsite_feature_id'); +select col_is_fk('campsite_feature_i18n', 'campsite_feature_id'); +select fk_ok('campsite_feature_i18n', 'campsite_feature_id', 'campsite_feature', 'campsite_feature_id'); +select col_type_is('campsite_feature_i18n', 'campsite_feature_id', 'integer'); +select col_not_null('campsite_feature_i18n', 'campsite_feature_id'); +select col_hasnt_default('campsite_feature_i18n', 'campsite_feature_id'); + +select has_column('campsite_feature_i18n', 'lang_tag'); +select col_is_fk('campsite_feature_i18n', 'lang_tag'); +select fk_ok('campsite_feature_i18n', 'lang_tag', 'language', 'lang_tag'); +select col_type_is('campsite_feature_i18n', 'lang_tag', 'text'); +select col_not_null('campsite_feature_i18n', 'lang_tag'); +select col_hasnt_default('campsite_feature_i18n', 'lang_tag'); + +select has_column('campsite_feature_i18n', 'name'); +select col_type_is('campsite_feature_i18n', 'name', 'text'); +select col_is_null('campsite_feature_i18n', 'name'); +select col_hasnt_default('campsite_feature_i18n', 'name'); + + +select * +from finish(); + +rollback; + diff --git a/test/campsite_i18n.sql b/test/campsite_i18n.sql new file mode 100644 index 0000000..c98dd45 --- /dev/null +++ b/test/campsite_i18n.sql @@ -0,0 +1,49 @@ +-- Test campsite_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_i18n'); +select has_pk('campsite_i18n'); +select col_is_pk('campsite_i18n', array['campsite_id', 'lang_tag']); +select table_privs_are('campsite_i18n', 'guest', array['SELECT']); +select table_privs_are('campsite_i18n', 'employee', array['SELECT']); +select table_privs_are('campsite_i18n', 'admin', array['SELECT', 'INSERT', 'UPDATE', 'DELETE']); +select table_privs_are('campsite_i18n', 'authenticator', array[]::text[]); + +select has_column('campsite_i18n', 'campsite_id'); +select col_is_fk('campsite_i18n', 'campsite_id'); +select fk_ok('campsite_i18n', 'campsite_id', 'campsite', 'campsite_id'); +select col_type_is('campsite_i18n', 'campsite_id', 'integer'); +select col_not_null('campsite_i18n', 'campsite_id'); +select col_hasnt_default('campsite_i18n', 'campsite_id'); + +select has_column('campsite_i18n', 'lang_tag'); +select col_is_fk('campsite_i18n', 'lang_tag'); +select fk_ok('campsite_i18n', 'lang_tag', 'language', 'lang_tag'); +select col_type_is('campsite_i18n', 'lang_tag', 'text'); +select col_not_null('campsite_i18n', 'lang_tag'); +select col_hasnt_default('campsite_i18n', 'lang_tag'); + +select has_column('campsite_i18n', 'info1'); +select col_type_is('campsite_i18n', 'info1', 'xml'); +select col_is_null('campsite_i18n', 'info1'); +select col_hasnt_default('campsite_i18n', 'info1'); + +select has_column('campsite_i18n', 'info2'); +select col_type_is('campsite_i18n', 'info2', 'xml'); +select col_is_null('campsite_i18n', 'info2'); +select col_hasnt_default('campsite_i18n', 'info2'); + + +select * +from finish(); + +rollback; + diff --git a/test/edit_campsite.sql b/test/edit_campsite.sql index b8191c6..e9d774b 100644 --- a/test/edit_campsite.sql +++ b/test/edit_campsite.sql @@ -9,15 +9,15 @@ set search_path to camper, public; select plan(12); -select has_function('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'boolean']); -select function_lang_is('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'boolean'], 'sql'); -select function_returns('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'boolean'], 'integer'); -select isnt_definer('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'boolean']); -select volatility_is('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'boolean'], 'volatile'); -select function_privs_are('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'boolean'], 'guest', array[]::text[]); -select function_privs_are('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'boolean'], 'employee', array[]::text[]); -select function_privs_are('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'boolean'], 'admin', array['EXECUTE']); -select function_privs_are('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'boolean'], 'authenticator', array[]::text[]); +select has_function('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'text', 'text', 'boolean']); +select function_lang_is('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'text', 'text', 'boolean'], 'sql'); +select function_returns('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'text', 'text', 'boolean'], 'integer'); +select isnt_definer('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'text', 'text', 'boolean']); +select volatility_is('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'text', 'text', 'boolean'], 'volatile'); +select function_privs_are('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'text', 'text', 'boolean'], 'guest', array[]::text[]); +select function_privs_are('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'text', 'text', 'boolean'], 'employee', array[]::text[]); +select function_privs_are('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'text', 'text', 'boolean'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'edit_campsite', array ['integer', 'integer', 'text', 'text', 'text', 'boolean'], 'authenticator', array[]::text[]); set client_min_messages to warning; truncate campsite cascade; @@ -46,25 +46,25 @@ values (11, 1, 3, 'Type A', false, 5) , (13, 1, 3, 'Type C', false, 5) ; -insert into campsite (campsite_id, company_id, campsite_type_id, label, active) -values (21, 1, 11, 'A1', true) - , (22, 1, 12, 'B1', false) +insert into campsite (campsite_id, company_id, campsite_type_id, label, info1, info2, active) +values (21, 1, 11, 'A1', '

A1.1

', '

A1.2

', true) + , (22, 1, 12, 'B1', '

B1.1

', '

B1.2

', false) ; select lives_ok( - $$ select edit_campsite(21, 13, 'C1', false) $$, + $$ select edit_campsite(21, 13, 'C1', '

C1.1

', '

C1.2

', false) $$, 'Should be able to edit the first campsite.' ); select lives_ok( - $$ select edit_campsite(22, 12, 'B2', true) $$, + $$ select edit_campsite(22, 12, 'B2', '

B2.1

', '

B2.2

', true) $$, 'Should be able to edit the second campsite.' ); select bag_eq( - $$ select campsite_id, campsite_type_id, label, active from campsite $$, - $$ values (21, 13, 'C1', false) - , (22, 12, 'B2', true) + $$ select campsite_id, campsite_type_id, label, info1::text, info2::text, active from campsite $$, + $$ values (21, 13, 'C1', '

C1.1

', '

C1.2

', false) + , (22, 12, 'B2', '

B2.1

', '

B2.2

', true) $$, 'Should have updated all campsites.' ); diff --git a/test/edit_campsite_feature.sql b/test/edit_campsite_feature.sql new file mode 100644 index 0000000..838bf5a --- /dev/null +++ b/test/edit_campsite_feature.sql @@ -0,0 +1,80 @@ +-- Test edit_campsite_feature +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(12); + +set search_path to camper, public; + +select has_function('camper', 'edit_campsite_feature', array['integer', 'text', 'text']); +select function_lang_is('camper', 'edit_campsite_feature', array['integer', 'text', 'text'], 'sql'); +select function_returns('camper', 'edit_campsite_feature', array['integer', 'text', 'text'], 'integer'); +select isnt_definer('camper', 'edit_campsite_feature', array['integer', 'text', 'text']); +select volatility_is('camper', 'edit_campsite_feature', array['integer', 'text', 'text'], 'volatile'); +select function_privs_are('camper', 'edit_campsite_feature', array ['integer', 'text', 'text'], 'guest', array[]::text[]); +select function_privs_are('camper', 'edit_campsite_feature', array ['integer', 'text', 'text'], 'employee', array[]::text[]); +select function_privs_are('camper', 'edit_campsite_feature', array ['integer', 'text', 'text'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'edit_campsite_feature', array ['integer', 'text', 'text'], 'authenticator', array[]::text[]); + + +set client_min_messages to warning; +truncate campsite_feature cascade; +truncate campsite 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, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag) +values (1, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') +; + +insert into media_content (media_type, bytes) +values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values (2, 1, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) +; + +insert into campsite_type (campsite_type_id, company_id, media_id, name, description, active, dogs_allowed, max_campers) +values (3, 1, 2, 'Type A', '

A

', true, false, 4) +; + +insert into campsite (campsite_id, company_id, label, campsite_type_id) +values (4, 1, 'A1', 3) +; + +insert into campsite_feature (campsite_feature_id, campsite_id, icon_name, name) +values (5, 4, 'information', 'Feature 1') + , (6, 4, 'wifi', 'Feature 2') +; + +select lives_ok( + $$ select edit_campsite_feature(5, 'toilet', 'Feature A') $$, + 'Should be able to edit the first feature' +); + +select lives_ok( + $$ select edit_campsite_feature(6, 'baby', 'Feature B') $$, + 'Should be able to edit the second feature' +); + +select bag_eq( + $$ select campsite_feature_id, campsite_id, icon_name, name from campsite_feature $$, + $$ values (5, 4, 'toilet', 'Feature A') + , (6, 4, 'baby', 'Feature B') + $$, + 'Should have updated all campsite type features.' +); + + +select * +from finish(); + +rollback; diff --git a/test/order_campsite_carousel.sql b/test/order_campsite_carousel.sql new file mode 100644 index 0000000..1bfff74 --- /dev/null +++ b/test/order_campsite_carousel.sql @@ -0,0 +1,107 @@ +-- Test order_campsite_carousel +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(11); + +set search_path to camper, public; + +select has_function('camper', 'order_campsite_carousel', array['text', 'integer', 'integer[]']); +select function_lang_is('camper', 'order_campsite_carousel', array['text', 'integer', 'integer[]'], 'sql'); +select function_returns('camper', 'order_campsite_carousel', array['text', 'integer', 'integer[]'], 'void'); +select isnt_definer('camper', 'order_campsite_carousel', array['text', 'integer', 'integer[]']); +select volatility_is('camper', 'order_campsite_carousel', array['text', 'integer', 'integer[]'], 'volatile'); +select function_privs_are('camper', 'order_campsite_carousel', array ['text', 'integer', 'integer[]'], 'guest', array[]::text[]); +select function_privs_are('camper', 'order_campsite_carousel', array ['text', 'integer', 'integer[]'], 'employee', array[]::text[]); +select function_privs_are('camper', 'order_campsite_carousel', array ['text', 'integer', 'integer[]'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'order_campsite_carousel', array ['text', 'integer', 'integer[]'], 'authenticator', array[]::text[]); + + +set client_min_messages to warning; +truncate campsite_carousel cascade; +truncate campsite 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, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag) +values (1, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') + , (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') +; + +insert into media_content (media_type, bytes) +values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};') + , ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ff00ff","a"};') + , ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffff00","a"};') + , ('text/plain', 'hello, world!') + , ('image/svg+xml', '') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values ( 3, 1, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) + , ( 4, 1, 'cover3.xpm', sha256('static char *s[]={"1 1 1 1","a c #ff00ff","a"};')) + , ( 5, 1, 'cover4.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffff00","a"};')) + , ( 6, 1, 'text.txt', sha256('hello, world!')) + , ( 7, 1, 'image.svg', sha256('')) + , ( 8, 1, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) + , ( 9, 1, 'cover3.xpm', sha256('static char *s[]={"1 1 1 1","a c #ff00ff","a"};')) + , (10, 1, 'cover4.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffff00","a"};')) + , (11, 1, 'text.txt', sha256('hello, world!')) + , (12, 1, 'image.svg', sha256('')) +; + +insert into campsite_type (campsite_type_id, company_id, media_id, name, description, max_campers, dogs_allowed, active) +values (13, 1, 3, 'Type A', '

A

', 5, false, true) + , (14, 2, 8, 'Type B', '

B

', 4, true, false) +; + +insert into campsite (campsite_id, company_id, label, campsite_type_id) +values (15, 1, 'A1', 13) + , (16, 2, 'A1', 14) +; + +insert into campsite_carousel (campsite_id, media_id, caption) +values (15, 3, '1') + , (15, 4, '2') + , (15, 5, '3') + , (15, 6, '4') + , (15, 7, '5') + , (16, 8, '1') + , (16, 9, '2') + , (16, 10, '3') + , (16, 11, '4') + , (16, 12, '5') +; + +select lives_ok( + $$ select order_campsite_carousel('A1', 1, '{5,7,6,3,4}') $$, + 'Should be able to sort campsite type slides using their media ID' +); + +select bag_eq( + $$ select campsite_id, media_id, position from campsite_carousel $$, + $$ values (15, 5, 1) + , (15, 7, 2) + , (15, 6, 3) + , (15, 3, 4) + , (15, 4, 5) + , (16, 8, 2147483647) + , (16, 9, 2147483647) + , (16, 10, 2147483647) + , (16, 11, 2147483647) + , (16, 12, 2147483647) + $$, + 'Should have sorted all campsite type slides.' +); + + +select * +from finish(); + +rollback; diff --git a/test/order_campsite_features.sql b/test/order_campsite_features.sql new file mode 100644 index 0000000..9ad0d3a --- /dev/null +++ b/test/order_campsite_features.sql @@ -0,0 +1,82 @@ +-- Test order_campsite_features +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(11); + +set search_path to camper, public; + +select has_function('camper', 'order_campsite_features', array['integer[]']); +select function_lang_is('camper', 'order_campsite_features', array['integer[]'], 'sql'); +select function_returns('camper', 'order_campsite_features', array['integer[]'], 'void'); +select isnt_definer('camper', 'order_campsite_features', array['integer[]']); +select volatility_is('camper', 'order_campsite_features', array['integer[]'], 'volatile'); +select function_privs_are('camper', 'order_campsite_features', array ['integer[]'], 'guest', array[]::text[]); +select function_privs_are('camper', 'order_campsite_features', array ['integer[]'], 'employee', array[]::text[]); +select function_privs_are('camper', 'order_campsite_features', array ['integer[]'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'order_campsite_features', array ['integer[]'], 'authenticator', array[]::text[]); + + +set client_min_messages to warning; +truncate campsite_feature cascade; +truncate campsite 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, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag) +values (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') +; + +insert into media_content (media_type, bytes) +values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values (6, 2, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) +; + +insert into campsite_type (campsite_type_id, company_id, name, media_id, dogs_allowed, max_campers) +values (16, 2, 'Wooden lodge', 6, false, 7) +; + +insert into campsite (campsite_id, company_id, label, campsite_type_id) +values (17, 2, 'A1', 16) +; + +insert into campsite_feature (campsite_feature_id, campsite_id, icon_name, name) +values (21, 17, 'information', '1') + , (22, 17, 'ball', '2') + , (23, 17, 'bicycle', '3') + , (24, 17, 'campfire', '4') + , (25, 17, 'castle', '5') +; + + +select lives_ok( + $$ select order_campsite_features('{23,25,24,21,22}') $$, + 'Should be able to sort campsite type features using their ID' +); + +select bag_eq( + $$ select campsite_feature_id, position from campsite_feature $$, + $$ values (23, 1) + , (25, 2) + , (24, 3) + , (21, 4) + , (22, 5) + $$, + 'Should have sorted all campsite type features.' +); + + +select * +from finish(); + +rollback; diff --git a/test/remove_campsite_carousel_slide.sql b/test/remove_campsite_carousel_slide.sql new file mode 100644 index 0000000..8946f47 --- /dev/null +++ b/test/remove_campsite_carousel_slide.sql @@ -0,0 +1,114 @@ +-- Test remove_campsite_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_carousel_slide', array['integer', 'text', 'integer']); +select function_lang_is('camper', 'remove_campsite_carousel_slide', array['integer', 'text', 'integer'], 'plpgsql'); +select function_returns('camper', 'remove_campsite_carousel_slide', array['integer', 'text', 'integer'], 'void'); +select isnt_definer('camper', 'remove_campsite_carousel_slide', array['integer', 'text', 'integer']); +select volatility_is('camper', 'remove_campsite_carousel_slide', array['integer', 'text', 'integer'], 'volatile'); +select function_privs_are('camper', 'remove_campsite_carousel_slide', array['integer', 'text', 'integer'], 'guest', array[]::text[]); +select function_privs_are('camper', 'remove_campsite_carousel_slide', array['integer', 'text', 'integer'], 'employee', array[]::text[]); +select function_privs_are('camper', 'remove_campsite_carousel_slide', array['integer', 'text', 'integer'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'remove_campsite_carousel_slide', array['integer', 'text', 'integer'], 'authenticator', array[]::text[]); + + +set client_min_messages to warning; +truncate campsite_carousel_i18n cascade; +truncate campsite_carousel cascade; +truncate campsite 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, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag) +values (1, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') + , (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') +; + +insert into media_content (media_type, bytes) +values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};') + , ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ff00ff","a"};') + , ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffff00","a"};') + , ('text/plain', 'hello, world!') + , ('image/svg+xml', '') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values (3, 1, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) + , (4, 1, 'cover3.xpm', sha256('static char *s[]={"1 1 1 1","a c #ff00ff","a"};')) + , (5, 2, 'cover4.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffff00","a"};')) + , (6, 2, 'text.txt', sha256('hello, world!')) + , (7, 2, 'image.svg', sha256('')) +; + +insert into campsite_type (campsite_type_id, company_id, media_id, name, description, max_campers, dogs_allowed, active) +values (10, 1, 3, 'Type A', '

A

', 5, false, true) + , (11, 2, 7, 'Type B', '

B

', 4, true, false) +; + +insert into campsite (campsite_id, label, company_id, campsite_type_id) +values (12, 'A1', 1, 10) + , (13, 'A1', 2, 11) +; + +insert into campsite_carousel (campsite_id, media_id, caption) +values (12, 3, 'Source caption') + , (12, 4, 'Source caption') + , (13, 5, 'Another caption') + , (13, 6, 'N/A') +; + +insert into campsite_carousel_i18n (campsite_id, media_id, lang_tag, caption) +values (12, 3, 'en', 'Target caption') + , (12, 3, 'es', 'Target caption (spanish)') + , (12, 4, 'en', 'Target caption') + , (12, 4, 'es', 'Target caption (spanish)') + , (13, 5, 'en', 'Target caption') + , (13, 5, 'es', 'Target caption (spanish)') + , (13, 6, 'en', 'Target caption') + , (13, 6, 'es', 'Target caption (spanish)') +; + +select lives_ok( + $$ select remove_campsite_carousel_slide(1, 'A1', 3) $$, + 'Should be able to delete a slide from the first campsite type' +); + +select lives_ok( + $$ select remove_campsite_carousel_slide(2, 'A1', 6) $$, + 'Should be able to delete a slide from the second campsite type' +); + +select bag_eq( + $$ select campsite_id, media_id, caption from campsite_carousel $$, + $$ values (12, 4, 'Source caption') + , (13, 5, 'Another caption') + $$, + 'Should have removed the slides' +); + +select bag_eq( + $$ select campsite_id, media_id, lang_tag, caption from campsite_carousel_i18n $$, + $$ values (12, 4, 'en', 'Target caption') + , (12, 4, 'es', 'Target caption (spanish)') + , (13, 5, 'en', 'Target caption') + , (13, 5, 'es', 'Target caption (spanish)') + $$, + 'Should have removed the slides’ translations' +); + + +select * +from finish(); + +rollback; diff --git a/test/remove_campsite_feature.sql b/test/remove_campsite_feature.sql new file mode 100644 index 0000000..77ff46c --- /dev/null +++ b/test/remove_campsite_feature.sql @@ -0,0 +1,109 @@ +-- Test remove_campsite_feature +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_feature', array['integer']); +select function_lang_is('camper', 'remove_campsite_feature', array['integer'], 'sql'); +select function_returns('camper', 'remove_campsite_feature', array['integer'], 'void'); +select isnt_definer('camper', 'remove_campsite_feature', array['integer']); +select volatility_is('camper', 'remove_campsite_feature', array['integer'], 'volatile'); +select function_privs_are('camper', 'remove_campsite_feature', array['integer'], 'guest', array[]::text[]); +select function_privs_are('camper', 'remove_campsite_feature', array['integer'], 'employee', array[]::text[]); +select function_privs_are('camper', 'remove_campsite_feature', array['integer'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'remove_campsite_feature', array['integer'], 'authenticator', array[]::text[]); + + +set client_min_messages to warning; +truncate campsite_feature_i18n cascade; +truncate campsite_feature cascade; +truncate campsite 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, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag) +values (1, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') +; + +insert into media_content (media_type, bytes) +values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};') + , ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ff00ff","a"};') + , ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffff00","a"};') + , ('text/plain', 'hello, world!') + , ('image/svg+xml', '') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values (2, 1, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) + , (3, 1, 'cover3.xpm', sha256('static char *s[]={"1 1 1 1","a c #ff00ff","a"};')) +; + +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', '

A

', 5, false, true) +; + +insert into campsite (campsite_id, company_id, label, campsite_type_id) +values (11, 1, 'A1', 10) + , (12, 1, 'A2', 10) +; + +insert into campsite_feature (campsite_feature_id, campsite_id, icon_name, name) +values (13, 11, 'wifi', 'Feature 1') + , (14, 11, 'baby', 'Feature 2') + , (15, 12, 'castle', 'Feature 3') + , (16, 12, 'ecofriendly', 'Feature 4') +; + +insert into campsite_feature_i18n (campsite_feature_id, lang_tag, name) +values (13, 'ca', 'Característica 1') + , (13, 'es', 'ES 1') + , (14, 'ca', 'Característica 2') + , (14, 'es', 'ES 2') + , (15, 'ca', 'Característica 3') + , (15, 'es', 'ES 3') + , (16, 'ca', 'Característica 4') + , (16, 'es', 'ES 4') +; + +select lives_ok( + $$ select remove_campsite_feature(13) $$, + 'Should be able to delete a feature from the first campsite' +); + +select lives_ok( + $$ select remove_campsite_feature(16) $$, + 'Should be able to delete a feature from the second campsite' +); + +select bag_eq( + $$ select campsite_feature_id, name from campsite_feature $$, + $$ values (14, 'Feature 2') + , (15, 'Feature 3') + $$, + 'Should have removed the features' +); + +select bag_eq( + $$ select campsite_feature_id, lang_tag, name from campsite_feature_i18n $$, + $$ values (14, 'ca', 'Característica 2') + , (14, 'es', 'ES 2') + , (15, 'ca', 'Característica 3') + , (15, 'es', 'ES 3') + $$, + 'Should have removed the features’ translations' +); + + +select * +from finish(); + +rollback; diff --git a/test/translate_campsite.sql b/test/translate_campsite.sql new file mode 100644 index 0000000..214b3c9 --- /dev/null +++ b/test/translate_campsite.sql @@ -0,0 +1,92 @@ +-- Test translate_campsite +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', 'translate_campsite', array['integer', 'text', 'text', 'text']); +select function_lang_is('camper', 'translate_campsite', array['integer', 'text', 'text', 'text'], 'sql'); +select function_returns('camper', 'translate_campsite', array['integer', 'text', 'text', 'text'], 'void'); +select isnt_definer('camper', 'translate_campsite', array['integer', 'text', 'text', 'text']); +select volatility_is('camper', 'translate_campsite', array['integer', 'text', 'text', 'text'], 'volatile'); +select function_privs_are('camper', 'translate_campsite', array['integer', 'text', 'text', 'text'], 'guest', array[]::text[]); +select function_privs_are('camper', 'translate_campsite', array['integer', 'text', 'text', 'text'], 'employee', array[]::text[]); +select function_privs_are('camper', 'translate_campsite', array['integer', 'text', 'text', 'text'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'translate_campsite', array['integer', 'text', 'text', 'text'], 'authenticator', array[]::text[]); + + +set client_min_messages to warning; +truncate campsite_i18n cascade; +truncate campsite cascade; +truncate campsite cascade; +truncate media cascade; +truncate media_content cascade; +truncate company cascade; +reset client_min_messages; + + +insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag) +values (1, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') +; + +insert into media_content (media_type, bytes) +values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values (3, 1, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) +; + +insert into campsite_type (campsite_type_id, company_id, media_id, name, dogs_allowed, max_campers) +values (11, 1, 3, 'Type A', false, 5) +; + +insert into campsite (campsite_id, company_id, campsite_type_id, label, info1, info2, active) +values (21, 1, 11, 'A1', '

Info 1

', '

Info 2

', true) + , (22, 1, 11, 'B1', '

Info 1

', '

Info 2

', true) +; + +insert into campsite_i18n (campsite_id, lang_tag, info1, info2) +values (22, 'ca', '

i1

', '

i2

') + , (22, 'en', '

i1

', '

i2

') +; + +select lives_ok( + $$ select translate_campsite(21, 'ca', '

Informació 1

', '') $$, + 'Should be able to translate the first type' +); + +select lives_ok( + $$ select translate_campsite(22, 'es', '', '

Información 2

') $$, + 'Should be able to translate the second type' +); + +select lives_ok( + $$ select translate_campsite(22, 'ca', '

Informació 1

', '

Informació 2

') $$, + 'Should be able to overwrite the catalan translation of the second type' +); + +select lives_ok( + $$ select translate_campsite(22, 'en', null, null) $$, + 'Should be able to overwrite the english translation of the second type with all empty values' +); + +select bag_eq( + $$ select campsite_id, lang_tag, info1::text, info2::text from campsite_i18n $$, + $$ values (21, 'ca', '

Informació 1

', null) + , (22, 'ca', '

Informació 1

', '

Informació 2

') + , (22, 'es', null, '

Información 2

') + , (22, 'en', null, null) + $$, + 'Should have added and updated all translations.' +); + +select * +from finish(); + +rollback; diff --git a/test/translate_campsite_carousel_slide.sql b/test/translate_campsite_carousel_slide.sql new file mode 100644 index 0000000..7879c97 --- /dev/null +++ b/test/translate_campsite_carousel_slide.sql @@ -0,0 +1,102 @@ +-- Test translate_campsite_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_carousel_slide', array['integer', 'text', 'integer', 'text', 'text']); +select function_lang_is('camper', 'translate_campsite_carousel_slide', array['integer', 'text', 'integer', 'text', 'text'], 'sql'); +select function_returns('camper', 'translate_campsite_carousel_slide', array['integer', 'text', 'integer', 'text', 'text'], 'void'); +select isnt_definer('camper', 'translate_campsite_carousel_slide', array['integer', 'text', 'integer', 'text', 'text']); +select volatility_is('camper', 'translate_campsite_carousel_slide', array['integer', 'text', 'integer', 'text', 'text'], 'volatile'); +select function_privs_are('camper', 'translate_campsite_carousel_slide', array['integer', 'text', 'integer', 'text', 'text'], 'guest', array[]::text[]); +select function_privs_are('camper', 'translate_campsite_carousel_slide', array['integer', 'text', 'integer', 'text', 'text'], 'employee', array[]::text[]); +select function_privs_are('camper', 'translate_campsite_carousel_slide', array['integer', 'text', 'integer', 'text', 'text'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'translate_campsite_carousel_slide', array['integer', 'text', 'integer', 'text', 'text'], 'authenticator', array[]::text[]); + + +set client_min_messages to warning; +truncate campsite_carousel_i18n cascade; +truncate campsite_carousel cascade; +truncate campsite 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, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag) +values (1, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') + , (2, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') +; + +insert into media_content (media_type, bytes) +values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};') + , ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ff00ff","a"};') + , ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffff00","a"};') + , ('text/plain', 'hello, world!') + , ('image/svg+xml', '') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values (3, 1, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) + , (4, 1, 'cover3.xpm', sha256('static char *s[]={"1 1 1 1","a c #ff00ff","a"};')) + , (5, 1, 'cover4.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffff00","a"};')) + , (6, 1, 'text.txt', sha256('hello, world!')) + , (7, 2, 'image.svg', sha256('')) +; + +insert into campsite_type (campsite_type_id, company_id, media_id, name, description, max_campers, dogs_allowed, active) +values (10, 1, 3, 'Type A', '

A

', 5, false, true) + , (11, 2, 7, 'Type B', '

B

', 7, true, false) +; + +insert into campsite (campsite_id, label, company_id, campsite_type_id) +values (12, 'A1', 1, 10) + , (13, 'A1', 2, 11) +; + +insert into campsite_carousel (campsite_id, media_id, caption) +values (13, 7, 'Source caption') + , (12, 5, 'Another caption') + , (12, 6, 'N/A') +; + +insert into campsite_carousel_i18n (campsite_id, media_id, lang_tag, caption) +values (13, 7, 'en', 'Target caption') +; + +select lives_ok( + $$ select translate_campsite_carousel_slide(1, 'A1', 5, 'ca', 'Traducció') $$, + 'Should be able to translate a carousel slide' +); + +select lives_ok( + $$ select translate_campsite_carousel_slide(1, 'A1', 5, 'es', '') $$, + 'Should be able to “translate” a carousel slide to the empty string' +); + +select lives_ok( + $$ select translate_campsite_carousel_slide(2, 'A1', 7, 'en', 'Not anymore') $$, + 'Should be able to overwrite a slide’s translation' +); + +select bag_eq( + $$ select campsite_id, media_id, lang_tag, caption from campsite_carousel_i18n $$, + $$ values (12, 5, 'ca', 'Traducció') + , (12, 5, 'es', null) + , (13, 7, 'en', 'Not anymore') + $$, + 'Should have all three slides' +); + + +select * +from finish(); + +rollback; diff --git a/test/translate_campsite_feature.sql b/test/translate_campsite_feature.sql new file mode 100644 index 0000000..79beb11 --- /dev/null +++ b/test/translate_campsite_feature.sql @@ -0,0 +1,96 @@ +-- Test translate_campsite_feature +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', 'translate_campsite_feature', array['integer', 'text', 'text']); +select function_lang_is('camper', 'translate_campsite_feature', array['integer', 'text', 'text'], 'sql'); +select function_returns('camper', 'translate_campsite_feature', array['integer', 'text', 'text'], 'void'); +select isnt_definer('camper', 'translate_campsite_feature', array['integer', 'text', 'text']); +select volatility_is('camper', 'translate_campsite_feature', array['integer', 'text', 'text'], 'volatile'); +select function_privs_are('camper', 'translate_campsite_feature', array['integer', 'text', 'text'], 'guest', array[]::text[]); +select function_privs_are('camper', 'translate_campsite_feature', array['integer', 'text', 'text'], 'employee', array[]::text[]); +select function_privs_are('camper', 'translate_campsite_feature', array['integer', 'text', 'text'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'translate_campsite_feature', array['integer', 'text', 'text'], 'authenticator', array[]::text[]); + + +set client_min_messages to warning; +truncate campsite_feature_i18n cascade; +truncate campsite_feature cascade; +truncate campsite 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, rtc_number, tourist_tax, country_code, currency_code, default_lang_tag) +values (1, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', '', 60, 'ES', 'EUR', 'ca') +; + +insert into media_content (media_type, bytes) +values ('image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};') +; + +insert into media (media_id, company_id, original_filename, content_hash) +values (2, 1, 'cover2.xpm', sha256('static char *s[]={"1 1 1 1","a c #ffffff","a"};')) +; + +insert into campsite_type (campsite_type_id, company_id, media_id, name, description, active, dogs_allowed, max_campers) +values (3, 1, 2, 'Type A', '

A

', true, false, 4) +; + +insert into campsite (campsite_id, company_id, label, campsite_type_id) +values (4, 1, 'A1', 3) +; + +insert into campsite_feature (campsite_feature_id, campsite_id, icon_name, name) +values (5, 4, 'toilet', 'Feature 1') + , (6, 4, 'toilet', 'Feature 2') +; + +insert into campsite_feature_i18n (campsite_feature_id, lang_tag, name) +values (6, 'ca', 'carácter2') +; + +select lives_ok( + $$ select translate_campsite_feature(5, 'ca', 'Carácter 1') $$, + 'Should be able to translate the first feature' +); + +select lives_ok( + $$ select translate_campsite_feature(6, 'es', 'Característica 2') $$, + 'Should be able to translate the second feature' +); + +select lives_ok( + $$ select translate_campsite_feature(6, 'en', '') $$, + 'Should be able to “translate” the second feature with an empty translation' +); + +select lives_ok( + $$ select translate_campsite_feature(6, 'ca', 'Carácter 2') $$, + 'Should be able to overwrite the catalan translation of the second feature' +); + +select bag_eq( + $$ select campsite_feature_id, lang_tag, name from campsite_feature_i18n $$, + $$ values (5, 'ca', 'Carácter 1') + , (6, 'ca', 'Carácter 2') + , (6, 'es', 'Característica 2') + , (6, 'en', null) + $$, + 'Should have added and updated all translations.' +); + + +select * +from finish(); + +rollback; diff --git a/verify/add_campsite.sql b/verify/add_campsite.sql index 11b04b2..4696d9b 100644 --- a/verify/add_campsite.sql +++ b/verify/add_campsite.sql @@ -2,6 +2,6 @@ begin; -select has_function_privilege('camper.add_campsite(integer, text)', 'execute'); +select has_function_privilege('camper.add_campsite(integer, text, text, text)', 'execute'); rollback; diff --git a/verify/add_campsite@v1.sql b/verify/add_campsite@v1.sql new file mode 100644 index 0000000..11b04b2 --- /dev/null +++ b/verify/add_campsite@v1.sql @@ -0,0 +1,7 @@ +-- Verify camper:add_campsite on pg + +begin; + +select has_function_privilege('camper.add_campsite(integer, text)', 'execute'); + +rollback; diff --git a/verify/add_campsite_carousel_slide.sql b/verify/add_campsite_carousel_slide.sql new file mode 100644 index 0000000..ef0820a --- /dev/null +++ b/verify/add_campsite_carousel_slide.sql @@ -0,0 +1,7 @@ +-- Verify camper:add_campsite_carousel_slide on pg + +begin; + +select has_function_privilege('camper.add_campsite_carousel_slide(integer, text, integer, text)', 'execute'); + +rollback; diff --git a/verify/add_campsite_feature.sql b/verify/add_campsite_feature.sql new file mode 100644 index 0000000..c8bc710 --- /dev/null +++ b/verify/add_campsite_feature.sql @@ -0,0 +1,7 @@ +-- Verify camper:add_campsite_feature on pg + +begin; + +select has_function_privilege('camper.add_campsite_feature(integer, text, text, text)', 'execute'); + +rollback; diff --git a/verify/campsite__info.sql b/verify/campsite__info.sql new file mode 100644 index 0000000..7fc2991 --- /dev/null +++ b/verify/campsite__info.sql @@ -0,0 +1,11 @@ +-- Verify camper:campsite__info on pg + +begin; + +select info1 + , info2 +from camper.campsite +where false +; + +rollback; diff --git a/verify/campsite_carousel.sql b/verify/campsite_carousel.sql new file mode 100644 index 0000000..fd02ccd --- /dev/null +++ b/verify/campsite_carousel.sql @@ -0,0 +1,18 @@ +-- Verify camper:campsite_carousel on pg + +begin; + +select campsite_id + , media_id + , caption + , position +from camper.campsite_carousel +where false; + +select 1 / count(*) from pg_class where oid = 'camper.campsite_carousel'::regclass and relrowsecurity; +select 1 / count(*) from pg_policy where polname = 'guest_ok' and polrelid = 'camper.campsite_carousel'::regclass; +select 1 / count(*) from pg_policy where polname = 'insert_to_company' and polrelid = 'camper.campsite_carousel'::regclass; +select 1 / count(*) from pg_policy where polname = 'update_company' and polrelid = 'camper.campsite_carousel'::regclass; +select 1 / count(*) from pg_policy where polname = 'delete_from_company' and polrelid = 'camper.campsite_carousel'::regclass; + +rollback; diff --git a/verify/campsite_carousel_i18n.sql b/verify/campsite_carousel_i18n.sql new file mode 100644 index 0000000..83df654 --- /dev/null +++ b/verify/campsite_carousel_i18n.sql @@ -0,0 +1,12 @@ +-- Verify camper:campsite_carousel_i18n on pg + +begin; + +select campsite_id + , media_id + , lang_tag + , caption +from camper.campsite_carousel_i18n +where false; + +rollback; diff --git a/verify/campsite_feature.sql b/verify/campsite_feature.sql new file mode 100644 index 0000000..ad4dd33 --- /dev/null +++ b/verify/campsite_feature.sql @@ -0,0 +1,19 @@ +-- Verify camper:campsite_feature on pg + +begin; + +select campsite_feature_id + , campsite_id + , icon_name + , name + , position +from camper.campsite_feature +where false; + +select 1 / count(*) from pg_class where oid = 'camper.campsite_feature'::regclass and relrowsecurity; +select 1 / count(*) from pg_policy where polname = 'guest_ok' and polrelid = 'camper.campsite_feature'::regclass; +select 1 / count(*) from pg_policy where polname = 'insert_to_company' and polrelid = 'camper.campsite_feature'::regclass; +select 1 / count(*) from pg_policy where polname = 'update_company' and polrelid = 'camper.campsite_feature'::regclass; +select 1 / count(*) from pg_policy where polname = 'delete_from_company' and polrelid = 'camper.campsite_feature'::regclass; + +rollback; diff --git a/verify/campsite_feature_i18n.sql b/verify/campsite_feature_i18n.sql new file mode 100644 index 0000000..5ab0ce3 --- /dev/null +++ b/verify/campsite_feature_i18n.sql @@ -0,0 +1,11 @@ +-- Verify camper:campsite_feature_i18n on pg + +begin; + +select campsite_feature_id + , lang_tag + , name +from camper.campsite_feature_i18n +where false; + +rollback; diff --git a/verify/campsite_i18n.sql b/verify/campsite_i18n.sql new file mode 100644 index 0000000..a03bde3 --- /dev/null +++ b/verify/campsite_i18n.sql @@ -0,0 +1,12 @@ +-- Verify camper:campsite_i18n on pg + +begin; + +select campsite_id + , lang_tag + , info1 + , info2 +from camper.campsite_i18n +where false; + +rollback; diff --git a/verify/edit_campsite.sql b/verify/edit_campsite.sql index 241e8e4..7d28d72 100644 --- a/verify/edit_campsite.sql +++ b/verify/edit_campsite.sql @@ -2,6 +2,6 @@ begin; -select has_function_privilege('camper.edit_campsite(integer, integer, text, boolean)', 'execute'); +select has_function_privilege('camper.edit_campsite(integer, integer, text, text, text, boolean)', 'execute'); rollback; diff --git a/verify/edit_campsite@v1.sql b/verify/edit_campsite@v1.sql new file mode 100644 index 0000000..241e8e4 --- /dev/null +++ b/verify/edit_campsite@v1.sql @@ -0,0 +1,7 @@ +-- Verify camper:edit_campsite on pg + +begin; + +select has_function_privilege('camper.edit_campsite(integer, integer, text, boolean)', 'execute'); + +rollback; diff --git a/verify/edit_campsite_feature.sql b/verify/edit_campsite_feature.sql new file mode 100644 index 0000000..1ff7115 --- /dev/null +++ b/verify/edit_campsite_feature.sql @@ -0,0 +1,7 @@ +-- Verify camper:edit_campsite_feature on pg + +begin; + +select has_function_privilege('camper.edit_campsite_feature(integer, text, text)', 'execute'); + +rollback; diff --git a/verify/order_campsite_carousel.sql b/verify/order_campsite_carousel.sql new file mode 100644 index 0000000..22363bc --- /dev/null +++ b/verify/order_campsite_carousel.sql @@ -0,0 +1,7 @@ +-- Verify camper:order_campsite_carousel on pg + +begin; + +select has_function_privilege('camper.order_campsite_carousel(text, integer, integer[])', 'execute'); + +rollback; diff --git a/verify/order_campsite_features.sql b/verify/order_campsite_features.sql new file mode 100644 index 0000000..e837902 --- /dev/null +++ b/verify/order_campsite_features.sql @@ -0,0 +1,7 @@ +-- Verify camper:order_campsite_features on pg + +begin; + +select has_function_privilege('camper.order_campsite_features(integer[])', 'execute'); + +rollback; diff --git a/verify/remove_campsite_carousel_slide.sql b/verify/remove_campsite_carousel_slide.sql new file mode 100644 index 0000000..f76737c --- /dev/null +++ b/verify/remove_campsite_carousel_slide.sql @@ -0,0 +1,7 @@ +-- Verify camper:remove_campsite_carousel_slide on pg + +begin; + +select has_function_privilege('camper.remove_campsite_carousel_slide(integer, text, integer)', 'execute'); + +rollback; diff --git a/verify/remove_campsite_feature.sql b/verify/remove_campsite_feature.sql new file mode 100644 index 0000000..55edaaf --- /dev/null +++ b/verify/remove_campsite_feature.sql @@ -0,0 +1,7 @@ +-- Verify camper:remove_campsite_feature on pg + +begin; + +select has_function_privilege('camper.remove_campsite_feature(integer)', 'execute'); + +rollback; diff --git a/verify/translate_campsite.sql b/verify/translate_campsite.sql new file mode 100644 index 0000000..a70f2bd --- /dev/null +++ b/verify/translate_campsite.sql @@ -0,0 +1,7 @@ +-- Verify camper:translate_campsite on pg + +begin; + +select has_function_privilege('camper.translate_campsite(integer, text, text, text)', 'execute'); + +rollback; diff --git a/verify/translate_campsite_carousel_slide.sql b/verify/translate_campsite_carousel_slide.sql new file mode 100644 index 0000000..b3bf8dd --- /dev/null +++ b/verify/translate_campsite_carousel_slide.sql @@ -0,0 +1,7 @@ +-- Verify camper:translate_campsite_carousel_slide on pg + +begin; + +select has_function_privilege('camper.translate_campsite_carousel_slide(integer, text, integer, text, text)', 'execute'); + +rollback; diff --git a/verify/translate_campsite_feature.sql b/verify/translate_campsite_feature.sql new file mode 100644 index 0000000..32fec5a --- /dev/null +++ b/verify/translate_campsite_feature.sql @@ -0,0 +1,7 @@ +-- Verify camper:translate_campsite_feature on pg + +begin; + +select has_function_privilege('camper.translate_campsite_feature(integer, text, text)', 'execute'); + +rollback; diff --git a/web/static/camper.css b/web/static/camper.css index 17f3925..6bce16f 100644 --- a/web/static/camper.css +++ b/web/static/camper.css @@ -398,7 +398,7 @@ label, legend { font-style: italic; } -fieldset + label, fieldset + fieldset, label + label:not([x-show]) { +fieldset + label, fieldset + fieldset, label + label:not([x-show]), label + fieldset { margin-top: 1rem; } diff --git a/web/static/map.js b/web/static/map.js index 7b414df..53a00d4 100644 --- a/web/static/map.js +++ b/web/static/map.js @@ -76,16 +76,13 @@ }); } - function zoomToAccommodation(e) { - map.fitBounds(e.target.getBounds()); - } - // XXX: this is from the “parceles” layer. const ctm = [1, 0, 0, 1, 83.2784, 66.1766]; const transform = function (x, y) { return [ctm[0] * x + ctm[2] * y + ctm[4], ctm[1] * x + ctm[3] * y + ctm[5]]; } + const language = document.documentElement.getAttribute('lang'); const prefix = 'cp_'; for (const campsite of Array.from(container.querySelectorAll(`[id^="${prefix}"]`))) { const label = campsite.id.substring(prefix.length); @@ -126,7 +123,9 @@ accommodation.on({ mouseover: highlightAccommodation, mouseout: resetHighlight, - click: zoomToAccommodation, + click: function () { + window.location = `/${language}/campsites/${label}`; + }, }) } })(); diff --git a/web/static/public.css b/web/static/public.css index 9b7dc2b..8b4afb0 100644 --- a/web/static/public.css +++ b/web/static/public.css @@ -283,7 +283,7 @@ h1 a .name { left: -9999em; } -nav ul, .campsite_type_features ul, .outside_activities > ul { +nav ul, .campsite_type_features ul, .campsite_features ul, .outside_activities > ul { list-style: none; padding-left: 0; display: flex; @@ -347,7 +347,7 @@ nav:last-of-type > ul > li:last-child { .boto-reserva { border: 2px solid; border-radius: .6rem; - height: 40px; + height: 4rem; display: flex; align-items: center; margin-bottom: 3px; @@ -505,7 +505,7 @@ nav:last-of-type > ul > li:last-child { } } -dl, .nature > div, .outside_activities > div { +dl, .nature > div, .outside_activities > div, .campsite_info { display: flex; gap: 5rem; } @@ -545,8 +545,8 @@ dl, .nature > div, .outside_activities > div { background-color: var(--accent); } -.campsite_services { - margin: 0 0 40px 0; +.campsite_services, .campsite.carousel { + margin: 0 0 4rem 0; } .carousel { @@ -907,13 +907,16 @@ dt { flex: 1; } -.campsite_type_features li { - flex: 1; - font-size: 2.4rem; +.campsite_type_features li, .campsite_features li { text-align: center; justify-content: space-between; background-repeat: no-repeat; background-position: top center; +} + +.campsite_type_features li { + flex: 1; + font-size: 2.4rem; background-size: 7.2rem 7.2rem; padding-top: 7.2rem; } @@ -1055,6 +1058,28 @@ dt { height: .8rem; } +.campsite_info > * { + flex: 1; +} + +.campsite_features { + display: flex; + justify-content: center; + align-items: center; +} + +.campsite_features ul { + display: grid; + grid-template-columns: repeat(2, 1fr); + grid-auto-rows: 1fr; + gap: 5rem; +} + +.campsite_features li { + background-size: 3.6rem 3.6rem; + padding-top: 3.6rem; +} + .checkin-checkout { flex-direction: column; gap: 0; @@ -1289,7 +1314,7 @@ input[type="checkbox"]:focus { body > footer section { width: 100% !important; - margin: 40px 0 0 0; + margin: 4rem 0 0 0; } } diff --git a/web/templates/admin/campsite/carousel/form.gohtml b/web/templates/admin/campsite/carousel/form.gohtml index 11ac15f..7afcfe1 100644 --- a/web/templates/admin/campsite/carousel/form.gohtml +++ b/web/templates/admin/campsite/carousel/form.gohtml @@ -3,37 +3,28 @@ 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 }} + {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite.slideForm*/ -}} + {{- if .MediaID -}} + {{( pgettext "Edit Campsite Carousel Slide" "title" )}} + {{- else -}} + {{( pgettext "New Campsite Carousel Slide" "title" )}} + {{- end -}} {{- end }} {{ define "breadcrumb" -}} {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.slideForm*/ -}}
  • {{( pgettext "Campsites" "title" )}}
  • -
  • {{( pgettext "Campsite Types" "title" )}}
  • -
  • {{( pgettext "Campsite Type Carousel" "title" )}}
  • +
  • {{( pgettext "Campsite Carousel" "title" )}}
  • {{- end }} {{ define "content" -}} - {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.slideForm*/ -}} + {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite.slideForm*/ -}}
    -

    - {{ if .MediaID }} - {{( pgettext "Edit Campsite Type Carousel Slide" "title" )}} - {{ else }} - {{( pgettext "New Campsite Type Carousel Slide" "title" )}} - {{ end }} -

    +

    {{ template "title" . }}

    {{ CSRFInput }}
    {{ with .Media -}} diff --git a/web/templates/admin/campsite/carousel/index.gohtml b/web/templates/admin/campsite/carousel/index.gohtml index 9a81b3b..341751e 100644 --- a/web/templates/admin/campsite/carousel/index.gohtml +++ b/web/templates/admin/campsite/carousel/index.gohtml @@ -3,22 +3,21 @@ SPDX-License-Identifier: AGPL-3.0-only --> {{ define "title" -}} - {{( pgettext "Campsite Type Carousel" "title" )}} + {{( pgettext "Campsite Carousel" "title" )}} {{- end }} {{ define "breadcrumb" -}}
  • {{( pgettext "Campsites" "title" )}}
  • -
  • {{( pgettext "Campsite Types" "title" )}}
  • {{- end }} {{ define "content" -}} - {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.carouselIndex*/ -}} -

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

    - {{( pgettext "Add slide" "action" )}} + {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite.carouselIndex*/ -}} +

    {{ template "title" . }}

    + {{( pgettext "Add slide" "action" )}} {{ if .Slides -}} - - {{ .Caption }} + {{ .Caption }} - diff --git a/web/templates/admin/campsite/feature/index.gohtml b/web/templates/admin/campsite/feature/index.gohtml index 3bb9745..30cc579 100644 --- a/web/templates/admin/campsite/feature/index.gohtml +++ b/web/templates/admin/campsite/feature/index.gohtml @@ -3,22 +3,21 @@ SPDX-License-Identifier: AGPL-3.0-only --> {{ define "title" -}} - {{( pgettext "Campsite Type Features" "title" )}} + {{( pgettext "Campsite Features" "title" )}} {{- end }} {{ define "breadcrumb" -}}
  • {{( pgettext "Campsites" "title" )}}
  • -
  • {{( pgettext "Campsite Types" "title" )}}
  • {{- end }} {{ define "content" -}} - {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.featureIndex*/ -}} - {{( pgettext "Add Feature" "action" )}} -

    {{( pgettext "Campsite Type Features" "title" )}}

    + {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite.featureIndex*/ -}} + {{( pgettext "Add Feature" "action" )}} +

    {{ template "title" . }}

    {{ if .Features -}}
    {{( pgettext "Name" "header" )}} + {{( pgettext "Actions" "header" )}} + {{ $confirm := (gettext "Are you sure you wish to delete this option?")}} {{ range .Features -}} @@ -39,12 +40,19 @@ {{ .Name }} + + + {{- end }}
    {{ else -}} -

    {{( gettext "No campsite type features added yet." )}}

    +

    {{( gettext "No campsite features added yet." )}}

    {{- end }} {{- end }} diff --git a/web/templates/admin/campsite/form.gohtml b/web/templates/admin/campsite/form.gohtml index ba7fe3e..48418ac 100644 --- a/web/templates/admin/campsite/form.gohtml +++ b/web/templates/admin/campsite/form.gohtml @@ -18,21 +18,13 @@ {{ define "content" -}} {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite.campsiteForm*/ -}}
    -

    - {{ if .ID }} - {{( pgettext "Edit Campsite" "title" )}} - {{ else }} - {{( pgettext "New Campsite" "title" )}} - {{ end }} -

    +

    {{ template "title" .}}

    {{ CSRFInput }} -
    +
    {{ if .ID }} {{ with .Active -}} {{ template "error-message" . }} {{- end }} + {{ with .Info1 -}} +
    + {{( pgettext "Info (First Column)" "input")}}
    + {{ template "lang-selector" . }} + {{ range $lang, $input := . -}} + + {{- end }} + {{ template "error-message" . }} +
    + {{- end }} + {{ with .Info2 -}} +
    + {{( pgettext "Info (Second Column)" "input")}}
    + {{ template "lang-selector" . }} + {{ range $lang, $input := . -}} + + {{- end }} + {{ template "error-message" . }} +
    + {{- end }}
    diff --git a/web/templates/admin/campsite/index.gohtml b/web/templates/admin/campsite/index.gohtml index ee6594d..b0d7ce9 100644 --- a/web/templates/admin/campsite/index.gohtml +++ b/web/templates/admin/campsite/index.gohtml @@ -22,6 +22,8 @@ {{( pgettext "Label" "header" )}} {{( pgettext "Type" "header" )}} + {{( pgettext "Features" "header" )}} + {{( pgettext "Carousel" "header" )}} {{( pgettext "Active" "campsite" )}} @@ -30,6 +32,12 @@ {{ .Label }} {{ .Type }} + + {{( pgettext "Edit Features" "action" )}} + + + {{( pgettext "Edit Carousel" "action" )}} + {{ if .Active }}{{( gettext "Yes" )}}{{ else }}{{( gettext "No" )}}{{ end }} {{- end }} diff --git a/web/templates/admin/campsite/type/carousel/form.gohtml b/web/templates/admin/campsite/type/carousel/form.gohtml new file mode 100644 index 0000000..11ac15f --- /dev/null +++ b/web/templates/admin/campsite/type/carousel/form.gohtml @@ -0,0 +1,66 @@ + +{{ 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 "breadcrumb" -}} + {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.slideForm*/ -}} +
  • {{( pgettext "Campsites" "title" )}}
  • +
  • {{( pgettext "Campsite Types" "title" )}}
  • +
  • {{( pgettext "Campsite Type Carousel" "title" )}}
  • +{{- end }} + +{{ define "content" -}} + {{- /*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 }} +

    + {{ CSRFInput }} +
    + {{ with .Media -}} + {{ template "media-picker" . }} + {{- end }} + {{ with .Caption -}} +
    + {{( pgettext "Caption" "input")}} + {{ template "lang-selector" . }} + {{ range $lang, $input := . -}} + + {{- end }} + {{ template "error-message" . }} +
    + {{- end }} +
    +
    + +
    +
    +{{- end }} diff --git a/web/templates/admin/campsite/type/carousel/index.gohtml b/web/templates/admin/campsite/type/carousel/index.gohtml new file mode 100644 index 0000000..9a81b3b --- /dev/null +++ b/web/templates/admin/campsite/type/carousel/index.gohtml @@ -0,0 +1,61 @@ + +{{ define "title" -}} + {{( pgettext "Campsite Type Carousel" "title" )}} +{{- end }} + +{{ define "breadcrumb" -}} +
  • {{( pgettext "Campsites" "title" )}}
  • +
  • {{( pgettext "Campsite Types" "title" )}}
  • +{{- end }} + +{{ define "content" -}} + {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.carouselIndex*/ -}} +

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

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

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

    + {{- end }} +{{- end }} diff --git a/web/templates/admin/campsite/type/feature/form.gohtml b/web/templates/admin/campsite/type/feature/form.gohtml new file mode 100644 index 0000000..9d870eb --- /dev/null +++ b/web/templates/admin/campsite/type/feature/form.gohtml @@ -0,0 +1,87 @@ + +{{ define "title" -}} + {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.featureForm*/ -}} + {{ if .ID}} + {{( pgettext "Edit Campsite Type Feature" "title" )}} + {{ else }} + {{( pgettext "New Campsite Type Feature" "title" )}} + {{ end }} +{{- end }} + +{{ define "breadcrumb" -}} + {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.featureForm*/ -}} +
  • {{( pgettext "Campsites" "title" )}}
  • +
  • {{( pgettext "Campsite Types" "title" )}}
  • +
  • {{( pgettext "Campsite Type Features" "title" )}}
  • +{{- end }} + +{{ define "content" -}} + {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.featureForm*/ -}} +
    +

    + {{ if .ID }} + {{( pgettext "Edit Campsite Type Feature" "title" )}} + {{ else }} + {{( pgettext "New Campsite Type Feature" "title" )}} + {{ end }} +

    + {{ CSRFInput }} +
    + {{ with $field := .Icon -}} +
    + {{( pgettext "Icon" "input")}} + +
      + {{- range .Options }} +
    • + +
    • + {{- end }} +
    + {{ template "error-message" . }} +
    + {{- end }} + {{ with .Name -}} +
    + {{( pgettext "Name" "input")}} + {{ template "lang-selector" . }} + {{ range $lang, $input := . -}} + + {{- end }} + {{ template "error-message" . }} +
    + {{- end }} +
    +
    + +
    +
    + + +{{- end }} diff --git a/web/templates/admin/campsite/type/feature/index.gohtml b/web/templates/admin/campsite/type/feature/index.gohtml new file mode 100644 index 0000000..3bb9745 --- /dev/null +++ b/web/templates/admin/campsite/type/feature/index.gohtml @@ -0,0 +1,50 @@ + +{{ define "title" -}} + {{( pgettext "Campsite Type Features" "title" )}} +{{- end }} + +{{ define "breadcrumb" -}} +
  • {{( pgettext "Campsites" "title" )}}
  • +
  • {{( pgettext "Campsite Types" "title" )}}
  • +{{- end }} + +{{ define "content" -}} + {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite/types.featureIndex*/ -}} + {{( pgettext "Add Feature" "action" )}} +

    {{( pgettext "Campsite Type Features" "title" )}}

    + {{ if .Features -}} +
    + {{ CSRFInput }} + + + + + + + + + {{ range .Features -}} + + + + + {{- end }} + +
    {{( pgettext "Name" "header" )}}
    + + + {{ .Name }}
    +
    + {{ else -}} +

    {{( gettext "No campsite type features added yet." )}}

    + {{- end }} +{{- end }} diff --git a/web/templates/admin/campsite/option/form.gohtml b/web/templates/admin/campsite/type/option/form.gohtml similarity index 100% rename from web/templates/admin/campsite/option/form.gohtml rename to web/templates/admin/campsite/type/option/form.gohtml diff --git a/web/templates/admin/campsite/option/index.gohtml b/web/templates/admin/campsite/type/option/index.gohtml similarity index 100% rename from web/templates/admin/campsite/option/index.gohtml rename to web/templates/admin/campsite/type/option/index.gohtml diff --git a/web/templates/public/campsite/page.gohtml b/web/templates/public/campsite/page.gohtml new file mode 100644 index 0000000..675e74a --- /dev/null +++ b/web/templates/public/campsite/page.gohtml @@ -0,0 +1,52 @@ + +{{ define "title" -}} + {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite.publicPage*/ -}} + {{ printf "%s %s" .TypeName .Label }} +{{- end }} + +{{ define "head" -}} + {{ template "carouselStyle" }} +{{- end }} + +{{ define "content" -}} + {{- /*gotype: dev.tandem.ws/tandem/camper/pkg/campsite.publicPage*/ -}} +

    {{ template "title" . }}

    + + {{ with .Carousel -}} + + {{- end }} + +
    + {{ range .Info -}} +
    {{ . | raw }}
    + {{- end }} + {{ with .Features -}} +
    +

    {{( pgettext "Features" "title" )}}

    +
      + {{ range . -}} +
    • {{ .Name }}
    • + {{- end }} +
    +
    + {{- end }} +
    + + {{ if .Carousel }} + {{ template "carouselInit" 3 }} + {{- end }} +{{- end }}